Files
nixos-router/flake.nix
T
nilsandClaude Sonnet 5.5 b5429ad876 Add local DNS records, DHCP reservations and an installer ISO
DNS and DHCP (needed to replace a dnsmasq-based router):
- router.dns.domain/hosts/overrides/forwardZones: authoritative local
  domain, split-horizon host records with reverse entries, wildcard
  overrides and per-zone forwarders (private zones skip DNSSEC).
- lans.<n>.dhcp.reservations: Kea host reservations, published in DNS.
- Tunnels with dns = true admit what their peers route, so a
  site-to-site peer without a transfer address can use the resolver.

Installer:
- router-install wipes a disk, creates an ESP and an ext4 root and
  installs a prebuilt system with its secrets; nothing is built on the
  box. installed-layout is the shared disk layout contract.
- lib.mkInstaller builds an ISO for a given nixosSystem;
  packages.installer-example is the example's ISO.

Covered by the dns and installer VM tests (the latter installs onto an
empty disk and boots it under UEFI), wireguard DNS and assertion cases.
PLAN.md records the remaining gaps for replacing the hand-written router.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 12:31:44 +01:00

116 lines
3.7 KiB
Nix

{
description = "nixos-router: a NixOS-based distribution for routers/firewalls";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs =
{ self, nixpkgs }:
let
systems = [
"x86_64-linux"
"aarch64-linux"
];
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
in
{
nixosModules = {
router = ./modules/router;
default = self.nixosModules.router;
# Disk layout contract shared by router-install and target configs.
installed-layout = ./modules/installer/layout.nix;
# The installer pieces; `lib.mkInstaller` wires them up.
installer = ./modules/installer/install-script.nix;
installer-iso = ./modules/installer/iso.nix;
};
# Installer ISO for a given nixosSystem:
# nix build .#installer-example (see packages)
lib.mkInstaller =
{ configuration }:
nixpkgs.lib.nixosSystem {
inherit (configuration.pkgs.stdenv.hostPlatform) system;
modules = [
self.nixosModules.installer-iso
{
router.installer.system = configuration.config.system.build.toplevel;
# Reach the live system with the keys that will reach the router.
users.users.root.openssh.authorizedKeys.keys =
configuration.config.users.users.root.openssh.authorizedKeys.keys;
}
];
};
packages.x86_64-linux.installer-example =
(self.lib.mkInstaller { configuration = self.nixosConfigurations.example; })
.config.system.build.isoImage;
# A deployable starting point; copy examples/desktop and adapt it.
nixosConfigurations.example = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
self.nixosModules.router
./examples/desktop
];
};
# `nix run .#deploy -- <flake-attr> <user@host>`: activate a new
# configuration with commit-confirm; see scripts/deploy.sh.
apps.x86_64-linux.deploy =
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
deploy = pkgs.writeShellApplication {
name = "router-deploy";
runtimeInputs = with pkgs; [
nixos-rebuild
openssh
coreutils
];
text = builtins.readFile ./scripts/deploy.sh;
};
in
{
type = "app";
program = "${deploy}/bin/router-deploy";
};
# VM tests need KVM; only wired up for x86_64 until aarch64 CI exists.
checks.x86_64-linux =
import ./tests {
inherit self;
pkgs = nixpkgs.legacyPackages.x86_64-linux;
}
// {
# The example must keep building as a complete system.
example = self.nixosConfigurations.example.config.system.build.toplevel;
};
# `nix run .#lab`: boot the basic test topology in tmux, one console pane
# per VM plus the interactive test-driver REPL.
apps.x86_64-linux.lab =
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
test = self.checks.x86_64-linux.basic;
lab = pkgs.writeShellApplication {
name = "router-lab";
runtimeInputs = with pkgs; [
tmux
util-linux
gnugrep
coreutils
];
text = import ./tests/lab.nix {
inherit (pkgs) lib;
driver = test.driverInteractive;
nodes = builtins.attrNames test.nodes;
};
};
in
{
type = "app";
program = "${lab}/bin/router-lab";
};
formatter = forAllSystems (pkgs: pkgs.nixfmt);
};
}