A Nix flake of personal NixOS and Home Manager (HM) configurations.
NixOS configuration highlights:
- Fully declarative configurations of multiple NixOS configurations of laptops and workstations
- ZFS-based root file system with optional encryption and automatic partitioning and formatting provided by disko
- Ephemeral dataset for
/
(through restoring a blank snapshot on boot) and opt-in persistence with help of the impermanence module - Mounted datasets nested under either
local
andsafe
parents, with only the latter group backed up (inspired by Graham Christensen) - Hosts in a private mesh network using Tailscale
There may be some rough edges as Nix Flakes are still considered experimental.
This flake contains private system configurations; it is not guaranteed to work for anyone but myself, and may change swiftly and randomly without warning! For incomplete features and planned changes, check out the to-do list.
Feel free to grab some inspiration from this repo but do not use it as a dependency. "You don't want my crap, you want your own." (dasJ)
Tip: to boot ISO images from a USB key or external SSD, my preferred method is to use Ventoy.
-
(Prerequisite) It is assumed that the NixOS configuration of the target machine has already been created in the flake. Otherwise,
-
Download the latest NixOS ISO image using
wget -O nixos-x86_64-linux.iso https://channels.nixos.org/nixos-unstable/latest-nixos-minimal-x86_64-linux.iso
write it onto some external medium and boot it.
-
Find out persistent virtual disk block device paths of the target machine in a live enviromnent by comparing
lsblk
andls -l /dev/disk/by-id
outputs. -
Find out the MAC addresses of network interfaces using
ip a
. -
Have a look at the output of
nixos-generate-config --show-hardware-config --no-filesystems | less
for recommended kernel modules and other settings. -
Edit the config of the target machine accordingly.
-
-
(Optional) Prepare a NixOS ISO image.
-
If you have access to a system where Nix is installed, it is preferred to build the ISO image for yourself as
nix --experimental-features 'nix-command flakes' build github:aolasz/groundzero#iso
The resulting ISO image is then located at
./result/iso/nixos-x86_64-linux.iso
. This way, you ensure that the Linux kernel, ZFS kernel module, file system tools etc. of the installer are identical to those of the installed system. -
Use the following command to testrun the iso file if you can use nix:
nix-shell -p qemu --run "qemu-system-x86_64 -m 2048 -vnc :0 -cdrom ./result/iso/nixos-x86_64-linux.iso"
-
Otherwise just use the latest minimal NixOS ISO image.
-
-
Boot the NixOS ISO image on the target machine.
-
Ensure that the machine has Internet access. To connect to a Wifi network, the custom ISO enables NetworkManager and the
nmtui
tool, while in case of the generic ISO image, the NixOS manual provides guidance on usingwpa_supplicant
andwpa_cli
. -
(If generic ISO image is used) Enable experimental features of Nix and export the
FLAKE0
environment variable to point to the online flake repo asexport NIX_CONFIG='experimental-features = nix-command flakes' export FLAKE0=github:aolasz/groundzero
-
Enter a host-specific installer devshell of this flake as follows
nix develop $FLAKE0#<hostname>
-
Run disko using a custom script. To destroy existing data on the target disks and (re-)create file systems, run
my-disko --mode disko
else to preserve existing file systems and mount them only, run
my-disko --mode mount
-
Install NixOS and reboot if successful as
my-install && sudo reboot
That's all! 😎
-
Set up
nix.conf
:NIXCONF="${XDG_CONFIG_HOME:-$HOME/.config}/nix/nix.conf" mkdir -p $(dirname $NIXCONF) echo 'experimental-features = nix-command flakes' >> $NIXCONF echo 'commit-lockfile-summary = chore: update flake.lock' >> $NIXCONF
The last
nix.conf
setting makes automatic lockfile commits follow the Conventional Commits specification. -
In addition, set the
FLAKE0
environment variable asexport FLAKE0=github:aolasz/groundzero
-
Install Nix (it is expected that
curl
is available)a. If the user has
sudo
rights, perform the official installation procedure.b. For an entirely rootless installation, the most convenient method is to use
nix-portable
:mkdir -p ~/.local/bin && cd ~/.local/bin curl -o nix-portable -L https://github.com/DavHau/nix-portable/releases/latest/download/nix-portable-$(uname -m) chmod +x nix-portable
Enter a Nix shell to proceed with HM setup:
NP_RUNTIME=bwrap ./nix-portable nix shell nixpkgs#{bashInteractive,nix}
Run the following1 as the target user
nix run $FLAKE0#home-manager -- switch -b old --flake $FLAKE0
After setting up HM, the user's HM environment needs to be activated explicitly. It is useful to create a script for it:
echo '#!/usr/bin/env bash' >> ~/.local/bin/hm-env
echo 'NP_RUNTIME=bwrap $HOME/.local/bin/nix-portable nix run nixpkgs#bashInteractive --offline' >> ~/.local/bin/hm-env
chmod +x ~/.local/bin/hm-env
With help of this script, the HM environment can be activate locally as
~/.local/bin/hm-env
or over SSH as
ssh -t <address> .local/bin/hm-env
Note that in the HM config itself, $HOME/.nix-profile/bin
must be prepended to the existing PATH
variable so that all commands enabled in the HM config become accessible!
Rootless HM setup has been tested under Debian GNU/Linux 12.
TODO: Since .profile
, .bash_profile
, and .bashrc
are all symlinks to into /nix/store
(that is inaccessible right after login), is there any way to avoid that manual activation with user privileges only (without switching to a different shell (e.g. zsh
) in the HM environment)?
-
Generate SSH keys for the user of the fresh installation and register the public key where needed or rely on SSH agent forwarding (FIXME: not yet working with rootless HM environment, maybe because
SSH_AUTH_SOCK
is redefined in the inner HM shell). -
Since the HM configuration redefines the
FLAKE0
variable to point to a directory inside the home directory of the user, ensure that this flake is cloned there:git clone git@github.com:aolasz/groundzero $FLAKE0
-
Within the local repo directory, install a
gitlint
commit-msg hook to ensure that future commit messages adhere to the Conventional Commits specification:cd $FLAKE0 gitlint install-hook
-
(NixOS installation only) Set up Tailscale if included in the OS configuration:
sudo tailscale up
Visit the given URL to activate the host on the tailnet.
Below is a table of commands for common management tasks, where environment variable FLAKE0
can either be a reference to the online flake repo or a path to a local clone.
Operation | Command (own alias) |
---|---|
Collect garbage2 | [sudo] nix-collect-garbage [-d] |
Switch to new OS config | sudo nixos-rebuild {switch|boot} --flake $FLAKE0 (nr {switch|boot} ) |
Switch to new home config | home-manager switch --flake $FLAKE0 -b old (hm switch ) |
Check the config3 | nix flake check |
Format source files3 | nix fmt |
Update the lock file3 | nix flake update --commit-lock-file |
On customizing Newt colors, see here.
If you get
error: filesystem error: cannot rename: Invalid cross-device link [...] [...]
during NixOS installation, then there is likely a different underlying error, which is unfortunately masked by this one. In such a case, try to build the system config first as
nix build .#nixosConfigurations.<hostname>.config.system.build.toplevel
which will then reveal the root cause for the error.
If one is forced to do a single-disk boot (e.g. due to a failed second disk), it may happen that one is dropped into the UEFI shell because the default ESP is missing. In that case, available (mounted) additional spare ESPs are listed when entering the UEFI shell or can be listed using map -r
. Additional mirrored (non-default) and mounted spare ESP file systems appear as FSn
where n
is an integer. Suppose our spare ESP file system is FS0
. In this case, all you need to do is to change to that file system and find & launch the corresponding EFI executable of the OS (say, BOOTX64.EFI
) as
FS0:
cd EFI/BOOT
BOOTX64.EFI
If on subsequent reboots, the EFI shell keeps coming up, it is worth examining the boot order inside the EFI shell using
bcfg boot dump -s
and -- if necessary -- move some entries around specifying their actual number and the target number, e.g.
bcfg boot mv 02 04
Credits: https://www.youtube.com/watch?v=t_7gBLUa600
Some parts of this flake were inspired by the following flakes:
In addition, this flake stands on the shoulders of other flake-giants, explicitly referenced in the inputs
attribute set of flake.nix
.
Footnotes
-
This flake exposes a frozen
home-manager
package (as dictated byflake.lock
) so that the one performing the setup would be the same as the one used afterward. ↩ -
The
-d
option also removes GC roots such as old system and home configurations, making it impossible to roll back to previous configs. Executing anixos-rebuild switch
is needed to clean up boot menu entries. ↩