README > Adding A New Host
FIXME These steps can and should be streamlined significantly during each roadmap stage. In particular, install from the liveISO rather than installing and then loading the config. I opted to forgo the latter until the config is more mature and I better understand the required process. FIXME(docs) Needs revision based on hostSpec and nixos/darwin support overhaul
Because this repo relies on a private nix-secrets
repository input as a flake uri, you must use a NixOS ISO versioned 23.11 or higher so that building the flake prompts for a passphrase.
-
Create a configuration file for the new host at
hosts/nixos/<hostname/default.nix
(replacenixos
with Darwin if that's what your using). Refer to existing host configs and define the config as needed. -
Add users to
hosts/common/users/<usern>.nix
if needed -
Create a host-specific home config for each user that will be accessing the host at
home/<user>/<hostname>.nix
. Refer to exiting user configs and define the config as needed. -
Edit
flake.nix
to include a the following entries:-
Host information, under the
nixosConfigurations
option.... nixosConfigurations = { # This is an example of an existing host called "grief" grief = lib.nixosSystem { modules = [ ./hosts/grief ]; specialArgs = { inherit inputs outputs;}; } # Add a description of your host [yournewhostname](yournewhostname) = lib.nixosSystem { modules = [ ./hosts/yournewhostname ]; specialArgs = { inherit inputs outputs;}; } ... }; ...
-
Primary user information for the primary user on each host, under the
homeConfigurations
option.... homeConfigurations = { "ta@grief" = lib.homeManagerConfiguration { modules = [ ./home/ta/grief.nix ]; pkgs = pkgsFor.x86_64-linux; extraSpecialArgs = {inherit inputs outputs;}; }; "username@yournewhostname" = lib.homeManagerConfiguration { modules = [ ./home/username/yournewhostname.nix ]; pkgs = pkgsFor.x86_64-linux; extraSpecialArgs = {inherit inputs outputs;}; }; ... }; ...
-
-
Commit and push the changes
These steps assume:
- installation on an UEFI system
-
Boot the new machine into a NixOS live environment and wait for a shell, or for the graphical installer to automatically open if you used a graphical ISO.
-
If in the graphical installer, and open a terminal. Confirm the boot process brought up networking successfully and a ip was acquired. Check
ip a
. If no ip was assigned, refer to https://nixos.org/manual/nixos/stable/#sec-installation-manual-networking -
To gain remote access right away, set a temporary password for the root user using
passwd root
and following the prompts. Then from a remote machine,ssh [email protected]
using the ip printed in step 1. -
Most of the following steps require root. If you are remoted in from step 2 you should have a root shell. Otherwise,
sudo su
IMPORTANT: the code samples below assume installation on the
sda
device. Modify if necessary. These are instructions come directly from https://nixos.org/manual/nixos/stable/#sec-installation-manual-partitioning with little to no modification.
-
Create a GPT partition table.
# parted /dev/sda -- mklabel gpt
-
Add the root partition. This will fill the disk except for the end part, where the swap will live, and the space left in front (512MiB) which will be used by the boot partition.
# parted /dev/sda -- mkpart root ext4 512MB -8GB
If you do not require swap, replace
-8GB
with100%
-
If you are adding a swap partition, the size required will vary according to needs, here a 8GB one is created. NixOS uses the standard linux swap file needs so this will depend on how much memory the host has.
# parted /dev/sda -- mkpart swap linux-swap -8GB 100%
-
Finally, the boot partition. NixOS by default uses the ESP (EFI system partition) as its /boot partition. It uses the initially reserved 512MiB at the start of the disk.
# parted /dev/sda -- mkpart ESP fat32 1MB 512MB # parted /dev/sda -- set 3 esp on
-
Initialize the Ext4 partitions using mkfs.ext4 and assign a unique symbolic label using the
-L label
argument. For example:# mkfs.ext4 -L nixos /dev/sda1
-
For swap, if required, use
mkswap
and assign a label using the-L label
argument. For example:# mkswap -L swap /dev/sda2
-
For UEFI system boot partitions use
mkfs.fat
and assign a label using-n label
. For example:# mkfs.fat -F 32 -n BOOT /dev/sda3
-
Mount the target file system on which NixOS should be installed on /mnt, e.g.
# mount /dev/disk/by-label/nixos /mnt
-
Mount the boot file system on /mnt/boot, e.g.
# mkdir -p /mnt/boot # mount /dev/disk/by-label/BOOT /mnt/boot
-
If you are using swap, activate swap devices now (swapon device). The installer (or rather, the build actions that it may spawn) may need quite a bit of RAM, depending on your configuration.
# swapon /dev/sda2
-
Generate default configs
# nixos-generate-config --root /mnt
-
Edit the config so that we can quickly remote in over ssh after installation.
# vim /mnt/etc/nixos/configuration.nix
-
Edit or add the following as needed.
-
Verify:
boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true;
-
Uncomment this line and replace
nixos
with your desired host name:# networking.hostname = "nixos";
This step isn't technically required but will make connected to the machine faster if you have aliases already setup.
-
Delete or comment out the following lines if the are present.
# services.xserver.enable = true; # services.xserver.displayManager.gdm.enable = true; # services.xserver.desktopManager.gnome.enable = true;
-
Uncomment the
users.users.alice
section and create a basic use. For example:#users.users.ta := { #isNormalUser = true; #extraGroups = [ "wheel" ]; #initialPassword = "temp"; #}; #users.mutableUsers = true;
-
Uncomment
services.openssh.enable = true
-
At the end of the file, but prior to the final
}
, add the following line:nix.settings.experimental-features = [ "nix-command" "flakes" ];
-
Save and exit the file
-
-
Do the installation.
# nixos-install
and set the root password when prompted. -
Once installation is complete:
# reboot
-
Sign in with the user you created.
-
In case something goes wrong in the next steps, set the password for the user defined in 15.4. For example:
passwd ta
-
Create as source directory in the users home and clone the nix-config repo.
$ mkdir -p ~/src $ cd ~/src $ nix-shell -p git --run 'git clone https://github.com/EmergentMind/nix-config.git'
-
Change to the repo directory and run nix-develop to access the dev shell defined in flake.nix.
$ cd nix-config $ nix develop
-
Generate an age key on the new host, based on it's ssh host key.
$ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age age00000000000000000000000000000000000000000000000000
-
On a system with access to the nix-secrets repo, add the generated age key as a host key entry to the
nix-secrets/.sops.yaml
file.nix-secrets/.sops.yaml ------------------------------ # pub keys keys: # ... - &hosts: - &yournewhostname age00000000000000000000000000000000000000000000000000 creation_rules: - path_regex: secrets.yaml$ key_groups: - age: # ... - *yournewhostname
-
Update the keys of the related sops file
$ sops --config ../nix-secrets/.sops.yaml updatekeys ../nix-secrets/secrets.yaml 2024/02/09 12:11:05 Syncing keys for file /home/ta/src/nix-secrets/secrets.yaml The following changes will be made to the file's groups: Group 1 age00000000000000000000000000000000000000000000000000 age00000000000000000000000000000000000000000000000000 +++ age00000000000000000000000000000000000000000000000000 Is this okay? (y/n):y 2024/02/09 12:16:54 File /home/ta/src/nix-secrets/secrets.yaml synced with new keys
-
Commit and push the changes to
nix-secrets
so they will be retrieved when the flake is built on the new host. -
Before we build the flake and home-manager confgs on the new host, we need to ensure that it can access the private
nix-secrets
repo. From a system with the required priv/pub key-pair, cp the keys to the newhost:$ scp ~/.ssh/key_name* [email protected]:.ssh/
-
Back on the new hosts, create a
~/.ssh/config
so the correct keys are used.~/.ssh/config ------------------------------ Host gitlab.com github.com IdentitiesOnly yes IdentityFile ~/.ssh/id_manu Host * ForwardAgent no Compression no ServerAliveInterval 0 ServerAliveCountMax 3 HashKnownHosts no UserKnownHostsFile ~/.ssh/known_hosts ControlMaster no ControlPath ~/.ssh/master-%r@%n:%p ControlPersist no
-
Since we've updated nix-secrets, we'll have to update the flake lock file to ensure that the latest revision is retrieved.
$ nix flake lock --update-input nix-secrets warning: Git tree '/home/ta/src/nix-config' is dirty Enter passphrase for key '/home/ta/.ssh/id_manu': warning: updating lock file '/home/ta/src/nix-config/flake.lock': • Updated input 'nix-secrets': 'git+ssh://[email protected]/emergentmind/nix-secrets.git?ref=main&rev=aa0165aff5f74d367b523cc27dbd028b0251c30d&shallow=1' (2024-02-09) → 'git+ssh://[email protected]/emergentmind/nix-secrets.git?ref=main&rev=2ef287a53f19be75a4ff1f5ba28595686d4b5cbb&shallow=1' (2024-02-13) warning: Git tree '/home/ta/src/nix-config' is dirty
Enter the passphrase when prompted.
-
Copy the generated hardware config from its default location to the nix-config location:
$ cp /etc/nixos/hardware-configuration.nix ~/src/nix-config/hosts/NEWHOSTNAME/hardware-configuration.nix
-
Build and switch to the flake:
$ sudo nixos-rebuild switch --flake .#newhostname`
-
Once the build is finished build home-manager configs for each user on the system:
$ home-manager build --flake .#user@newhostname ... $ home-manager build --flake .#user@newhostname
-
Commit and push the new hardware-configuration that was copied in step 2
README > Adding A New Host