Migrating a gateway's hardware
Replace a gateway computer without losing its configuration or data. The difference from a fresh install boils down to one sentence : the machine is new, the state is not.
That is where almost all the pitfalls on this page come from.
What carries over on its own, what does not
Section titled “What carries over on its own, what does not”| Repris automatiquement | À reprendre à la main |
|---|---|
| DNS and DHCP for the zone | Service data |
| Service registry, portal, reverse proxy | Backup repository |
| Monitoring targets, deployment tags | VPN identity |
| sops secret recipients | Owners of restored files |
| Deployment SSH keys | system.stateVersion |
Secrets are not tied to the hostname : the sops rules file only knows the administration key and the infrastructure key. Renaming changes nothing here.
Record the new hardware
Section titled “Record the new hardware”Nothing is modified at this stage : you collect what will need to be written into the configuration.
-
Boot from the USB drive (
just build-isoimage), USB Wi-Fi card plugged into the port that will be its final port. -
Record interfaces, MAC addresses and disks
Fenêtre de terminal ip -o linklsblk -o NAME,SIZE,MODEL,SERIAL,TYPEA Wi-Fi card’s permanent MAC differs from its current, often random, MAC. The permanent one is what matters, visible in the
permaddrfield. -
Physically identify which port will be the WAN and which the LAN, by unplugging and replugging. Label the sockets.
Prepare the configuration
Section titled “Prepare the configuration”The Wi-Fi interfaces do not need to appear in gateway.lan.interfaces :
hostapd places its own interface in the bridge.
zones: maison: gateway: wan: interface: "eno0" lan: interfaces: ["eno1", "eno2", "eno3"]
hosts: - hostname: "gw" zone: "maison:1.1" profile: "gateway" mac: "00:00:5e:00:53:00" disko: profile: "luks-btrfs-1-disk" devices: main: "/dev/nvme0n1"Renaming the host along the way is the right time, since the machine is being reinstalled anyway. An alias carrying the new name must then be removed : the generator refuses a name being both an alias and a hostname.
On the machine folder side, git mv usr/machines/<ancien> usr/machines/gw, then
import ./generated-configuration.nix and ./disko.nix in default.nix.
Install
Section titled “Install”just install gw nixos <ip>The command formats, installs and reboots. On an encrypted disk, the
installation passphrase is requested during partitioning : note it down,
just luks will need it.
Prefer the separate steps to just full-install : on an encrypted disk,
waiting for the machine to come back assumes a boot without intervention,
which entering the passphrase forbids.
Switch over
Section titled “Switch over”-
Back up, on the old gateway
Fenêtre de terminal systemctl stop forgejo postgresqlsystemctl start restic-backups-system-main.serviceDo not stop the zone’s DNS resolver : the backup target is referred to by name, stopping it makes it unfindable.
-
Rename the repository, on the backup server
Fenêtre de terminal mv /mnt/backup/restic/<ancien> /mnt/backup/restic/gwA repository’s path contains the hostname. Renaming keeps the whole history, whereas a new name would start from an empty repository.
-
Swap the hardware: shut down, move the data disks, identical wiring, boot and unlock the disk.
-
Configure and deploy
Fenêtre de terminal just configure gwjust apply-verbose gwjust configurepushes the infrastructure key : this is the step that unlocks sops, and therefore the emergency console access. -
Republish the backup accounts on the server that hosts them
Fenêtre de terminal just apply-local
Restore the data
Section titled “Restore the data”The backup server isolates repositories per host : the authenticated user must equal the path’s first segment. The renamed repository therefore stays inaccessible until the server has republished the new account.
restic-system-main snapshotsThis check is the real control : it must list the old machine’s history. An empty repository signals a successful authentication but against the wrong path, restore nothing in that case.
-
Stop the services whose state is going to be replaced.
-
Empty the state directories before restoring.
-
Restore, one mode at a time
Fenêtre de terminal restic-system-main restore latest --target / \--include /var/lib/forgejo --include /var/lib/postgresql -
Restore the owners, by name.
-
Restart the services and check.
Verify before concluding
Section titled “Verify before concluding”| Contrôle | Attendu |
|---|---|
systemctl --failed | no failed units |
ls /var/lib/postgresql | a single major version |
| Application accounts and repositories | the ones from before the migration |
restic-system-main snapshots | full history |
| Address on the VPN mesh | unchanged |
| Wi-Fi access points | present, clients served |
| Cold reboot | the machine comes back on its own |
The disko block in etc/config.yaml is only read at install time, comment
it out once the migration is complete. Recipes detail in
Justfile and configuration keys in
Le fichier config.yaml.