Skip to content

Using Nix

Hint: whenever you see nix-<command> it's probably not what you want, the new way to do everything is with the nix <command> style.

nix-shell

The following command will enter you into a Nix shell with the supplied programs available. This is a great way to test a program, or use it temporarily, without having to keep it installed on your system

sh
nix-shell -p program1 program2
# exit the shell with 'exit' or 'Ctrl+D'
nix-shell -p program1 program2
# exit the shell with 'exit' or 'Ctrl+D'

Search for packages at https://search.nixos.org/packages Once you've located a package. start a shell with that package using the -p/--packages flag.

nix develop

Ref: https://zero-to-nix.com/start/nix-develop

When entering into a folder with a flake.nix file, use nix develop to initialize you development environment given what is specified in the Flake.

Use nix develop -c $SHELL to enter into the shell defined by $SHELL

You can define development environment of ay complexity using the Nix language.

You activate a Nix environment with the nix develop command.

nix
nix develop <flake_reference>#<some_flake>
nix develop <flake_reference>#<some_flake>

Where for example <flake_reference> is the package source, can be (and often is) nixpkgs, or it can be github:DeterminateSystems/zero-to-nix (or any git repository); and <some_flake> is a flake output that can be found in the flake.nix of the flake reference.

Nix dev enviornments can be used to initialize shell hooks (code that runned when the env is started), and environment variables.

You can also run arbitrary commands that use the enviornment, but you never enter the environment yourself. do this by appending the -c/--command argument to nix develop

nix develop "github:DeterminateSystems/zero-to-nix#example" --command curl https://example.com
nix develop "github:DeterminateSystems/zero-to-nix#example" --command curl https://example.com

Some awesome dev enviornment templates for various languages are available here: https://zero-to-nix.com/start/nix-develop

But you can define aribtrarily complex environment with tools such as kubernetes, terraform, openSSL, etc.

nix build

will also build a flaske but place the relevant items into a result directory. nix build .#a_flake_to_run

Derivations

The most important built-in function is derivation, which is used to describe a single derivation (a build action). It takes as input a set, the attributes of which specify the inputs of the build.

Make Packages

nixpkgs is a community maintained list of packages that you can pre-install, but sometimes you need to be able to create your own.

Nix language

https://dram.page/p/nix-lang-with/

Standard environment: https://ryantm.github.io/nixpkgs/stdenv/stdenv/#chap-stdenv

fully functional

nix
{
  outputs = { self, nixpkgs }: {
	  packages.ax86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello
  }
}
{
  outputs = { self, nixpkgs }: {
	  packages.ax86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello
  }
}

The above snip defines a function output of one argument, whereby it appears as two arguments { self, nixpkgs } using a standard destructuring system (like JS), e.g., { self, nixpkgs } = input. Both self and nixpkgs then expose themselves to the function output.

{
  outputs = { 
      self, nixpkgs 
  }: let 
    system = "x86_64-linux";
    # 'inherit system' is the same as 'system = system'
    pkgs = import nixpks { inherit system; } 
  in {
      packages.${system} = {
    	  myPackage = pkgs.firefox  
      }

  };
}
(noteL spacing not correct)
{
  outputs = { 
      self, nixpkgs 
  }: let 
    system = "x86_64-linux";
    # 'inherit system' is the same as 'system = system'
    pkgs = import nixpks { inherit system; } 
  in {
      packages.${system} = {
    	  myPackage = pkgs.firefox  
      }

  };
}
(noteL spacing not correct)

The above snip uses a let in syntax to define additional variables for easier access

stdenv.mkDerivation

is a key to understanding how to compose derivations in a flake.nix file.

  • Use buildInputs = [ pkgs.foo pkgs.bar ] to specify the dependencies you want in your environment.
  • Use nativeBuildInputs for packages that would otherwise be available on the base system, but aren't required at runtime, e.g., cmake, gcc, clang, pkg-config, etc
  • Use propogatedBuildInputs for dependencies that you need to propogate to anything using the Flake.

Overlays

https://nixos.wiki/wiki/Overlays

Let you change or introduce packages that aren't available on the main pal=ckage set through nixpkgs. This way, you can apply overlays to create new package sets

This overlay works

nix
overlays.default = final: prev: {
  package1 = self.packages.${prev.system}.default;
}
overlays.default = final: prev: {
  package1 = self.packages.${prev.system}.default;
}

Where previously in the flake a packages.default is defined.

Also note that when using the flake-utils.lib.eachDefaultSystem you need to merge the sets of the output flake using the // syntax. Ref: https://nixos.org/manual/nix/unstable/language/index.html Ref: https://discourse.nixos.org/t/why-is-my-flake-overlay-failing/24775

Now, in another flake that has theis flake as as input, once you add it as on overlay with

nix
https://discourse.nixos.org/t/why-is-my-flake-overlay-failing/24775
https://discourse.nixos.org/t/why-is-my-flake-overlay-failing/24775

Using direnv

this will search for the file .envrc in each folder and execute steps when you enter the folder.

Using Home Manager

Ask Home Manager to build and deploy the environment defined by our home.nix with a single command:

shell
$ home-manager switch
$ home-manager switch

Outstanding questions

Keys: a flake has to be tracked by git to work correctly.

My Config requirements

  • .profile: not done
  • .zshrc: not done
  • home-manager folder with flake and home: not done
  • What goes in .config/nixpkgs/ folder?