├── README.md ├── nixpkgs ├── config.nix ├── overlays.nix └── path.nix ├── rebuild └── root.nix /README.md: -------------------------------------------------------------------------------- 1 | # Sane stable stateless NixOS setup 2 | 3 | This is a fairly straightforward setup for making a NixOS system configuration stateless without relying on experimental Nix features. 4 | 5 | This means: 6 | - `nix-channel` is disabled 7 | - Nixpkgs is managed with [niv](https://github.com/nmattia/niv) [^1] 8 | - The same Nixpkgs is used for the system and all Nix commands 9 | - This includes the Nixpkgs version, config and overlays 10 | 11 | [^1]: Yes niv is a third-party tool, but it's essentially just a nice wrapper around `nix-prefetch-url` and co. 12 | 13 | ## Usage 14 | 15 | We're assuming that you just installed NixOS by going through the [official installation docs](https://nixos.org/manual/nixos/stable/#sec-installation). 16 | 17 | ### Setup 18 | 19 | 1. Clone this repo to a local directory and enter it: 20 | ``` 21 | nix-shell -p git --run \ 22 | 'git clone https://github.com/infinisil/sane-stable-nixos nixos' 23 | cd nixos 24 | ``` 25 | 2. Add your initial NixOS configuration files, either 26 | - Move your existing configuration files into it: 27 | ``` 28 | sudo mv /etc/nixos/* . 29 | ``` 30 | - Generate new ones: 31 | ``` 32 | nixos-generate-config --dir . 33 | ``` 34 | 3. Pin Nixpkgs to the [latest stable version](https://nixos.org/manual/nixos/stable/release-notes) using [niv](https://github.com/nmattia/niv): 35 | ``` 36 | nix-shell -p niv --run \ 37 | 'niv init --nixpkgs NixOS/nixpkgs --nixpkgs-branch nixos-23.11' 38 | ``` 39 | 4. Remove all stateful channels: 40 | ``` 41 | sudo rm -v /nix/var/nix/profiles/per-user/*/channels* 42 | ``` 43 | 5. Rebuild: 44 | ``` 45 | sudo ./rebuild switch 46 | ``` 47 | 6. Log out and back in again. 48 | 49 | ### Making changes 50 | 51 | Here are some changes you can make: 52 | - Change the NixOS configuration in `./configuration.nix` 53 | - Update the pinned Nixpkgs: 54 | ``` 55 | niv update nixpkgs 56 | ``` 57 | - Upgrade to a newer release: 58 | ``` 59 | niv update nixpkgs --branch nixos-23.11 60 | ``` 61 | - Change the Nixpkgs config by editing `nixpkgs/config.nix` 62 | - Add Nixpkgs overlays to `nixpkgs/overlays.nix` 63 | - Regenerate the hardware configuration: 64 | ``` 65 | nixos-generate-configuration --dir . 66 | ``` 67 | 68 | To apply the changes, run 69 | ``` 70 | sudo ./rebuild switch 71 | ``` 72 | 73 | All options to `./rebuild` are forwarded to `nixos-rebuild`. 74 | 75 | After rebuilding, the changes are reflected in the system. 76 | Furthermore, all Nix commands on the system will also use the the same values. 77 | -------------------------------------------------------------------------------- /nixpkgs/config.nix: -------------------------------------------------------------------------------- 1 | # https://nixos.org/manual/nixpkgs/stable/#chap-packageconfig 2 | { 3 | 4 | } 5 | -------------------------------------------------------------------------------- /nixpkgs/overlays.nix: -------------------------------------------------------------------------------- 1 | # https://nixos.org/manual/nixpkgs/stable/#sec-overlays-definition 2 | [ 3 | 4 | ] 5 | -------------------------------------------------------------------------------- /nixpkgs/path.nix: -------------------------------------------------------------------------------- 1 | # The Nixpkgs path to use 2 | (import ../nix/sources.nix).nixpkgs.outPath 3 | -------------------------------------------------------------------------------- /rebuild: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # nix-instantiate --eval has no raw mode yet 5 | nixpkgsPath=$(nix-instantiate --eval --read-write-mode nixpkgs/path.nix | tr -d \") 6 | # Get the ./root.nix relative to this script 7 | configPath=$(realpath -- "$(dirname -- "${BASH_SOURCE[0]}")/root.nix") 8 | 9 | # nixos-rebuild always reads Nixpkgs from the NIX_PATH, 10 | # so we need to set it explicitly to our pinned version 11 | exec nixos-rebuild "$@" -I nixpkgs="$nixpkgsPath" -I nixos-config="$configPath" 12 | -------------------------------------------------------------------------------- /root.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, config, ... }: { 2 | imports = [ 3 | # Import your main configuration 4 | ./configuration.nix 5 | ]; 6 | 7 | environment.systemPackages = with pkgs; [ 8 | # We're using niv to manage the systems Nixpkgs version, install it globally for ease 9 | niv 10 | ]; 11 | 12 | # Use the Nixpkgs config and overlays from the local files for this NixOS build 13 | nixpkgs = { 14 | config = import ./nixpkgs/config.nix; 15 | overlays = import ./nixpkgs/overlays.nix; 16 | }; 17 | 18 | # Makes commands default to the same Nixpkgs, config, overlays and NixOS configuration 19 | nix.nixPath = [ 20 | "nixpkgs=${pkgs.path}" 21 | "nixos-config=${toString ./root.nix}" 22 | "nixpkgs-overlays=${toString ./nixpkgs/overlays.nix}" 23 | ]; 24 | environment.variables.NIXPKGS_CONFIG = lib.mkForce (toString ./nixpkgs/config.nix); 25 | 26 | # Remove the stateful nix-channel command 27 | environment.extraSetup = '' 28 | rm --force $out/bin/nix-channel 29 | ''; 30 | 31 | # This option is broken when set false, prevent people from setting it to false 32 | # And we implement the important bit above ourselves 33 | nix.channel.enable = true; 34 | } 35 | --------------------------------------------------------------------------------