Configure a router from settings.json and rebuild it on the device

nixosModules.settings builds a router from a JSON file: the router
options as they are, plus host name, time zone, SSH keys and
stateVersion; the module system validates it. lib.mkRouterSystem builds
such a system, lib.mkConfigDir the configuration directory installed to
/var/lib/router/config (a flake pinned to this router source, the
settings and an optional local.nix). router-apply builds it and switches
with commit-confirm.

The device must be able to rebuild without internet, so the packages the
rebuilt derivations need are part of the system; they were found by
diffing the derivation graphs of typical changes against the installed
system.

checks.apply installs such a router, boots it offline, checks that the
unchanged settings rebuild to the installed system, applies and
confirms a change, and rolls back an unconfirmed one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-28 22:22:26 +01:00
co-authored by Claude Opus 5.5
parent a4f4ec12a3
commit 2c8d5562f9
4 changed files with 305 additions and 0 deletions
+56
View File
@@ -23,8 +23,64 @@
installer-iso = ./modules/installer/iso.nix;
# Appliance disk image: dm-verity store, volatile root, state on /var.
image = ./modules/image;
# Configuration from a settings file (JSON), rebuilt on the device.
settings = ./modules/settings;
};
# A router built from settings.json; this is what the device's own
# configuration flake (see mkConfigDir) evaluates.
lib.mkRouterSystem =
{
settings,
modules ? [ ],
}:
nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
self.nixosModules.router
self.nixosModules.settings
self.nixosModules.installed-layout
{
routerSettings.file = settings;
# The device rebuilds itself, offline if need be: it needs the
# sources its configuration flake points to.
system.extraDependencies = [
self.outPath
nixpkgs.outPath
];
}
]
++ modules;
};
# The configuration directory installed to /var/lib/router/config: a
# flake pinned to exactly this router source, the settings and an
# optional local.nix with extra NixOS configuration.
lib.mkConfigDir =
{
pkgs,
settings,
local ? null,
}:
pkgs.runCommand "router-config" { } ''
mkdir -p $out
cat > $out/flake.nix <<'EOF'
{
inputs.nixos-router.url = "path:${self.outPath}";
outputs =
{ nixos-router, ... }:
{
nixosConfigurations.router = nixos-router.lib.mkRouterSystem {
settings = ./settings.json;
modules = if builtins.pathExists ./local.nix then [ ./local.nix ] else [ ];
};
};
}
EOF
cp ${settings} $out/settings.json
${pkgs.lib.optionalString (local != null) "cp ${local} $out/local.nix"}
'';
# Installer ISO for a given nixosSystem:
# nix build .#installer-example (see packages)
lib.mkInstaller =