mirror of
https://github.com/mdlayher/homelab.git
synced 2024-12-14 11:47:32 +00:00
nixos/routnerr-2: initial switch to systemd-networkd
Signed-off-by: Matt Layher <mdlayher@gmail.com>
This commit is contained in:
parent
c345d44c4d
commit
7c9fe56522
7 changed files with 166 additions and 106 deletions
|
@ -58,9 +58,9 @@ func main() {
|
||||||
var (
|
var (
|
||||||
// Trusted subnets which will have internal DNS and other services
|
// Trusted subnets which will have internal DNS and other services
|
||||||
// deployed on them.
|
// deployed on them.
|
||||||
enp2s0 = newSubnet("enp2s0", 0, gua6, trusted)
|
mgmt0 = newSubnet("mgmt0", 0, gua6, trusted)
|
||||||
lan0 = newSubnet("lan0", 10, gua6, trusted)
|
lan0 = newSubnet("lan0", 10, gua6, trusted)
|
||||||
wg0 = newSubnet("wg0", 20, gua6, trusted)
|
wg0 = newSubnet("wg0", 20, gua6, trusted)
|
||||||
|
|
||||||
// When multiple subnets are available, prefer the 10GbE subnet.
|
// When multiple subnets are available, prefer the 10GbE subnet.
|
||||||
tengb0 = func() subnet {
|
tengb0 = func() subnet {
|
||||||
|
@ -78,14 +78,14 @@ func main() {
|
||||||
|
|
||||||
server = newHost(
|
server = newHost(
|
||||||
"servnerr-3",
|
"servnerr-3",
|
||||||
enp2s0,
|
mgmt0,
|
||||||
netaddr.MustParseIP("192.168.1.6"),
|
netaddr.MustParseIP("192.168.1.6"),
|
||||||
mac("1c:1b:0d:ea:83:0f"),
|
mac("1c:1b:0d:ea:83:0f"),
|
||||||
)
|
)
|
||||||
|
|
||||||
desktop = newHost(
|
desktop = newHost(
|
||||||
"nerr-3",
|
"nerr-3",
|
||||||
enp2s0,
|
mgmt0,
|
||||||
netaddr.MustParseIP("192.168.1.7"),
|
netaddr.MustParseIP("192.168.1.7"),
|
||||||
mac("04:d9:f5:7e:1c:47"),
|
mac("04:d9:f5:7e:1c:47"),
|
||||||
)
|
)
|
||||||
|
@ -129,25 +129,25 @@ func main() {
|
||||||
Infra: []host{
|
Infra: []host{
|
||||||
newHost(
|
newHost(
|
||||||
"switch-livingroom01",
|
"switch-livingroom01",
|
||||||
enp2s0,
|
mgmt0,
|
||||||
netaddr.MustParseIP("192.168.1.2"),
|
netaddr.MustParseIP("192.168.1.2"),
|
||||||
mac("f0:9f:c2:0b:28:ca"),
|
mac("f0:9f:c2:0b:28:ca"),
|
||||||
),
|
),
|
||||||
newHost(
|
newHost(
|
||||||
"switch-office01",
|
"switch-office01",
|
||||||
enp2s0,
|
mgmt0,
|
||||||
netaddr.MustParseIP("192.168.1.3"),
|
netaddr.MustParseIP("192.168.1.3"),
|
||||||
mac("f0:9f:c2:ce:7e:e1"),
|
mac("f0:9f:c2:ce:7e:e1"),
|
||||||
),
|
),
|
||||||
newHost(
|
newHost(
|
||||||
"switch-office02",
|
"switch-office02",
|
||||||
enp2s0,
|
mgmt0,
|
||||||
netaddr.MustParseIP("192.168.1.4"),
|
netaddr.MustParseIP("192.168.1.4"),
|
||||||
mac("74:ac:b9:e2:4e:a5"),
|
mac("74:ac:b9:e2:4e:a5"),
|
||||||
),
|
),
|
||||||
newHost(
|
newHost(
|
||||||
"ap-livingroom02",
|
"ap-livingroom02",
|
||||||
enp2s0,
|
mgmt0,
|
||||||
netaddr.MustParseIP("192.168.1.5"),
|
netaddr.MustParseIP("192.168.1.5"),
|
||||||
mac("74:83:c2:7a:c6:15"),
|
mac("74:83:c2:7a:c6:15"),
|
||||||
),
|
),
|
||||||
|
@ -188,7 +188,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach interface definitions from subnet definitions.
|
// Attach interface definitions from subnet definitions.
|
||||||
out.addInterface("enp2s0", enp2s0)
|
out.addInterface("mgmt0", mgmt0)
|
||||||
out.addInterface("lan0", lan0)
|
out.addInterface("lan0", lan0)
|
||||||
out.addInterface("guest0", guest0)
|
out.addInterface("guest0", guest0)
|
||||||
out.addInterface("iot0", iot0)
|
out.addInterface("iot0", iot0)
|
||||||
|
@ -201,7 +201,7 @@ func main() {
|
||||||
// TODO: WANs are special cases and should probably live in their own
|
// TODO: WANs are special cases and should probably live in their own
|
||||||
// section with different rules.
|
// section with different rules.
|
||||||
out.Interfaces["wan0"] = iface{
|
out.Interfaces["wan0"] = iface{
|
||||||
Name: "enp1s0",
|
Name: "wan0",
|
||||||
Preference: medium,
|
Preference: medium,
|
||||||
IPv4: wan4,
|
IPv4: wan4,
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,17 +149,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"interfaces": {
|
"interfaces": {
|
||||||
"enp2s0": {
|
|
||||||
"name": "enp2s0",
|
|
||||||
"preference": "medium",
|
|
||||||
"internal_dns": true,
|
|
||||||
"ipv4": "192.168.1.1",
|
|
||||||
"ipv6": {
|
|
||||||
"gua": "2600:6c4a:787f:1900::1",
|
|
||||||
"ula": "fd9e:1a04:f01d::1",
|
|
||||||
"lla": "fe80::1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"guest0": {
|
"guest0": {
|
||||||
"name": "guest0",
|
"name": "guest0",
|
||||||
"preference": "medium",
|
"preference": "medium",
|
||||||
|
@ -204,8 +193,19 @@
|
||||||
"lla": "fe80::1"
|
"lla": "fe80::1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mgmt0": {
|
||||||
|
"name": "mgmt0",
|
||||||
|
"preference": "medium",
|
||||||
|
"internal_dns": true,
|
||||||
|
"ipv4": "192.168.1.1",
|
||||||
|
"ipv6": {
|
||||||
|
"gua": "2600:6c4a:787f:1900::1",
|
||||||
|
"ula": "fd9e:1a04:f01d::1",
|
||||||
|
"lla": "fe80::1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"wan0": {
|
"wan0": {
|
||||||
"name": "enp1s0",
|
"name": "wan0",
|
||||||
"preference": "medium",
|
"preference": "medium",
|
||||||
"internal_dns": false,
|
"internal_dns": false,
|
||||||
"ipv4": "24.247.223.150",
|
"ipv4": "24.247.223.150",
|
||||||
|
|
|
@ -104,7 +104,7 @@ in {
|
||||||
avahi = {
|
avahi = {
|
||||||
enable = true;
|
enable = true;
|
||||||
interfaces = with vars.interfaces; [
|
interfaces = with vars.interfaces; [
|
||||||
"${enp2s0.name}"
|
"${mgmt0.name}"
|
||||||
"${lan0.name}"
|
"${lan0.name}"
|
||||||
"${iot0.name}"
|
"${iot0.name}"
|
||||||
];
|
];
|
||||||
|
|
|
@ -26,7 +26,7 @@ in {
|
||||||
})
|
})
|
||||||
|
|
||||||
# Downstream advertising interfaces.
|
# Downstream advertising interfaces.
|
||||||
++ lib.forEach [ enp2s0 lab0 lan0 guest0 iot0 ] (ifi:
|
++ lib.forEach [ mgmt0 lab0 lan0 guest0 iot0 ] (ifi:
|
||||||
{
|
{
|
||||||
name = ifi.name;
|
name = ifi.name;
|
||||||
advertise = true;
|
advertise = true;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
vars = import ./lib/vars.nix;
|
vars = import ./lib/vars.nix;
|
||||||
lans = with vars.interfaces; [ enp2s0 lan0 guest0 iot0 lab0 ];
|
lans = with vars.interfaces; [ mgmt0 lan0 guest0 iot0 lab0 ];
|
||||||
|
|
||||||
in {
|
in {
|
||||||
services.dhcpd4 = {
|
services.dhcpd4 = {
|
||||||
|
|
|
@ -3,80 +3,21 @@
|
||||||
let
|
let
|
||||||
vars = import ./lib/vars.nix;
|
vars = import ./lib/vars.nix;
|
||||||
|
|
||||||
# Produces the configuration for a LAN interface.
|
|
||||||
mkInterface = (ifi: {
|
|
||||||
ipv4.addresses = [{
|
|
||||||
address = "${ifi.ipv4}";
|
|
||||||
prefixLength = 24;
|
|
||||||
}];
|
|
||||||
ipv6.addresses = [{
|
|
||||||
address = "${ifi.ipv6.ula}";
|
|
||||||
prefixLength = 64;
|
|
||||||
}];
|
|
||||||
tempAddress = "disabled";
|
|
||||||
});
|
|
||||||
|
|
||||||
mkPeer = (peer: {
|
mkPeer = (peer: {
|
||||||
publicKey = peer.public_key;
|
publicKey = peer.public_key;
|
||||||
allowedIPs = peer.allowed_ips;
|
allowedIPs = peer.allowed_ips;
|
||||||
});
|
});
|
||||||
|
|
||||||
in {
|
in {
|
||||||
# LAN interface.
|
|
||||||
networking = {
|
networking = {
|
||||||
hostName = "routnerr-2";
|
hostName = "routnerr-2";
|
||||||
|
# TODO(mdlayher): systemd-resolved with fallback nameservers.
|
||||||
nameservers = with vars.localhost; [ "${ipv4}" "${ipv6}" ];
|
nameservers = with vars.localhost; [ "${ipv4}" "${ipv6}" ];
|
||||||
|
|
||||||
dhcpcd = {
|
# Use systemd-networkd for configuration. Forcibly disable legacy DHCP
|
||||||
enable = true;
|
# client.
|
||||||
# Do not remove interface configuration on shutdown.
|
useNetworkd = true;
|
||||||
persistent = true;
|
useDHCP = false;
|
||||||
allowInterfaces = [ "${vars.interfaces.wan0.name}" ];
|
|
||||||
extraConfig = with vars.interfaces; ''
|
|
||||||
noipv6rs
|
|
||||||
interface ${wan0.name}
|
|
||||||
ipv6rs
|
|
||||||
# DHCPv6-PD.
|
|
||||||
ia_na 0
|
|
||||||
ia_pd 1/::/56 ${enp2s0.name}/0/64 ${lab0.name}/2/64 ${guest0.name}/9/64 ${lan0.name}/10/64 ${iot0.name}/66/64
|
|
||||||
|
|
||||||
# IPv4 DHCP ISP settings overrides.
|
|
||||||
static domain_name_servers=${vars.localhost.ipv4}
|
|
||||||
static domain_search=
|
|
||||||
static domain_name=
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
interfaces = with vars.interfaces; {
|
|
||||||
# WAN interface: allow dhcpcd and NM to coexist.
|
|
||||||
${wan0.name}.useDHCP = true;
|
|
||||||
|
|
||||||
# LAN interfaces.
|
|
||||||
${enp2s0.name} = mkInterface enp2s0;
|
|
||||||
${lan0.name} = mkInterface lan0;
|
|
||||||
${lab0.name} = mkInterface lab0;
|
|
||||||
${guest0.name} = mkInterface guest0;
|
|
||||||
${iot0.name} = mkInterface iot0;
|
|
||||||
};
|
|
||||||
|
|
||||||
vlans = with vars.interfaces; {
|
|
||||||
${lab0.name} = {
|
|
||||||
id = 2;
|
|
||||||
interface = "${enp2s0.name}";
|
|
||||||
};
|
|
||||||
${guest0.name} = {
|
|
||||||
id = 9;
|
|
||||||
interface = "${enp2s0.name}";
|
|
||||||
};
|
|
||||||
${lan0.name} = {
|
|
||||||
id = 10;
|
|
||||||
interface = "${enp2s0.name}";
|
|
||||||
};
|
|
||||||
${iot0.name} = {
|
|
||||||
id = 66;
|
|
||||||
interface = "${enp2s0.name}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
wireguard = with vars.wireguard; {
|
wireguard = with vars.wireguard; {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -95,26 +36,145 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Use nftables instead.
|
||||||
nat.enable = false;
|
nat.enable = false;
|
||||||
firewall.enable = false;
|
firewall.enable = false;
|
||||||
|
};
|
||||||
|
|
||||||
# Use NM/MM only to manage the LTE modem.
|
# TODO(mdlayher): enable after working out CoreDNS dependency.
|
||||||
networkmanager = {
|
services.resolved.enable = false;
|
||||||
enable = false;
|
|
||||||
dns = "none";
|
# Manage network configuration with networkd.
|
||||||
unmanaged = [ "*,except:type:gsm" ];
|
#
|
||||||
|
# TODO(mdlayher): template out again.
|
||||||
|
systemd.network = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
# Wired WAN.
|
||||||
|
links."10-wan0" = {
|
||||||
|
matchConfig.MACAddress = "00:0d:b9:53:ea:cc";
|
||||||
|
linkConfig.Name = "wan0";
|
||||||
|
};
|
||||||
|
networks."10-wan0" = {
|
||||||
|
matchConfig.Name = "wan0";
|
||||||
|
networkConfig.DHCP = "yes";
|
||||||
|
# Never accept ISP DNS or search domains.
|
||||||
|
dhcpV4Config = {
|
||||||
|
UseDNS = false;
|
||||||
|
UseDomains = false;
|
||||||
|
};
|
||||||
|
dhcpV6Config = {
|
||||||
|
# Spectrum gives a /56.
|
||||||
|
PrefixDelegationHint = "::/56";
|
||||||
|
|
||||||
|
UseDNS = false;
|
||||||
|
# TODO(mdlayher): NixOS doesn't allow this?
|
||||||
|
# UseDomains = false;
|
||||||
|
};
|
||||||
|
ipv6AcceptRAConfig = {
|
||||||
|
UseDNS = false;
|
||||||
|
UseDomains = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO(mdlayher): wireless WAN.
|
||||||
|
|
||||||
|
# Physical management LAN.
|
||||||
|
links."11-mgmt0" = {
|
||||||
|
# Important: match on Ethernet device type because VLANs share this MAC.
|
||||||
|
matchConfig = {
|
||||||
|
Type = "ether";
|
||||||
|
MACAddress = "00:0d:b9:53:ea:cd";
|
||||||
|
};
|
||||||
|
linkConfig.Name = "mgmt0";
|
||||||
|
};
|
||||||
|
networks."11-mgmt0" = {
|
||||||
|
matchConfig.Name = "mgmt0";
|
||||||
|
address = [ "fd9e:1a04:f01d::1/64" "192.168.1.1/24" ];
|
||||||
|
|
||||||
|
# VLANs associated with this physical interface.
|
||||||
|
vlan = [ "lan0" "iot0" "guest0" "lab0" ];
|
||||||
|
|
||||||
|
networkConfig.DHCPv6PrefixDelegation = true;
|
||||||
|
dhcpV6PrefixDelegationConfig = {
|
||||||
|
Token = "::1";
|
||||||
|
SubnetId = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Home VLAN.
|
||||||
|
netdevs."12-lan0" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Name = "lan0";
|
||||||
|
Kind = "vlan";
|
||||||
|
};
|
||||||
|
vlanConfig.Id = 10;
|
||||||
|
};
|
||||||
|
networks."12-lan0" = {
|
||||||
|
matchConfig.Name = "lan0";
|
||||||
|
address = [ "fd9e:1a04:f01d:10::1/64" "192.168.10.1/24" ];
|
||||||
|
networkConfig.DHCPv6PrefixDelegation = true;
|
||||||
|
dhcpV6PrefixDelegationConfig = {
|
||||||
|
Token = "::1";
|
||||||
|
SubnetId = "a";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# IoT VLAN.
|
||||||
|
netdevs."13-iot0" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Name = "iot0";
|
||||||
|
Kind = "vlan";
|
||||||
|
};
|
||||||
|
vlanConfig.Id = 66;
|
||||||
|
};
|
||||||
|
networks."13-iot0" = {
|
||||||
|
matchConfig.Name = "iot0";
|
||||||
|
address = [ "fd9e:1a04:f01d:66::1/64" "192.168.66.1/24" ];
|
||||||
|
networkConfig.DHCPv6PrefixDelegation = true;
|
||||||
|
dhcpV6PrefixDelegationConfig = {
|
||||||
|
Token = "::1";
|
||||||
|
SubnetId = "42";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Guest VLAN.
|
||||||
|
netdevs."14-guest0" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Name = "guest0";
|
||||||
|
Kind = "vlan";
|
||||||
|
};
|
||||||
|
vlanConfig.Id = 9;
|
||||||
|
};
|
||||||
|
networks."14-guest0" = {
|
||||||
|
matchConfig.Name = "guest0";
|
||||||
|
address = [ "fd9e:1a04:f01d:9::1/64" "192.168.9.1/24" ];
|
||||||
|
networkConfig.DHCPv6PrefixDelegation = true;
|
||||||
|
dhcpV6PrefixDelegationConfig = {
|
||||||
|
Token = "::1";
|
||||||
|
SubnetId = "9";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Lab VLAN.
|
||||||
|
netdevs."15-lab0" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Name = "lab0";
|
||||||
|
Kind = "vlan";
|
||||||
|
};
|
||||||
|
vlanConfig.Id = 2;
|
||||||
|
};
|
||||||
|
networks."15-lab0" = {
|
||||||
|
matchConfig.Name = "lab0";
|
||||||
|
address = [ "fd9e:1a04:f01d:2::1/64" "192.168.2.1/24" ];
|
||||||
|
networkConfig.DHCPv6PrefixDelegation = true;
|
||||||
|
dhcpV6PrefixDelegationConfig = {
|
||||||
|
Token = "::1";
|
||||||
|
SubnetId = "2";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Bring up MM and exporter with NM.
|
|
||||||
systemd.services.ModemManager = {
|
|
||||||
enable = false;
|
|
||||||
wantedBy = [ "NetworkManager.service" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Tailscale experiments to replace WireGuard full-tunnel VPN.
|
|
||||||
services.tailscale.enable = false;
|
|
||||||
|
|
||||||
# Enable WireGuard Prometheus exporter and set up peer key/name mappings.
|
# Enable WireGuard Prometheus exporter and set up peer key/name mappings.
|
||||||
# TODO: nixify the configuration.
|
# TODO: nixify the configuration.
|
||||||
services.wireguard_exporter = {
|
services.wireguard_exporter = {
|
||||||
|
|
|
@ -31,8 +31,8 @@ let
|
||||||
all_wans = with vars.interfaces; [ wan0 wwan0 ];
|
all_wans = with vars.interfaces; [ wan0 wwan0 ];
|
||||||
|
|
||||||
# LAN interfaces, segmented into trusted, limited, and untrusted groups.
|
# LAN interfaces, segmented into trusted, limited, and untrusted groups.
|
||||||
metered_lans = with vars.interfaces; [ enp2s0 lan0 ];
|
metered_lans = with vars.interfaces; [ mgmt0 lan0 ];
|
||||||
trusted_lans = with vars.interfaces; [ enp2s0 lan0 lab0 wg0 ];
|
trusted_lans = with vars.interfaces; [ mgmt0 lan0 lab0 wg0 ];
|
||||||
limited_lans = with vars.interfaces; [ guest0 ];
|
limited_lans = with vars.interfaces; [ guest0 ];
|
||||||
untrusted_lans = with vars.interfaces; [ iot0 ];
|
untrusted_lans = with vars.interfaces; [ iot0 ];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue