installation.md

Installation
These are instruction on how to install this configuration on a (new) machine.
Note: command lines starting with #
should be run as the root user.
Prepare Device Config
You'll need a device config that sets up the device-specific configuration.
-
create a file for your device config in
devices/HOSTNAME.nix
-
start off with an existing device config and customize the imported modules, the network config and so on
-
detect your hardware config with
nixos-generate-config
on the corresponding device, you can find it on a NixOS install disk or in thenixos-install-tools
package if you have a running Nix installation# nixos-generate-config --show-hardware-config
-
incorporate the relevant options into the device config
That'll mostly be the kernel modules, stuff like microcode things and the file systems if you want to keep some of them. My configs don't use the suggested network config and some other stuff from there though, so leave that out.
Note: you probably won't actually need some of the modules detected for
boot.initrd.availableKernelModules
, the detection script just puts modules for all connected hardware there, whether you need them to boot or not. You can experiment with which modules you actually need after the installation is done if you want to. If you can't boot anymore, you can always just boot an older configuration! -
TODO: machine-id
-
add entries in
flake/configurations.nix
andflake/colmena.nix
for your device with the correct system set (the correct system is in the detected hardware config undernixpkgs.hostPlatform
)
Partitioning
GPT partition labels (not the same thing as filesystem labels!) are used to refer to partitions, so the config doesn't need to be adjusted to new partition UUIDs on a reinstall.
This of course means that the partition labels have to be set as the configs expect.
-
create a GPT partition table on your target device
-
create 1 GiB partition at beginning of device, with partition label "boot" ("partition name" in GParted)
-
format boot as FAT (
mkfs.vfat
), flag it as esp -
create partition filling the rest of the device, with partition label "main"
-
create a LUKS container on
/dev/disk/by-partlabel/main
:# cryptsetup luksFormat /dev/disk/by-partlabel/main
-
open the created LUKS container:
# cryptsetup open /dev/disk/by-partlabel/main main
-
format
/dev/mapper/main
as btrfs:# mkfs.btrfs /dev/mapper/main
Mounting & Subvolumes
btrfs subvolumes are used to organize persistent data.
-
mount
/dev/disk/by-partlabel/boot
at/mnt/boot
# mkdir -p /mnt/boot # mount /dev/disk/by-partlabel/boot /mnt/boot
-
mount
/dev/mapper/main
at/mnt/mnt/main
:# mkdir -p /mnt/mnt/main # mount /dev/mapper/main /mnt/mnt/main
Note: This mounts the root subvolume of
main
. This won't actually be used for data, but we need to be able to access it, e.g. to create subvolumes. It will also be accessible at that mountpoint in the installed system (without the first/mnt
prefix of course, so at/mnt/main
). -
create btrfs subvolumes on main:
/nix
,/persist
,/persist/.snapshots
(for snapper snapshots) and/swap
:# btrfs subvolume create /mnt/mnt/main/nix # btrfs subvolume create /mnt/mnt/main/persist # btrfs subvolume create /mnt/mnt/main/persist/.snapshots # btrfs subvolume create /mnt/mnt/main/swap
-
create btrfs swapfile in
/mnt/mnt/main/swap/swapfile
:# btrfs filesystem mkswapfile /mnt/mnt/main/swap/swapfile -s $SIZE
$SIZE
could be something like32G
. -
mount the subvolumes with the right options at
/mnt/nix
:# mkdir /mnt/nix /mnt/persist /mnt/swap # mount -o "subvol=/nix" -o "compress=zstd" -o "noatime" \ /dev/mapper/main /mnt/nix # mount -o "subvol=/persist" -o "compress=zstd" \ /dev/mapper/main /mnt/persist # mount -o "subvol=/swap" -o "noatime" \ /dev/mapper/main /mnt/swap
Create home dir in /persist
For devices with home dir persistence, we'll need to create that manually. That's because it's managed by impermanence in home-manager, which doesn't have the permissions to create a directory in the root-owned persist dir.
# mkdir -p /mnt/persist/home/eisfunke
# chown 1000:100 /mnt/persist/home/eisfunke
# chmod 700 /mnt/persist/home/eisfunke
TODO: shouldn't be necessary anymore (I don't use the impermanence home-manager module anymore)
Create Host Keys
Regardless of whether the machine will be running an sshd
SSH server, you'll need to generate an SSH host key. This is needed for decrypting secrets via agenix
.
If the device uses remote unlocking of an encrypted root partition you'll also need another, different, SSH key for use inside the initrd during boot for entering the key remotely.
# mkdir -p /mnt/persist/etc/ssh
# ssh-keygen -t ed25519 -N "" -f /mnt/persist/etc/ssh/ssh_host_ed25519_key -C "host_yourhostname_2000-00-00"
# ssh-keygen -t ed25519 -N "" -f /mnt/persist/etc/ssh/ssh_boot_ed25519_key -C "boot_yourhostname_2000-00-00"
-t
for ssh-keygen
sets the key type, we use ed25519. -N
sets the passphrase, we don't want one, -f
sets the output file and -C
sets the key comment, which is appended to the public key file.
Add the public key from /persist/etc/ssh/ssh_host_ed25519_key.pub
to res/ssh-public-keys.nix
and in secrets/secrets.nix
. Then run agenix -r
in the secrets
folder to reencrypt all secrets with the new keys so the new machine will be able to decrypt them. Commit and push the changes.
TODO: create user keys
Install NixOS
With the device config prepared and everything partitioned, mounted and keyed, you're ready to actually install NixOS from this flake. Note that the flake must be given as Git repo because the config uses things like the current flake revision, which isn't available for e.g. a tarball.
TODO: this requires git to be installed, is it? TODO: maybe use nixos-rebuild instead, remotely?
# nixos-install --no-root-password --root /mnt \
--flake git+https://git.eisfunke.com/config/nixos.git#$HOSTNAME
If git.eisfunke.com is not available, say because I'm trying to reinstall the server it's running on, the mirror repository at https://gitlab.fachschaften.org/nicolas.lenz/nixos.git
can be used.
In case you need to reset the cached repo, delete Nix's Git cache:
# rm -r ~root/.cache/nix/gitv3
Post Installation Setup
Sadly, not all setup and logins can be automated using the config. Some steps have to be done manually after a fresh install.
-
If the installation includes calendar / contact sync, you have to run
vdirsyncer discover
manually once (and after every change to the accounts config or after adding a new collection). See calcard.nix. -
If the installation includes a graphical desktop, you have to setup a default keyring without (e.g. named "Default keyring") any password using Seahorse (called "Passwords and Keys" in the launcher).
On first automatic login, you might be prompted to create a keyring automatically. Just leave the password empty then.
On a non-automatic login, a keyring with your login password will be created automatically without prompt. In that case you'll have to change the password to no password using Seahorse.
No password is required in order for the keyring to be automatically unlocked even with automatic login. Otherwise you'll be prompted to unlock it manually every time. See also /nixos/desktop.nix.
-
If the installation includes Nextcloud, you have to setup the Nextcloud sync client using the GUI application.