1
0
Fork 0
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:
Matt Layher 2022-03-02 10:30:10 -05:00
parent c345d44c4d
commit 7c9fe56522
No known key found for this signature in database
GPG key ID: 77BFE531397EDE94
7 changed files with 166 additions and 106 deletions

View file

@ -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,
} }

View file

@ -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",

View file

@ -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}"
]; ];

View file

@ -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;

View file

@ -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 = {

View file

@ -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 = {

View file

@ -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 ];