This is a demo NixOS config, with optional flakes support. Along with notes on why flakes is useful and worth adopting.
WARNING: You should understand that:
there is currently no path to flakes being stable
we can't even experiment with flakes alternatives without committing to pure-eval as a stepping stone
the people that CARE about the problems solved by flakes seem to care about solving this problem
the people using impurity everywhere don't seem very motivated to dive into this problem-space
as a result, the tooling is completely fractured and stagnant
besides some UX fixes, bugfixes, and other feature-work in Nix, this has more or less been the case for years
I'm tired of seeing (often self-proclaimed, repeated-from-others) FUD by non-flakes users
Anyway, now you know. Proceed at your own caution.
NOTE: nixflk is a better example repo for a full NixOS config layout, this repo is mostly to provide more context+examples around flakes, and to show that you can produce the same EXACT system with flakes as with nix-build, if you know what to do.
This readme starts out with an attempt to explain and justify flakes. It also contains
some examples of nix
cli flakes syntax and tips for adopting flakes in your project.
Finally, at the end of the readme
is an example NixOS config with a supporting flake.nix
,
and instructions to build it with and without flakes support at the same time.
Flakes is a few things:
flake.nix
: a Nix file, with a specific structure to describe inputs and outputs for a Nix project
flake.lock
: a manifest that "locks" inputs and records the exact versions in useThis ultimately enables:
This removes the need for:
niv
or other tooling to lock dependenciesNIX_PATH
is set consistently for your teamnix
and nix-daemon
boot.isContainer = true;
on configuration.nix
(as the article suggests) if you want to use nixos-rebuild
rather than nixos-container
Nix is in flakes mode when:
--flake
is used with the nixos-rebuild
commandnix build
is used with an argument like '.#something'
(the hash symbol separates the flake source from the attribute to build)When in this mode:
flake.nix
insidenix build '.#something'
, the .
means current directory, and #something
means to build the something
output attributenixos-rebuild build --flake '.#'
flake.nix
in .
(current dir)nixos-rebuild
, it automatically tries to build:
#nixosConfigurations.{hostname}.config.system.build.toplevel
nixos-rebuild build --flake '/code/nixos-config#mysystem'
flake.nix
in /code/nixos-config
nixos-rebuild
, it automatically tries to build:
#nixosConfigurations.mysystem.config.system.build.toplevel
mysystem
config)nix build 'github:colemickens/nixpkgs-wayland#obs-studio'
flake.nix
in (a checkout of github.com/colemickens/nixpkgs-wayland
)#obs-studio
#packages.{currentSystem}.obs-studio
nix flake update --recreate-lock-file
flake.lock
nix flake update --update-input nixpkgs
flake.lock
Nix CLI will try to be ... smart and auto-coerce some output attribute paths for you.
nix build '/some/path#obs-studio'
:
/some/path#obs-studio
/some/path#packages.x86_64-linux.obs-studio
/some/path#legacyPackages.x86_64-linux.obs-studio
Remove Impurities - Since nix flakes does a 'pure' build by default,
NIX_PATH
is ignored<nixpkgs>
imports do not work, and explicitly error~/.config/{nix,nixpkgs}
) are ignorefetchTarball
without a pinned rev
+sha256
) are forbiddenTo fix these:
flake.nix
instead of using fetchTarball
nixpkgs-wayland
.getFlake
vs passing inputs
in specialArgs
Consider the nixos configuration in this repo:
These represent an example, minimal NixOS system configuration.
The easiest way to build it, without cloning this repo:
nix build 'github:colemickens/nixos-flake-example#nixosConfigurations.mysystem.config.system.build.toplevel'
Let's prove that we can build this config, with and without flakes:
Using nixos-rebuild
:
# with flakes
unset NIX_PATH
nixos-rebuild build --flake '.#mysystem'
readlink -f ./result
/nix/store/gg1jhmzqndqa0rfnwfdbnzrn8f74ckr6-nixos-system-mysystem-21.03pre-git
# !! for this next step, match the git SHA1 to what the flake.lock uses
# otherwise you'll have a hash mismatch due to different nixpkgs
# without flakes
export NIX_PATH=nixpkgs=https://github.com/nixos/nixpkgs/archive/007126eef72271480cb7670e19e501a1ad2c1ff2.tar.gz:nixos-config=/home/cole/code/nixos-flake-example/configuration.nix
nixos-rebuild build
readlink -f ./result
/nix/store/gg1jhmzqndqa0rfnwfdbnzrn8f74ckr6-nixos-system-mysystem-21.03pre-git
Using nix build
:
# with flakes
unset NIX_PATH
nix build '.#nixosConfigurations.mysystem.config.system.build.toplevel
readlink -f ./result
/nix/store/gg1jhmzqndqa0rfnwfdbnzrn8f74ckr6-nixos-system-mysystem-21.03pre-git
# without flakes
export NIX_PATH=nixpkgs=https://github.com/nixos/nixpkgs/archive/007126eef72271480cb7670e19e501a1ad2c1ff2.tar.gz:nixos-config=/home/cole/code/nixos-flake-example/configuration.nix
nix-build '<nixos/nixpkgs>' -A config.system.build.toplevel
readlink -f ./result
/nix/store/gg1jhmzqndqa0rfnwfdbnzrn8f74ckr6-nixos-system-mysystem-21.03pre-git
The ./check.sh
script automates this process:
cole@slynux ~/code/nixos-flake-example master* 7s
❯ ./check.sh
:: Updating the 'nixpkgs' input in flake.nix
+ nix flake update --update-input nixpkgs
+ set +x
:: Using 'nixos-rebuild' to build the 'mysystem' toplevel
+ nixos-rebuild build --flake '.#mysystem'
warning: Git tree '/home/cole/code/nixos-flake-example' is dirty
building the system configuration...
warning: Git tree '/home/cole/code/nixos-flake-example' is dirty
+ set +x
:: Using rev=007126eef72271480cb7670e19e501a1ad2c1ff2 for <nixpkgs> (extracted from flake.nix)
:: Setting NIX_PATH to the same values flakes is using
+ NIX_PATH=nixpkgs=https://github.com/nixos/nixpkgs/archive/007126eef72271480cb7670e19e501a1ad2c1ff2.tar.gz:nixos-config=/home/cole/code/nixos-flake-example/configuration.nix
+ nix-build '<nixpkgs/nixos>' -A config.system.build.toplevel
/nix/store/gg1jhmzqndqa0rfnwfdbnzrn8f74ckr6-nixos-system-mysystem-21.03pre-git
+ set +x
flake: /nix/store/gg1jhmzqndqa0rfnwfdbnzrn8f74ckr6-nixos-system-mysystem-21.03pre-git
clssc: /nix/store/gg1jhmzqndqa0rfnwfdbnzrn8f74ckr6-nixos-system-mysystem-21.03pre-git
Is the hash tag syntax really worth it?
nix build 'github:colemickens/nixpkgs-wayland#obs-studio'
nix build --flake 'github:colemickens/nixpkgs-wayland' 'obs-studio'
?Are the auto-coercion rules for attribute paths worth it? They definitely add some mental overhead...