My NixOS configuration and deployment.
Go to file
2023-09-29 14:23:49 +02:00
assets ssh config 2023-09-27 20:12:19 +02:00
hosts yodaNas hardware-config 2023-09-28 16:21:04 +02:00
modules journalwatch config 2023-09-29 14:23:49 +02:00
nix chore 2023-09-25 21:27:30 +02:00
secrets add sendmail (OpenSMTPD) and journalwatch 2023-09-18 15:32:43 +02:00
.gitignore add sendmail (OpenSMTPD) and journalwatch 2023-09-18 15:32:43 +02:00
hive.nix cleanup 2023-09-27 20:12:49 +02:00
README.md update README 2023-09-28 16:34:34 +02:00

NixOS

For each host (server, laptop, etc.), there is a subdirectory inside hosts.

NixOS installation

For beginners, NixOS can be installed with a graphical installer.

Getting the ISO:

During installation:

  • If the installation target is a SSD
    • Trim the whole disk to mark all cells as unused and restore its initial performance
    • sudo blkdiscard -f /dev/nvmeXXX
  • Select manual partitioning:
    • One 512MB (or larger) Fat32 partition, mounted at /boot, "boot" flag enabled
    • Another partition (e.g. BTRFS) covering the rest of the drive, mounted at /, encryption enabled

Update, build and switch

Update

Update channel and configuration:

sudo nix-channel --update && niv update

To apply the updates, continue with "Build and switch".

Build and switch: Using Colmena

See section "Colmena: Deployment and secret management" to build and apply updates.

Build and switch: Manually

Option I: Build new config and activate it:

sudo nixos-rebuild -I nixos-config=hosts/$(hostname)/configuration.nix switch

To view changes, see section "Compare two versions of NixOS system profile".

Option II: Build new config and activate it during next boot:

sudo nixos-rebuild -I nixos-config=hosts/$(hostname)/configuration.nix boot

Option III: Build config and view changes:

# This leaves a symlink named `result` in the current directory.
sudo nixos-rebuild -I nixos-config=hosts/$(hostname)/configuration.nix build
nix --extra-experimental-features nix-command store diff-closures /run/current-system ./result
#=> ...
#=> linux: 6.1.47, 6.1.47-modules → 6.1.51, 6.1.51-modules, -11.8 KiB

Depending on if there are large kernel changes, either switch to it directly or wait until next boot:

# TODO: This is not persistent (after reboot).
sudo ./result/bin/switch-to-configuration switch
# or
# TODO: This does not work. There is no new boot menu entry :/
sudo ./result/bin/switch-to-configuration boot

niv: Dependency management

niv:

Easy dependency management for Nix projects.

Nix is a very powerful tool for building code and setting up environments. niv complements it by making it easy to describe and update remote dependencies (URLs, GitHub repos, etc). It is a simple, practical alternative to Nix flakes.

https://github.com/nmattia/niv

Niv is an easy dependency management for Nix projects with package pinning.

https://github.com/mikeroyal/NixOS-Guide

Initialize:

niv init

Change the tracking branch of nixpkgs from unstable to 23.05:

niv modify nixpkgs --branch nixos-23.05

Add Home Manager with niv

Home Manager:

[Home Manager] allows declarative configuration of user specific (non-global) packages and dotfiles.

To avoid breaking users' configurations, Home Manager is released in branches corresponding to NixOS releases ( e.g. release-23.05).

Home Manager provides both the channel-based setup and the flake-based one.

https://github.com/nix-community/home-manager

Check your channel:

sudo nix-channel --list
#=> nixos https://nixos.org/channels/nixos-23.05

Use the corresponding branch:

niv add nix-community/home-manager -n home-manager -b release-23.05

Add NUR with niv

The Nix User Repository (NUR) is community-driven meta repository for Nix packages.

... packages are built from source and are not reviewed by any Nixpkgs member.

https://github.com/nix-community/NUR

niv add nix-community/NUR -n NUR

disko and nixos-anywhere: Remote installation

TODO. This is at low priority as I don't install new systems too often. And it is a quite fast process with the graphical NixOS installer.

Colmena: Deployment and secret management

Colmena is a simple, stateless NixOS deployment tool modeled after NixOps and morph, written in Rust.

Alternative: Deployment with Morph: https://xeiaso.net/blog/morph-setup-2021-04-25

Configuration is done inside hive.nix.

Build config:

colmena build

Apply to all non-local nodes:

colmena apply --on @server switch
#colmena apply --on @server boot

#colmena apply --on @yodaTab switch
#colmena apply --on @yodaTab boot

Apply to local node:

colmena apply-local --sudo switch
#colmena apply-local --sudo boot

Filtering:

  • You can filter hosts by tags with --on @tag-a,@tag-b.
  • You can use globs in tag matching as well: colmena apply --on '@infra-*'

BTRFS swap file

Summary:

  • Create subvolume @swap directly below top-level subvolume.
  • Mount at /swap
  • Create swapfile: sudo btrfs filesystem mkswapfile --size 8g --uuid clear /swap/swapfile
  • Regenerate hardware-configuration: sudo nixos-generate-config --dir hosts/$(hostname)
  • Add swapDevices = [ { device = "/swap/swapfile"; } ]; to hardware configuration and run nixos-rebuild switch (see above).

LUKS Parameters

Warning: NixOS has a hardcoded timeout of 10 seconds when opening encrypted drives during boot. Please choose --iter-time <= 5000.

Automount encrypted drive

* Generate and add keyfile to LUKS device

sudo nixos-generate-config --dir hosts/$(hostname)
  • If it is an SSD, enable boot.initrd.luks.devices.<name>.allowDiscards

Failed services

If there are e.g. file conflicts due to preexisting dotfiles, the Home Manager user service might fail. To list all failed services, run:

systemctl --failed

Garbage collection

For all profiles:

sudo nix-collect-garbage --delete-older-than 14d

Remove old generations from EFI:

sudo /run/current-system/bin/switch-to-configuration boot

Run AppImages

# Note how your shell prefix changes.
nix-shell -p appimage-run
# Inside the shell, you can run an AppImage:
appimage-run ~/Downloads/ubports-installer_0.10.0_linux_x86_64.AppImage

General Notes

  • There is controversy about flakes, rather use channels (e.g. with niv)
  • Prins, P., Suresh, J. and Dolstra, E., "Nix fixes dependency hell on all Linux distributions," Archived December 26, 2008, at the Wayback Machine linux.com, December 22, 2008

Nix Pills

It provides a tutorial introduction into the Nix package manager and Nixpkgs package collection, in the form of short chapters called 'pills'.

Papers

Papers about Nix:

System information

nix-info -m
 - system: `"x86_64-linux"`
 - host os: `Linux 6.1.51, NixOS, 23.05 (Stoat), 23.05.3242.da5adce0ffaf`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.13.5`
 - channels(root): `"nixos-23.05"`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`

Search for packages

Search for options

Search wich package owns a file

# Note how your shell prefix changes.
nix-shell -p nix-index
# Either build the index manually (requires >12GB RAM):
nix-index
# Or download weekly build:
mkdir -p ~/.cache/nix-index/ && wget -q -N https://github.com/nix-community/nix-index-database/releases/latest/download/index-x86_64-linux -O ~/.cache/nix-index/files

# Then search for a file
nix-locate --whole-name '/bash'

List files of package

Example for nano:

find $(nix-build '<nixpkgs>' -A nano --no-link)

Excerpt of the result:

/nix/store/jqvxmx65mfinbsm6db9kmcqmphl44xhp-nano-7.2/share/nano
/nix/store/jqvxmx65mfinbsm6db9kmcqmphl44xhp-nano-7.2/share/nano/asm.nanorc
/nix/store/jqvxmx65mfinbsm6db9kmcqmphl44xhp-nano-7.2/share/nano/autoconf.nanorc

Compare two versions of NixOS system profile

Get latest system profile. This is the profile (usually) being active after booting the system:

ls -1 /nix/var/nix/profiles/ | sort -t'-' -n -k2 | tail -n 1
#=> 120

Compare current with previous profile:

# https://stackoverflow.com/a/36641298
prev="$(ls -1 /nix/var/nix/profiles/ | sort -t'-' -n -k2 | tail -n 2 | head -n 1)"
curr="$(ls -1 /nix/var/nix/profiles/ | sort -t'-' -n -k2 | tail -n 1)"
nix --extra-experimental-features nix-command store diff-closures /nix/var/nix/profiles/"${prev}" /nix/var/nix/profiles/"${curr}"

Compare two arbitrary system profiles:

nix --extra-experimental-features nix-command store diff-closures /nix/var/nix/profiles/system-110-link /nix/var/nix/profiles/system-116-link
cpupower: 6.1.47 → 6.1.51
element-desktop: 1.11.38 → 1.11.40, +2218.9 KiB
element-web: 1.11.38 → 1.11.40, -73.1 KiB
exempi: 2.6.3 → 2.6.4
firefox: 116.0.3 → 117.0
firefox-unwrapped: 116.0.3 → 117.0, -292.6 KiB
gnome-shell-extension-openweather: ∅ → 121, +590.5 KiB
hm_fontconfigconf.d10hmfonts.conf: ∅ → ε
initrd: ∅ → ε
initrd-linux: 6.1.47 → 6.1.51
libcap: 2.68 → 2.69
linux: 6.1.47, 6.1.47-modules → 6.1.51, 6.1.51-modules, -11.8 KiB
meld: ∅ → 3.22.0, +3858.5 KiB
net-snmp: 5.9.3 → 5.9.4
nixos-system-yodaTab: 23.05.3085.2ab91c8d65c0 → 23.05.3242.da5adce0ffaf
openjdk: +19.5 KiB
python3.10-pygobject: +27.0 KiB
stage: ∅ → 1-init.sh, +29.5 KiB
tor-browser-bundle-bin: 12.5.2 → 12.5.3, +18.1 KiB
user: +2885.0 KiB

NixOS configuration debugging

Evaluating parts of the configuration.

First, start nix repl:

nix repl --file '<nixpkgs/nixos>' -I nixos-config=hosts/$(hostname)/configuration.nix

Example: config.home-manager

config.home-manager.
# Press `TAB`
#=> config.home-manager.backupFileExtension  config.home-manager.useUserPackages
#=> config.home-manager.extraSpecialArgs     config.home-manager.users
#=> config.home-manager.sharedModules        config.home-manager.verbose
#=> config.home-manager.useGlobalPkgs

Example: The home variable:

config.home-manager.users.yoda.home

Example: The value of one config option

# The following option is set to `"${config.xdg.dataHome}/.histfile";`
# where `config` is the Home Manager configuration.

config.home-manager.users.yoda.programs.zsh.history.path
#=> "/home/yoda/.local/share/.histfile"

Evaluate NixOS configuration to JSON

See also section "NixOS Configuration Debugging"!

TODO: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-show-config.html

This evaluates configuration.nix (single module):

NIXPKGS_ALLOW_UNFREE=1 nix-instantiate --strict --json --eval -E '
import ./hosts/yodaTab/configuration.nix  {
  config = {};
  pkgs = import <nixpkgs> {};
  lib = import <nixpkgs/lib>;
}
' > evaluated-config.json

Then open evaluated-config.json.

References

Some references to websites that helped me create this repository:

TODOs