README (6673B)
1 # NixOS Notes 2 3 ## Installation 4 5 Partition Disk 6 7 # lsblk 8 # parted /dev/sdX -- p 9 # parted /dev/sdX -- mklabel gpt 10 # parted /dev/sdX -- mkpart primary 1024MiB 100% 11 # parted /dev/sdX -- mkpart ESP fat32 256MiB 1024MiB 12 # parted /dev/sdX -- mkpart GRUB 1MiB 256MiB 13 # parted /dev/sdX -- set 2 esp on 14 # parted /dev/sdX -- set 2 boot on 15 # parted /dev/sdX -- set 3 bios_grub on 16 # parted /dev/sdX -- align-check optimal 1 17 18 Format Disks 19 20 # mkfs.vfat -F32 /dev/sdX2 21 # cryptsetup -v luksFormat /dev/sdX1 22 # cryptsetup luksOpen /dev/sdX1 luksroot 23 # mkfs.nilfs2 -L root /dev/mapper/luksroot 24 25 Mount Disks 26 27 # mount /dev/mapper/luksroot /mnt 28 # mkdir /mnt/boot 29 # mount /dev/sdX2 /mnt/boot 30 31 Install NixOS 32 33 # nixos-generate-config --root /mnt 34 # ...edit /mnt/etc/nixos/configuration.nix 35 # nixos-install 36 # ...set root password 37 # reboot 38 39 ## WiFi from Command Line 40 41 $ sudo wpa_supplicant -B -i iface -c <(wpa_passphrase ssid key) 42 43 Without passphrase is more complex: create file /tmp/cbase.wifi with 44 the following contents: 45 46 network={ 47 ssid="c-base-public" 48 key_mgmt=NONE 49 } 50 51 $ sudo wpa_supplicant -i wlp3s0 -c /tmp/cbase.wifi 52 53 ## Backups 54 55 $ sudo cryptsetup -v luksFormat /dev/sdX 56 $ sudo cryptsetup luksOpen /dev/sdX backup 57 $ sudo cryptsetup luksDump /dev/sdX 58 $ sudo cryptsetup -v status backup 59 $ sudo dd if=/dev/zero of=/dev/mapper/backup status=progress bs=128M 60 $ sudo mkfs.ext3 /dev/mapper/backup 61 $ sudo mount /dev/mapper/backup /mnt 62 $ sudo umount /dev/mapper/backup 63 $ sudo cryptsetup luksClose backup 64 65 $ sudo cryptsetup luksAddKey /dev/sdX 66 $ sudo cryptsetup luksRemoveKey /dev/sdX 67 68 ## Deployment 69 70 There are several deployment tools for nixos each with pros and cons. 71 72 - nixops: tried it, didn't like it. too stateful and fragile. 73 74 - hail: did not try. looks abandoned. pulls updates from hydra. 75 76 - morph: did not try. looks complex. 77 78 - krops: did not try. actively used. builds remotely, which I don't 79 want. A production server should serve specific purpose and things 80 which don't serve that purpose should not be there, i.e. I don't 81 want to build there anything and I don't want the build artefacts to 82 be stored there. 83 84 - nixos-rebuild: nixos native command. supports deploying to other 85 machines but doesn't do substitutes, which is a major flaw on 86 asymetric connections with bad upload speed. 87 88 nixos-rebuild is actually closest to what I want. 89 90 Here is an example of a deployment scripts for several machines, each 91 with different nixpkgs. Deployment scripts are first built for all 92 machines (can be built and cached by hydra, for example). Running a 93 deployment script handles local and remote deployments accordingly. 94 Remote deployments immitate "nixos-rebuild switch" but allow 95 substitutes by copying the closure first. 96 97 Have subdir with configuration.nix for each machine. default.nix can 98 look something like this: 99 100 # nix-build && ./result/bin/deploy-all 101 # nix-build && ./result/bin/deploy-hostname1 102 # nix-build && ./result/bin/deploy-hostname2 103 let 104 pkgs = import <nixpkgs> {}; 105 nixpkgs1809 = fetchTarball { 106 url = https://nixos.org/channels/nixos-18.09/nixexprs.tar.xz; 107 }; 108 nixpkgs1903 = fetchTarball { 109 url = https://nixos.org/channels/nixos-19.03/nixexprs.tar.xz; 110 }; 111 local = name: nixpkgs: 112 pkgs.writeScript "deploy-local-${name}" '' 113 sudo nixos-rebuild switch \ 114 -I nixos-config=./${name}/configuration.nix \ 115 -I nixpkgs=${nixpkgs} 116 ''; 117 buildSystem = name: nixpkgs: 118 let 119 # https://stackoverflow.com/questions/47655567/how-to-build-a-nixops-deployment-on-hydra 120 pkgs2 = import nixpkgs {}; 121 nixosSystem = import (pkgs2.path + "/nixos/lib/eval-config.nix") { 122 inherit (pkgs2) system; 123 modules = [(./. + "/${name}/configuration.nix")]; 124 }; 125 in nixosSystem.config.system.build.toplevel; 126 remote = name: nixpkgs: 127 let 128 sshName = "${name}.tincnet"; 129 system = buildSystem name nixpkgs; 130 pkgs2 = import nixpkgs {}; 131 switch = pkgs.writeScript "switch-${name}" '' 132 #!${pkgs2.bash}/bin/bash 133 set -euo pipefail 134 cd /tmp 135 ls -al /nix/var/nix/profiles 136 echo register ${system} 137 sudo nix-env -p /nix/var/nix/profiles/system --set ${system} 138 echo switch 139 sudo nohup ${system}/bin/switch-to-configuration switch 140 ls -al /nix/var/nix/profiles 141 ''; 142 in 143 pkgs.writeScript "deploy-remote-${name}" '' 144 #!${pkgs.bash}/bin/bash 145 set -euo pipefail 146 echo starting ${name} to ${sshName} 147 #nix-copy-closure --sign --use-substitutes --to ${sshName} ${switch} 148 nix-copy-closure --gzip --use-substitutes --to ${sshName} ${switch} 149 #nix copy --to ssh://${sshName} ${switch} 150 ssh -t ${sshName} ${switch} 151 echo ok ${name} to ${sshName} 152 ''; 153 deploy1 = name: nixpkgs: 154 pkgs.writeScriptBin "deploy-${name}" '' 155 #!${pkgs.bash}/bin/bash 156 set -euo pipefail 157 if test ${name} == $(hostname -s); then 158 exec ${local name nixpkgs} 159 else 160 exec ${remote name nixpkgs} 161 fi 162 ''; 163 all = [ 164 (deploy1 "hostname1" nixpkgs1809) 165 (deploy1 "hostname2" nixpkgs1903) 166 ]; 167 in 168 pkgs.buildEnv { 169 name = "deploy"; 170 paths = all ++ [ 171 (pkgs.writeScriptBin "deploy-all" ('' 172 #!${pkgs.bash}/bin/bash 173 set -euo pipefail 174 '' 175 + (pkgs.stdenv.lib.concatMapStrings (x: "${x}\n") all))) 176 ]; 177 } 178 179 If the closure is not signed, your user needs to be trusted by nix in 180 the target machine configuration.nix: 181 182 nix.trustedUsers = ["root" "myuser"]; 183 184 ## Secrets 185 186 Nix does not address management of secrets. 187 188 Some NixOS deployment tools try to handle it by creating the secret 189 keys somewhere and then pushing them to the target machines. I am not 190 convinced that this is the right approach. Secrets should not be 191 pushed around unnecessarily. 192 193 What I do, for example, for tinc: 194 195 - define the tinc service with empty fields for unknown public keys 196 197 - deploy the the tinc service, let it generate the keys on the target 198 machine 199 200 - read the public key from the target machine and update the tinc 201 service with the newly acquired public key 202 203 - deploy the tinc service for the second time, this time with the 204 public key already filled in