Archived
feat(networking): declare static IPs for all NixOS-managed hosts in flake
Adds static IP configuration to every NixOS host in the flake that has a fixed LAN address, and centralises all network primitives (IPs, gateway, prefix length, interface names) in variables.nix so there is one place to update if any of them change. variables.nix additions: - lanGateway / lanPrefixLength — LAN gateway and /24 prefix, replacing every hardcoded 192.168.2.254 / 24 across host files - lxcLanInterface / vmLanInterface / vmStorageInterface — NIC names for LXC containers (eth0), Proxmox VMs (ens18), and the HA storage NIC (ens19), used as attribute keys so changing the name is a one-line edit - haStoragePrefixLength — /29 for the storage subnet, mirrors haStorageCidr - Per-host IP variables: nixCacheIp (.224), tailscaleRouterIp (.222), torRelayIp (.221), serverIp (.226), dockerIp (.225) host.nix changes: - tailscale-router, tor-relay, nix-cache, pxe-boot: useDHCP = false, static address on eth0 (lxcLanInterface), struct-form defaultGateway (required when using systemd-networkd which LXC containers use) - server, docker: useDHCP = false, static address on ens18 (vmLanInterface), struct-form defaultGateway (works for both scripted networking and networkd) - ha-server-1, ha-server-2: replace hardcoded 192.168.2.254 / 24 / 29 with the new variables; no functional change for these hosts modules/build-types/pxe-boot.nix: - Domain-controller kickstart template: replace hardcoded 192.168.2.138 and 192.168.2.254 with vars.domainControllerIp / vars.lanGateway / vars.lanPrefixLength / vars.homeDomain so the template stays correct if the DC IP or domain is ever changed again Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ULXzafSDwGhmFGnn3LtDSQ
This commit is contained in:
+12
-3
@@ -1,8 +1,17 @@
|
|||||||
_:
|
{ vars, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
networking.hostName = "docker";
|
networking = {
|
||||||
networking.hostId = "007f0200";
|
hostName = "docker";
|
||||||
|
hostId = "007f0200";
|
||||||
|
useDHCP = false;
|
||||||
|
interfaces.${vars.vmLanInterface}.ipv4.addresses = [{
|
||||||
|
address = vars.dockerIp;
|
||||||
|
prefixLength = vars.lanPrefixLength;
|
||||||
|
}];
|
||||||
|
defaultGateway = { address = vars.lanGateway; interface = vars.vmLanInterface; };
|
||||||
|
nameservers = [ vars.domainControllerIp ];
|
||||||
|
};
|
||||||
boot.zfs.forceImportRoot = false;
|
boot.zfs.forceImportRoot = false;
|
||||||
|
|
||||||
# Preserved from the pre-refactor `docker` target — stateVersion must never
|
# Preserved from the pre-refactor `docker` target — stateVersion must never
|
||||||
|
|||||||
@@ -11,15 +11,15 @@
|
|||||||
hostName = vars.haServer1Host;
|
hostName = vars.haServer1Host;
|
||||||
hostId = "3a4b5c6d";
|
hostId = "3a4b5c6d";
|
||||||
useDHCP = false;
|
useDHCP = false;
|
||||||
interfaces.ens18.ipv4.addresses = [{
|
interfaces.${vars.vmLanInterface}.ipv4.addresses = [{
|
||||||
address = vars.haServer1Ip;
|
address = vars.haServer1Ip;
|
||||||
prefixLength = 24;
|
prefixLength = vars.lanPrefixLength;
|
||||||
}];
|
}];
|
||||||
interfaces.ens19.ipv4.addresses = [{
|
interfaces.${vars.vmStorageInterface}.ipv4.addresses = [{
|
||||||
address = vars.haServer1StorageIp;
|
address = vars.haServer1StorageIp;
|
||||||
prefixLength = 29;
|
prefixLength = vars.haStoragePrefixLength;
|
||||||
}];
|
}];
|
||||||
defaultGateway = "192.168.2.254";
|
defaultGateway = { address = vars.lanGateway; interface = vars.vmLanInterface; };
|
||||||
nameservers = [ vars.domainControllerIp ];
|
nameservers = [ vars.domainControllerIp ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,15 @@
|
|||||||
hostName = vars.haServer2Host;
|
hostName = vars.haServer2Host;
|
||||||
hostId = "7e8f9a0b";
|
hostId = "7e8f9a0b";
|
||||||
useDHCP = false;
|
useDHCP = false;
|
||||||
interfaces.ens18.ipv4.addresses = [{
|
interfaces.${vars.vmLanInterface}.ipv4.addresses = [{
|
||||||
address = vars.haServer2Ip;
|
address = vars.haServer2Ip;
|
||||||
prefixLength = 24;
|
prefixLength = vars.lanPrefixLength;
|
||||||
}];
|
}];
|
||||||
interfaces.ens19.ipv4.addresses = [{
|
interfaces.${vars.vmStorageInterface}.ipv4.addresses = [{
|
||||||
address = vars.haServer2StorageIp;
|
address = vars.haServer2StorageIp;
|
||||||
prefixLength = 29;
|
prefixLength = vars.haStoragePrefixLength;
|
||||||
}];
|
}];
|
||||||
defaultGateway = "192.168.2.254";
|
defaultGateway = { address = vars.lanGateway; interface = vars.vmLanInterface; };
|
||||||
nameservers = [ vars.domainControllerIp ];
|
nameservers = [ vars.domainControllerIp ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,16 @@
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = vars.nixCacheHost;
|
networking = {
|
||||||
|
hostName = vars.nixCacheHost;
|
||||||
|
useDHCP = false;
|
||||||
|
interfaces.${vars.lxcLanInterface}.ipv4.addresses = [{
|
||||||
|
address = vars.nixCacheIp;
|
||||||
|
prefixLength = vars.lanPrefixLength;
|
||||||
|
}];
|
||||||
|
defaultGateway = { address = vars.lanGateway; interface = vars.lxcLanInterface; };
|
||||||
|
nameservers = [ vars.domainControllerIp ];
|
||||||
|
};
|
||||||
|
|
||||||
services.beszel.agent.environment = {
|
services.beszel.agent.environment = {
|
||||||
#DOCKER_HOST = "tcp://docker-socket-proxy:2375";
|
#DOCKER_HOST = "tcp://docker-socket-proxy:2375";
|
||||||
|
|||||||
+11
-2
@@ -1,7 +1,16 @@
|
|||||||
_:
|
{ vars, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
networking.hostName = "pxe-boot";
|
networking = {
|
||||||
|
hostName = "pxe-boot";
|
||||||
|
useDHCP = false;
|
||||||
|
interfaces.${vars.lxcLanInterface}.ipv4.addresses = [{
|
||||||
|
address = vars.pxeServerIp;
|
||||||
|
prefixLength = vars.lanPrefixLength;
|
||||||
|
}];
|
||||||
|
defaultGateway = { address = vars.lanGateway; interface = vars.lxcLanInterface; };
|
||||||
|
nameservers = [ vars.domainControllerIp ];
|
||||||
|
};
|
||||||
|
|
||||||
# Preserved from the pre-refactor `pxe-boot` target — stateVersion must
|
# Preserved from the pre-refactor `pxe-boot` target — stateVersion must
|
||||||
# never be bumped on an already-installed machine.
|
# never be bumped on an already-installed machine.
|
||||||
|
|||||||
+11
-2
@@ -8,8 +8,17 @@
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = vars.nfsServerHost;
|
networking = {
|
||||||
networking.hostId = "6689f93e";
|
hostName = vars.nfsServerHost;
|
||||||
|
hostId = "6689f93e";
|
||||||
|
useDHCP = false;
|
||||||
|
interfaces.${vars.vmLanInterface}.ipv4.addresses = [{
|
||||||
|
address = vars.serverIp;
|
||||||
|
prefixLength = vars.lanPrefixLength;
|
||||||
|
}];
|
||||||
|
defaultGateway = { address = vars.lanGateway; interface = vars.vmLanInterface; };
|
||||||
|
nameservers = [ vars.domainControllerIp ];
|
||||||
|
};
|
||||||
|
|
||||||
services.beszel.agent.environment = {
|
services.beszel.agent.environment = {
|
||||||
#DOCKER_HOST = "tcp://docker-socket-proxy:2375";
|
#DOCKER_HOST = "tcp://docker-socket-proxy:2375";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
_:
|
{ vars, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
@@ -8,7 +8,16 @@ _:
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = "tailscale-router";
|
networking = {
|
||||||
|
hostName = "tailscale-router";
|
||||||
|
useDHCP = false;
|
||||||
|
interfaces.${vars.lxcLanInterface}.ipv4.addresses = [{
|
||||||
|
address = vars.tailscaleRouterIp;
|
||||||
|
prefixLength = vars.lanPrefixLength;
|
||||||
|
}];
|
||||||
|
defaultGateway = { address = vars.lanGateway; interface = vars.lxcLanInterface; };
|
||||||
|
nameservers = [ vars.domainControllerIp ];
|
||||||
|
};
|
||||||
|
|
||||||
services.beszel.agent.environment = {
|
services.beszel.agent.environment = {
|
||||||
KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG";
|
KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{ ... }:
|
{ vars, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
@@ -8,10 +8,19 @@
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = "tor-relay";
|
networking = {
|
||||||
|
hostName = "tor-relay";
|
||||||
|
useDHCP = false;
|
||||||
|
interfaces.${vars.lxcLanInterface}.ipv4.addresses = [{
|
||||||
|
address = vars.torRelayIp;
|
||||||
|
prefixLength = vars.lanPrefixLength;
|
||||||
|
}];
|
||||||
|
defaultGateway = { address = vars.lanGateway; interface = vars.lxcLanInterface; };
|
||||||
|
nameservers = [ vars.domainControllerIp ];
|
||||||
|
};
|
||||||
|
|
||||||
# No networking.hostId: only ZFS-touching hosts (server, docker) need one
|
# No networking.hostId: only ZFS-touching hosts need one for pool-import
|
||||||
# for pool-import safety, and this host does neither.
|
# safety, and this host does neither.
|
||||||
|
|
||||||
services.beszel.agent.environment = {
|
services.beszel.agent.environment = {
|
||||||
KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG";
|
KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG";
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ let
|
|||||||
rockyFreeIpaKs = pkgs.writeText "rocky-freeipa.ks" ''
|
rockyFreeIpaKs = pkgs.writeText "rocky-freeipa.ks" ''
|
||||||
#version=RHEL9
|
#version=RHEL9
|
||||||
# Unattended Rocky Linux 9 + FreeIPA install
|
# Unattended Rocky Linux 9 + FreeIPA install
|
||||||
# Target: domain-controller.sweet.home 192.168.2.138
|
# Target: domain-controller.${vars.homeDomain} ${vars.domainControllerIp}
|
||||||
|
|
||||||
url --url=${rockyMirror}/BaseOS/${rockyArch}/os/
|
url --url=${rockyMirror}/BaseOS/${rockyArch}/os/
|
||||||
repo --name=appstream --baseurl=${rockyMirror}/AppStream/${rockyArch}/os/
|
repo --name=appstream --baseurl=${rockyMirror}/AppStream/${rockyArch}/os/
|
||||||
@@ -136,10 +136,10 @@ let
|
|||||||
|
|
||||||
[ipv4]
|
[ipv4]
|
||||||
method=manual
|
method=manual
|
||||||
addresses=192.168.2.138/24
|
addresses=${vars.domainControllerIp}/${toString vars.lanPrefixLength}
|
||||||
gateway=192.168.2.254
|
gateway=${vars.lanGateway}
|
||||||
dns=192.168.2.253;
|
dns=${vars.domainControllerIp};
|
||||||
dns-search=sweet.home;
|
dns-search=${vars.homeDomain};
|
||||||
|
|
||||||
[ipv6]
|
[ipv6]
|
||||||
method=auto
|
method=auto
|
||||||
@@ -148,7 +148,7 @@ let
|
|||||||
|
|
||||||
# -- /etc/hosts: FQDN must resolve to the real IP (not loopback) for IPA --
|
# -- /etc/hosts: FQDN must resolve to the real IP (not loopback) for IPA --
|
||||||
sed -i '/domain-controller/d' /etc/hosts
|
sed -i '/domain-controller/d' /etc/hosts
|
||||||
echo '192.168.2.138 domain-controller.sweet.home domain-controller' >> /etc/hosts
|
echo '${vars.domainControllerIp} domain-controller.${vars.homeDomain} domain-controller' >> /etc/hosts
|
||||||
|
|
||||||
# -- Generate IPA passwords and store securely --
|
# -- Generate IPA passwords and store securely --
|
||||||
DM_PASS=$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 24)
|
DM_PASS=$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 24)
|
||||||
|
|||||||
+14
-3
@@ -4,9 +4,19 @@
|
|||||||
homeDomain = "sweet.home"; # base LAN domain for service subdomains (pve., docker.)
|
homeDomain = "sweet.home"; # base LAN domain for service subdomains (pve., docker.)
|
||||||
tailnetDomain = "tail13f623.ts.net"; # Tailscale MagicDNS suffix
|
tailnetDomain = "tail13f623.ts.net"; # Tailscale MagicDNS suffix
|
||||||
lanCidr = "192.168.2.0/24"; # LAN subnet
|
lanCidr = "192.168.2.0/24"; # LAN subnet
|
||||||
pxeServerIp = "192.168.2.223"; # pxe-boot host's LAN IP
|
lanGateway = "192.168.2.254"; # LAN default gateway (router)
|
||||||
pbsIp = "192.168.2.244"; # Proxmox Backup Server LAN IP
|
lanPrefixLength = 24; # LAN subnet prefix length (/24 = 255.255.255.0)
|
||||||
domainControllerIp = "192.168.2.253"; # FreeIPA domain controller / primary DNS
|
lxcLanInterface = "eth0"; # LAN NIC name in LXC containers (set by Proxmox --net0 name=eth0)
|
||||||
|
vmLanInterface = "ens18"; # LAN NIC name in Proxmox VMs (virtio, first NIC)
|
||||||
|
vmStorageInterface = "ens19"; # storage NIC name in HA server VMs (virtio, second NIC on vmbr1)
|
||||||
|
pxeServerIp = "192.168.2.223"; # pxe-boot LXC container LAN IP
|
||||||
|
nixCacheIp = "192.168.2.224"; # nix-cache LXC container LAN IP
|
||||||
|
tailscaleRouterIp = "192.168.2.222"; # tailscale-router LXC container LAN IP
|
||||||
|
torRelayIp = "192.168.2.221"; # tor-relay LXC container LAN IP
|
||||||
|
serverIp = "192.168.2.226"; # server (NFS/ZFS) Proxmox VM LAN IP
|
||||||
|
dockerIp = "192.168.2.225"; # docker Proxmox VM LAN IP
|
||||||
|
pbsIp = "192.168.2.244"; # Proxmox Backup Server LAN IP (not NixOS-managed)
|
||||||
|
domainControllerIp = "192.168.2.253"; # FreeIPA domain controller / primary DNS (not NixOS-managed)
|
||||||
|
|
||||||
# Cross-host references (LAN hostnames/users other hosts reach over the network)
|
# Cross-host references (LAN hostnames/users other hosts reach over the network)
|
||||||
nixCacheHost = "nix-cache"; # substituter/remote-builder hostname
|
nixCacheHost = "nix-cache"; # substituter/remote-builder hostname
|
||||||
@@ -83,6 +93,7 @@
|
|||||||
haServer1StorageIp = "192.168.4.228"; # storage-net IP, node 1 (vmbr1 / ens19)
|
haServer1StorageIp = "192.168.4.228"; # storage-net IP, node 1 (vmbr1 / ens19)
|
||||||
haServer2StorageIp = "192.168.4.227"; # storage-net IP, node 2 (vmbr1 / ens19)
|
haServer2StorageIp = "192.168.4.227"; # storage-net IP, node 2 (vmbr1 / ens19)
|
||||||
haStorageCidr = "192.168.4.0/29"; # storage subnet — internal to pve1 only
|
haStorageCidr = "192.168.4.0/29"; # storage subnet — internal to pve1 only
|
||||||
|
haStoragePrefixLength = 29; # storage subnet prefix length (/29)
|
||||||
haStorageRoot = "/srv/ha-data"; # XFS-over-DRBD mount point on the Active node
|
haStorageRoot = "/srv/ha-data"; # XFS-over-DRBD mount point on the Active node
|
||||||
haIscsiIqn = "iqn.2026-01.home.sweet:ha-storage";
|
haIscsiIqn = "iqn.2026-01.home.sweet:ha-storage";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user