Flakes

Updated: July 17, 2026

Flakes help create standalone builds whether a single program or an entire OS.


Table of Contents


It is the replacement of using channels. You are using either one or the other.
Channels work fine but flakes gives more granular control.



There are a few things to note about flakes:

Basic flake

{
  description = "flake for cross platform";
  inputs = {
    nixpkgs.url = "githut:NixOS/nixpkgs/nixpkgs-unstable";
  };

  outputs = { self, nixpkgs }:
    let
      supportedSystems = [ "x86_64-darwin" "x86_64-linux" "aarch64-darwin" "aarch64-linux" ]:
      forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
  };
}

In regard to items above: when we declare a default it is referring to self and pointing to an input.

{ }:              # set and semicolon means it is a function
self              # is a flake listed as a parameter, currently looking at
nixpkgs           # also a flake listed as a parameter, but comes from inputs

Lock

# update all flake inputs
nix flake update

# update inputs for commit changes
nix flake update --commit-lock-file

# update a specific input in the flake
nix flake lock --update-input <input>

Hashes

Sometimes you need a hash during the build of a flake.
You cant get ahead of time so use lib.fakeHash.

{lib, ...}:
{
  services.somesuch = {
    hash = lib.fakeHash;
  };
}

This will produce an error that is actually helpful. It will say while building
that your hash is wrong and got out:
place the correct hash where lib.fakeHash is and remove lib if nothing else uses it.