Add MVP router flake with VM test and tmux lab
router.* schema (wan, lans, dns.forwarders) compiled to systemd-networkd, a generated nftables ruleset with NAT, Kea DHCPv4 and Unbound, plus build-time assertions against lock-out and interface conflicts. tests/basic.nix is a three-node VM test (upstream/router/client) covering WAN DHCP, LAN DHCP and DNS, NAT, WAN-deny and LAN SSH/ping. `nix run .#lab` boots the same topology in tmux with one console pane per VM and the driver REPL. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption mkEnableOption types;
|
||||
in
|
||||
{
|
||||
options.router = {
|
||||
enable = mkEnableOption "the router role";
|
||||
|
||||
wan = {
|
||||
interface = mkOption {
|
||||
type = types.str;
|
||||
example = "eth0";
|
||||
description = "Name of the uplink interface.";
|
||||
};
|
||||
};
|
||||
|
||||
lans = mkOption {
|
||||
default = { };
|
||||
description = "LAN segments served by this router, keyed by name.";
|
||||
type = types.attrsOf (
|
||||
types.submodule {
|
||||
options = {
|
||||
interface = mkOption {
|
||||
type = types.str;
|
||||
example = "eth1";
|
||||
description = "Interface (or bridge/VLAN device) carrying this LAN.";
|
||||
};
|
||||
|
||||
ipv4 = {
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
example = "192.168.10.1";
|
||||
description = "Router address on this LAN.";
|
||||
};
|
||||
prefixLength = mkOption {
|
||||
type = types.ints.between 8 30;
|
||||
default = 24;
|
||||
};
|
||||
subnet = mkOption {
|
||||
type = types.str;
|
||||
example = "192.168.10.0/24";
|
||||
description = "Network in CIDR notation; must contain `address`.";
|
||||
};
|
||||
};
|
||||
|
||||
dhcp = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
pool = {
|
||||
start = mkOption {
|
||||
type = types.str;
|
||||
example = "192.168.10.100";
|
||||
};
|
||||
end = mkOption {
|
||||
type = types.str;
|
||||
example = "192.168.10.199";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
allowManagement = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether clients on this LAN may reach SSH on the router.";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
dns.forwarders = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = "Upstream resolvers. When empty, Unbound resolves recursively.";
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user