01 /Writing / 2 min read

NixOS Flakes

What a flake actually is: inputs, outputs, and a NixOS configuration with every dependency pinned.

Introduction to Flakes

Flakes in NixOS allow you to write Nix code that has custom inputs and outputs.

For example this is a simple example of a Flake. You can get a copy for

yourself by running nix flake init.

{
  description = "A very basic flake";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
  };

  outputs = { self, nixpkgs }: {

    packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;

    packages.x86_64-linux.default = self.packages.x86_64-linux.hello;

  };
}

Flake Structure

As you can see there are inputs (nixpkgs), and outputs (self, nixpkgs).

Managing Dependencies with flake.lock

If you build this Flake using nix build you'll end up with a new directory

called result which is a symlink to where the package was built in your Nix

store.

result -> /nix/store/yh6x9ia5kxxw3w90vkb09vqgfvhb416k-hello-2.12.1

You'll also end up with a flake.lock. If you've used npm before

flake.lock is very similar to package-lock.json. If you haven't, a quick

explanation is that it keeps track of package versions and keeps them locked

between updates. If you want to update your lockfile so you can get a newer

package version you can do so with nix flake update

Now so far I've only showed a very basic example of a Flake, the example from

nix flake init. You can see more templates with nix flake show templates.

Development Shells (devShell)

One thing I like using Flakes for is to create a devShell. You can initialize

a Flake with a devShell preconfigured with `nix flake init -t

templates#utils-generic`

{
  inputs = {
    utils.url = "github:numtide/flake-utils";
  };
  outputs = { self, nixpkgs, utils }: utils.lib.eachDefaultSystem (system:
    let
      pkgs = nixpkgs.legacyPackages.${system};
    in
    {
      devShell = pkgs.mkShell {
        buildInputs = with pkgs; [
        ];
      };
    }
  );
}

In this example you can add packages from nixpkgs to buildInputs for them to

be installed temporarily. You can activate it with nix develop. This is the

devShell I use for my typescript projects.

# ...
      devShell = pkgs.mkShell {
        buildInputs = with pkgs; [
          efm-langserver
          nil
          nodePackages_latest.nodejs
          nodePackages_latest.typescript-language-server
          nodePackages_latest.prettier
          vscode-langservers-extracted
          nodePackages_latest.bash-language-server
        ];
      };
# ...

Building Packages with Flakes

You can use Flakes to build packages as well. You can look at just about any

Nix package for an example. Just choose one in

nixpkgs. Flakes have many functions to

build different types of packages as you can see in nixpkgs.