Compare commits

..

1 Commits

Author SHA1 Message Date
a04e725988 Add mailtngbert IPv4 address 2022-02-20 20:46:03 +01:00
87 changed files with 19611 additions and 4804 deletions

View File

@ -78,10 +78,6 @@ ausgeführt.
### LXC-Containers auf Server ### LXC-Containers auf Server
Warum Container? Mehrere Routing-Tabellen verteile auf virtuelle
Router statt Policy Routing oder Virtual Routing Functions. Container
sind einfach zwischen Servern migrierbar.
Ein Server erwartet die für ihn (`location = hostName`) konfigurierten Ein Server erwartet die für ihn (`location = hostName`) konfigurierten
Container. systemd versucht sie zu starten. Das wird erst nach Container. systemd versucht sie zu starten. Das wird erst nach
`build-container` funktionieren, welches das Rootfs anlegt. `build-container` funktionieren, welches das Rootfs anlegt.

View File

@ -26,11 +26,11 @@ Alle Stecker im Haus sind in Schema A gecrimpt.
| | ![][gi] B 2.05.02 | ![][gi] UVB 1.09 | | 14 | | | ![][gi] B 2.05.02 | ![][gi] UVB 1.09 | | 14 |
| ![][ri] B 4.02.01 *v* | ![][gi] B 2.05.05 | ![][gi] UVB 1.10 | | 15 | | ![][ri] B 4.02.01 *v* | ![][gi] B 2.05.05 | ![][gi] UVB 1.10 | | 15 |
| ![][ri] B 4.01.01 *v* | ![][gi] B 2.05.06 | ![][gi] 1.06 | | 16 | | ![][ri] B 4.01.01 *v* | ![][gi] B 2.05.06 | ![][gi] 1.06 | | 16 |
| ![][ri] B 4.03.01 *v* | ![][gi] B 2.05.03 *v* | ![][gi] 1.16 *v* | | 17 | | ![][ri] B 4.03.01 | ![][gi] B 2.05.03 *v* | | | 17 |
| ![][ri] B 4.04.01 *v* | ![][gi] B 2.05.07 *v* | | | 18 | | ![][ri] B 4.04.01 *v* | ![][gi] B 2.05.07 *v* | | | 18 |
| ![][ri] B 4.05.02 *v* | ![][gi] B 2.06 | | | 19 | | ![][ri] B 4.05.02 *v* | ![][gi] B 2.06 | | | 19 |
| ![][ri] B 4.06.01 *v* | ![][ri] B 2.07 | | | 20 | | ![][ri] B 4.06.01 | ![][ri] B 2.07 | | | 20 |
| ![][ri] B 4.07.05 *v* | | | | 21 | | ![][ri] B 4.07.05 | | | | 21 |
| ![][ri] B 4.08.01 | | | | 22 | | ![][ri] B 4.08.01 | | | | 22 |
| ![][ri] B 4.09.01 *v* | | | | 23 | | ![][ri] B 4.09.01 *v* | | | | 23 |
| ![][ri] B 4.10.01 *v* | | | | 24 | | ![][ri] B 4.10.01 *v* | | | | 24 |

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,4 @@
{ config, lib, ... }: { lib, ... }:
let
# https://github.com/NixOS/nixpkgs/pull/206965
concatMapAttrsRecursive = with lib; f: flip pipe [ (mapAttrs f) attrValues (foldl' recursiveUpdate { }) ];
in
{ {
imports = [ imports = [
# Secrets # Secrets
@ -14,8 +9,7 @@ in
./switch.nix ./switch.nix
./ap.nix ./ap.nix
./server.nix ./server.nix
] ] ++
# IP networks # IP networks
++ lib.filesystem.listFilesRecursive ./net; lib.filesystem.listFilesRecursive ./net;
} }

View File

@ -8,74 +8,65 @@
fixed-hosts = { fixed-hosts = {
"172.22.99.96" = "08:00:27:bb:8c:b3"; "172.22.99.96" = "08:00:27:bb:8c:b3";
"172.22.99.98" = "08:00:27:aa:90:e2"; "172.22.99.98" = "08:00:27:aa:90:e2";
# "astrom" = "aa:00:5b:08:f0:5c"; "astrom.hq.c3d2.de" = "aa:00:5b:08:f0:5c";
# "astron" = "aa:00:5b:08:f0:5b"; "astron.hq.c3d2.de" = "aa:00:5b:08:f0:5b";
# "batman" = "5c:cf:7f:c0:05:28"; "batman.hq.c3d2.de" = "5c:cf:7f:c0:05:28";
# "beere" = "b8:27:eb:ac:65:d2"; "beere.hq.c3d2.de" = "b8:27:eb:ac:65:d2";
# "beere2" = "b8:27:eb:53:0b:27"; "beere2.hq.c3d2.de" = "b8:27:eb:53:0b:27";
# "bender.hq.c3de.de" = "00:23:df:7e:c8:0a"; "bender.hq.c3de.de" = "00:23:df:7e:c8:0a";
# "cider" = "00:0d:93:75:ee:fa"; "cider.hq.c3d2.de" = "00:0d:93:75:ee:fa";
"dacbert" = "dc:a6:32:e0:46:bf"; "dacbert.hq.c3d2.de" = "dc:a6:32:31:b6:32";
"dn42" = "aa:00:42:7a:32:46"; "dn42.hq.c3d2.de" = "aa:00:42:7a:32:46";
# "drucker" = "00:23:c3:d2:12:0f"; "drucker.hq.c3d2.de" = "00:23:c3:d2:12:0f";
# "feile" = "aa:00:5b:12:c1:f7"; "feile.hq.c3d2.de" = "aa:00:5b:12:c1:f7";
# "fernandopoo" = "aa:00:f7:52:85:27"; "fernandopoo.hq.c3d2.de" = "aa:00:f7:52:85:27";
# "fhem" = "b8:27:eb:9e:8b:db"; "fhem.hq.c3d2.de" = "b8:27:eb:9e:8b:db";
# "git" = "aa:00:47:d8:57:10"; "git.hq.c3d2.de" = "aa:00:47:d8:57:10";
"glotzbert" = "90:1b:0e:88:da:0a"; "glotzbert.hq.c3d2.de" = "ec:a8:6b:fe:b4:cb";
# "wled-nix-snowflake" = "44:17:93:10:77:e8"; "icq.hq.c3d2.de" = "aa:00:30:f6:27:89";
# "wled-fairy-dust" = "3c:61:05:e3:2f:ad"; "jabber1.hq.c3d2.de" = "aa:00:0b:19:8f:14";
# "wled-warnbert" = "3c:61:05:fc:21:37"; "jabber2.hq.c3d2.de" = "aa:00:3d:6a:23:b8";
# "wled-matrix" = "e8:db:84:e4:f4:30"; "knot.hq.c3d2.de" = "52:54:cf:fd:ce:3f";
# "ledball1" = "b8:27:eb:53:0b:27"; "ledball1.hq.c3d2.de" = "b8:27:eb:53:0b:27";
# Beleuchtungskiste auf Traverse über Fernseher "ledbeere.hq.c3d2.de" = "b8:27:eb:60:99:59";
# "ledbeere" = "b8:27:eb:60:99:59"; "leviathan.hq.c3d2.de" = "00:ff:08:31:db:e5";
# "leviathan" = "00:ff:08:31:db:e5"; "lisbeth.hq.c3d2.de" = "b8:27:eb:a5:ee:5c";
# "lisbeth" = "b8:27:eb:a5:ee:5c"; "marenz-build.hq.c3d2.de" = "44:1e:a1:59:2e:e8";
# "marenz-build" = "44:1e:a1:59:2e:e8"; "matemat.hq.c3d2.de" = "a2:1b:7c:e8:19:72";
# "matemat" = "a2:1b:7c:e8:19:72"; "minecraft.hq.c3d2.de" = "4a:57:d3:64:fe:e9";
# "minecraft" = "4a:57:d3:64:fe:e9"; "moleflap.hq.c3d2.de" = "aa:00:0d:b1:6c:67";
# "moleflap" = "aa:00:0d:b1:6c:67"; "monit.hq.c3d2.de" = "00:23:ae:94:e7:19";
# "monit" = "00:23:ae:94:e7:19"; "public-access-proxy.hq.c3d2.de" = "12:24:5f:bd:9b:e7";
"pipebert" = "ec:a8:6b:fe:b4:cb"; "pulsebert.hq.c3d2.de" = "b8:27:eb:16:31:61";
# "public-access-proxy" = "12:24:5f:bd:9b:e7"; "ruststripe1.hq.c3d2.de" = "06:32:0e:39:21:69";
"pulsebert" = "b8:27:eb:16:31:61"; "schalter.hq.c3d2.de" = "b8:27:eb:4c:be:ff";
# "ruststripe1" = "06:32:0e:39:21:69"; "semanta.hq.c3d2.de" = "00:ff:e4:bb:ea:2a";
"schalter" = "b8:27:eb:ac:65:d2"; "server2.hq.c3d2.de" = "d0:67:e5:f3:57:10";
# "semanta" = "00:ff:e4:bb:ea:2a"; "server3.hq.c3d2.de" = "e4:1f:13:2e:4f:c0";
# "server2" = "d0:67:e5:f3:57:10"; "server4.hq.c3d2.de" = "00:9c:02:a9:26:01";
# "server3" = "e4:1f:13:2e:4f:c0"; "sharing.hq.c3d2.de" = "00:23:c3:d2:75:18";
# "server4" = "00:9c:02:a9:26:01"; "sofafon.hq.c3d2.de" = "b8:27:eb:23:8d:01";
# "sharing" = "00:23:c3:d2:75:18"; "storage2.hq.c3d2.de" = "42:5e:0f:4e:f3:cc";
# "sofafon" = "b8:27:eb:23:8d:01"; "ustriper.hq.c3d2.de" = "aa:bb:95:33:bb:aa";
# "storage2" = "42:5e:0f:4e:f3:cc"; "wiefelspuetz.hq.c3d2.de" = "aa:00:7f:01:8a:d0";
# "ustriper" = "aa:bb:95:33:bb:aa"; "wormhole.hq.c3d2.de" = "00:23:c3:d2:00:76";
# "wiefelspuetz" = "aa:00:7f:01:8a:d0"; "www1.hq.c3d2.de" = "aa:00:13:8b:03:47";
# "wormhole" = "00:23:c3:d2:00:76";
# "www1" = "aa:00:13:8b:03:47";
# "riscbert" = "6c:cf:39:00:05:95";
}; };
time = 300; time = 86400;
max-time = 30 * 24 * 3600; max-time = 2592000;
router = "c3d2-gw3"; router = "c3d2-anon";
}; };
domainName = "c3d2.zentralwerk.org"; domainName = "c3d2.zentralwerk.org";
dynamicDomain = true; dynamicDomain = true;
subnet4 = "172.22.99.0/24"; subnet4 = "172.22.99.0/24";
hosts4 = { hosts4 = {
bgp = "172.22.99.250";
c3d2-anon = "172.22.99.1"; c3d2-anon = "172.22.99.1";
c3d2-gw1 = "172.22.99.2"; c3d2-gw1 = "172.22.99.2";
c3d2-gw2 = "172.22.99.3"; c3d2-gw2 = "172.22.99.3";
c3d2-gw3 = "172.22.99.4"; c3d2-gw3 = "172.22.99.4";
dacbert = "172.22.99.203";
schalter = "172.22.99.204";
glotzbert = "172.22.99.205";
pulsebert = "172.22.99.208";
pipebert = "172.22.99.209";
bgp = "172.22.99.250";
dn42 = "172.22.99.253"; dn42 = "172.22.99.253";
}; };
ipv6Router = "c3d2-gw3";
hosts6.dn42 = { hosts6.dn42 = {
bgp = "fd23:42:c3d2:523::c3d2:ff0b"; bgp = "fd23:42:c3d2:523::c3d2:ff0b";
c3d2-anon = "fd23:42:c3d2:523::c3d2:1"; c3d2-anon = "fd23:42:c3d2:523::c3d2:1";
@ -89,12 +80,12 @@
c3d2-gw1 = "2a00:8180:2c00:223::c3d2:2"; c3d2-gw1 = "2a00:8180:2c00:223::c3d2:2";
c3d2-gw2 = "2a00:8180:2c00:223::c3d2:3"; c3d2-gw2 = "2a00:8180:2c00:223::c3d2:3";
c3d2-gw3 = "2a00:8180:2c00:223::c3d2:4"; c3d2-gw3 = "2a00:8180:2c00:223::c3d2:4";
glotzbert = "2a00:8180:2c00:223:e1ad:6c2b:af9f:2d13";
pipebert = "2a00:8180:2c00:223:eea8:6bff:fefe:b4cb";
}; };
hosts6.yggdrasil.c3d2-gw3 = "30c:c3d2:b946:76d0::1";
subnets6 = { subnets6 = {
dn42 = "fd23:42:c3d2:523::/64"; dn42 = "fd23:42:c3d2:523::/64";
up4 = "2a00:8180:2c00:223::/64"; up4 = "2a00:8180:2c00:223::/64";
yggdrasil = "30c:c3d2:b946:76d0::/64";
}; };
}; };
@ -121,21 +112,21 @@
c3d2.hwaddr = "0A:14:48:01:21:01"; c3d2.hwaddr = "0A:14:48:01:21:01";
core.hwaddr = "0A:14:48:01:21:00"; core.hwaddr = "0A:14:48:01:21:00";
}; };
ospf.allowedUpstreams = [ "flpk-gw" "freifunk" "upstream4" "upstream3" "anon1" ]; ospf.allowedUpstreams = [ "upstream3" "upstream4" "upstream1" "anon1" "freifunk" ];
}; };
c3d2-gw2 = makeGateway { c3d2-gw2 = makeGateway {
interfaces = { interfaces = {
c3d2.hwaddr = "0A:14:48:01:21:03"; c3d2.hwaddr = "0A:14:48:01:21:03";
core.hwaddr = "0A:14:48:01:21:02"; core.hwaddr = "0A:14:48:01:21:02";
}; };
ospf.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ]; ospf.allowedUpstreams = [ "upstream1" "upstream3" "upstream4" "anon1" "freifunk" ];
}; };
c3d2-gw3 = makeGateway { c3d2-gw3 = makeGateway {
interfaces = { interfaces = {
c3d2.hwaddr = "0A:14:48:01:21:05"; c3d2.hwaddr = "0A:14:48:01:21:05";
core.hwaddr = "0A:14:48:01:21:04"; core.hwaddr = "0A:14:48:01:21:04";
}; };
ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; ospf.allowedUpstreams = [ "upstream4" "upstream3" "upstream1" "anon1" "freifunk" ];
}; };
}; };
} }

View File

@ -1,47 +0,0 @@
{
site.net.c3d2iot = {
dhcp = {
start = "10.22.0.2";
end = "10.22.255.253";
router = "iot-gw";
server = "iot-gw";
# devices don't often change and a missing DNS record causes trouble
time = 3600;
max-time = 24 * 3600;
};
dynamicDomain = true;
domainName = "c3d2iot.zentralwerk.org";
hosts4 = {
iot-gw = "10.22.0.1";
};
hosts6 = {
dn42 = {
iot-gw = "fd23:42:c3d2:587:ffff:ffff:ffff:ffff";
};
};
subnet4 = "10.22.0.0/16";
subnets6 = {
dn42 = "fd23:42:c3d2:587::/64";
up4 = "2a00:8180:2c00:287::/64";
};
};
site.hosts.iot-gw = {
# TODO: needs to be done more granular, aka allow c3d2 and serv network
# firewall.enable = true;
interfaces = {
core = {
hwaddr = "0A:22:48:01:24:01";
type = "veth";
};
c3d2iot = {
hwaddr = "0A:22:48:01:24:00";
type = "veth";
};
};
ospf = {
allowedUpstreams = [ "upstream4" "upstream3" "anon1" ];
};
role = "container";
};
}

View File

@ -4,18 +4,10 @@ let
in in
{ {
site.net.cluster = { site.net.cluster = {
ipv6Router = "cls-gw";
domainName = "cluster.zentralwerk.org"; domainName = "cluster.zentralwerk.org";
extraRecords = map (host: { extraRecords = map (host: {
data = { data = "1 1 6789 ${host}";
service = "ceph-mon"; name = "_ceph-mon._tcp";
proto = "tcp";
priority = 1;
weight = 1;
port = 6789;
target = host;
};
name = "@";
type = "SRV"; type = "SRV";
}) cephMonServers }) cephMonServers
++ ++
@ -133,7 +125,7 @@ in
let let
makeServer = { makeServer = {
role = "client"; role = "client";
model = "nixos"; model = "proxmox";
interfaces = builtins.foldl' (interfaces: net: interfaces = builtins.foldl' (interfaces: net:
interfaces // { interfaces // {
"${net}".type = "bridge"; "${net}".type = "bridge";
@ -144,13 +136,10 @@ in
"mgmt" "mgmt"
"serv" "serv"
"c3d2" "c3d2"
"c3d2iot"
"pub" "pub"
"priv23" "priv23"
"priv31" "priv31"
"priv45"
"bmx" "bmx"
"flpk"
]; ];
}; };
in { in {
@ -166,7 +155,7 @@ in
type = "veth"; type = "veth";
}; };
}; };
ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; ospf.allowedUpstreams = [ "upstream4" "upstream1" "upstream3" "anon1" "freifunk" ];
}; };
server3 = makeServer; server3 = makeServer;
server5 = makeServer; server5 = makeServer;
@ -174,6 +163,5 @@ in
server7 = makeServer; server7 = makeServer;
server8 = makeServer; server8 = makeServer;
server9 = makeServer; server9 = makeServer;
server10 = makeServer;
}; };
} }

View File

@ -1,38 +0,0 @@
{
site.net.coloradio = {
domainName = "coloradio.zentralwerk.org";
subnet4 = "192.168.9.0/24";
hosts4 = {
coloradio-gw = "192.168.9.1";
coloradio-in = "192.168.9.2";
};
ipv6Router = "coloradio-gw";
subnets6.dn42 = "fd23:42:c3d2:590::/64";
hosts6.dn42 = {
coloradio-gw = "fd23:42:c3d2:590::1";
};
};
site.hosts = {
coloradio-gw = {
role = "container";
interfaces = {
core = {
type = "veth";
hwaddr = "0A:14:48:01:06:08";
gw4 = null;
gw6 = null;
};
coloradio = {
type = "veth";
hwaddr = "0A:14:48:01:06:09";
gw4 = null;
gw6 = null;
};
};
ospf.allowedUpstreams =
[ "upstream4" "upstream3" "freifunk" ];
};
};
}

View File

@ -50,12 +50,6 @@
priv41-gw = "172.20.72.65"; priv41-gw = "172.20.72.65";
priv42-gw = "172.20.72.67"; priv42-gw = "172.20.72.67";
priv43-gw = "172.20.72.68"; priv43-gw = "172.20.72.68";
priv44-gw = "172.20.72.70";
priv45-gw = "172.20.72.72";
priv46-gw = "172.20.72.73";
priv47-gw = "172.20.72.74";
priv48-gw = "172.20.72.75";
priv49-gw = "172.20.72.76";
priv5-gw = "172.20.72.15"; priv5-gw = "172.20.72.15";
priv6-gw = "172.20.72.16"; priv6-gw = "172.20.72.16";
priv7-gw = "172.20.72.17"; priv7-gw = "172.20.72.17";
@ -69,12 +63,12 @@
server6 = "172.20.72.56"; server6 = "172.20.72.56";
server7 = "172.20.72.57"; server7 = "172.20.72.57";
server8 = "172.20.72.58"; server8 = "172.20.72.58";
server9 = "172.20.72.59";
upstream1 = "172.20.72.6";
upstream2 = "172.20.72.10";
upstream3 = "172.20.72.11"; upstream3 = "172.20.72.11";
upstream4 = "172.20.72.12"; upstream4 = "172.20.72.12";
coloradio-gw = "172.20.72.62"; yggdrasil = "172.20.72.62";
vpn-gw = "172.20.72.69";
flpk-gw = "172.20.72.71";
iot-gw = "172.20.72.77";
}; };
hosts6 = { hosts6 = {
dn42 = { dn42 = {
@ -84,10 +78,8 @@
c3d2-gw1 = "fd23:42:c3d2:581::c3d2:1"; c3d2-gw1 = "fd23:42:c3d2:581::c3d2:1";
c3d2-gw2 = "fd23:42:c3d2:581::c3d2:2"; c3d2-gw2 = "fd23:42:c3d2:581::c3d2:2";
c3d2-gw3 = "fd23:42:c3d2:581::c3d2:3"; c3d2-gw3 = "fd23:42:c3d2:581::c3d2:3";
cls-gw = "fd23:42:c3d2:581::c3d2:4";
freifunk = "fd23:42:c3d2:581:8000::1"; freifunk = "fd23:42:c3d2:581:8000::1";
mgmt-gw = "fd23:42:c3d2:581::8:3"; mgmt-gw = "fd23:42:c3d2:581::8:3";
iot-gw = "fd23:42:c3d2:581::8:7";
priv1-gw = "fd23:42:c3d2:581::c:0"; priv1-gw = "fd23:42:c3d2:581::c:0";
priv10-gw = "fd23:42:c3d2:581::c:9"; priv10-gw = "fd23:42:c3d2:581::c:9";
priv11-gw = "fd23:42:c3d2:581::c:a"; priv11-gw = "fd23:42:c3d2:581::c:a";
@ -125,13 +117,7 @@
priv40-gw = "fd23:42:c3d2:581::c:27"; priv40-gw = "fd23:42:c3d2:581::c:27";
priv41-gw = "fd23:42:c3d2:581::c:28"; priv41-gw = "fd23:42:c3d2:581::c:28";
priv42-gw = "fd23:42:c3d2:581::c:29"; priv42-gw = "fd23:42:c3d2:581::c:29";
priv43-gw = "fd23:42:c3d2:581::c:2a"; priv43-gw = "fd23:42:c3d2:581::c:30";
priv44-gw = "fd23:42:c3d2:581::c:2b";
priv45-gw = "fd23:42:c3d2:581::c:2c";
priv46-gw = "fd23:42:c3d2:581::c:2d";
priv47-gw = "fd23:42:c3d2:581::c:2e";
priv48-gw = "fd23:42:c3d2:581::c:2f";
priv49-gw = "fd23:42:c3d2:581::c:30";
priv5-gw = "fd23:42:c3d2:581::c:4"; priv5-gw = "fd23:42:c3d2:581::c:4";
priv6-gw = "fd23:42:c3d2:581::c:5"; priv6-gw = "fd23:42:c3d2:581::c:5";
priv7-gw = "fd23:42:c3d2:581::c:6"; priv7-gw = "fd23:42:c3d2:581::c:6";
@ -139,10 +125,11 @@
priv9-gw = "fd23:42:c3d2:581::c:8"; priv9-gw = "fd23:42:c3d2:581::c:8";
pub-gw = "fd23:42:c3d2:581::8:2"; pub-gw = "fd23:42:c3d2:581::8:2";
serv-gw = "fd23:42:c3d2:581::8:1"; serv-gw = "fd23:42:c3d2:581::8:1";
upstream1 = "fd23:42:c3d2:581::b:0";
upstream2 = "fd23:42:c3d2:581::b:1";
upstream3 = "fd23:42:c3d2:581::b:2"; upstream3 = "fd23:42:c3d2:581::b:2";
upstream4 = "fd23:42:c3d2:581::b:3"; upstream4 = "fd23:42:c3d2:581::b:3";
vpn-gw = "fd23:42:c3d2:581:9001::1"; yggdrasil = "fd23:42:c3d2:581:9000::1";
coloradio-gw = "fd23:42:c3d2:581:9009::1";
}; };
up4 = { up4 = {
anon1 = "2a00:8180:2c00:281::9:1"; anon1 = "2a00:8180:2c00:281::9:1";
@ -154,7 +141,6 @@
cls-gw = "2a00:8180:2c00:281::8:4"; cls-gw = "2a00:8180:2c00:281::8:4";
freifunk = "2a00:8180:2c00:281:8000::1"; freifunk = "2a00:8180:2c00:281:8000::1";
mgmt-gw = "2a00:8180:2c00:281::8:3"; mgmt-gw = "2a00:8180:2c00:281::8:3";
iot-gw = "2a00:8180:2c00:281::8:7";
priv1-gw = "2a00:8180:2c00:281::c:0"; priv1-gw = "2a00:8180:2c00:281::c:0";
priv10-gw = "2a00:8180:2c00:281::c:9"; priv10-gw = "2a00:8180:2c00:281::c:9";
priv11-gw = "2a00:8180:2c00:281::c:a"; priv11-gw = "2a00:8180:2c00:281::c:a";
@ -192,22 +178,16 @@
priv40-gw = "2a00:8180:2c00:281::c:27"; priv40-gw = "2a00:8180:2c00:281::c:27";
priv41-gw = "2a00:8180:2c00:281::c:28"; priv41-gw = "2a00:8180:2c00:281::c:28";
priv42-gw = "2a00:8180:2c00:281::c:29"; priv42-gw = "2a00:8180:2c00:281::c:29";
priv43-gw = "2a00:8180:2c00:281::c:2a"; priv43-gw = "2a00:8180:2c00:281::c:30";
priv44-gw = "2a00:8180:2c00:281::c:2b";
priv45-gw = "2a00:8180:2c00:281::c:2c";
priv46-gw = "2a00:8180:2c00:281::c:2d";
priv47-gw = "2a00:8180:2c00:281::c:2e";
priv48-gw = "2a00:8180:2c00:281::c:2f";
priv49-gw = "2a00:8180:2c00:281::c:30";
priv5-gw = "2a00:8180:2c00:281::c:4"; priv5-gw = "2a00:8180:2c00:281::c:4";
priv6-gw = "2a00:8180:2c00:281::c:5"; priv6-gw = "2a00:8180:2c00:281::c:5";
priv7-gw = "2a00:8180:2c00:281::c:6"; priv7-gw = "2a00:8180:2c00:281::c:6";
priv8-gw = "2a00:8180:2c00:281::c:7"; priv8-gw = "2a00:8180:2c00:281::c:7";
priv9-gw = "2a00:8180:2c00:281::c:8"; priv9-gw = "2a00:8180:2c00:281::c:8";
serv-gw = "2a00:8180:2c00:281::8:1"; serv-gw = "2a00:8180:2c00:281::8:1";
upstream1 = "2a00:8180:2c00:281::b:0";
upstream4 = "2a00:8180:2c00:281::b:1"; upstream4 = "2a00:8180:2c00:281::b:1";
vpn-gw = "2a00:8180:2c00:281:9001::1"; yggdrasil = "2a00:8180:2c00:281:9000::1";
coloradio-gw = "2a00:8180:2c00:281:9009::1";
}; };
}; };
subnet4 = "172.20.72.0/25"; subnet4 = "172.20.72.0/25";
@ -238,10 +218,10 @@
}; };
ospf = { ospf = {
allowedUpstreams = allowedUpstreams =
[ "upstream4" "upstream3" "anon1" "freifunk" ]; [ "upstream4" "upstream1" "upstream3" "anon1" "freifunk" ];
stubNets4 = [ "172.20.0.0/14" "10.0.0.0/8" ]; stubNets4 = [ "172.20.0.0/14" "10.0.0.0/8" ];
stubNets6 = stubNets6 =
[ "fd00::/8" "2a00:8180:2c00:200::/56" ]; [ "fd00::/8" "2a02:8106:208:5200::/56" "2a02:8106:211:e900::/56" ];
}; };
role = "container"; role = "container";
}; };

View File

@ -1,65 +0,0 @@
{
site.net.flpk = {
domainName = "flpk.zentralwerk.org";
ipv6Router = "flpk-gw";
subnet4 = "45.158.40.160/27";
# we get a /56
subnets6.flpk = "2a0f:5382:acab:1400::/64";
hosts4 = {
flpk-gw = "45.158.40.160";
notice-me-senpai = "45.158.40.162"; # tlms monitoring
sshlog = "45.158.40.163";
caveman = "45.158.40.164";
# tlms-37c3-ctf vm on server9
ctf = "45.158.40.165";
mastodon = "45.158.40.166";
c3d2-web = "45.158.40.167";
mail = "45.158.40.168";
dresden-zone-dns = "45.158.40.169";
# server7 = "45.158.40.170"; # unused
rtrlab = "45.158.40.171"; # temporary
};
hosts6.flpk = {
flpk-gw = "2a0f:5382:acab:1400::c3d2";
notice-me-senpai = "2a0f:5382:acab:1400:2de:5bff:fef9:e23e"; # tlms-monitoring
sshlog = "2a0f:5382:acab:1400::22";
caveman = "2a0f:5382:acab:1400::a4";
# tlms-37c3-ctf vm on server9
ctf = "2a0f:5382:acab:1400::a5";
mastodon = "2a0f:5382:acab:1400::a6";
c3d2-web = "2a0f:5382:acab:1400::a7";
# mail = "2a0f:5382:acab:1400::a8"; # we don't have an PTR for IPv6 and it gets way more often marked as spam
dresden-zone-dns = "2a0f:5382:acab:1400::a9";
# server7 = "2a0f:5382:acab:1400::aa";
rtrlab = "2a0f:5382:acab:1400::ab";
};
};
site.hosts.flpk-gw = {
interfaces = {
core = {
hwaddr = "0A:14:48:b7:e4:91";
type = "veth";
};
flpk = {
hwaddr = "0A:14:48:01:16:01";
type = "veth";
};
up-flpk = {
type = "wireguard";
upstream = {
provider = "flpk";
noNat = {
subnets4 = [ "45.158.40.160/27" ];
subnets6 = [ "2a0f:5382:acab:1400::/56" ];
};
};
};
};
ospf = {
allowedUpstreams = [ "upstream4" "upstream3" "freifunk" ];
upstreamInstance = 2;
};
role = "container";
};
}

View File

@ -63,16 +63,7 @@
ap62 = "10.0.0.102"; ap62 = "10.0.0.102";
ap63 = "10.0.0.103"; ap63 = "10.0.0.103";
ap64 = "10.0.0.104"; ap64 = "10.0.0.104";
ap65 = "10.0.0.105";
ap66 = "10.0.0.106";
ap67 = "10.0.0.107";
ap68 = "10.0.0.108";
ap69 = "10.0.0.109";
ap7 = "10.0.0.47"; ap7 = "10.0.0.47";
ap70 = "10.0.0.110";
ap71 = "10.0.0.111";
ap72 = "10.0.0.112";
ap73 = "10.0.0.113";
ap8 = "10.0.0.48"; ap8 = "10.0.0.48";
ap9 = "10.0.0.49"; ap9 = "10.0.0.49";
logging = "10.0.0.251"; logging = "10.0.0.251";
@ -104,10 +95,6 @@
switch-c3d2-main = "10.0.0.14"; switch-c3d2-main = "10.0.0.14";
switch-d1 = "10.0.0.13"; switch-d1 = "10.0.0.13";
switch-dach = "10.0.0.17"; switch-dach = "10.0.0.17";
switch-b3 = "10.0.0.18";
switch-ds1 = "10.0.0.20";
switch-ds2 = "10.0.0.21";
switch-ds3 = "10.0.0.22";
}; };
hosts6 = { hosts6 = {
dn42 = { dn42 = {
@ -172,16 +159,7 @@
ap62 = "fd23:42:c3d2:580::4:3e"; ap62 = "fd23:42:c3d2:580::4:3e";
ap63 = "fd23:42:c3d2:580::4:3f"; ap63 = "fd23:42:c3d2:580::4:3f";
ap64 = "fd23:42:c3d2:580::4:40"; ap64 = "fd23:42:c3d2:580::4:40";
ap65 = "fd23:42:c3d2:580::4:41";
ap66 = "fd23:42:c3d2:580::4:42";
ap67 = "fd23:42:c3d2:580::4:43";
ap68 = "fd23:42:c3d2:580::4:44";
ap69 = "fd23:42:c3d2:580::4:45";
ap7 = "fd23:42:c3d2:580::4:7"; ap7 = "fd23:42:c3d2:580::4:7";
ap70 = "fd23:42:c3d2:580::4:46";
ap71 = "fd23:42:c3d2:580::4:47";
ap72 = "fd23:42:c3d2:580::4:48";
ap73 = "fd23:42:c3d2:580::4:49";
ap8 = "fd23:42:c3d2:580::4:8"; ap8 = "fd23:42:c3d2:580::4:8";
ap9 = "fd23:42:c3d2:580::4:9"; ap9 = "fd23:42:c3d2:580::4:9";
mgmt-gw = "fd23:42:c3d2:580:ffff:ffff:ffff:ffff"; mgmt-gw = "fd23:42:c3d2:580:ffff:ffff:ffff:ffff";
@ -213,7 +191,7 @@
}; };
ospf = { ospf = {
allowedUpstreams = allowedUpstreams =
[ "upstream4" "upstream3" "anon1" "freifunk" ]; [ "upstream4" "upstream1" "upstream3" "anon1" "freifunk" ];
}; };
role = "container"; role = "container";
}; };

View File

@ -1,6 +1,6 @@
{ lib, ... }: { lib, ... }:
let let
privCount = 49; privCount = 43;
seq = n: max: seq = n: max:
if n <= max if n <= max
then [ n ] ++ seq (n + 1) max then [ n ] ++ seq (n + 1) max
@ -16,9 +16,9 @@ lib.mkMerge (
site.net."priv${toString n}" = { site.net."priv${toString n}" = {
dhcp = { dhcp = {
server = "priv${toString n}-gw"; server = "priv${toString n}-gw";
time = 300; time = 120;
max-time = 60 * 24 * 3600; max-time = 86400;
router = "priv${toString n}-gw"; router = "priv${toString n}-gw.priv${toString n}";
}; };
domainName = "priv${toString n}.zentralwerk.org"; domainName = "priv${toString n}.zentralwerk.org";
dynamicDomain = true; dynamicDomain = true;
@ -38,7 +38,7 @@ lib.mkMerge (
core.type = "veth"; core.type = "veth";
"priv${toString n}".type = "veth"; "priv${toString n}".type = "veth";
}; };
ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; ospf.allowedUpstreams = [ "upstream4" "upstream3" "upstream1" "anon1" "freifunk" ];
}; };
} }
) (seq 1 privCount) ) (seq 1 privCount)
@ -58,12 +58,10 @@ lib.mkMerge (
subnet4 = "172.20.75.0/27"; subnet4 = "172.20.75.0/27";
dhcp = { dhcp = {
start = "172.20.75.2"; start = "172.20.75.2";
end = "172.20.75.30"; end = "172.20.75.31";
fixed-hosts = { fixed-hosts = {
"172.20.75.2" = "ac:1f:6b:dc:93:8e";
"172.20.75.3" = "ac:1f:6b:dc:95:de";
"172.20.75.9" = "ac:1f:6b:dc:95:df";
"172.20.75.7" = "60:33:4b:0b:cd:fc"; "172.20.75.7" = "60:33:4b:0b:cd:fc";
"172.20.75.9" = "00:11:32:22:95:79";
}; };
}; };
}; };
@ -204,6 +202,7 @@ lib.mkMerge (
dhcp = { dhcp = {
start = "172.20.73.194"; start = "172.20.73.194";
end = "172.20.73.254"; end = "172.20.73.254";
max-time = lib.mkForce 2592000;
}; };
}; };
priv20 = { priv20 = {
@ -238,10 +237,9 @@ lib.mkMerge (
end = "172.20.73.190"; end = "172.20.73.190";
fixed-hosts = { fixed-hosts = {
"172.20.73.162" = "da:2c:3a:2c:87:22"; "172.20.73.162" = "da:2c:3a:2c:87:22";
"172.20.73.163" = "b8:27:eb:16:31:61"; "172.20.73.163" = "ca:9f:27:b2:bf:6d";
"172.20.73.164" = "ca:71:c4:90:3e:c7"; "172.20.73.164" = "60:01:94:6f:81:a6";
}; };
time = lib.mkForce 900;
}; };
}; };
priv24 = { priv24 = {
@ -305,11 +303,7 @@ lib.mkMerge (
subnet4 = "172.20.75.208/28"; subnet4 = "172.20.75.208/28";
dhcp = { dhcp = {
start = "172.20.75.210"; start = "172.20.75.210";
end = "172.20.75.221"; end = "172.20.75.222";
fixed-hosts = {
# zw-ev-vm
"172.20.75.222" = "92:a8:00:49:a6:61";
};
}; };
}; };
priv32 = { priv32 = {
@ -408,54 +402,6 @@ lib.mkMerge (
end = "172.20.76.110"; end = "172.20.76.110";
}; };
}; };
priv44 = {
hosts4 = { priv44-gw = "172.20.77.97"; };
subnet4 = "172.20.77.96/28";
dhcp = {
start = "172.20.77.98";
end = "172.20.77.110";
};
};
priv45 = {
hosts4 = { priv45-gw = "172.20.77.161"; };
subnet4 = "172.20.77.160/28";
dhcp = {
start = "172.20.77.162";
end = "172.20.77.174";
};
};
priv46 = {
hosts4 = { priv46-gw = "172.20.77.225"; };
subnet4 = "172.20.77.224/28";
dhcp = {
start = "172.20.77.226";
end = "172.20.77.238";
};
};
priv47 = {
hosts4 = { priv47-gw = "172.20.76.161"; };
subnet4 = "172.20.76.160/28";
dhcp = {
start = "172.20.76.162";
end = "172.20.76.174";
};
};
priv48 = {
hosts4 = { priv48-gw = "172.20.77.33"; };
subnet4 = "172.20.77.32/28";
dhcp = {
start = "172.20.77.34";
end = "172.20.77.46";
};
};
priv49 = {
hosts4 = { priv49-gw = "172.20.76.49"; };
subnet4 = "172.20.76.48/28";
dhcp = {
start = "172.20.76.50";
end = "172.20.76.62";
};
};
}; };
site.hosts = { site.hosts = {
@ -574,7 +520,7 @@ lib.mkMerge (
hwaddr = "0A:14:47:02:2A:19"; hwaddr = "0A:14:47:02:2A:19";
}; };
}; };
ospf.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ]; ospf.allowedUpstreams = [ "upstream3" "upstream4" "upstream1" "anon1" "freifunk" ];
}; };
priv18-gw = { priv18-gw = {
interfaces = { interfaces = {
@ -732,42 +678,6 @@ lib.mkMerge (
priv43.hwaddr = "0A:14:48:01:2A:53"; priv43.hwaddr = "0A:14:48:01:2A:53";
}; };
}; };
priv44-gw = {
interfaces = {
core.hwaddr = "0A:14:48:01:2A:54";
priv44.hwaddr = "0A:14:48:01:2A:55";
};
};
priv45-gw = {
interfaces = {
core.hwaddr = "0A:14:48:01:2A:56";
priv45.hwaddr = "0A:14:48:01:2A:57";
};
};
priv46-gw = {
interfaces = {
core.hwaddr = "0A:14:48:01:2A:58";
priv46.hwaddr = "0A:14:48:01:2A:59";
};
};
priv47-gw = {
interfaces = {
core.hwaddr = "0A:14:48:01:2A:5A";
priv47.hwaddr = "0A:14:48:01:2A:5B";
};
};
priv48-gw = {
interfaces = {
core.hwaddr = "0A:14:48:01:2A:5C";
priv48.hwaddr = "0A:14:48:01:2A:5D";
};
};
priv49-gw = {
interfaces = {
core.hwaddr = "0A:14:48:01:2A:5E";
priv49.hwaddr = "0A:14:48:01:2A:5F";
};
};
}; };
} ] } ]
) )

View File

@ -1,31 +1,19 @@
{ {
site.net.pub = { site.net.pub = {
dhcp = { dhcp = {
start = "172.20.78.2"; end = "172.20.79.254";
end = "172.20.79.253"; max-time = 3600;
router = "pub-gw"; router = "pub-gw.pub";
server = "pub-gw"; server = "pub-gw";
time = 120; start = "172.20.78.2";
max-time = 12 * 3600; time = 300;
}; };
domainName = "pub.zentralwerk.org"; domainName = "pub.zentralwerk.org";
dynamicDomain = true; dynamicDomain = true;
hosts4 = { hosts4 = { pub-gw = "172.20.78.1"; };
pub-gw = "172.20.78.1"; hosts6 = { dn42 = { pub-gw = "fd23:42:c3d2:583::1"; }; };
};
hosts6 = {
dn42 = {
pub-gw = "fd23:42:c3d2:583::1";
};
flpk = {
pub-gw = "2a0f:5382:acab:1403::1";
};
};
subnet4 = "172.20.78.0/23"; subnet4 = "172.20.78.0/23";
subnets6 = { subnets6 = { dn42 = "fd23:42:c3d2:583::/64"; };
dn42 = "fd23:42:c3d2:583::/64";
flpk = "2a0f:5382:acab:1403::/64";
};
}; };
site.hosts.pub-gw = { site.hosts.pub-gw = {
@ -41,7 +29,6 @@
}; };
ospf = { ospf = {
allowedUpstreams = [ "anon1" "freifunk" ]; allowedUpstreams = [ "anon1" "freifunk" ];
allowedUpstreams6 = [ "flpk-gw" "anon1" "freifunk" ];
}; };
role = "container"; role = "container";
}; };

View File

@ -3,12 +3,7 @@
# not switched, only a wifi # not switched, only a wifi
vlan = null; vlan = null;
# leave space for vxlan # leave space for vxlan
mtu = 1574; mtu = 2048;
subnet4 = "10.0.57.0/24";
hosts4 = {
ap57 = "10.0.57.1";
ap58 = "10.0.57.2";
};
hosts6.dn42 = { hosts6.dn42 = {
ap57 = "fd23:42:c3d2:584::39"; ap57 = "fd23:42:c3d2:584::39";
ap58 = "fd23:42:c3d2:584::40"; ap58 = "fd23:42:c3d2:584::40";

View File

@ -7,136 +7,123 @@
serv-gw = "172.20.73.1"; serv-gw = "172.20.73.1";
dns = "172.20.73.2"; dns = "172.20.73.2";
stats = "172.20.73.3"; stats = "172.20.73.3";
dresden-zone = "172.20.73.4"; radius = "172.20.73.4";
tlms-elastic = "172.20.73.7"; # tlms zeit = "172.20.73.5";
minecraft = "172.20.73.6";
used1 = "172.20.73.7";
dnscache = "172.20.73.8"; dnscache = "172.20.73.8";
tlms-ctfd = "172.20.73.9"; # tlms used2 = "172.20.73.9";
buzzrelay = "172.20.73.15"; used3 = "172.20.73.10";
used4 = "172.20.73.11";
used5 = "172.20.73.12";
logging = "172.20.73.13";
used6 = "172.20.73.14";
c3d2-web = "172.20.73.15";
deployer = "172.20.73.16";
used7 = "172.20.73.17";
used8 = "172.20.73.18";
used9 = "172.20.73.19";
ipa = "172.20.73.20";
matemat = "172.20.73.21"; matemat = "172.20.73.21";
used10 = "172.20.73.22";
used11 = "172.20.73.23";
used12 = "172.20.73.24";
spaceapi = "172.20.73.25"; spaceapi = "172.20.73.25";
used13 = "172.20.73.26";
mucbot = "172.20.73.27"; mucbot = "172.20.73.27";
used14 = "172.20.73.28";
used15 = "172.20.73.29";
used16 = "172.20.73.30";
used17 = "172.20.73.31";
scrape = "172.20.73.32"; scrape = "172.20.73.32";
pretalx = "172.20.73.33"; used19 = "172.20.73.33";
vaultwarden = "172.20.73.34"; used20 = "172.20.73.34";
uranus = "172.20.73.37"; # tlms used21 = "172.20.73.35";
tram-borzoi = "172.20.73.38"; # tlms used22 = "172.20.73.36";
borken-data-hoarder = "172.20.73.39"; # tlms used23 = "172.20.73.37";
matrix = "172.20.73.40"; used24 = "172.20.73.38";
activity-relay = "172.20.73.41"; used25 = "172.20.73.39";
luulaatsch-asterisk = "172.20.73.42"; used26 = "172.20.73.40";
# unused = "172.22.73.41";
mailtngbert = "172.22.73.42";
grafana = "172.20.73.43"; grafana = "172.20.73.43";
kibana = "172.20.73.44";
public-access-proxy = "172.20.73.45"; public-access-proxy = "172.20.73.45";
marenz = "172.20.73.46"; marenz = "172.20.73.46";
network-homepage = "172.20.73.47"; leonos = "172.20.73.47";
home-assistant = "172.20.73.48"; minetest = "172.20.73.48";
hydra = "172.20.73.49"; hydra = "172.20.73.49";
owncast = "172.20.73.50"; netboot = "172.20.73.50";
nfsroot = "172.20.73.51"; vps1 = "172.20.73.51";
ticker = "172.20.73.52"; ticker = "172.20.73.52";
gitea = "172.20.73.53"; gitea = "172.20.73.53";
stream = "172.20.73.54"; stream = "172.20.73.54";
jabber = "172.20.73.55"; jabber = "172.20.73.55";
mobilizon = "172.20.73.56"; mobilizon = "172.20.73.56";
radiobert = "172.20.73.57"; radiobert = "172.20.73.57";
# mail = "172.20.73.58"; mail = "172.20.73.58";
keycloak = "172.20.73.59";
sdrweb = "172.20.73.60"; sdrweb = "172.20.73.60";
knot = "172.20.73.61"; bind = "172.20.73.61";
blogs = "172.20.73.62"; blogs = "172.20.73.62";
staging-data-hoarder = "172.20.73.64"; # tlms
oparl = "172.20.73.65";
hedgedoc = "172.20.73.66";
mediawiki = "172.20.73.67";
gnunet = "172.20.73.68";
data-hoarder = "172.20.73.69"; # tlms
broker = "172.20.73.70";
ftp = "172.20.73.71";
auth = "172.20.73.72";
doubleblind-science = "172.20.73.73";
prometheus = "172.20.73.75";
drone = "172.20.73.77";
# FILL IN THE HOLES BEFORE APPENDING!
}; };
ipv6Router = "serv-gw";
subnets6.dn42 = "fd23:42:c3d2:582::/64"; subnets6.dn42 = "fd23:42:c3d2:582::/64";
subnets6.up4 = "2a00:8180:2c00:282::/64"; subnets6.up4 = "2a00:8180:2c00:282::/64";
hosts6.dn42 = { hosts6.dn42 = {
knot = "fd23:42:c3d2:582:cd7:56ff:fe69:6366"; bind = "fd23:42:c3d2:582:cd7:56ff:fe69:6366";
blogs = "fd23:42:c3d2:582:b8a8:7dff:fee8:5ac2"; blogs = "fd42:42:c3d2:582:b8a8:7dff:fee8:5ac2";
c3d2-web = "fd23:42:c3d2:582:642e:95ff:fe34:49f9";
dns = "fd23:42:c3d2:582:2:0:0:2"; dns = "fd23:42:c3d2:582:2:0:0:2";
dnscache = "fd23:42:c3d2:582:f096:dbff:fee8:427d"; dnscache = "fd23:42:c3d2:582:f096:dbff:fee8:427d";
gitea = "fd23:42:c3d2:582:702a:daff:fe35:83be";
grafana = "fd23:42:c3d2:582:4042:fbff:fe4b:2de8"; grafana = "fd23:42:c3d2:582:4042:fbff:fe4b:2de8";
hydra = "fd23:42:c3d2:582:e2cb:4eff:fe3b:f94b"; hydra = "fd23:42:c3d2:582:e03c:d7ff:fe8e:fe16";
jabber = "fd23:42:c3d2:582:b869:ccff:fe46:902a"; jabber = "fd23:42:c3d2:582:b869:ccff:fe46:902a";
# mail = "fd23:42:c3d2:582:88c0:41ff:fe70:d6cd"; keycloak = "fd23:42:c3d2:582:c48:bbff:fe87:721d";
logging = "fd23:42:c3d2:582:6811:edff:fe40:89c6";
mail = "fd23:42:c3d2:582:88c0:41ff:fe70:d6cd";
matemat = "fd23:42:c3d2:582:f82b:1bff:fedc:8572"; matemat = "fd23:42:c3d2:582:f82b:1bff:fedc:8572";
minetest = "fd23:42:c3d2:582:c3a:42ff:fe5d:b20c";
mobilizon = "fd23:42:c3d2:582:48d1:5cff:fea7:1676"; mobilizon = "fd23:42:c3d2:582:48d1:5cff:fea7:1676";
mongo = "fd23:42:c3d2:582:14ec:c8ff:fe0a:fc5c"; mongo = "fd23:42:c3d2:582:14ec:c8ff:fe0a:fc5c";
mucbot = "fd23:42:c3d2:582:28db:dff:fe6b:e89a"; mucbot = "fd23:42:c3d2:582:28db:dff:fe6b:e89a";
netboot = "fd23:42:c3d2:582:2:0:0:6";
radiobert = "fd23:42:c3d2:582:e65f:1ff:fe5d:1679"; radiobert = "fd23:42:c3d2:582:e65f:1ff:fe5d:1679";
radius = "fd23:42:c3d2:582:2:0:0:4"; radius = "fd23:42:c3d2:582:2:0:0:4";
sdrweb = "fd23:42:c3d2:582:3078:bbff:fe76:e9ef"; sdrweb = "fd23:42:c3d2:582:3078:bbff:fe76:e9ef";
serv-gw = "fd23:42:c3d2:582::1"; serv-gw = "fd23:42:c3d2:582::1";
spaceapi = "fd23:42:c3d2:582:1457:adff:fe93:62e9"; spaceapi = "fd23:42:c3d2:582:1457:adff:fe93:62e9";
stats = "fd23:42:c3d2:582:2:0:0:3"; stats = "fd23:42:c3d2:582:2:0:0:3";
staging-data-hoarder = "fd23:42:c3d2:582:2de:5bff:fef9:e23d"; zeit = "fd23:42:c3d2:582:2:0:0:5";
oparl = "fd23:42:c3d2:582:2de:9aff:fece:3879";
gnunet = "fd23:42:c3d2:582::44";
broker = "fd23:42:c3d2:582::46";
ftp = "fd23:42:c3d2:582::47";
network-homepage = "fd23:42:c3d2:582::2f";
owncast = "fd23:42:c3d2:582::32";
prometheus = "fd23:42:c3d2:582::4b";
buzzrelay = "fd23:42:c3d2:582::f";
oxigraph = "fd23:42:c3d2:582::4c";
luulaatsch-asterisk = "fd23:42:c3d2:582::2a";
stream = "fd23:42:c3d2:583:dc91:c7ff:fe51:d1c5";
}; };
hosts6.up4 = { hosts6.up4 = {
knot = "2a00:8180:2c00:282:cd7:56ff:fe69:6366"; bind = "2a00:8180:2c00:282:cd7:56ff:fe69:6366";
blogs = "2a00:8180:2c00:282:b8a8:7dff:fee8:5ac2"; blogs = "2a00:8180:2c00:282:b8a8:7dff:fee8:5ac2";
c3d2-web = "2a00:8180:2c00:282:642e:95ff:fe34:49f9";
dns = "2a00:8180:2c00:282:2:0:0:2"; dns = "2a00:8180:2c00:282:2:0:0:2";
dnscache = "2a00:8180:2c00:282:f096:dbff:fee8:427d"; dnscache = "2a00:8180:2c00:282:f096:dbff:fee8:427d";
gitea = "2a00:8180:2c00:282:702a:daff:fe35:83be";
grafana = "2a00:8180:2c00:282:4042:fbff:fe4b:2de8"; grafana = "2a00:8180:2c00:282:4042:fbff:fe4b:2de8";
hydra = "2a00:8180:2c00:282:e2cb:4eff:fe3b:f94b"; hydra = "2a00:8180:2c00:282:e03c:d7ff:fe8e:fe16";
jabber = "2a00:8180:2c00:282:b869:ccff:fe46:902a"; jabber = "2a00:8180:2c00:282:b869:ccff:fe46:902a";
# mail = "2a00:8180:2c00:282:88c0:41ff:fe70:d6cd"; keycloak = "2a00:8180:2c00:282:c48:bbff:fe87:721d";
logging = "2a00:8180:2c00:282:6811:edff:fe40:89c6";
mail = "2a00:8180:2c00:282:88c0:41ff:fe70:d6cd";
matemat = "2a00:8180:2c00:282:f82b:1bff:fedc:8572"; matemat = "2a00:8180:2c00:282:f82b:1bff:fedc:8572";
minetest = "2a00:8180:2c00:282:c3a:42ff:fe5d:b20c";
mobilizon = "2a00:8180:2c00:282:48d1:5cff:fea7:1676"; mobilizon = "2a00:8180:2c00:282:48d1:5cff:fea7:1676";
mongo = "2a00:8180:2c00:282:14ec:c8ff:fe0a:fc5c";
mucbot = "2a00:8180:2c00:282:28db:dff:fe6b:e89a"; mucbot = "2a00:8180:2c00:282:28db:dff:fe6b:e89a";
netboot = "2a00:8180:2c00:282:2:0:0:6";
public-access-proxy = "2a00:8180:2c00:282:1024:5fff:febd:9be7"; public-access-proxy = "2a00:8180:2c00:282:1024:5fff:febd:9be7";
radiobert = "2a00:8180:2c00:282:e65f:1ff:fe5d:1679"; radiobert = "2a00:8180:2c00:282:e65f:1ff:fe5d:1679";
radius = "2a00:8180:2c00:282:2:0:0:4"; radius = "2a00:8180:2c00:282:2:0:0:4";
scrape = "2a00:8180:2c00:282:e073:50ff:fef5:eb6e"; scrape = "2a00:8180:2c00:282:e073:50ff:fef5:eb6e";
sdrweb = "2a00:8180:2c00:282:3078:bbff:fe76:e9ef"; sdrweb = "2a00:8180:2c00:282:3078:bbff:fe76:e9ef";
serv-gw = "2a00:8180:2c00:282::1";
spaceapi = "2a00:8180:2c00:282:1457:adff:fe93:62e9"; spaceapi = "2a00:8180:2c00:282:1457:adff:fe93:62e9";
stats = "2a00:8180:2c00:282:2:0:0:3"; stats = "2a00:8180:2c00:282:2:0:0:3";
stream = "2a00:8180:2c00:282:dc91:c7ff:fe51:d1c5"; stream = "fd23:42:c3d2:583:dc91:c7ff:fe51:d1c5";
ticker = "2a00:8180:2c00:282:b407:40ff:fec1:81f2"; ticker = "2a00:8180:2c00:282:b407:40ff:fec1:81f2";
staging-data-hoarder = "2a00:8180:2c00:282:2de:5bff:fef9:e23d"; zeit = "2a00:8180:2c00:282:2:0:0:5";
oparl = "2a00:8180:2c00:282:2de:9aff:fece:3879";
serv-gw = "2a00:8180:2c00:282::1";
luulaatsch-asterisk = "2a00:8180:2c00:282::2a";
drone = "2a00:8180:2c00:282::2b";
pretalx = "2a00:8180:2c00:282::2c";
matrix = "2a00:8180:2c00:282::2d";
activity-relay = "2a00:8180:2c00:282::2e";
network-homepage = "2a00:8180:2c00:282::2f";
vaultwarden = "2a00:8180:2c00:282::31";
owncast = "2a00:8180:2c00:282::32";
mediawiki = "2a00:8180:2c00:282::43";
gnunet = "2a00:8180:2c00:282::44";
data-hoarder = "2a00:8180:2c00:282::45";
broker = "2a00:8180:2c00:282::46";
ftp = "2a00:8180:2c00:282::47";
auth = "2a00:8180:2c00:282::48";
dresden-zone = "2a00:8180:2c00:282::49";
prometheus = "2a00:8180:2c00:282::4b";
oxigraph = "2a00:8180:2c00:282::4c";
hedgedoc = "2a00:8180:2c00:282::6";
buzzrelay = "2a00:8180:2c00:282::f";
}; };
}; };
@ -160,6 +147,9 @@
dnscache = makeContainer { dnscache = makeContainer {
services.dnscache.enable = true; services.dnscache.enable = true;
}; };
netboot = makeContainer {
interfaces.serv.hwaddr = "0A:14:48:01:15:01";
};
serv-gw = makeContainer { serv-gw = makeContainer {
interfaces = { interfaces = {
core = { core = {
@ -175,16 +165,10 @@
}; };
}; };
ospf.allowedUpstreams = ospf.allowedUpstreams =
[ "upstream4" "upstream3" "anon1" "freifunk" ]; [ "upstream4" "upstream1" "upstream3" "anon1" "freifunk" ];
}; };
stats = makeContainer { stats = makeContainer {
interfaces.serv.hwaddr = "0A:14:48:01:15:00"; interfaces.serv.hwaddr = "0A:14:48:01:15:00";
}; };
hydra = {
role = "client";
model = "nixos";
interfaces.serv.type = "phys";
};
}; };
} }

View File

@ -2,10 +2,159 @@
let let
servHosts = config.site.net.serv.hosts4; servHosts = config.site.net.serv.hosts4;
inherit (config.site.net.c3d2.hosts4) dn42; inherit (config.site.net.c3d2.hosts4) dn42;
inherit (config.site.net.flpk.hosts4) c3d2-web;
in in
{ {
site.hosts = { site.hosts = {
upstream1 = {
forwardPorts = [
{
destination = "${servHosts.public-access-proxy}:80";
proto = "tcp";
reflect = true;
sourcePort = 80;
}
{
destination = "${servHosts.public-access-proxy}:443";
proto = "tcp";
reflect = true;
sourcePort = 443;
}
{
destination = dn42;
proto = "udp";
reflect = true;
sourcePort = 2325;
}
{
destination = dn42;
proto = "udp";
reflect = true;
sourcePort = 2399;
}
{
destination = dn42;
proto = "udp";
reflect = true;
sourcePort = 2327;
}
{
destination = dn42;
proto = "udp";
reflect = true;
sourcePort = 2338;
}
{
destination = dn42;
proto = "udp";
reflect = true;
sourcePort = 2339;
}
{
destination = dn42;
proto = "udp";
reflect = true;
sourcePort = 40533;
}
{
destination = dn42;
proto = "udp";
reflect = true;
sourcePort = 61699;
}
{
destination = "172.20.74.210:22";
proto = "tcp";
reflect = true;
sourcePort = 2222;
}
{
destination = "172.20.74.210:443";
proto = "tcp";
reflect = true;
sourcePort = 8443;
}
{
destination = "172.20.73.47:22";
proto = "tcp";
reflect = true;
sourcePort = 2223;
}
{
destination = "172.20.73.48:30000";
proto = "udp";
reflect = true;
sourcePort = 30000;
}
{
destination = config.site.net.core.hosts4.yggdrasil;
proto = "tcp";
reflect = true;
sourcePort = 1337;
}
];
interfaces = {
core = {
hwaddr = "0A:14:48:01:26:00";
type = "veth";
};
up1 = {
hwaddr = "00:23:74:D7:2D:7C";
type = "veth";
upstream = {
link = null;
noNat = { subnets6 = [ "2a02:8106:208:5200::/56" ]; };
provider = "vodafone";
staticIpv4Address = "24.134.104.53";
upBandwidth = 52500;
};
};
};
ospf.upstreamInstance = 3;
role = "container";
};
upstream2 = {
forwardPorts = [
{
destination = "172.20.75.9:1194";
proto = "udp";
reflect = true;
sourcePort = 1194;
}
{
destination = "172.20.74.210:22";
proto = "tcp";
reflect = true;
sourcePort = 2222;
}
{
destination = "172.20.74.210:443";
proto = "tcp";
reflect = true;
sourcePort = 8443;
}
];
interfaces = {
core = {
hwaddr = "0A:14:48:01:27:00";
type = "veth";
};
up2 = {
hwaddr = "00:23:74:D7:42:7C";
type = "veth";
upstream = {
link = null;
noNat = { subnets6 = [ "2a02:8106:208:e900::/56" ]; };
provider = "vodafone";
staticIpv4Address = null;
upBandwidth = 52500;
};
};
};
ospf.upstreamInstance = 4;
role = "container";
};
upstream3 = { upstream3 = {
interfaces = { interfaces = {
core = { core = {
@ -28,191 +177,221 @@ in
role = "container"; role = "container";
}; };
upstream4 = rec { upstream4 = {
forwardPorts = [ forwardPorts = [
{ # http {
destination = servHosts.public-access-proxy; destination = "172.20.73.45";
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 80; sourcePort = 80;
} }
{ # https {
destination = servHosts.public-access-proxy; destination = "172.20.73.45";
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 443; sourcePort = 443;
} }
{ # gemini
destination = "${c3d2-web}:1965";
proto = "tcp";
sourcePort = 1965;
}
{ {
destination = servHosts.knot; destination = "172.20.73.61";
proto = "tcp"; proto = "tcp";
reflect = false;
sourcePort = 53; sourcePort = 53;
} }
{ {
destination = servHosts.knot; destination = "172.20.73.61";
proto = "udp"; proto = "udp";
reflect = false;
sourcePort = 53; sourcePort = 53;
} }
{ {
destination = dn42; destination = dn42;
proto = "udp"; proto = "udp";
reflect = true;
sourcePort = 2325; sourcePort = 2325;
} }
{ {
destination = dn42; destination = dn42;
proto = "udp"; proto = "udp";
reflect = true;
sourcePort = 2327; sourcePort = 2327;
} }
{ {
destination = dn42; destination = dn42;
proto = "udp"; proto = "udp";
reflect = true;
sourcePort = 2337; sourcePort = 2337;
} }
{ {
destination = dn42; destination = dn42;
proto = "udp"; proto = "udp";
reflect = true;
sourcePort = 2338; sourcePort = 2338;
} }
{ {
destination = dn42; destination = dn42;
proto = "udp"; proto = "udp";
reflect = true;
sourcePort = 2339; sourcePort = 2339;
} }
{ {
destination = dn42; destination = dn42;
proto = "udp"; proto = "udp";
reflect = true;
sourcePort = 2340; sourcePort = 2340;
} }
{ {
destination = dn42; destination = dn42;
proto = "udp"; proto = "udp";
sourcePort = 2342; reflect = true;
}
{
destination = dn42;
proto = "udp";
sourcePort = 2399; sourcePort = 2399;
} }
{ {
destination = dn42; destination = dn42;
proto = "udp"; proto = "udp";
reflect = true;
sourcePort = 24699; sourcePort = 24699;
} }
{ {
destination = dn42; destination = dn42;
proto = "udp"; proto = "udp";
reflect = true;
sourcePort = 64699; sourcePort = 64699;
} }
{
destination = "${servHosts.leonos}:22";
proto = "tcp";
reflect = true;
sourcePort = 2223;
}
{
destination = servHosts.minetest;
proto = "udp";
reflect = true;
sourcePort = 30000;
}
# ? # ?
{ {
destination = "172.22.99.175:22"; destination = "172.22.99.175:22";
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 2224; sourcePort = 2224;
} }
{ {
destination = servHosts.gitea; destination = servHosts.gitea;
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 22; sourcePort = 22;
} }
{ {
destination = servHosts.jabber; destination = servHosts.jabber;
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 5222; sourcePort = 5222;
} }
{ {
destination = servHosts.jabber; destination = servHosts.jabber;
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 5223; sourcePort = 5223;
} }
{ {
destination = servHosts.jabber; destination = servHosts.jabber;
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 5269; sourcePort = 5269;
} }
{ {
destination = servHosts.jabber; destination = servHosts.jabber;
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 3478; sourcePort = 3478;
} }
{ {
destination = servHosts.jabber; destination = servHosts.jabber;
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 3479; sourcePort = 3479;
} }
{ {
destination = servHosts.jabber; destination = servHosts.jabber;
proto = "udp"; proto = "udp";
reflect = true;
sourcePort = 3478; sourcePort = 3478;
} }
{ {
destination = servHosts.jabber; destination = servHosts.jabber;
proto = "udp"; proto = "udp";
reflect = true;
sourcePort = 3479; sourcePort = 3479;
} }
# leon's vps1
{
destination = "${servHosts.vps1}:22";
proto = "tcp";
reflect = true;
sourcePort = 2225;
}
{
destination = servHosts.mail;
proto = "tcp";
reflect = true;
sourcePort = 25;
}
{
destination = servHosts.mail;
proto = "tcp";
reflect = true;
sourcePort = 465;
}
{
destination = servHosts.mail;
proto = "tcp";
reflect = true;
sourcePort = 587;
}
{
destination = servHosts.mail;
proto = "tcp";
reflect = true;
sourcePort = 110;
}
{
destination = servHosts.mail;
proto = "tcp";
reflect = true;
sourcePort = 143;
}
{
destination = servHosts.mail;
proto = "tcp";
reflect = true;
sourcePort = 993;
}
{
destination = servHosts.mail;
proto = "tcp";
reflect = true;
sourcePort = 995;
}
# poelzi # poelzi
{ {
destination = "172.20.73.162:22"; destination = "172.20.73.162:22";
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 2323; sourcePort = 2323;
} }
# jan
{
destination = "172.20.75.3:51820";
proto = "udp";
sourcePort = 30057;
}
# zw-ev RDP # zw-ev RDP
{ {
destination = "172.20.75.222:3389"; destination = "172.20.75.222:3389";
proto = "tcp"; proto = "tcp";
reflect = true;
sourcePort = 45000; sourcePort = 45000;
} }
{ {
destination = config.site.net.core.hosts4.vpn-gw; destination = config.site.net.core.hosts4.yggdrasil;
proto = "udp"; proto = "tcp";
sourcePort = config.site.vpn.wireguard.port;
reflect = true; reflect = true;
} sourcePort = 1337;
{
destination = servHosts.gnunet;
proto = "tcp";
sourcePort = 2086;
}
# dresden zone
{
destination = servHosts.dresden-zone;
proto = "udp";
sourcePort = 51844;
}
# data-hoarder
{
destination = servHosts.data-hoarder;
proto = "udp";
sourcePort = 51820;
}
{
destination = "${servHosts.data-hoarder}:22";
proto = "tcp";
sourcePort = 2269;
}
# data-hoarder-staging
{
destination = "${servHosts.staging-data-hoarder}:51820";
proto = "udp";
sourcePort = 51821;
}
{
destination = "${servHosts.ftp}:22";
proto = "tcp";
sourcePort = 1022;
}
# coloRadio
{
proto = "tcp";
sourcePort = 8000;
destination = "192.168.9.127";
} }
]; ];
interfaces = { interfaces = {
@ -238,12 +417,7 @@ in
}; };
}; };
}; };
ospf = { ospf.upstreamInstance = 8;
upstreamInstance = 8;
stubNets4 = [
"${interfaces.up4-pppoe.upstream.staticIpv4Address}/32"
];
};
role = "container"; role = "container";
}; };
@ -264,7 +438,7 @@ in
}; };
}; };
ospf = { ospf = {
allowedUpstreams = [ "upstream3" "upstream4" "freifunk" ]; allowedUpstreams = [ "upstream1" "upstream3" "upstream4" "freifunk" ];
upstreamInstance = 5; upstreamInstance = 5;
}; };
role = "container"; role = "container";

View File

@ -1,40 +0,0 @@
{ ... }:
{
site.net.vpn = {
vlan = null;
domainName = "core.zentralwerk.org";
ipv6Router = "vpn-gw";
hosts4 = {
vpn-gw = "172.20.76.225";
};
hosts6 = {
dn42 = {
vpn-gw = "fd23:42:c3d2:585::1";
};
up4 = {
vpn-gw = "2a00:8180:2c00:285::1";
};
};
subnet4 = "172.20.76.224/28";
subnets6 = {
dn42 = "fd23:42:c3d2:585::/64";
up4 = "2a00:8180:2c00:285::/64";
};
};
site.hosts.vpn-gw = {
role = "container";
interfaces = {
core = {
hwaddr = "0A:14:42:01:26:01";
type = "veth";
};
vpn = {
type = "wireguard";
};
};
ospf = {
allowedUpstreams = [ "flpk-gw" "anon1" "freifunk" ];
};
};
}

18
config/net/yggdrasil.nix Normal file
View File

@ -0,0 +1,18 @@
{
site.hosts.yggdrasil = {
role = "container";
interfaces = {
core = {
hwaddr = "0A:14:48:01:26:ff";
type = "veth";
};
};
ospf = {
allowedUpstreams =
[ "upstream4" "upstream1" "upstream3" "anon1" "freifunk" ];
stubNets6 = [ "200::/7" ];
};
services.yggdrasil.enable = true;
};
}

View File

@ -1,85 +1,63 @@
-----BEGIN PGP MESSAGE----- -----BEGIN PGP MESSAGE-----
hQEMA2PKcvDMvlKLAQgAjGer7r8wCoigtDTS5zzUnJI02b3RQvhbqjv4a6RD52ry hQEMA2PKcvDMvlKLAQgAgRgCEJoGQg7p5nvRCDgO8NmJDavhdpGTqT8kCUYbCIS/
NzqqX7yIVyOEP2SnqoBpmWHYFJ3WcRb5Io3DXBLjgVHZbWJMP/DtVzHN+1ix3A5T HLPdX5zTBJXauuAWCxdLWn5afAL/aw5SN9rl2HyUBCRfEpCRCT+TvCQCZpzB2Epy
ZjxROLc/EDyd+prSvbol5UJkHJeoH7PWwPmO1VPOVZwAV+NGJS/qKXz/wUGFA6y5 bKTXmRuFkX/WhSHZqIGCF/Nn9kHB6JVul9rCNb2Eme/ixEChFZGz/XgUf43DMLfl
iH6vzetTvxSBt08dYVulzmI/B6MwHUz8W7YTTal7QTKftlyzXWZHydbj1AWJjGoR P5uiDY0i3FCzYk4/aB3l8zQESMpopppnjsLjjVFOahe5+7bMIaLLbVfBs07u840D
qadxsH4ZlqdHJrP/j5Yvw72XgdzAN7MQrofslqFI9ro9nccLQ7Q3B7kzt/EvoOPm XO1MKlrkgy8rFtt3Lgy8W8EBVYS/v6G0WOQReSE1qADZ/9gBZoPKJIY6MqTGtEDn
obPHW1I0UFoFXhfTujROXwVlernk6qmxO/oNr5UZB9LqAaroXhliddAzPZPT5qcK rSZlxSU/Y4o3qyRclp08qPDQhGV+hSjkBGQ2xYZFy9LrAc0rT7Chpycuj+exyr+H
szctWSv1eNlGO44iwIJyrh/Yetmrhll8flPl9URWIi9r383xkawhxG52alUVjRIz x+Xe6KCwCAhxLqD9jJJ/r3xlwp+Jz/DM6u50agmpd4KPgSzErXOCqNDcgjWEvOwE
u2BC3vdrt5o0GfEpZlDo23UbIxLIFbMg2xTXcFBq5TJEw0+owwhz+m+JRrXY9h1+ 1QBVy+Um9BBXRrlTOnEBHB8cjNVJ0JWtNrS9INznhxvDB6zLjj9KGaYcnCY7GTrG
SVlMX0PcUUg4vmX+7/KVIwrSECFpfPcBTSyMafUT6SfxG02/WmvzcEXk8E8hK+a3 PgIDDd+CSRrmwt01h7xhhW968Jz0NBw77oIayqSokCA3BsGki2fJ8jOYBRO4XHJh
VzolJIqirrv1CRwm60xOucytFI5OnxYI3kV9saiLwB6i9KI8Hw91pM7T+kQmXbbl 6CFVKFJBvOe136ESdtYXEAQFJDl7+/PWlEJE+NcXuK/ylL7rxjboPknuBmqe9X6f
etRddcQLXdhjRB/bCUJbQeEKZx0gjVAQkTFtdz6tp2vc9u/WS6UMrrQIkzdwLIOg Rrhd8g7Dx06VAvGpT6sdtb0BEw5LbypmN/3FbOq+gnkHtzdIioQzFlU+Z1hVN1OV
AXa8JmCtlTcN1uVVDlmQqba5li6ObqM4dtyOwHkXmpwBLObtoSg2yxTExxVwtAxz wWrv29Zf9OJ7OMEdvrOZgrv1CxB+TVJ6wvzlEkDEQa9MuLDXM03sBAXdhtqOytbV
CgNcPZ9snnht8MpXGrrzQUsdGfBY4gZ8Hgh1oScqW9b8o5XtT74hdtWXFMv6tE2F 2sdK2r9xTAYdgUbKYSw8kYkpoI8S/9a5UajwwGKMVP6z2po3tZBh+vfxIDyYT3/I
8bco4QBt6q95aYSi/wcyLwIyhUI+PEh2m5UM7KjYs2xxWbzU7Q0nj70VI9x+0Y+U pOeT0lQJX1FtX8T5DKWWJ6u3eeLRm50DcjaheiEQ8KFtklpq1AAZln3Kbc+uA3ZU
Apez4mYlqiep5l94E4Q4wb3rizYeXFAzZDe5FXfcpRgVPHGSq6XWUYSgyQENuRTB NkLjV9qjLYZ7HvrC/oNVRR6RoZiv5f2qswNemGPkGTiCZ5NByiPnHLtxD1I/vdvV
Ll8usdYLgT3Y7ULxT4O/8OKkDFMyfmTIdSiJRUJ8izMTm0yq5lKrSsqYTZVNOF6v d0/Y3G2X/Fzv8QMiKIjGOS1dXX2Sr5yBKd4gr84rWGNgD+wx1rZ9w842qvDccTHE
NDEolddj4DOaRV07DkrQRMpukrTCauZdC/c/hwmr3+ZcaMi33ZKHIbCXex/34D9z A/0DkKCGNGN+g0pCZNrfpO1drh4aQIujg054nUp2VqgZqdrO39Ar4n/3WfKne8H3
0CH3fA0nn/w3jh9CwOKBrT+cbOlMF3gVJbQU8xGgf7QHyaf8dEoayiInk9wKfUJd w3n1t2EL5GDDCgSc7xhDHEUPG62ozlDW+Rpmn5DVlMvgNojhZEPB40qs9ZlgYKBF
BQ6YGukQBb6KDDNuDq0r9UYeRPjWc/mGSZkluoEl1GVFkFNpxlKStB68hNRJg63i UEZt3VRccBF1nE2M0uzPXhOhWhKxmbYBDevJAXyzSPtX9VBkM8CErJRzhfk80Va1
gS/l6jSkj1IKmsnbkJVtC+YwH/Pkx6+fcisXmUGPZ9KUiw2qiCGLFbHm5Shc7YBW ZSg3ZyAX8ONgZppv934DtXurpQz9REDw3hA4zdelGomP5stXHvqdzCXuzAgXWenj
BpiZzCEjRrp71lB5URbbY+zhf+lcAdxewbw8v0R0tJP2hzmXCqsvJnB4jcEc1YD5 mQy+a7QYTZzgOjzbkrMqhaQz4lTEfWKaZPcUyt8sbebqX01d+9Q90B5rQXCyJyJ1
lFD/4ivgZ95pVaoV+WsjETZZd3pkvo2PQC0f/2momT+KwYAdwcPfwJH8S9FLBjKE BAy90+N7rePAm7hcDYatEiayQXmGQqEB/LPxk+xC4qV5CIwffWeyJ8c8BUkt2+HE
nQRlYRjiUUEMO7TZ9J7a8onyFxozVwH7IJMz/L2wEs0u8dPr3Rj3kpCbHD8tNCE4 WuUtqX1vdgsit5rVND0HLD7pxgB9UJT5K4rH+W66JuiZxDe6odt0H+wKoeXom2zO
BP5s1d+S18vSKNRBYY2z7t1eyBZ+9hu1vgWR7GsAcgwCv6YTfVT8VE9RBdkglwP2 Cx8zo+RZwauIgh37V53RaNt1tc/Zuyw1xNeoN2x/4w1j6oIeYc4J2Xnv/lMHWfL0
Me6G1Af5KMNyQq0GDaKT/pPlS3WCdjpkOHCpw+2HfSjPVDAvWbBkrB8xQrQp8kwg VeDqVfM25BjaU87HqmjtQBcqRfETECr1Ur8cpjlJF1G5/RxZTl3gzH37EqTOvDlU
mHMD9udGsfpUSQVoNxIjIeK9EfFEjgXA+53/BVuCbSL5bWQXnKCMba656z7UrWqo d6vBt+bTtlGq23r68f6vzAHeXh8T9MCfQknlUluepKcNqlYnxkXE0KRIwQoIrN4u
NqVdJ7c8N7/U9fxaUaagDoziBUsV+eT58eGFRZJJHkbDZvmRthYOQnR82KSQz2cx ea6PGik/L7phwOGkgFQcuMpPjCt3Q1ROqykx+XdUAU/K8EMYEcY7IssjuCSGApeI
Neo9z3mSVA8FVRnwNaSNZiHRRKoFY+6HfDOmP5PzAIrW1/TBVYR6+5gmqou3KPqY Mt9qHMLeCDTLppbLeYI6y6n3lC0hfub3RxDXF4N35VMblM2LM4T7wvIajt1v1rEa
1I8DKkVYqlRSve+GXeFIEkeiJ8N5BZ4WZw3EglWSrP+uG7zywJ1pWNja5WNKSzX4 u7aRR82HiYkzF90AjMIz7dTHrE97MuKUo4gEvvDeiaZvLA1RbdWurxk1ubrdRv+q
mXPdI6KxTL40V06SraUqAOhd8uqH4fEhaBJVCqtm9cdXar7dqAbkaX5RARDb/BNg 6kMwwNY1/+G6dK2VlxQFn5Ocmoc5uBUJOSRP4CH70rYgZUxymZMBS2xcGIlgXxQn
K4m8iDRkrFCO6JYMmwWJz+q/HxY5u71szxFKUiYREeP0udxapekx6IELMwnMrdUT WAijIC0EV9a/P9SXWhPZ2HrbT04DxrCd30JGEzzhZks4ho0HoZO3QzGkLobcgT1t
GCryJs0VJuRDsOxSyuGprz+UnhY/K7NXRmE6hIrXJQ5mjsHtyjd2vk+OzJY6mL7S /gwpWDzURopR7yZIuEHfasQJHgAk/poZUEOMWk8vBHvmySdlMQXNLvIXcHCRAYQa
vRZw5FUqRvFsXXLNq/+YtRZSSZChMX0BM42prcC61PIm8qiVLs2199hKWmJmBill klgNTsy32rhXLPBzLuX4jvCZmIgG97UijYhgM+9YDLOcWaJBeZStEyCu6f2gm+72
DZnTJzvm38EWBPkm5JGh4tJ9VN769kyhDtWKtZ4aEuykcPJor+Did+oYuMadKUCN 80UaSHg+R9OONEVEPuQ5+FEjOR5zWY9hb3TYUfNsRBrNaRffll3EXRG6oqdURBg4
0NAuKxXAUHc/TfnSxBZxRdHWZo9vyYhiIWNoy5724yWfBH+STgNy3c+Z/JeKXvVB hRjMXwLUYtFxUfMMLIgHPht2JH+vCY77rKoO0ju0BejUk982q8eWedve6m4GsjB7
YUM4J7ys2TEnTmcoR43MPrF2+bdDsgsItQjtLlBmRvRItdswFYkunuQRBYmXoNBb 87fkYYgExEAywtm8Eo6REwmxLC9h7a5w/Pi1NSnXNMF+cV4/aOYDQSi77FfOTWQk
2MTTxHSU4jyM5FUxBi9XAk0mnWgo/aK/FhfE73VxvVXwfwpEkomL/TFexGzfFx7d pslFRSNLPTjNunhmLKN4+k8Q5Kfx+PRm8gpFdA6e8zEnARgKPgtDojbW3mpnSVMn
70T8RWCYgFHOuoe+O04wo2qyvCZZittRQGlInNztDCQI6lqa8TSILVgIRMgvnrcR ELf3ywWWy7y+6uuTEEf0Lr3xBvtYjYVTwOgyllF3SMjnQhRrX0NuhtTaWWSuLBTG
P9BUixDlFfl8x4g0lacxZm9nN5XNgnI1RTiXNXeigIciRydyeAKoV3gxY54i5jOm w3B3JfH4/QLsHddvn4H/N/DEgivWBqg13K4ZvKCJX/EeQaOgHyJnOrq9etvMtZuf
VFUClFfQFz+nBStRQumqxMXKa433J1l8NENmZmkc+D2TeLt8kbgNN4Zg7zKiNRFt VdhPWOn6YmBwweM2iTOHYwLWQD7xfgQK5O80QF1NNoigfBxhsKICjVe5B+JN//l6
UvFEtqPxQSiFgLCjrMH2wLkq79EtP/Zfpok/1iGbKfT+/bhDFB0iWE0AdIAa0oiu QAwuyG+TaLnL8papg4ID276gX3jth3qN/BxykOLSXfDZt4+mcINsssBPJ+JBgN4i
1JDsSFmoMTtMHgywSvVxaDVE4/0C81D3foLERbc+dwo00+YyROrQ74+mNoFrY4vd uksj+yQeD35xpumn6V+vcjn2sqj4sSQWjmWItFmm/Dun1D0yPVHsKa6XGE2Cu//5
xcDKxgkcZeZXxsUlox0F26OVZ3B7krUQC7EbBBVvdimJk7S0WXTHfR5ENz7lp1C2 p31MEROWAuU3dzCxJXHSuwf6SnfWNDgvgSKMmmiby1kppBDGS0Jv/lXTEkJP99fI
2gRL8Pdj9I4VsOmGAfcNPV2J5RVdRwyL9dSxCPVQ4ECrBqHSPqGbQoT7aHX9b+6A 2m0wjgLZLhBbjagVohbU9pPgmVsNs3ShIi+ioeN4j5gjU1LECOPktLC7j2jmbq4K
LKCWUqC18NxrRr4dbSxcjkE4w+vPmENrDh+yR7zDgdWY03rGN/jT2CV1le69AAaq ad7Ic+bdG32mtFsAWyEiA98APhWVKniFshvoO7Nr1vcjo/nox6yy1o33BsPMrXBC
RTf5n+skzsWz+u09bW7b43gpwhh7YeSFKpogNZ8z2ujEr0fkrGsOWWba9z620Xls ksKp51LHFrSTtcRqsOygnK/wm8W6tAt4cgBvLMwQK+4pC69/CyYkjbLeAhzh6yJm
f/4dPKcNiJLOIOXT555xZSpsgzAtPO1g9QM+l8Q6PZjqAvGjbHsYMw5ao+iwL0qt LFHOuFMAo+7X5ZUnqPxtifrOgEpofPWRT+fDe9wqlLPWuFJCNQYmLIos+RNfGg2z
M93Uj47PxD4qqz4MwYQw8S/dtrUkvBDEoA2fVU/00Fb9XzrECDUffDxHEUmDIcJQ A5s1rayD2PLqkYlllPstVt+4ilSGY9PRRQ+kNeKrMk4TH6au6pR1cxuigiJvuthg
h/q7ZntcVp//Gy4DeEiqp63s6poWGdbDmccN3hWmzWHEI0HR7pNS/FHEzESCw9oh /k0EXy1qax+N2LfEesb27dvBNQsMxRxUMs8mHAAn6foRw9wo50a8ktvkt45mh675
PkZzOa76GmyDqbopneVUmtfCuBjahTjVSAv4YlAsqQMI5wUgV+bwlfB7Rm2v8X4R DySilTtWemFsyzAAYmddp9xcp6qn2k1ohQqbq3QzZT0iA908+BUjfBaMfXCnkfhX
cyka3F9xWxuC3/5vxuPyyxA1YZc/fzpOqafFCU3mGF2byOKCL0YNuoqUbQBtagHZ 03K7mvUDbgEsx7eBmgTcLVuv4idziYaHQCCTbR69JLWxZ8q+lPyDugLBGjqSf5rG
6rrmGqNjyVuUG15KLBF29sYlJTBYF7tAeyVx2vLJqzKPRMGL2Ph8wg8Rg58eqKgU E2HD+jU5lUteyZ3UDe3qJP8t26SBSlRZ0k36xLGx0Ud9e5TQv5AmbzdHpqIWrtVl
gUIlCGzxGoqK1fVlrvvRATHplO77s+W/dA0svfSeD3xrtEd5oF9oQeI78A71Vmrw HG33516XvLmU6HvoB119tkIhm8FgdBtdxptTjMyPrpW3H6JN2w0QTJZHvqU4jb8W
ZsMech54mketddbn9t2MID8rVWxTtX5xIAxnW5TBfO8DucsqbxsJNm7Edzue0C2L Amhblrl8OaTxF3wZg549gxZ1grUlIv5x/AOfwLsBzFy8CTNUFp+UpfF0hF+tl2I4
i7tDKM5ZSbkivh0C7G1w7cu9SAv7gHStu+3DKGlW7MmCfLSEGk34jRdTRUu/2KAh vmOWFgk8Nd4QE82+eH21A4U52WwFDLXcQlBwAWmv/XDUvXMarPnW8O/3+NBPzU/B
cbHxHj25mDC6ZPz54FX6iDA0epm0ILVXZa75gjlfq4o9ldjKbR6yueIuc2hy7H1b K9ZfbTzm97oh+4fkPb2XcKNUvbxlXKeSL3DLxRHezWSkSoRvxMI4WZtbZF/0EzXT
QFlmx415H5TGTpjSJdjXCqvbbwphOIqsN0Qh3ZqUdaboVGipZdlFv3FH/2uxAFKW XadjjkTE7SxNDHuOGgO+aXheKR19TAtaIFrIUZHh1lr4ITfBTl5aAnjNANK0oa3k
VMJ1CpFAWe2iLtQEgrxJ15xpsLx+zcFUfftR8vXNRwMcEffV7xQguTugGic5O0DB /l9jRCODVtVqD8PVTA6mLyY/bPCHlxT2qCxWyFmwvhYfs6YCufOYXDBq1fnj+XKo
m5Oopo6bB9wMU4tvDRosjnvMEkuwbSPLSA/8JeZFO1zCK8Pa2znYNEwHNxeHiTCT hqL6Elj5VBxLp3gan1N1kypx7gLbf57tZ1WTAE1auDpm4gLbe+C7/Q==
+oouXDqdcT9dnH4cg4GeHjVDZO0I9yZL/cMDUPtqN0XySXe8Zj7VxtpQmcePklV/ =or0t
RDoGKHxEVz2a16foONjtVfsoheFHLWAI47IOTFDHA/CSQLCmCqwpfZQIuX2oWRwc
aPN4t5Qkx5TllLzL6keXkDV43/yw0dnXBQQDQ/Z4DP5GShwahyFggA/XonKYb9F0
B+pz+NOOkZjcFrcFeMr4cMdffc2ACxDJZWH4BHcwM9WICqoefJHlUu65ZTBBlisJ
mwP4Xapx8khsln2xXDUfhsoXu5+FHBexyVP1OUmZZ+zO3UEXPa+OwpglqrYGMueE
iXEO2lCOi6HrQCd7cvONPEwLaqavojMhsP42ywirWK7J9XuCoaEWtZjlA/Sq2D2B
upK6WuFMr+eE5lhrp5LFCRMJoiiwJb/bA7sMdZhg6HjIZNoNkrCvdgvLScbKxHM8
4G82FAafs/fbel5mdUNEe3nOXhQX2KH1MkUhnKGv5hi9gsXLaJlQTZBFsjoT8MUX
XUNdEWQ/xtGjs7eNBn/MzpP3JeByrDG0u0Tbt2whOkwhKQt+odph7sMRxwtvvniu
ij9nA3OlSGpTEItmC1jls29sJy5/0Ojp6Y3v/ZBfG6xh0xhhjpZIoOGQoK1wdG4m
m0j6TZqRKwX9FqQ9aCVY65lp/MsdXehe6/EShyT4K56KuGbpDuzoeZRshDPOvcjU
A1t44vBp3aYH9gE6QfM/dg8akN+LXOM7komveAbFvcvE8KFVdfHOUJIjPyy+saX0
ZHWLrH/SU+vUuFUw9VSuEavar95l9pRyWCeV67DWN2+FY8HESlfltjwiswActvrt
uDeIdtd42y4yA5u3BFCGEAWgZm+aVkQxuMN4OynTHM3NGJ6NUOeL8cGMA02KE65v
8pg4o3sIjfmsD76srDx7hKIpIe+K4QpAIxxL21HPZuXhE3ksNHh3x5x7hjkvNAUi
z3xbaR03avMeSle1LvUH/A88Fn+/0ataHYiQiIM95RXvMdKAk6SNNsN7rp1RZNhV
X6cNTBz2uUVbAXMUgbbBc9O2AVMR0pbfAYBKHPm24b+tWMShG/DR9f/mFFdUznEX
9+ydjRh9Mh9ZYgzKXqA9SZ/4Zhqn2Mve3r3Rii4K2w6KUbxRHev7FpV/KGgYsMmw
bLjSgS/cwQ7Ky9yRM12EmoAcimy/7vpyPRBM1tWnPBKhZf1xq15UM/lf53OcBjxb
ezeETqSQc6flKtEAxRv6nWSuormgn6JbClMjhII3velUKyfPCe29HNtFQ3LWJu4R
WLMH7A2qx0cIuyOuoFXefWh/9C3fiO72hqI5yQ2x4dxtEutUNTmByxZxTxJD/tSN
BI3ZmHeysFpUVdfDdt3Nc/Jw3lQCuBk=
=sq5B
-----END PGP MESSAGE----- -----END PGP MESSAGE-----

View File

@ -2,8 +2,6 @@
{ {
site.net = { site.net = {
core.ospf.secret = "encrypted"; core.ospf.secret = "encrypted";
pub.wifi.ieee80211rKey = "2dc40abba46da9490ea0e00f93f18ce5";
c3d2.wifi.ieee80211rKey = "d1b1fa2461efc0df9e2d96579607b7f6";
}; };
site.hosts = { site.hosts = {
@ -45,6 +43,7 @@
ap40.password = "encrypted"; ap40.password = "encrypted";
ap41.password = "encrypted"; ap41.password = "encrypted";
ap42.password = "encrypted"; ap42.password = "encrypted";
ap43.password = "encrypted";
ap44.password = "encrypted"; ap44.password = "encrypted";
ap45.password = "encrypted"; ap45.password = "encrypted";
ap46.password = "encrypted"; ap46.password = "encrypted";
@ -61,30 +60,13 @@
ap57.password = "encrypted"; ap57.password = "encrypted";
ap58.password = "encrypted"; ap58.password = "encrypted";
ap59.password = "encrypted"; ap59.password = "encrypted";
ap60.password = "encrypted";
ap61.password = "encrypted";
ap63.password = "encrypted";
ap64.password = "encrypted";
ap65.password = "encrypted";
ap66.password = "encrypted";
ap67.password = "encrypted";
ap68.password = "encrypted";
ap69.password = "encrypted";
ap70.password = "encrypted";
ap71.password = "encrypted";
ap72.password = "encrypted";
ap73.password = "encrypted";
switch-a1.password = "encrypted"; switch-a1.password = "encrypted";
switch-b1.password = "encrypted"; switch-b1.password = "encrypted";
switch-b2.password = "encrypted"; switch-b2.password = "encrypted";
switch-b3.password = "encrypted";
switch-c1.password = "encrypted"; switch-c1.password = "encrypted";
switch-c3d2-main.password = "encrypted"; switch-c3d2-main.password = "encrypted";
switch-d1.password = "encrypted"; switch-d1.password = "encrypted";
switch-dach.password = "encrypted"; switch-dach.password = "encrypted";
switch-ds1.password = "encrypted";
switch-ds2.password = "encrypted";
switch-ds3.password = "encrypted";
upstream4.interfaces.up4-pppoe.upstream = { upstream4.interfaces.up4-pppoe.upstream = {
user = "encrypted"; user = "encrypted";
@ -97,75 +79,74 @@
privateKey = "encrypted"; privateKey = "encrypted";
publicKey = "encrypted"; publicKey = "encrypted";
}; };
flpk-gw.interfaces.up-flpk.wireguard = {
addresses = [ "fec0::1/64" "192.168.0.1/24" ]; yggdrasil.services.yggdrasil.keys = ''
endpoint = "0.0.0.1"; {
privateKey = "encrypted"; "PublicKey": "0000000000000000000000000000000000000000000000000000000000000000",
publicKey = "encrypted"; "PrivateKey": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
}; }
'';
ap1.wifi."platform/qca953x_wmac".ssids."uebergangsnetz".psk = "encrypted"; ap1.wifi."platform/qca953x_wmac".ssids."uebergangsnetz".psk = "encrypted";
ap10.wifi."platform/qca953x_wmac".ssids = { ap10.wifi."platform/qca953x_wmac".ssids = {
"iz-dresden.org".psk = "encrypted"; "iz-dresden.org".psk = "encrypted";
}; };
ap11.wifi."platform/ahb/18100000.wmac".ssids."braeunigkoschnik".psk = "encrypted"; ap11.wifi."platform/qca955x_wmac".ssids."braeunigkoschnik".psk = "encrypted";
ap12.wifi."platform/ar934x_wmac".ssids = { ap12.wifi."platform/ar934x_wmac".ssids = {
"IrèneMélix".psk = "encrypted"; "IrèneMélix".psk = "encrypted";
"paperheart".psk = "encrypted"; "paperheart".psk = "encrypted";
}; };
ap15.wifi."platform/ahb/18100000.wmac".ssids."etz250".psk = "encrypted"; ap15.wifi."platform/qca955x_wmac".ssids."etz250".psk = "encrypted";
ap17.wifi."platform/ahb/18100000.wmac".ssids = { ap17.wifi."platform/qca955x_wmac".ssids = {
"EDUB".psk = "encrypted"; "EDUB".psk = "encrypted";
"Zweitwohnsitz".psk = "encrypted"; "Zweitwohnsitz".psk = "encrypted";
"e-Stuetzpunkt".psk = "encrypted"; "e-Stuetzpunkt".psk = "encrypted";
}; };
ap18.wifi."platform/qca953x_wmac".ssids."Restaurierung Wolff/Kober".psk = "encrypted"; ap18.wifi."platform/qca953x_wmac".ssids."Restaurierung Wolff/Kober".psk = "encrypted";
ap19.wifi."platform/qca953x_wmac".ssids = { ap19.wifi."platform/qca953x_wmac".ssids = {
"Bockwurst".psk = "encrypted"; "Studio 01127".psk = "encrypted";
"Walter".psk = "encrypted"; "Walter".psk = "encrypted";
}; };
ap2.wifi = { ap2.wifi = {
"pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted"; "pci0000:01/0000:01:00.0".ssids."C3D2".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids = { "platform/qca955x_wmac".ssids."C3D2 legacy".psk = "encrypted";
"C3D2 legacy".psk = "encrypted";
"C3D2 IoT".psk = "encrypted";
}; };
ap21.wifi = {
"pci0000:00/0000:00:00.0".ssids."ZW stage".psk = "encrypted";
"platform/qca956x_wmac".ssids."ZW stage legacy".psk = "encrypted";
}; };
ap23.wifi = { ap23.wifi = {
"pci0000:00/0000:00:00.0".ssids."LBK Network".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."LBK Network".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."LBK Network".psk = "encrypted"; "platform/qca956x_wmac".ssids."LBK Network".psk = "encrypted";
}; };
ap24.wifi."platform/ar933x_wmac".ssids."farbwerk".psk = "encrypted"; ap24.wifi."platform/ar933x_wmac".ssids."farbwerk".psk = "encrypted";
ap25.wifi."platform/ar933x_wmac".ssids."farbwerk".psk = "encrypted"; ap25.wifi."platform/ar933x_wmac".ssids."farbwerk".psk = "encrypted";
ap26.wifi."pci0000:00/0000:00:00.0".ssids."Dezember".psk = "encrypted"; ap26.wifi."pci0000:00/0000:00:00.0".ssids."Dezember".psk = "encrypted";
ap29.wifi = { ap29.wifi = {
"pci0000:00/0000:00:00.0".ssids."jungnickel-fotografie".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."jungnickel-fotografie".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."jungnickel-fotografie".psk = "encrypted"; "platform/qca956x_wmac".ssids."jungnickel-fotografie".psk = "encrypted";
}; };
ap3.wifi = { ap3.wifi = {
"pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted";
"platform/ar934x_wmac".ssids."C3D2 legacy".psk = "encrypted"; "platform/ar934x_wmac".ssids."C3D2 legacy".psk = "encrypted";
}; };
ap30.wifi."platform/ahb/18100000.wmac".ssids."WLANb0402".psk = "encrypted"; ap30.wifi."platform/qca956x_wmac".ssids."WLANb0402".psk = "encrypted";
ap31.wifi = { ap31.wifi = {
"pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids = { "platform/qca956x_wmac".ssids = {
"C3D2 legacy" = { "psk" = "encrypted"; }; "C3D2 legacy" = { "psk" = "encrypted"; };
"C3D2 IoT" = { "psk" = "encrypted"; };
"FOTOAKADEMIEdd" = { "psk" = "encrypted"; }; "FOTOAKADEMIEdd" = { "psk" = "encrypted"; };
}; };
}; };
ap32.wifi = { ap32.wifi = {
"pci0000:00/0000:00:00.0".ssids."ZW stage".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."ZW stage".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."ZW stage legacy".psk = "encrypted"; "platform/qca956x_wmac".ssids."ZW stage legacy".psk = "encrypted";
}; };
ap33.wifi = { ap33.wifi = {
"pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."C3D2 legacy".psk = "encrypted"; "platform/qca956x_wmac".ssids."C3D2 legacy".psk = "encrypted";
}; };
ap34.wifi."pci0000:00/0000:00:00.0".ssids."etz250".psk = "encrypted"; ap35.wifi."platform/qca956x_wmac".ssids."Koch".psk = "encrypted";
ap34.wifi."platform/ahb/18100000.wmac".ssids."etz250".psk = "encrypted";
ap35.wifi."platform/ahb/18100000.wmac".ssids."Koch".psk = "encrypted";
ap36.wifi."platform/ar933x_wmac".ssids."C3D2 legacy".psk = "encrypted"; ap36.wifi."platform/ar933x_wmac".ssids."C3D2 legacy".psk = "encrypted";
ap37.wifi = { ap37.wifi = {
"pci0000:00/0000:00:00.0".ssids."hechtfilm.de".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."hechtfilm.de".psk = "encrypted";
@ -176,26 +157,26 @@
"ZW heinrichsgarten" = { "psk" = "encrypted"; }; "ZW heinrichsgarten" = { "psk" = "encrypted"; };
"plop" = { "psk" = "encrypted"; }; "plop" = { "psk" = "encrypted"; };
}; };
"platform/ahb/18100000.wmac".ssids = { "platform/qca956x_wmac".ssids = {
"ZW heinrichsgarten" = { "psk" = "encrypted"; }; "ZW heinrichsgarten" = { "psk" = "encrypted"; };
"plop" = { "psk" = "encrypted"; }; "plop" = { "psk" = "encrypted"; };
"millimeter" = { "psk" = "encrypted"; };
}; };
}; };
ap39.wifi."platform/10180000.wmac".ssids."EckiTino".psk = "encrypted"; ap39.wifi."platform/10180000.wmac".ssids."EckiTino".psk = "encrypted";
ap4.wifi."platform/ahb/18100000.wmac".ssids."jam-circle.de".psk = "encrypted"; ap4.wifi."platform/qca955x_wmac".ssids."jam-circle.de".psk = "encrypted";
ap40.wifi = { ap40.wifi = {
"pci0000:00/0000:00:00.0".ssids."M".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."M".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."M legacy".psk = "encrypted"; "platform/qca956x_wmac".ssids."M legacy".psk = "encrypted";
}; };
ap41.wifi = { ap41.wifi = {
"pci0000:00/0000:00:00.0".ssids."Walter".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."Walter".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."Walter".psk = "encrypted"; "platform/qca956x_wmac".ssids."Walter".psk = "encrypted";
}; };
ap42.wifi = { ap42.wifi = {
"pci0000:00/0000:00:00.0".ssids."jam-circle.de".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."jam-circle.de".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."jam-circle.de legacy".psk = "encrypted"; "platform/qca956x_wmac".ssids."jam-circle.de legacy".psk = "encrypted";
}; };
ap43.wifi."platform/qca955x_wmac".ssids."Kaffeetasse".psk = "encrypted";
ap44.wifi = { ap44.wifi = {
"1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids."ZW stage legacy".psk = "encrypted"; "1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids."ZW stage legacy".psk = "encrypted";
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted"; "1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted";
@ -226,7 +207,7 @@
"1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids."ZW stage legacy".psk = "encrypted"; "1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids."ZW stage legacy".psk = "encrypted";
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted"; "1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted";
}; };
ap5.wifi."platform/ahb/18100000.wmac".ssids."verbalwerk.de".psk = "encrypted"; ap5.wifi."platform/qca955x_wmac".ssids."verbalwerk.de".psk = "encrypted";
ap50.wifi = { ap50.wifi = {
"1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids = { "1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids = {
"ZW stage legacy".psk = "encrypted"; "ZW stage legacy".psk = "encrypted";
@ -236,7 +217,7 @@
}; };
ap51.wifi = { ap51.wifi = {
"pci0000:01/0000:01:00.0".ssids."antrares".psk = "encrypted"; "pci0000:01/0000:01:00.0".ssids."antrares".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."antrares".psk = "encrypted"; "platform/qca955x_wmac".ssids."antrares".psk = "encrypted";
}; };
ap52.wifi = { ap52.wifi = {
"1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids."ZW stage legacy".psk = "encrypted"; "1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids."ZW stage legacy".psk = "encrypted";
@ -245,15 +226,15 @@
ap53.wifi."platform/qca953x_wmac".ssids."Karen Koschnick".psk = "encrypted"; ap53.wifi."platform/qca953x_wmac".ssids."Karen Koschnick".psk = "encrypted";
ap54.wifi = { ap54.wifi = {
"pci0000:00/0000:00:00.0".ssids."Abyssinia".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."Abyssinia".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."Abyssinia".psk = "encrypted"; "platform/qca956x_wmac".ssids."Abyssinia".psk = "encrypted";
}; };
ap55.wifi = { ap55.wifi = {
"pci0000:00/0000:00:00.0".ssids."MagLAN".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."MagLAN".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."MagLAN (legacy)".psk = "encrypted"; "platform/qca956x_wmac".ssids."MagLAN (legacy)".psk = "encrypted";
}; };
ap56.wifi = { ap56.wifi = {
"pci0000:00/0000:00:00.0".ssids."MagLAN".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."MagLAN".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."MagLAN (legacy)".psk = "encrypted"; "platform/qca956x_wmac".ssids."MagLAN (legacy)".psk = "encrypted";
}; };
ap57.wifi = { ap57.wifi = {
"pci0000:00/0000:00:00.0".ssids."Zentralwerk".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."Zentralwerk".psk = "encrypted";
@ -266,61 +247,7 @@
"pci0000:00/0000:00:00.0".ssids."Ebs 5000".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."Ebs 5000".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."Ebs 2000".psk = "encrypted"; "platform/ahb/18100000.wmac".ssids."Ebs 2000".psk = "encrypted";
}; };
ap60.wifi = {
"pci0000:00/0000:00:00.0".ssids."Abyssinia".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."Abyssinia".psk = "encrypted";
};
ap61.wifi = {
"pci0000:00/0000:00:00.0".ssids."tomiru".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."tomiru".psk = "encrypted";
};
ap62.wifi = {
"pci0000:00/0000:00:00.0".ssids."Wolke7".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."Wolke7 legacy".psk = "encrypted";
};
ap63.wifi = {
"pci0000:00/0000:00:00.0".ssids."EckiTino".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."EckiTino legacy".psk = "encrypted";
};
ap64.wifi = {
"platform/ahb/18100000.wmac".ssids."Princess Castle".psk = "encrypted";
};
ap65.wifi = {
"1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids = {
"farbwerk".psk = "encrypted";
"Kaffeetasse".psk = "encrypted";
};
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids."farbwerk".psk = "encrypted";
};
ap66.wifi = {
"pci0000:00/0000:00:00.0".ssids."Buschfunk4.03".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."Buschfunk4.03 legacy".psk = "encrypted";
};
ap67.wifi = {
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids."farbwerk".psk = "encrypted";
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0+1".ssids."farbwerk".psk = "encrypted";
};
ap68.wifi = {
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids."farbwerk".psk = "encrypted";
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0+1".ssids."farbwerk".psk = "encrypted";
};
ap69.wifi = {
"pci0000:00/0000:00:00.0".ssids."LIZA".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."LIZA".psk = "encrypted";
};
ap7.wifi."platform/qca953x_wmac".ssids."mino".psk = "encrypted"; ap7.wifi."platform/qca953x_wmac".ssids."mino".psk = "encrypted";
ap70.wifi = {
"pci0000:00/0000:00:00.0".ssids."M".psk = "encrypted";
"platform/ahb/18100000.wmac".ssids."M legacy".psk = "encrypted";
};
ap72.wifi = {
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids."farbwerk".psk = "encrypted";
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0+1".ssids."farbwerk".psk = "encrypted";
};
ap73.wifi = {
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids."Princess Castle".psk = "encrypted";
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0+1".ssids."Princess Castle".psk = "encrypted";
};
ap8.wifi = { ap8.wifi = {
"pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted"; "pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted";
"platform/ar934x_wmac".ssids = { "platform/ar934x_wmac".ssids = {
@ -331,18 +258,5 @@
ap9.wifi."platform/qca953x_wmac".ssids."Herzzbuehne".psk = "encrypted"; ap9.wifi."platform/qca953x_wmac".ssids."Herzzbuehne".psk = "encrypted";
}; };
site.dyndnsKey = "oYmxXCIa0nArp0679L6v+y/UfnhripOudLv+R5Cop8I="; site.dyndnsKey = "SECRET";
site.vpn.wireguard = {
privateKey = "wPNXY4ED3Jz3Kz0KOmvfQOou6/wHrgqSsykaMYrtb28=";
peers = [ {
# privateKey: GOdfeizQZjPmyYnh3LMI3LrYeEtqYMyOvK8KASVgI1Q=
publicKey = "4aTjdm/APMTERczvtnLXRFYjSWYsmwPFTumjyno4nx4=";
allowedIPs = [
"172.20.76.226"
"fd23:42:c3d2:585::/64"
"2a00:8180:2c00:285::/64"
];
} ];
};
} }

View File

@ -14,7 +14,7 @@ let
) )
) {} (builtins.attrValues containers); ) {} (builtins.attrValues containers);
makeServer = _name: { makeServer = name: {
role = "server"; role = "server";
model = "pc"; model = "pc";
interfaces = bridgeInterfaces // { interfaces = bridgeInterfaces // {

View File

@ -8,30 +8,10 @@
links = { links = {
switch-a2.ports = [ "7" ]; switch-a2.ports = [ "7" ];
priv25.ports = [ priv25.ports = [ "2" "3" "4" "5" ];
# A6: Kleiner Saal Schaltschrank priv31.ports = [ "6" ];
"1" pub.ports = [ "8" ];
# Kabinett A10 iso4.ports = [ "1" ];
"2"
"3"
# A16: Buehne rechts unten
"4"
# artnet node
"5"
# Panel A2: Foyer
"8"
# Panel A8: Kleiner Saal Buehne
];
priv31.ports = [
# A4: Buero
"6"
];
# A3: Techniklager
# (DS23: Hackcenter vor kleinem Saal)
# A17: Grosser Saal ueber der Buehne
# switch-a2 Port 13
# Panel A6: kl Saal hinten
}; };
}; };
switch-a2 = { switch-a2 = {
@ -42,9 +22,6 @@
links = { links = {
switch-c1.ports = [ "1" ]; switch-c1.ports = [ "1" ];
switch-a1.ports = [ "2" ]; switch-a1.ports = [ "2" ];
switch-ds1.ports = [ "3" ];
switch-ds2.ports = [ "4" ];
switch-ds3.ports = [ "5" ];
ap44.ports = [ "10" ]; ap44.ports = [ "10" ];
ap45.ports = [ "11" ]; ap45.ports = [ "11" ];
ap46.ports = [ "12" ]; ap46.ports = [ "12" ];
@ -56,9 +33,9 @@
}; };
}; };
switch-b3 = { switch-b1 = {
role = "switch"; role = "switch";
model = "junos"; model = "linksys-srw2048";
location = "Haus B Souterrain"; location = "Haus B Souterrain";
interfaces = { mgmt.type = "phys"; }; interfaces = { mgmt.type = "phys"; };
@ -68,144 +45,127 @@
# Ports 21-24 unten seitlich (optional optisch) # Ports 21-24 unten seitlich (optional optisch)
# Port 7 geht aktuell nach Turm C Erdgeschoss und dadurch zur Ecce # Port 7 geht aktuell nach Turm C Erdgeschoss und dadurch zur Ecce
links = { links = {
ap23.ports = [ "ge-0/0/10" ]; ap23.ports = [ "g10" ];
ap8.ports = [ "ge-0/0/16" ]; ap8.ports = [ "g16" ];
iso1.ports = [ "ge-0/0/2" ]; c3d2.ports = [ "g23" ];
iso2.ports = [ "ge-0/0/3" ]; iso1.ports = [ "g2" ];
iso3.ports = [ "ge-0/0/4" ]; iso2.ports = [ "g3" ];
coloradio.ports = [ iso3.ports = [ "g4" ];
# Patchpanel C8 mgmt.ports = [ "g1" ];
"ge-0/0/22" serv.ports = [ "g22" ];
]; # server1 had g46,g47,g48 too but this switch has too few
c3d2.ports = [ # port-channel groups
"ge-0/0/5" server1.ports = [ "g24" ];
"ge-0/0/8"
# riscbert
"ge-0/0/13"
];
server1 = {
group = "3";
ports = [
"ge-0/0/24"
"ge-0/0/25"
"ge-1/0/24"
"ge-1/0/25"
];
};
server2 = { server2 = {
group = "1"; group = "1";
ports = [ ports = [ "g12" "g38" "g39" "g40" ];
"ge-0/0/38" "ge-0/0/39"
"ge-1/0/32" "ge-1/0/33"
];
}; };
hydra = { server5 = {
group = "6";
ports = [ "g17" "g18" "g19" "g20" ];
};
server6 = {
group = "8";
ports = [ "g5" "g6" "g7" "g8" ];
};
server7 = {
group = "7"; group = "7";
trunk = false; ports = [ "g9" "g11" "g14" "g15" ];
ports = [
"ge-0/0/14" "ge-0/0/15"
"ge-1/0/14" "ge-1/0/15"
];
}; };
server10 = { server8 = {
group = "5"; group = "5";
ports = [ ports = [ "g35" "g36" "g37" "g13" ];
"ge-0/0/36" "ge-0/0/37" };
"ge-1/0/36" "ge-1/0/37" switch-b2 = {
]; group = "3";
ports = [ "g25" "g26" "g27" "g28" ];
}; };
switch-c1 = { switch-c1 = {
group = "2"; group = "2";
ports = [ "ge-0/0/30" "ge-0/0/31" "ge-1/0/30" "ge-1/0/31" ]; ports = [ "g29" "g30" "g31" "g32" ];
}; };
switch-c3d2-main = { switch-c3d2-main = {
group = "4"; group = "4";
ports = [ ports = [ "g41" "g42" "g43" "g44" ];
"ge-0/0/26"
"ge-0/0/27"
"ge-1/0/26"
"ge-1/0/27"
];
}; };
switch-d1.ports = [ "ge-0/0/34" ]; switch-d1.ports = [ "g34" ];
};
};
switch-b2 = {
role = "switch";
model = "3com-4200G";
location = "Haus B Souterrain";
interfaces = { mgmt.type = "phys"; };
ap1.ports = [ "ge-1/0/8" ]; links = {
ap11.ports = [ "ge-1/0/10" ]; ap1.ports = [ "GigabitEthernet 1/0/8" ];
ap34.ports = [ "ge-1/0/12" ]; ap11.ports = [ "GigabitEthernet 1/0/10" ];
ap18.ports = [ "ge-1/0/18" ]; ap15.ports = [ "GigabitEthernet 1/0/12" ];
ap29.ports = [ "ge-0/0/46" ]; ap18.ports = [ "GigabitEthernet 1/0/18" ];
ap30.ports = [ "ge-1/0/22" ]; ap24.ports = [ "GigabitEthernet 1/0/34" ];
ap35.ports = [ "ge-1/0/23" ]; ap25.ports = [ "GigabitEthernet 1/0/35" ];
ap37.ports = [ "ge-1/0/39" ]; ap29.ports = [ "GigabitEthernet 1/0/36" ];
ap63.ports = [ "ge-1/0/17" ]; ap30.ports = [ "GigabitEthernet 1/0/22" ];
ap40.ports = [ "ge-1/0/21" ]; ap35.ports = [ "GigabitEthernet 1/0/23" ];
ap41.ports = [ "ge-0/0/47" ]; ap37.ports = [ "GigabitEthernet 1/0/39" ];
ap42.ports = [ "ge-1/0/6" ]; ap39.ports = [ "GigabitEthernet 1/0/17" ];
ap5.ports = [ "ge-1/0/7" ]; ap40.ports = [ "GigabitEthernet 1/0/21" ];
ap51.ports = [ "ge-1/0/13" ]; ap41.ports = [ "GigabitEthernet 1/0/37" ];
ap53.ports = [ "ge-0/0/7" ]; ap42.ports = [ "GigabitEthernet 1/0/6" ];
ap72.ports = [ "ge-1/0/38" ]; ap5.ports = [ "GigabitEthernet 1/0/7" ];
ap55.ports = [ "ge-1/0/19" ]; ap51.ports = [ "GigabitEthernet 1/0/13" ];
ap56.ports = [ "ge-1/0/9" ]; ap53.ports = [ "GigabitEthernet 1/0/15" ];
ap60.ports = [ "ge-1/0/20" ]; ap54.ports = [ "GigabitEthernet 1/0/38" ];
ap62.ports = [ "ge-0/0/11" ]; ap55.ports = [ "GigabitEthernet 1/0/19" ];
ap65.ports = [ "ge-0/0/9" ]; ap56.ports = [ "GigabitEthernet 1/0/9" ];
ap66.ports = [ "ge-1/0/43" ];
mgmt.ports = [ mgmt.ports = [
"ge-0/0/0" "GigabitEthernet1/0/1"
"ge-0/0/1" # server3
"ge-1/0/44" "GigabitEthernet1/0/41"
# server1
"GigabitEthernet1/0/42"
"GigabitEthernet1/0/43"
# server5
"GigabitEthernet1/0/44"
# server6
"GigabitEthernet1/0/45"
# server7 # server7
"ge-1/0/45" "GigabitEthernet1/0/46"
"ge-1/0/46"
# server8 # server8
"ge-1/0/47" "GigabitEthernet1/0/47"
# server9 # server9
"ge-1/0/48" "GigabitEthernet1/0/48"
]; ];
flpk.ports = [ priv1.ports = [ "GigabitEthernet 1/0/3" ];
# server7 priv19.ports = [ "GigabitEthernet 1/0/40" ];
"ge-0/0/40" priv2.ports = [ "GigabitEthernet 1/0/4" ];
]; priv24.ports = [ "GigabitEthernet 1/0/14" "GigabitEthernet 1/0/16" ];
priv1.ports = [ "ge-1/0/3" ]; priv3.ports = [ "GigabitEthernet 1/0/5" ];
priv19.ports = [ "ge-1/0/40" ];
priv2.ports = [ "ge-1/0/4" ];
priv24.ports = [ "ge-0/0/6" "ge-1/0/16" ];
priv3.ports = [ "ge-1/0/5" ];
priv30.ports = [ "ge-0/0/12" ];
priv49.ports = [ "ge-1/0/1" ];
ap67.ports = [ "ge-1/0/34" ];
ap68.ports = [ "ge-1/0/35" ];
ap69.ports = [ "ge-0/0/35" ];
ap73.ports = [ "ge-0/0/45" ];
pub.ports = [ pub.ports = [
"ge-1/0/11" "GigabitEthernet 1/0/11"
"GigabitEthernet 1/0/20"
"GigabitEthernet 1/0/24"
]; ];
server3 = {
group = "1";
ports = [ "GigabitEthernet1/0/30" "GigabitEthernet1/0/31" ];
};
server9 = { server9 = {
group = "10"; group = "3";
ports = [ ports = [
"ge-0/0/28" "GigabitEthernet1/0/2"
"ge-0/0/29" "GigabitEthernet1/0/29"
"ge-1/0/28" "GigabitEthernet1/0/32"
"ge-1/0/29"
]; ];
}; };
server8 = { switch-b1 = {
group = "6"; group = "2";
ports = [ ports = [
"ge-0/0/41" "TenGigabitEthernet 1/1/1"
"ge-0/0/42" "GigabitEthernet 1/0/25"
"ge-1/0/41" "GigabitEthernet 1/0/26"
"ge-1/0/42" "GigabitEthernet 1/0/27"
]; "GigabitEthernet 1/0/28"
};
server6 = {
group = "9";
ports = [
"ge-0/0/18"
"ge-0/0/19"
"ge-1/0/0"
"ge-1/0/2"
]; ];
}; };
}; };
@ -223,7 +183,7 @@
group = "1"; group = "1";
ports = [ "15-16" ]; ports = [ "15-16" ];
}; };
switch-b3 = { switch-b1 = {
group = "2"; group = "2";
ports = [ "21-24" ]; ports = [ "21-24" ];
}; };
@ -238,15 +198,13 @@
ap19.ports = [ "17" ]; ap19.ports = [ "17" ];
ap26.ports = [ "18" ]; ap26.ports = [ "18" ];
ap38.ports = [ "7" ]; ap38.ports = [ "7" ];
ap61.ports = [ "13" ];
# Iso nets # Iso nets
iso1.ports = [ "9" ]; iso1.ports = [ "9" ];
iso2.ports = [ "10" ]; iso2.ports = [ "10" ];
iso3.ports = [ "11" ]; iso3.ports = [ "11" ];
iso4.ports = [ "12" ]; iso4.ports = [ "12" ];
iso5.ports = [ "13" ];
iso6.ports = [ "14" ]; iso6.ports = [ "14" ];
# Saal Foyer
priv25.ports = [ "20" ];
}; };
}; };
@ -258,7 +216,7 @@
links = { links = {
mgmt.ports = [ "1" ]; mgmt.ports = [ "1" ];
switch-b3 = { switch-b1 = {
group = "1"; group = "1";
ports = [ "21-24" ]; ports = [ "21-24" ];
}; };
@ -269,8 +227,11 @@
# Fenster # Fenster
ap33.ports = [ "5" ]; ap33.ports = [ "5" ];
c3d2.ports = [ "8-20" ]; c3d2.ports = [ "8-20" ];
# Testing
ap-test1.ports = [ "4" ];
bmx.ports = [ "7" ];
# tmp Datenspuren: VOC # tmp Datenspuren: VOC
iso4.ports = [ "4" "6" "7" ]; iso4.ports = [ "6" ];
}; };
}; };
@ -281,7 +242,7 @@
interfaces = { mgmt.type = "phys"; }; interfaces = { mgmt.type = "phys"; };
links = { links = {
switch-b3 = { switch-b1 = {
group = "1"; group = "1";
ports = [ "1" ]; ports = [ "1" ];
}; };
@ -304,7 +265,7 @@
links = { links = {
switch-d1 = { switch-d1 = {
group = "1"; group = "1";
ports = [ "12" ]; ports = [ "1" ];
}; };
ap3.ports = [ "1" ]; ap3.ports = [ "1" ];
ap59.ports = [ "2" ]; ap59.ports = [ "2" ];
@ -328,142 +289,8 @@
up3.ports = [ "3" ]; up3.ports = [ "3" ];
# unifiac-mesh # unifiac-mesh
ap57.ports = [ "10" ]; ap57.ports = [ "10" ];
# TLMS tetra and traffic-stop-box
c3d2.ports = [ "19,20" ];
};
};
switch-ds1 = {
role = "switch";
model = "3com-5500G";
location = "Foyer";
interfaces = { mgmt.type = "phys"; };
links = {
# Public
pub.ports = [
"GigabitEthernet1/0/1"
"GigabitEthernet1/0/2"
"GigabitEthernet1/0/3"
"GigabitEthernet1/0/4"
"GigabitEthernet1/0/5"
"GigabitEthernet1/0/6"
"GigabitEthernet1/0/7"
"GigabitEthernet1/0/8"
"GigabitEthernet1/0/9"
"GigabitEthernet1/0/10"
"GigabitEthernet1/0/11"
"GigabitEthernet1/0/12"
"GigabitEthernet1/0/13"
"GigabitEthernet1/0/14"
"GigabitEthernet1/0/15"
];
# Stage uplink
priv25.ports = [
"GigabitEthernet1/0/16"
"GigabitEthernet1/0/17"
"GigabitEthernet1/0/18"
"GigabitEthernet1/0/19"
];
# Freifunk
bmx.ports = [
"GigabitEthernet1/0/20"
"GigabitEthernet1/0/21"
"GigabitEthernet1/0/22"
"GigabitEthernet1/0/23"
];
# Uplink
switch-a2.ports = [ "GigabitEthernet1/0/24" ];
};
};
switch-ds2 = {
role = "switch";
model = "3com-5500G";
location = "Grosser Saal oben";
interfaces = { mgmt.type = "phys"; };
links = {
# Public
pub.ports = [
"GigabitEthernet1/0/1"
"GigabitEthernet1/0/2"
"GigabitEthernet1/0/3"
"GigabitEthernet1/0/4"
"GigabitEthernet1/0/5"
"GigabitEthernet1/0/6"
"GigabitEthernet1/0/7"
"GigabitEthernet1/0/8"
"GigabitEthernet1/0/9"
"GigabitEthernet1/0/10"
"GigabitEthernet1/0/11"
"GigabitEthernet1/0/12"
"GigabitEthernet1/0/13"
"GigabitEthernet1/0/14"
"GigabitEthernet1/0/15"
"GigabitEthernet1/0/16"
"GigabitEthernet1/0/17"
"GigabitEthernet1/0/18"
"GigabitEthernet1/0/19"
];
# Stage uplink
priv25.ports = [
"GigabitEthernet1/0/20"
"GigabitEthernet1/0/21"
];
# VOC isolated
iso4.ports = [
"GigabitEthernet1/0/22"
"GigabitEthernet1/0/23"
];
# Uplink
switch-a2.ports = [ "GigabitEthernet1/0/24" ];
};
};
switch-ds3 = {
firstboot = true;
role = "switch";
model = "3com-5500G";
location = "Kleiner Saal";
interfaces = { mgmt.type = "phys"; };
links = {
# Public
pub.ports = [
"GigabitEthernet1/0/1"
"GigabitEthernet1/0/2"
"GigabitEthernet1/0/3"
"GigabitEthernet1/0/4"
"GigabitEthernet1/0/5"
"GigabitEthernet1/0/6"
"GigabitEthernet1/0/7"
"GigabitEthernet1/0/8"
"GigabitEthernet1/0/9"
"GigabitEthernet1/0/10"
"GigabitEthernet1/0/11"
"GigabitEthernet1/0/12"
"GigabitEthernet1/0/13"
"GigabitEthernet1/0/14"
"GigabitEthernet1/0/15"
"GigabitEthernet1/0/16"
"GigabitEthernet1/0/17"
"GigabitEthernet1/0/18"
"GigabitEthernet1/0/19"
];
# Stage uplink
priv25.ports = [
"GigabitEthernet1/0/20"
"GigabitEthernet1/0/21"
];
# VOC isolated
iso4.ports = [
"GigabitEthernet1/0/22"
"GigabitEthernet1/0/23"
];
# Uplink
switch-a2.ports = [ "GigabitEthernet1/0/24" ];
}; };
}; };
}; };
} }

View File

@ -18,15 +18,11 @@ in
c3d2 = 5; c3d2 = 5;
cluster = 6; cluster = 6;
bmx = 7; bmx = 7;
flpk = 8;
coloradio = 9;
# Modems # Modems
up1 = 10; up1 = 10;
up2 = 11; up2 = 11;
up3 = 12; up3 = 12;
up4 = 13; up4 = 13;
# Isolated other stuff
c3d2iot = 20;
# Isolated neighbors directly connectied with their modems # Isolated neighbors directly connectied with their modems
iso1 = 101; iso1 = 101;
iso2 = 102; iso2 = 102;

Binary file not shown.

View File

@ -55,14 +55,10 @@ Von geeigneten Routern haben wir stets zu wenige übrig, so dass wir sie
gemeinsam kaufen und bezahlen müssen. Such dir einen aus, dann gemeinsam kaufen und bezahlen müssen. Such dir einen aus, dann
bestellen und konfigurieren wir ihn. bestellen und konfigurieren wir ihn.
* Zyxel WSM20 (Multy M1) ([25€](https://geizhals.de/zyxel-multy-m1-v101058.html))
* TP-Link Archer C7 v2 ([58€](http://geizhals.de/tp-link-archer-c7-v2-a923544.html)) * TP-Link Archer C7 v2 ([58€](http://geizhals.de/tp-link-archer-c7-v2-a923544.html))
* Ubiquiti UniFi nanoHD ([150€](https://geizhals.de/ubiquiti-unifi-nanohd-uap-nanohd-a1802819.html))
* [Jedes Gerät auf dem OpenWRT läuft](https://openwrt.org/supported_devices) * [Jedes Gerät auf dem OpenWRT läuft](https://openwrt.org/supported_devices)
Die genannten Preise sind unverbindlich und schwanken stark mit den
Situationen rund um die Straße von Malaka, Rotem Meer und
Suez-Kanal. Auf eBay gibts gebrauchte Geräte.
![WLAN-Router](https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Linksys-Wireless-G-Router.jpg/280px-Linksys-Wireless-G-Router.jpg) ![WLAN-Router](https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Linksys-Wireless-G-Router.jpg/280px-Linksys-Wireless-G-Router.jpg)
### Netzverteilung ### Netzverteilung
@ -158,8 +154,11 @@ mitbenutzen indem wir dir ein [VLAN](https://de.wikipedia.org/wiki/VLAN)
konfigurieren, welches nur dein Kabelmodem und deine Datendose bekommen. konfigurieren, welches nur dein Kabelmodem und deine Datendose bekommen.
--- # Sprechstunden
Dienstags und Donnerstags 16:00-18:00 Uhr
[C3D2](https://www.c3d2.de/space.html), Haus B Souterrain, genau in der Mitte [C3D2](https://www.c3d2.de/space.html), Haus B Souterrain, genau in der Mitte
![Kernnetz visualisiert von eri!](core.png) ![Kernnetz visualisiert von eri!](core.png)

View File

@ -1,16 +0,0 @@
# Wireguard VPN Dialin
## wg-quick template
```ini
[Interface]
Address = 172.20.76.TODO/28
Address = fd23:42:c3d2:585::TODO/64
Address = 2a00:8180:2c00:285::TODO/64
PrivateKey = TODO
[Peer]
PublicKey = PG2VD0EB+Oi+U5/uVMUdO5MFzn59fAck6hz8GUyLMRo=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = upstream4.dyn.zentralwerk.org:1337
```

View File

@ -1,53 +1,32 @@
{ {
"nodes": { "nodes": {
"dns-nix": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1703643450,
"narHash": "sha256-EUUF5oxFFPX/etKm0FNQg+7MPHQlNjmM1XhNgyDf7A0=",
"owner": "SuperSandro2000",
"repo": "dns.nix",
"rev": "70dcce71560d4253f63812fa36dee994c81ae814",
"type": "github"
},
"original": {
"owner": "SuperSandro2000",
"repo": "dns.nix",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1614513358,
"narHash": "sha256-LakhOx3S1dRjnh0b5Dg3mbZyH0ToC9I8Y2wKSkBaTzU=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5466c5bbece17adaab2d82fae80b46e807611bf3",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1717104653, "lastModified": 1641924320,
"narHash": "sha256-0ZkToL+IOOP3xw0JPgTj8WP8aeKwxNNiG3gr6prfnig=", "narHash": "sha256-DuOpJqoMmQ3Yk4C64QQHFaByhbSIi872He6z5BXY1YM=",
"owner": "SuperSandro2000", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "b15c037e83ebf28278abc1769df8792ea30a223f", "rev": "05f3de54d568dba52efaad966f0e09bfea796dcb",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "SuperSandro2000", "owner": "NixOS",
"ref": "nixos-24.05", "ref": "release-21.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-master": {
"locked": {
"lastModified": 1641927215,
"narHash": "sha256-96otEPy5y/4aeM6Sjl//Qr8v3+CdjTBNtnS4eKyoY0U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0fdbcb2355f0681908cc9fef0cc9138f938ae1a3",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@ -55,46 +34,25 @@
"openwrt": { "openwrt": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1713442482, "lastModified": 1641673875,
"narHash": "sha256-OAcv1qiM2V6wPQm4Tz2QnnDpw34pifG6QRDZea7AP9o=", "narHash": "sha256-Eb9tVxE9Pmob/xWZ6wRt95cTycPeyPkyyaaWaz6cWtA=",
"ref": "openwrt-23.05", "ref": "openwrt-21.02",
"rev": "9b33b74ef71225442361d5192d3a727be212c3cd", "rev": "6ced8cad8edd2a04fc6bb914c333c8aac9a1c825",
"revCount": 58296, "revCount": 50927,
"type": "git", "type": "git",
"url": "https://git.openwrt.org/openwrt/openwrt.git" "url": "https://git.openwrt.org/openwrt/openwrt.git"
}, },
"original": { "original": {
"ref": "openwrt-23.05", "ref": "openwrt-21.02",
"type": "git", "type": "git",
"url": "https://git.openwrt.org/openwrt/openwrt.git" "url": "https://git.openwrt.org/openwrt/openwrt.git"
} }
}, },
"openwrt-imagebuilder": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1713693953,
"narHash": "sha256-DsJ/pzBSF3CxQWyiw4V3k96h7Q3UaRnQnL1N9tw+uWg=",
"owner": "astro",
"repo": "nix-openwrt-imagebuilder",
"rev": "d4dc8c84f4397be494ae834709276f099df892e7",
"type": "github"
},
"original": {
"owner": "astro",
"repo": "nix-openwrt-imagebuilder",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"dns-nix": "dns-nix",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"openwrt": "openwrt", "nixpkgs-master": "nixpkgs-master",
"openwrt-imagebuilder": "openwrt-imagebuilder" "openwrt": "openwrt"
} }
} }
}, },

View File

@ -2,22 +2,13 @@
description = "Zentralwerk network"; description = "Zentralwerk network";
inputs = { inputs = {
dns-nix = { nixpkgs.url = "github:NixOS/nixpkgs/release-21.11";
url = "github:SuperSandro2000/dns.nix"; nixpkgs-master.url = "github:NixOS/nixpkgs";
inputs.nixpkgs.follows = "nixpkgs"; openwrt.url = "git+https://git.openwrt.org/openwrt/openwrt.git?ref=openwrt-21.02";
}; openwrt.flake = false;
nixpkgs.url = "github:SuperSandro2000/nixpkgs/nixos-24.05";
openwrt = {
url = "git+https://git.openwrt.org/openwrt/openwrt.git?ref=openwrt-23.05";
flake = false;
};
openwrt-imagebuilder = {
url = "github:astro/nix-openwrt-imagebuilder";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = inputs@{ self, dns-nix, nixpkgs, openwrt, openwrt-imagebuilder }: outputs = inputs@{ self, nixpkgs, nixpkgs-master, openwrt }:
let let
system = "x86_64-linux"; system = "x86_64-linux";
systems = [ system ]; systems = [ system ];
@ -27,23 +18,24 @@
self.lib.nixosSystem { self.lib.nixosSystem {
inherit system; inherit system;
modules = [ self.nixosModule ]; modules = [ self.nixosModule ];
specialArgs = { specialArgs.hostName = name;
hostName = name; specialArgs.lib = self.lib;
inherit (self) lib; specialArgs.self = self;
inherit inputs dns-nix self; specialArgs.inputs = inputs;
}; specialArgs.nixpkgs-master = nixpkgs-master;
}; };
in { in {
# Config, and utilities # Config, and utilities
lib = nixpkgs.lib.extend (_final: _prev: lib = nixpkgs.lib.extend (final: prev:
import ./nix/lib { import ./nix/lib {
inherit self openwrt; inherit self;
inherit (nixpkgs.legacyPackages.x86_64-linux) lib pkgs; inherit openwrt;
pkgs = nixpkgs.legacyPackages.x86_64-linux;
}); });
# Everything that can be built locally outside of NixOS # Everything that can be built locally outside of NixOS
packages = forAllSystems (system: packages = forAllSystems (system:
import ./nix/pkgs { inherit self nixpkgs system openwrt-imagebuilder; } import ./nix/pkgs { inherit self nixpkgs system; }
); );
# Configuration for nixosConfigurations # Configuration for nixosConfigurations
@ -76,10 +68,12 @@
'' ''
); );
wrappers = { wrappers = {
"all-device-scripts" = hydraJob; "all-device-scripts" = pkg:
hydraJob pkg;
"export-config" = exportFileWrapper; "export-config" = exportFileWrapper;
"switch-.*" = exportFileWrapper; "switch-.*" = exportFileWrapper;
"ap.*-image" = exportFileWrapper; "ap.*" = exportFileWrapper;
}; };
in in
builtins.mapAttrs (name: pkg: builtins.mapAttrs (name: pkg:

View File

@ -4,14 +4,14 @@
let let
result = pkgs.lib.evalModules { result = pkgs.lib.evalModules {
args = {
inherit self pkgs;
};
modules = [ modules = [
( (
{ lib, ... }: { lib, ... }:
with lib; with lib;
{ {
config._module.args = {
inherit self pkgs;
};
options.assertions = mkOption { options.assertions = mkOption {
type = with types; listOf unspecified; type = with types; listOf unspecified;
internal = true; internal = true;

View File

@ -158,11 +158,6 @@ let
type = with types; nullOr (submodule { options = dhcpOpts; }); type = with types; nullOr (submodule { options = dhcpOpts; });
default = null; default = null;
}; };
ipv6Router = mkOption {
description = "Who sends router advertisements?";
type = with types; nullOr str;
default = config.site.net.${name}.dhcp.router or null;
};
domainName = mkOption { domainName = mkOption {
description = "Domain name option"; description = "Domain name option";
type = types.str; type = types.str;
@ -178,7 +173,7 @@ let
type = enum [ "A" "AAAA" "MX" "SRV" "CNAME" "TXT" ]; type = enum [ "A" "AAAA" "MX" "SRV" "CNAME" "TXT" ];
}; };
data = mkOption { data = mkOption {
type = oneOf [ str (attrsOf (oneOf [ int str ])) ]; type = str;
}; };
}; };
}); });
@ -194,22 +189,6 @@ let
type = with types; nullOr int; type = with types; nullOr int;
default = null; default = null;
}; };
wifi.ieee80211rKey = mkOption {
type = with types; nullOr str;
default = null;
description = ''
Key between WiFi access points for Fast Transition
'';
};
captiveJson = mkOption {
type = with types; nullOr str;
default = null;
description = ''
Optional URL to Captive Portal JSON file.
See: <https://datatracker.ietf.org/doc/html/draft-ietf-capport-api>
'';
};
}; };
}; };
@ -230,11 +209,6 @@ let
type = with types; nullOr int; type = with types; nullOr int;
default = null; default = null;
}; };
noNat.subnets4 = mkOption {
type = with types; listOf str;
default = [];
description = "Do not NAT traffic from these public static subnets";
};
noNat.subnets6 = mkOption { noNat.subnets6 = mkOption {
type = with types; listOf str; type = with types; listOf str;
default = []; default = [];
@ -250,7 +224,7 @@ let
}; };
}; };
interfaceOpts = { ... }: { interfaceOpts = { name, ... }: {
options = { options = {
hwaddr = mkOption { hwaddr = mkOption {
type = with types; nullOr str; type = with types; nullOr str;
@ -369,8 +343,7 @@ let
# isRouter = Part of the core network? # isRouter = Part of the core network?
default = default =
config.site.hosts.${name}.interfaces ? core && config.site.hosts.${name}.interfaces ? core &&
config.site.net.core.hosts4 ? ${name} && config.site.net.core.hosts4 ? ${name};
config.site.hosts.${name}.role == "container";
description = "Should this host route?"; description = "Should this host route?";
}; };
firewall.enable = mkOption { firewall.enable = mkOption {
@ -421,11 +394,6 @@ let
default = []; default = [];
description = "Accept default routes from these OSPF routers, in order of preference"; description = "Accept default routes from these OSPF routers, in order of preference";
}; };
ospf.allowedUpstreams6 = mkOption {
type = with types; listOf str;
default = config.site.hosts.${name}.ospf.allowedUpstreams;
description = "Accept IPv6 default routes from these OSPF3 routers, in order of preference";
};
ospf.upstreamInstance = mkOption { ospf.upstreamInstance = mkOption {
type = with types; nullOr int; type = with types; nullOr int;
default = null; default = null;
@ -447,6 +415,16 @@ let
type = types.bool; type = types.bool;
default = false; default = false;
}; };
services.yggdrasil = {
enable = mkOption {
type = types.bool;
default = false;
};
keys = mkOption {
type = types.str;
default = "";
};
};
links = mkOption { links = mkOption {
description = "Which port is connected to what other device? Keys are either network names or known hostnames."; description = "Which port is connected to what other device? Keys are either network names or known hostnames.";
default = {}; default = {};
@ -455,25 +433,17 @@ let
wifi = mkOption { wifi = mkOption {
default = {}; default = {};
type = with types; attrsOf (submodule ( type = with types; attrsOf (submodule (
{ config, ... }: { { name, ... }: {
options = { options = {
band = mkOption {
type = enum [ "2g" "5g" ];
default =
if config.channel >= 1 && config.channel <= 14
then "2g"
else if config.channel >= 32 && config.channel <= 177
then "5g"
else throw "What band is channel ${toString config.channel}?";
};
htmode = mkOption { htmode = mkOption {
type = enum [ "HT20" "HT40-" "HT40+" "HT40" "VHT80" ]; type = enum [ "HT20" "HT40-" "HT40+" "VHT80" ];
}; };
channel = mkOption { channel = mkOption {
type = int; type = int;
}; };
ssids = mkOption { ssids = mkOption {
type = attrsOf (submodule ({ config, ... }: { type = attrsOf (submodule (
{ name, ... }: {
options = { options = {
net = mkOption { net = mkOption {
type = str; type = str;
@ -482,34 +452,13 @@ let
type = nullOr str; type = nullOr str;
default = null; default = null;
}; };
hidden = mkOption {
type = bool;
default = false;
};
encryption = mkOption {
type = enum [ "none" "owe" "wpa2" "wpa3" ];
default =
if config.psk == null
then "none"
else "wpa3";
};
mode = mkOption { mode = mkOption {
type = enum [ "ap" "sta" ]; type = enum [ "ap" "sta" ];
default = "ap"; default = "ap";
}; };
ifname = mkOption {
type = nullOr str;
default = null;
}; };
disassocLowAck = mkOption { }
type = bool; ));
default = true;
description = ''
Disable for wireless bridges.
'';
};
};
}));
}; };
}; };
} }
@ -530,7 +479,7 @@ let
type = types.int; type = types.int;
}; };
peers = mkOption { peers = mkOption {
type = with types; attrsOf (submodule ({ ... }: { type = with types; attrsOf (submodule ({ name, ... }: {
options = { options = {
asn = mkOption { asn = mkOption {
type = types.int; type = types.int;
@ -580,30 +529,6 @@ let
}; };
}; };
}; };
vpnOpts = {
privateKey = mkOption {
type = types.str;
};
port = mkOption {
type = types.int;
default = 1337;
};
peers = mkOption {
type = with types; listOf (submodule {
options = {
publicKey = mkOption {
type = str;
};
allowedIPs = mkOption {
type = listOf str;
};
};
});
};
};
in in
{ {
options.site = { options.site = {
@ -613,7 +538,6 @@ in
type = with types; attrsOf (submodule netOpts); type = with types; attrsOf (submodule netOpts);
}; };
hosts = mkOption { hosts = mkOption {
description = "All the static hosts"; description = "All the static hosts";
default = {}; default = {};
@ -627,23 +551,6 @@ in
dyndnsKey = mkOption { dyndnsKey = mkOption {
type = types.str; type = types.str;
}; };
vpn.wireguard = vpnOpts;
mqttServer = {
host = mkOption {
type = types.str;
default = config.site.net.serv.hosts4.broker;
};
user = mkOption {
type = types.str;
default = "user";
};
password = mkOption {
type = types.str;
default = "secret";
};
};
}; };
config.warnings = config.warnings =
@ -678,7 +585,7 @@ in
else [] else []
) (builtins.attrNames config.site.hosts); ) (builtins.attrNames config.site.hosts);
in in
(reportCollisions "VLAN tag" (x: lib.optional (x.vlan != null) x.vlan) config.site.net) ++ (reportCollisions "VLAN tag" (x: [x.vlan]) config.site.net) ++
(reportCollisions "IPv4 subnet" (x: if x.subnet4 == null then [] else [x.subnet4]) config.site.net) ++ (reportCollisions "IPv4 subnet" (x: if x.subnet4 == null then [] else [x.subnet4]) config.site.net) ++
(reportCollisions "IPv6 subnet" (x: builtins.attrValues x.subnets6) config.site.net) ++ (reportCollisions "IPv6 subnet" (x: builtins.attrValues x.subnets6) config.site.net) ++
ospfUpstreamXorGw; ospfUpstreamXorGw;
@ -747,67 +654,5 @@ in
in map (vlan: { in map (vlan: {
assertion = builtins.length vlanNets.${vlan} == 1; assertion = builtins.length vlanNets.${vlan} == 1;
message = "VLAN ${vlan} is used by more than one network: ${lib.concatStringsSep " " vlanNets.${vlan}}"; message = "VLAN ${vlan} is used by more than one network: ${lib.concatStringsSep " " vlanNets.${vlan}}";
}) (builtins.attrNames vlanNets)) }) (builtins.attrNames vlanNets));
++
# Duplicate switch port check
builtins.concatMap (hostName:
let
ports = lib.unique (
builtins.concatMap (linkName:
config.site.hosts.${hostName}.links.${linkName}.ports
) (builtins.attrNames config.site.hosts.${hostName}.links)
);
linksOfPort = port:
builtins.attrNames (
lib.filterAttrs (_: { ports, ... }: builtins.elem port ports)
config.site.hosts.${hostName}.links
);
in map (port: {
assertion = builtins.length (linksOfPort port) == 1;
message = "${hostName}: port ${port} is used in more than one link: ${lib.concatStringsSep " " (linksOfPort port)}";
}) ports
) (builtins.attrNames config.site.hosts)
++
# Duplicate switch port group check
builtins.concatMap (hostName:
let
groups = lib.unique (
builtins.filter builtins.isString (
builtins.map (linkName:
config.site.hosts.${hostName}.links.${linkName}.group
) (builtins.attrNames config.site.hosts.${hostName}.links)
)
);
linksOfGroup = wantedGroup:
builtins.attrNames (
lib.filterAttrs (_: { group, ... }: group == wantedGroup)
config.site.hosts.${hostName}.links
);
in map (group: {
assertion = builtins.length (linksOfGroup group) == 1;
message = "${hostName}: group ${group} is used in more than one link: ${lib.concatStringsSep " " (linksOfGroup group)}";
}) groups
) (builtins.attrNames config.site.hosts)
++
# wifi psk checks
builtins.concatMap (hostName:
builtins.concatMap (wifiPath:
map (ssid:
let
ssidConf = config.site.hosts.${hostName}.wifi.${wifiPath}.ssids.${ssid};
in
if builtins.elem ssidConf.encryption [ "none" "owe" ]
then {
assertion = ssidConf.psk == null;
message = "${hostName}: SSID ${ssid} has encryption ${ssidConf.encryption} but a PSK is set";
}
else if builtins.elem ssidConf.encryption [ "wpa2" "wpa3" ]
then {
assertion = ssidConf.psk != null;
message = "${hostName}: SSID ${ssid} has encryption ${ssidConf.encryption} but no PSK is set";
}
else throw "Unsupported WiFi encryption ${ssidConf.encryption}"
) (builtins.attrNames config.site.hosts.${hostName}.wifi.${wifiPath}.ssids)
) (builtins.attrNames config.site.hosts.${hostName}.wifi)
) (builtins.attrNames config.site.hosts);
} }

View File

@ -1,13 +1,13 @@
{ self, lib, openwrt, pkgs }: { self, pkgs, openwrt }:
rec { rec {
inherit (import ./config { inherit self pkgs; }) config; config = (import ./config { inherit self pkgs; }).config;
netmasks = import ./netmasks.nix; netmasks = import ./netmasks.nix;
subnet = import ./subnet { inherit pkgs; }; subnet = import ./subnet { inherit pkgs; };
dns = import ./dns.nix { inherit config lib; }; dns = import ./dns.nix { inherit pkgs config; };
openwrtModels = import ./openwrt-models.nix { inherit self openwrt; }; openwrtModels = import ./openwrt-models.nix { inherit self openwrt; };
@ -15,9 +15,8 @@ rec {
let let
models = models =
builtins.filter ({ models, ... }: builtins.filter ({ models, ... }:
self.lib.any ({ model, vendor, ... }: self.lib.any ({ model, ... }:
model == wantedModel || model == wantedModel
"${vendor}_${model}" == wantedModel
) models ) models
) openwrtModels; ) openwrtModels;
result = result =

View File

@ -1,18 +1,15 @@
{ config, lib }: { pkgs, config }:
let
lib = pkgs.lib;
in
rec { rec {
ns = "dns.serv.zentralwerk.org"; ns = "dns.serv.zentralwerk.org";
internalNS = [ ns ]; internalNS = [ ns ];
# public servers (slaves) # public servers (slaves)
publicNS = [ publicNS = [ "ns.c3d2.de" "ns.spaceboyz.net" ];
"ns.c3d2.de"
"ns.spaceboyz.net"
"ns1.supersandro.de"
];
publicIPv4 = config.site.hosts.upstream4.interfaces.up4-pppoe.upstream.staticIpv4Address; dynamicReverseZones = [
dynamicReverseZones4 = [
"73.20.172.in-addr.arpa" "73.20.172.in-addr.arpa"
"74.20.172.in-addr.arpa" "74.20.172.in-addr.arpa"
"75.20.172.in-addr.arpa" "75.20.172.in-addr.arpa"
@ -21,25 +18,7 @@ rec {
"78.20.172.in-addr.arpa" "78.20.172.in-addr.arpa"
"79.20.172.in-addr.arpa" "79.20.172.in-addr.arpa"
"99.22.172.in-addr.arpa" "99.22.172.in-addr.arpa"
"22.10.in-addr.arpa"
]; ];
dynamicReverseZones6 = [
"2.0.0.0.c.2.0.8.1.8.0.0.a.2.ip6.arpa"
"4.1.b.a.c.a.2.8.3.5.f.0.a.2.ip6.arpa"
"5.0.2.d.3.c.2.4.0.0.3.2.d.f.ip6.arpa"
];
mapI = start: end: f:
if start >= end
then []
else [ (f start) ] ++ mapI (start + 1) end f;
isRfc1918Reverse = reverse:
builtins.any (suffix: lib.hasSuffix suffix reverse) ([
"10.in-addr.arpa"
"168.192.in-addr.arpa"
] ++ mapI 0 32 (i:
"${toString (16 + i)}.172.in-addr.arpa"
));
localZones = localZones =
let let
@ -64,9 +43,8 @@ rec {
); );
# generate zones only for nets with hosts # generate zones only for nets with hosts
namedNets = lib.filterAttrs (_name: { hosts4, hosts6, dynamicDomain, ... }: namedNets = lib.filterAttrs (name: { hosts4, hosts6, dynamicDomain, ... }:
hosts4 != {} || (hosts4 != [] && hosts6 != []) ||
hosts6 != {} ||
dynamicDomain dynamicDomain
) config.site.net; ) config.site.net;
@ -99,7 +77,7 @@ rec {
"${zone}" = true; "${zone}" = true;
} }
) {} (builtins.attrNames reverseHosts4) ) {} (builtins.attrNames reverseHosts4)
) ++ dynamicReverseZones4 ) ++ dynamicReverseZones
); );
# turns `::` into `0000:0000:0000:0000:0000:0000:0000:0000` # turns `::` into `0000:0000:0000:0000:0000:0000:0000:0000`
@ -145,12 +123,17 @@ rec {
# `{ dn42 = { "...ip6.arpa" = "lo.core.zentralwerk.dn42"; }; }` # `{ dn42 = { "...ip6.arpa" = "lo.core.zentralwerk.dn42"; }; }`
reverseHosts6 = builtins.foldl' (result: net: lib.recursiveUpdate result ( reverseHosts6 = builtins.foldl' (result: net: lib.recursiveUpdate result (
builtins.mapAttrs (ctx: hosts: builtins.mapAttrs (ctx: hosts:
if ctx == "yggdrasil"
then {}
else
builtins.foldl' (result: host: builtins.foldl' (result: host:
let let
domain = domain =
if ctx == "dn42" if ctx == "dn42"
then "${net}.zentralwerk.dn42" then "${net}.zentralwerk.dn42"
else namedNets.${net}.domainName; else if builtins.match "up.*" ctx != null
then namedNets.${net}.domainName
else throw "Invalid IPv6 context: ${ctx}";
in in
lib.recursiveUpdate result { lib.recursiveUpdate result {
"${ipv6ToReverse hosts.${host}}" = "${host}.${domain}"; "${ipv6ToReverse hosts.${host}}" = "${host}.${domain}";
@ -160,10 +143,9 @@ rec {
)) {} (builtins.attrNames namedNets); )) {} (builtins.attrNames namedNets);
# `{ dn42 = [ "....ip6.arpa" ]; }` # `{ dn42 = [ "....ip6.arpa" ]; }`
reverseZones6 = builtins.mapAttrs (_ctx: reverseHosts6ctx: reverseZones6 = builtins.mapAttrs (ctx: reverseHosts6ctx:
builtins.attrNames ( builtins.attrNames (
builtins.foldl' (result: rname: builtins.foldl' (result: rname: result // {
result // {
"${builtins.substring ((128 - reverseZone6Size) / 2) (72 - ((128 - reverseZone6Size) / 2)) rname}" = true; "${builtins.substring ((128 - reverseZone6Size) / 2) (72 - ((128 - reverseZone6Size) / 2)) rname}" = true;
}) {} (builtins.attrNames reverseHosts6ctx) }) {} (builtins.attrNames reverseHosts6ctx)
) )
@ -172,38 +154,28 @@ rec {
in [ { in [ {
name = "zentralwerk.org"; name = "zentralwerk.org";
ns = publicNS; ns = publicNS;
records = [ { records = [];
name = "@";
type = "A";
data = publicIPv4;
} {
name = "www";
type = "A";
data = publicIPv4;
} {
name = "@";
type = "AAAA";
data = config.site.net.serv.hosts6.up4.network-homepage;
} {
name = "www";
type = "AAAA";
data = config.site.net.serv.hosts6.up4.network-homepage;
} ];
} { } {
name = "zentralwerk.dn42"; name = "zentralwerk.dn42";
ns = internalNS; ns = internalNS;
records = [ ]; records = [ {
name = "ipa";
type = "A";
data = config.site.net.serv.hosts4.ipa;
} ];
} { } {
name = "dyn.zentralwerk.org"; name = "dyn.zentralwerk.org";
ns = publicNS; ns = publicNS;
records = [ { records = [ {
name = "upstream4"; name = "upstream1";
type = "A"; type = "A";
data = publicIPv4; data = "24.134.104.53";
} {
name = "upstream2";
type = "A";
data = "24.134.252.105";
} ]; } ];
} ] } ] ++ builtins.concatLists (
++
builtins.concatLists (
builtins.attrValues ( builtins.attrValues (
builtins.mapAttrs (net: { dynamicDomain, hosts4, hosts6, extraRecords, ... }: [ builtins.mapAttrs (net: { dynamicDomain, hosts4, hosts6, extraRecords, ... }: [
{ {
@ -219,20 +191,14 @@ rec {
records = records =
hosts4Records hosts4 ++ hosts4Records hosts4 ++
lib.optionals (hosts6 ? up4) (hosts6Records hosts6.up4) ++ lib.optionals (hosts6 ? up4) (hosts6Records hosts6.up4) ++
lib.optionals (hosts6 ? flpk) (hosts6Records hosts6.flpk) ++
extraRecords; extraRecords;
dynamic = dynamicDomain; dynamic = dynamicDomain;
} }
]) namedNets ]) namedNets
) )
) ) ++ map (zone: {
++
map (zone: {
name = zone; name = zone;
ns = ns = internalNS;
if isRfc1918Reverse zone
then internalNS
else publicNS;
records = records =
map (reverse: { map (reverse: {
name = builtins.head ( name = builtins.head (
@ -244,16 +210,17 @@ rec {
builtins.filter (lib.hasSuffix ".${zone}") builtins.filter (lib.hasSuffix ".${zone}")
(builtins.attrNames reverseHosts4) (builtins.attrNames reverseHosts4)
); );
dynamic = builtins.elem zone dynamicReverseZones4; dynamic = builtins.elem zone dynamicReverseZones;
}) reverseZones4 }) reverseZones4
++ ++ builtins.concatMap (ctx:
builtins.concatMap (ctx:
map (zone: { map (zone: {
name = zone; name = zone;
ns = ns =
if ctx == "dn42" if ctx == "dn42"
then internalNS then internalNS
else publicNS; else if builtins.match "up.*" ctx != null
then publicNS
else throw "Invalid IPv6 context: ${ctx}";
records = records =
map (reverse: { map (reverse: {
name = builtins.substring 0 ((128 - reverseZone6Size) / 2 - 1) reverse; name = builtins.substring 0 ((128 - reverseZone6Size) / 2 - 1) reverse;
@ -263,7 +230,6 @@ rec {
builtins.filter (lib.hasSuffix ".${zone}") builtins.filter (lib.hasSuffix ".${zone}")
(builtins.attrNames reverseHosts6.${ctx}) (builtins.attrNames reverseHosts6.${ctx})
); );
dynamic = builtins.elem zone dynamicReverseZones6;
}) reverseZones6.${ctx} }) reverseZones6.${ctx}
) (builtins.attrNames reverseZones6); ) (builtins.attrNames reverseZones6);
} }

View File

@ -28,14 +28,8 @@ let
builtins.filter (word: builtins.filter (word:
word != [] && word != "" word != [] && word != ""
) tokens; ) tokens;
command = command = builtins.head words;
if words != [] args = builtins.tail words;
then builtins.head words
else "-";
args =
if words != []
then builtins.tail words
else [];
makeLinkFromArg = port: arg: makeLinkFromArg = port: arg:
builtins.foldl' (result: interface: builtins.foldl' (result: interface:
@ -95,9 +89,7 @@ let
ucidef_set_interfaces_lan_wan.ports = ucidef_set_interfaces_lan_wan.ports =
makeLinkFromArg "lan" (builtins.elemAt args 0) // makeLinkFromArg "lan" (builtins.elemAt args 0) //
self.lib.optionalAttrs (builtins.length args > 1) ( makeLinkFromArg "wan" (builtins.elemAt args 1);
makeLinkFromArg "wan" (builtins.elemAt args 1)
);
}; };
in in
if commands ? ${command} if commands ? ${command}

View File

@ -47,15 +47,6 @@ in
Forward true Forward true
Server "${config.site.net.serv.hosts4.spaceapi}" "${toString networkPort}" Server "${config.site.net.serv.hosts4.spaceapi}" "${toString networkPort}"
Server "${config.site.net.serv.hosts4.grafana}" "${toString networkPort}" Server "${config.site.net.serv.hosts4.grafana}" "${toString networkPort}"
Server "${config.site.net.serv.hosts4.prometheus}" "${toString networkPort}"
'';
plugins.mqtt = ''
<Publish "broker">
Host "${config.site.mqttServer.host}"
User "${config.site.mqttServer.user}"
Password "${config.site.mqttServer.password}"
ClientId "collectd-${hostName}"
</Publish>
''; '';
}) (lib.optionalAttrs (hostName != "stats") { }) (lib.optionalAttrs (hostName != "stats") {
plugins.network = '' plugins.network = ''
@ -90,7 +81,7 @@ in
Host "inbert.c3d2.de" Host "inbert.c3d2.de"
Host "heise.de" Host "heise.de"
''; '';
}) (lib.optionalAttrs config.services.kea.dhcp4.enable { }) (lib.optionalAttrs config.services.dhcpd4.enable {
plugins.exec = plugins.exec =
let let
maxTimeout = builtins.foldl' (maxTimeout: net: maxTimeout = builtins.foldl' (maxTimeout: net:
@ -104,7 +95,7 @@ in
else maxTimeout else maxTimeout
) 180 (builtins.attrNames config.site.net); ) 180 (builtins.attrNames config.site.net);
in '' in ''
Exec "${execUser}" "/run/wrappers/bin/collectd-dhcpcount" "${toString maxTimeout}" Exec "${execUser}" "${pkgs.ruby}/bin/ruby" "${./dhcpcount.rb}" "${toString maxTimeout}"
''; '';
}) (lib.optionalAttrs config.services.unbound.enable { }) (lib.optionalAttrs config.services.unbound.enable {
plugins.exec = '' plugins.exec = ''
@ -115,29 +106,4 @@ in
Exec "nobody" "${self.packages.${system}.starlink-stats}/bin/starlink-stats" "192.168.100.1:9200" Exec "nobody" "${self.packages.${system}.starlink-stats}/bin/starlink-stats" "192.168.100.1:9200"
''; '';
}) ]; }) ];
systemd.services.collectd = lib.mkIf config.services.kea.dhcp4.enable {
after = [ "kea-dhcp4-server.service" ];
};
security.wrappers = lib.mkIf config.services.kea.dhcp4.enable {
collectd-dhcpcount =
let
dhcpcount = pkgs.runCommand "dhcpcount" {
src = ./dhcpcount.rb;
buildInputs = [ pkgs.ruby ];
} ''
cp $src dhcpcount.rb
patchShebangs dhcpcount.rb
mkdir -p $out/bin
cp dhcpcount.rb $out/bin/dhcpcount
'';
in {
setuid = true;
owner = "root";
group = "root";
source = "${dhcpcount}/bin/dhcpcount";
};
};
} }

32
nix/nixos-module/collectd/dhcpcount.rb Executable file → Normal file
View File

@ -1,30 +1,38 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require 'csv' require 'date'
INTERVAL = 60 INTERVAL = 10
TIMEOUT = ARGV[0].to_i # TODO: now unused TIMEOUT = ARGV[0].to_i
hostname = CSV::readlines("/proc/sys/kernel/hostname").join.strip hostname = IO::readlines("/proc/sys/kernel/hostname").join.strip
STDOUT.sync = true STDOUT.sync = true
loop do loop do
seen = {} seen = {}
count = 0 count = 0
now = Time.now.to_i
CSV::readlines("/var/lib/kea/kea-leases4.csv", headers: true).each do |rec| addr = nil
h = rec.to_h starts = nil
addr = h["hwaddr"]
next unless addr IO::readlines("/var/lib/dhcp/dhcpd.leases").each do |line|
last = h["expire"].to_i if line =~ /^lease (.+) \{/
elapsed = now - last addr = $1
next if elapsed >= TIMEOUT
starts = nil
elsif line =~ /starts \d+ (.+?);/
starts = DateTime.parse($1).to_time
elsif line =~ /^\}/
now = Time.now
if starts and
now >= starts and now < starts + TIMEOUT
unless seen[addr] unless seen[addr]
count += 1 count += 1
seen[addr] = true seen[addr] = true
end end
end end
end
end
puts "PUTVAL \"#{hostname}/exec-dhcpd/current_sessions-leases\" interval=#{INTERVAL} N:#{count}" puts "PUTVAL \"#{hostname}/exec-dhcpd/current_sessions-leases\" interval=#{INTERVAL} N:#{count}"
sleep INTERVAL sleep INTERVAL

0
nix/nixos-module/collectd/unbound.rb Executable file → Normal file
View File

View File

@ -1,9 +1,7 @@
# Routing daemon configuration # Routing daemon configuration
{ hostName, config, lib, pkgs, ... }: { hostName, config, options, lib, pkgs, ... }:
let let
hostNameEscaped = builtins.replaceStrings [ "-" ] [ "_" ] hostName;
hostConf = config.site.hosts.${hostName}; hostConf = config.site.hosts.${hostName};
upstreamInterfaces = lib.filterAttrs (_: { upstream, ... }: upstreamInterfaces = lib.filterAttrs (_: { upstream, ... }:
@ -12,11 +10,17 @@ let
isUpstream = upstreamInterfaces != {}; isUpstream = upstreamInterfaces != {};
ipv6RouterNets = builtins.attrNames ( # Configuring a gateway? If so, this is the associated net.
lib.filterAttrs (net: { ipv6Router, ... }: gatewayNet =
ipv6Router == hostName let
) config.site.net m = builtins.match "(.+)-gw" hostName;
); in if hostName == "c3d2-gw3"
then "c3d2"
else if m == [ "cls" ]
then "cluster"
else if m == null
then null
else builtins.head m;
enumerate = n: list: enumerate = n: list:
if list == [] if list == []
@ -65,61 +69,50 @@ in
protocol device { protocol device {
scan time 10; scan time 10;
} }
${lib.optionalString isUpstream ''
# Import address ranges of upstream interfaces so that # Import address ranges of upstream interfaces so that
# internal traffic to local public services take no detours # internal traffic to local public services take no detours
# if the default router takes another upstream gateway. # if the default router takes another upstream gateway.
protocol direct { protocol direct {
ipv4 { ipv4 {
${if isUpstream # No RFC6598
then '' import where net !~ 100.64.0.0/10
# No RFC1918, RFC6598 # No RFC1918
import where net !~ [ 100.64.0.0/10 ] && net !~ [ 10.0.0.0/8 ] && net !~ [ 172.16.0.0/12 ] && net !~ [ 192.168.0.0/16 ]; && net !~ 10.0.0.0/8
'' && net !~ 172.16.0.0/12
else ""} && net !~ 192.168.0.0/16;
}; };
ipv6; ipv6;
interface ${lib.concatMapStringsSep ", " (iface: interface ${lib.concatMapStringsSep ", " (iface:
''"${iface}"'' ''"${iface}"''
)(builtins.attrNames hostConf.interfaces)}; )(builtins.attrNames upstreamInterfaces)};
check link yes; check link yes;
} }
''}
${lib.optionalString ( ${lib.optionalString (builtins.match "anon.*" hostName != null) ''
builtins.match "anon.*" hostName != null ||
hostName == "flpk-gw"
) ''
# BIRD routing table for Wireguard transport # BIRD routing table for Wireguard transport
ipv4 table vpn_table; ipv4 table vpn4_table;
# Kernel routing table for Wireguard transport # Kernel routing table for Wireguard transport
protocol kernel VPN { protocol kernel VPN4 {
# "vpn_table" configured on anon routers # "vpn4_table" configured on anon routers
kernel table 100; kernel table 100;
ipv4 { ipv4 {
export all; export all;
table vpn_table; table vpn4_table;
}; };
} }
''} ''}
${lib.optionalString (ipv6RouterNets != []) '' ${lib.optionalString (gatewayNet != null) ''
# Router advertisements # Router advertisements
protocol radv { protocol radv {
rdnss ${config.site.net.serv.hosts6.dn42.dnscache}; rdnss ${config.site.net.serv.hosts6.dn42.dnscache};
${lib.concatMapStrings (net: '' interface "${gatewayNet}" {
interface "${net}" {
min ra interval 10; min ra interval 10;
max ra interval 60; max ra interval 60;
solicited ra unicast yes;
${if (config.site.net.${net}.dhcp.server or null) == null
then ''
# Do not use DHCP6.
managed no;
'' else ''
# Use DHCP6 for DynDNS.
managed yes;
''}
${builtins.concatStringsSep "\n" ( ${builtins.concatStringsSep "\n" (
map (subnet6: '' map (subnet6: ''
@ -127,27 +120,26 @@ in
preferred lifetime 600; preferred lifetime 600;
valid lifetime 1800; valid lifetime 1800;
}; };
'') (builtins.attrValues config.site.net.${net}.subnets6) '') (builtins.attrValues config.site.net.${gatewayNet}.subnets6)
)} )}
dnssl "${config.site.net.${net}.domainName}"; dnssl "${config.site.net.${gatewayNet}.domainName}";
}; };
'') ipv6RouterNets}
} }
''} ''}
# OSPFv2 for site-local IPv4 # OSPFv2 for site-local IPv4
protocol ospf v2 ZW4 { protocol ospf v2 ZW4 {
ipv4 { ipv4 {
import all; export where net != 0.0.0.0/0 && source != RTS_BGP;
# OSPF is self-contained
export none;
}; };
area 0 { area 0 {
${builtins.concatStringsSep "\n" ( ${builtins.concatStringsSep "\n" (
builtins.attrValues ( builtins.attrValues (
builtins.mapAttrs (net: _: builtins.mapAttrs (net: _:
# Enable OSPF only on networks with a secret. # Enable OSPF only on networks with a secret. Others
# are treated as a stubnet whose routes to
# advertise.
if config.site.net ? "${net}" && config.site.net.${net}.ospf.secret != null if config.site.net ? "${net}" && config.site.net.${net}.ospf.secret != null
then '' then ''
interface "${net}" { interface "${net}" {
@ -158,12 +150,12 @@ in
password "${config.site.net.${net}.ospf.secret}"; password "${config.site.net.${net}.ospf.secret}";
}; };
'' ''
else '' else if config.site.net ? "${net}" && config.site.net.${net}.subnet4 != null
interface "${net}" { then ''
stub yes; # Advertise route of network ${net}
cost 10; stubnet ${config.site.net.${net}.subnet4} {};
};
'' ''
else ""
) hostConf.interfaces ) hostConf.interfaces
) )
)} )}
@ -178,7 +170,7 @@ in
${lib.optionalString isUpstream '' ${lib.optionalString isUpstream ''
# OSPFv2 to advertise my default route # OSPFv2 to advertise my default route
protocol ospf v2 ZW4_${hostNameEscaped} { protocol ospf v2 ZW4_${hostName} {
ipv4 { ipv4 {
export where net = 0.0.0.0/0; export where net = 0.0.0.0/0;
}; };
@ -211,19 +203,14 @@ in
${text} ${text}
# OSPFv2 to receive a default route from ${upstream} # OSPFv2 to receive a default route from ${upstream}
protocol ospf v2 ZW4_${ protocol ospf v2 ZW4_${upstream} {
builtins.replaceStrings [ "-" ] [ "_" ] upstream
} {
ipv4 { ipv4 {
import filter { import filter {
preference = preference + ${toString (100 - n)}; preference = preference + ${toString (100 - n)};
accept; accept;
}; };
${lib.optionalString ( ${lib.optionalString (builtins.match "anon.*" hostName != null) ''
builtins.match "anon.*" hostName != null || table vpn4_table;
hostName == "flpk-gw"
) ''
table vpn_table;
''} ''}
}; };
area 0 { area 0 {
@ -232,11 +219,7 @@ in
builtins.mapAttrs (net: _: builtins.mapAttrs (net: _:
# Enable OSPF only on interfaces with a secret. # Enable OSPF only on interfaces with a secret.
lib.optionalString (config.site.net.${net}.ospf.secret != null) '' lib.optionalString (config.site.net.${net}.ospf.secret != null) ''
interface "${net}" instance ${ interface "${net}" instance ${toString config.site.hosts.${upstream}.ospf.upstreamInstance} {
builtins.replaceStrings [ "-" ] [ "_" ] (
toString config.site.hosts.${upstream}.ospf.upstreamInstance
)
} {
hello 10; hello 10;
wait 20; wait 20;
authentication cryptographic; authentication cryptographic;
@ -256,15 +239,15 @@ in
# OSPFv3 for site-local IPv6 # OSPFv3 for site-local IPv6
protocol ospf v3 ZW6 { protocol ospf v3 ZW6 {
ipv6 { ipv6 {
import all; export where net != ::/0 && source != RTS_BGP;
# OSPF is self-contained
export none;
}; };
area 0 { area 0 {
${builtins.concatStringsSep "\n" ( ${builtins.concatStringsSep "\n" (
builtins.attrValues ( builtins.attrValues (
builtins.mapAttrs (net: _: builtins.mapAttrs (net: _:
# Enable OSPF only on networks with a secret. # Enable OSPF only on networks with a secret. Others
# are treated as a stubnet whose routes to
# advertise.
if config.site.net.${net}.ospf.secret != null if config.site.net.${net}.ospf.secret != null
then '' then ''
interface "${net}" { interface "${net}" {
@ -275,12 +258,12 @@ in
password "${config.site.net.${net}.ospf.secret}"; password "${config.site.net.${net}.ospf.secret}";
}; };
'' ''
else '' else builtins.concatStringsSep "\n" (
interface "${net}" { map (subnet6: ''
stub yes; # Advertise route of network ${net}
cost 10; stubnet ${subnet6} {};
}; '') (builtins.attrValues config.site.net.${net}.subnets6)
'' )
) hostConf.physicalInterfaces ) hostConf.physicalInterfaces
) )
)} )}
@ -296,7 +279,7 @@ in
${lib.optionalString isUpstream '' ${lib.optionalString isUpstream ''
# OSPFv3 to advertise my default route # OSPFv3 to advertise my default route
protocol ospf v3 ZW6_${hostNameEscaped} { protocol ospf v3 ZW6_${hostName} {
ipv6 { ipv6 {
export where net = ::/0; export where net = ::/0;
}; };
@ -329,9 +312,7 @@ in
${text} ${text}
# OSPFv3 to receive a default route from ${upstream} # OSPFv3 to receive a default route from ${upstream}
protocol ospf v3 ZW6_${ protocol ospf v3 ZW6_${upstream} {
builtins.replaceStrings [ "-" ] [ "_" ] upstream
} {
ipv6 { ipv6 {
import filter { import filter {
preference = preference + ${toString (100 - n)}; preference = preference + ${toString (100 - n)};
@ -344,11 +325,7 @@ in
builtins.mapAttrs (net: _: builtins.mapAttrs (net: _:
# Enable OSPF only on interfaces with a secret. # Enable OSPF only on interfaces with a secret.
lib.optionalString (config.site.net.${net}.ospf.secret != null) '' lib.optionalString (config.site.net.${net}.ospf.secret != null) ''
interface "${net}" instance ${ interface "${net}" instance ${toString config.site.hosts.${upstream}.ospf.upstreamInstance} {
builtins.replaceStrings [ "-" ] [ "_" ] (
toString config.site.hosts.${upstream}.ospf.upstreamInstance
)
} {
hello 10; hello 10;
wait 20; wait 20;
authentication cryptographic; authentication cryptographic;
@ -362,7 +339,7 @@ in
} }
''; '';
n = n + 1; n = n + 1;
}) { text = ""; n = 0; } hostConf.ospf.allowedUpstreams6 }) { text = ""; n = 0; } hostConf.ospf.allowedUpstreams
).text} ).text}
# Zentralwerk DN42 # Zentralwerk DN42
@ -373,8 +350,11 @@ in
protocol static { protocol static {
ipv6; ipv6;
route fd23:42:c3d2:580::/57 unreachable; route fd23:42:c3d2:580::/57 unreachable;
# TODO: remove
route 2a02:8106:208:5200::/56 unreachable;
# TODO: remove
route 2a02:8106:211:e900::/56 unreachable;
route 2a00:8180:2c00:200::/56 unreachable; route 2a00:8180:2c00:200::/56 unreachable;
route 2a0f:5382:acab:1400::/56 unreachable;
} }
${lib.optionalString (hostConf.bgp != null) '' ${lib.optionalString (hostConf.bgp != null) ''
@ -436,8 +416,8 @@ in
]; ];
}; };
instance = { instance = {
ipv4 = "ZW4_${hostNameEscaped}"; ipv4 = "ZW4_${hostName}";
ipv6 = "ZW6_${hostNameEscaped}"; ipv6 = "ZW6_${hostName}";
}; };
checkService = addressFamily: { checkService = addressFamily: {
description = "Check connectivity for ${addressFamily}"; description = "Check connectivity for ${addressFamily}";
@ -447,7 +427,7 @@ in
User = "bird2"; User = "bird2";
Group = "bird2"; Group = "bird2";
}; };
path = with pkgs; [ bird2 iputils ]; path = [ pkgs.bird2 "/run/wrappers" ];
script = '' script = ''
STATE=unknown STATE=unknown

View File

@ -1,4 +1,4 @@
{ config, lib, modulesPath, pkgs, ... }: { config, lib, modulesPath, ... }:
{ {
imports = [ imports = [
@ -6,19 +6,22 @@
(modulesPath + "/virtualisation/lxc-container.nix") (modulesPath + "/virtualisation/lxc-container.nix")
]; ];
environment = { boot = {
etc."machine-id".text = builtins.substring 0 8 (builtins.hashString "sha256" config.networking.hostName); isContainer = true;
systemPackages = with pkgs; [ loader = {
ripgrep initScript.enable = true;
]; };
}; };
environment.etc."machine-id".text =
builtins.substring 0 8 (
builtins.hashString "sha256" config.networking.hostName
);
nix = { nix = {
settings = { useSandbox = false;
sandbox = false; maxJobs = lib.mkDefault 1;
max-jobs = lib.mkDefault 4; buildCores = lib.mkDefault 1;
cores = lib.mkDefault 4;
};
}; };
systemd.services = systemd.services =

View File

@ -1,5 +1,5 @@
# ISC DHCP/IPv4 server configuration # ISC DHCP/IPv4 server configuration
{ hostName, config, lib, ... }: { hostName, inputs, config, lib, ... }:
let let
dhcpNets = dhcpNets =
@ -8,341 +8,81 @@ let
dhcp.server == hostName dhcp.server == hostName
) config.site.net; ) config.site.net;
concatMapDhcpNets = f:
lib.pipe dhcpNets [
(builtins.mapAttrs f)
builtins.attrValues
(map (r: if builtins.isList r then r else [ r ]))
builtins.concatLists
];
enabled = builtins.length (builtins.attrNames dhcpNets) > 0; enabled = builtins.length (builtins.attrNames dhcpNets) > 0;
in in
{ {
services.kea.dhcp4 = lib.mkIf enabled { services.dhcpd4 = lib.optionalAttrs enabled {
enable = true; enable = true;
settings = { interfaces = builtins.attrNames dhcpNets;
interfaces-config.interfaces = builtins.attrNames dhcpNets;
dhcp-ddns.enable-updates = true;
ddns-send-updates = true;
# TODO: use with kea >= 2.5.0
# ddns-conflict-resolution-mode = "check-exists-with-dhcid";
ddns-use-conflict-resolution = false;
ddns-replace-client-name = "when-not-present";
expired-leases-processing.hold-reclaimed-time = builtins.foldl' lib.max
3600 (concatMapDhcpNets (net: { dhcp, ... }: dhcp.max-time));
subnet4 = concatMapDhcpNets (net: { vlan, subnet4, hosts4, dhcp, domainName, captiveJson, ... }: { extraConfig = ''
id = vlan; ${builtins.concatStringsSep "\n" (
subnet = subnet4;
pools = [ {
pool = "${dhcp.start} - ${dhcp.end}";
} ];
renew-timer = builtins.ceil (.5 * dhcp.time);
rebind-timer = builtins.ceil (.85 * dhcp.time);
valid-lifetime = dhcp.time;
option-data = [ {
space = "dhcp4";
name = "routers";
code = 3;
data = config.site.net.${net}.hosts4.${dhcp.router};
} {
space = "dhcp4";
name = "domain-name";
code = 15;
data = domainName;
} {
space = "dhcp4";
name = "domain-name-servers";
code = 6;
data = "${config.site.net.serv.hosts4.dnscache}, 9.9.9.9";
} ] ++ lib.optional (captiveJson != null) {
space = "dhcp4";
name = "v4-captive-portal";
code = 114;
data = captiveJson;
};
ddns-qualifying-suffix = domainName;
reservations = lib.pipe dhcp.fixed-hosts [
(builtins.mapAttrs (fixedAddr: hwaddr:
if hosts4 ? ${fixedAddr}
then # fixedAddr is a known hostname
let
name = fixedAddr;
addr = hosts4.${fixedAddr};
in {
hostname = "${name}.${net}.zentralwerk.org";
hw-address = hwaddr;
ip-address = addr;
}
else
let
names = builtins.attrNames (
lib.filterAttrs (_: hostAddr:
hostAddr == fixedAddr
) hosts4);
name = builtins.head names;
in
if builtins.length names > 0
then { # fixedAddr is IPv4 of a known hostname
hostname = "${name}.${net}.zentralwerk.org";
hw-address = hwaddr;
ip-address = hosts4.${name};
} # fixedAddr is IPv4?
else {
hw-address = hwaddr;
ip-address = fixedAddr;
}
))
builtins.attrValues
(builtins.filter (r: r != null))
];
});
match-client-id = false;
host-reservation-identifiers = [ "hw-address" ];
# Netbooting
option-def = [ {
name = "PXEDiscoveryControl";
code = 6;
space = "vendor-encapsulated-options-space";
type = "uint8";
array = false;
} {
name = "PXEMenuPrompt";
code = 10;
space = "vendor-encapsulated-options-space";
type = "record";
array = false;
record-types = "uint8,string";
} {
name = "PXEBootMenu";
code = 9;
space = "vendor-encapsulated-options-space";
type = "record";
array = false;
record-types = "uint16,uint8,string";
} ];
client-classes =
let
rpi4Class = {
name = "rpi4-pxe";
test = "option[vendor-class-identifier].text == 'PXEClient:Arch:00000:UNDI:002001'";
option-data = [ {
name = "boot-file-name";
data = "bootcode.bin";
} {
name = "vendor-class-identifier";
data = "PXEClient";
} {
name = "vendor-encapsulated-options";
} {
name = "PXEBootMenu";
csv-format = true;
data = "0,17,Raspberry Pi Boot";
space = "vendor-encapsulated-options-space";
} {
name = "PXEDiscoveryControl";
data = "3";
space = "vendor-encapsulated-options-space";
} {
name = "PXEMenuPrompt";
csv-format = true;
data = "0,PXE";
space = "vendor-encapsulated-options-space";
} ];
};
pxeClassData = {
PXE-Legacy = {
arch = "00000";
boot-file-name = "netboot.xyz.kpxe";
};
PXE-UEFI-32-1.arch = "00002";
PXE-UEFI-32-2.arch = "00006";
PXE-UEFI-64-1.arch = "00007";
PXE-UEFI-64-2.arch = "00008";
PXE-UEFI-64-3.arch = "00009";
};
makePxe = name: { boot-file-name ? "netboot.xyz.efi", arch }: {
inherit name boot-file-name;
test = "substring(option[60].hex,0,20) == 'PXEClient:Arch:${arch}'";
next-server = config.site.net.serv.hosts4.nfsroot;
};
in
[ rpi4Class ]
++
builtins.attrValues ( builtins.attrValues (
builtins.mapAttrs makePxe pxeClassData builtins.mapAttrs (net: { dhcp, subnet4Net, subnet4Len, domainName, ...}:
); ''
ddns-update-style standard;
control-socket = { key dyndns {
socket-type = "unix"; algorithm hmac-sha256;
socket-name = "/run/kea/dhcp4-socket"; secret ${config.site.dyndnsKey};
}; };
hooks-libraries = [ { zone ${domainName}. {
library = "/run/current-system/sw/lib/kea/hooks/libdhcp_stat_cmds.so"; primary ${config.site.net.serv.hosts4.dns};
} { primary6 ${config.site.net.serv.hosts6.dn42.dns};
library = "/run/current-system/sw/lib/kea/hooks/libdhcp_lease_cmds.so"; key dyndns;
} ];
};
};
services.kea.dhcp6 = lib.mkIf enabled {
enable = true;
settings = {
interfaces-config.interfaces = builtins.attrNames dhcpNets;
dhcp-ddns.enable-updates = true;
ddns-override-no-update = true;
ddns-override-client-update = true;
ddns-replace-client-name = "when-not-present";
# TODO: use with kea >= 2.5.0
# ddns-conflict-resolution-mode = "check-exists-with-dhcid";
ddns-use-conflict-resolution = false;
subnet6 = concatMapDhcpNets (net: { vlan, subnets6, dhcp, domainName, captiveJson, ... }:
let
subnet = subnets6.up4 or subnets6.flpk or null;
prefix = builtins.head (builtins.split "::/" subnet);
in
if subnet != null
then {
id = vlan;
interface = net;
inherit subnet;
pools = [ {
pool = "${prefix}:c3d2:c3d2:c3d2:1000 - ${prefix}:c3d2:c3d2:c3d2:ffff";
#pool = subnet;
} ];
valid-lifetime = dhcp.time;
max-valid-lifetime = dhcp.max-time;
option-data = [ {
space = "dhcp6";
name = "domain-search";
code = 24;
data = domainName;
} {
space = "dhcp6";
name = "dns-servers";
code = 23;
data = "${config.site.net.serv.hosts6.dn42.dnscache}, 2620:fe::9";
} ] ++ lib.optional (captiveJson != null) {
space = "dhcp6";
name = "v6-captive-portal";
code = 103;
data = captiveJson;
};
ddns-generated-prefix = "d";
ddns-qualifying-suffix = domainName;
} }
else [] ${lib.concatMapStrings ({ name, dynamic, ... }:
); lib.optionalString (
host-reservation-identifiers = [ "hw-address" ];
#reservations = concatMapDhcpNets (net: { hosts6, dhcp, ... }:
# builtins.filter (r: r != null) (
# builtins.attrValues (
# builtins.mapAttrs (name: hwaddr:
# let
# ip-addresses = lib.pipe hosts6 [
# (builtins.mapAttrs (_: hosts6: hosts6.${name} or null))
# builtins.attrValues
# (builtins.filter (a: a != null))
# ];
# in
# if builtins.trace (lib.generators.toPretty {} ip-addresses) (builtins.length ip-addresses) > 0
# then {
# hostname = "${name}.${net}.zentralwerk.org";
# hw-address = hwaddr;
# inherit ip-addresses;
# }
# else null
# ) dhcp.fixed-hosts
# )));
control-socket = {
socket-type = "unix";
socket-name = "/run/kea/dhcp6.socket";
};
hooks-libraries = [ {
library = "/run/current-system/sw/lib/kea/hooks/libdhcp_stat_cmds.so";
} {
library = "/run/current-system/sw/lib/kea/hooks/libdhcp_lease_cmds.so";
} ];
};
};
services.kea.dhcp-ddns = lib.mkIf enabled {
enable = true;
settings = {
tsig-keys = [ {
name = "dyndns";
algorithm = "hmac-sha256";
secret = config.site.dyndnsKey;
} ];
forward-ddns.ddns-domains = concatMapDhcpNets (net: { domainName, ... }: {
name = "${domainName}.";
key-name = "dyndns";
dns-servers = [ {
ip-address = config.site.net.serv.hosts4.dns;
} {
ip-address = config.site.net.serv.hosts6.dn42.dns;
} ];
});
reverse-ddns.ddns-domains = map ({ name, ...}: {
name = "${name}.";
key-name = "dyndns";
dns-servers = [ {
ip-address = config.site.net.serv.hosts4.dns;
} {
ip-address = config.site.net.serv.hosts6.dn42.dns;
} ];
}) (
builtins.filter ({ name, dynamic, ... }:
dynamic && dynamic &&
(lib.hasSuffix ".in-addr.arpa" name || lib.hasSuffix ".in-addr.arpa" name
lib.hasSuffix ".ip6.arpa" name) ) ''
) config.site.dns.localZones zone ${name}. {
); primary ${config.site.net.serv.hosts4.dns};
control-socket = { primary6 ${config.site.net.serv.hosts6.dn42.dns};
socket-type = "unix"; key dyndns;
socket-name = "/run/kea/dhcp-ddns.socket"; }
}; ''
}; ) config.site.dns.localZones}
};
services.kea.ctrl-agent = lib.mkIf enabled { option arch code 93 = unsigned integer 16;
enable = true; group {
settings.control-sockets = { default-lease-time ${toString dhcp.time};
dhcp4 = { max-lease-time ${toString dhcp.max-time};
socket-type = "unix"; option routers ${config.site.net.${net}.hosts4.${builtins.replaceStrings [".${net}"] [""] dhcp.router}};
socket-name = "/run/kea/dhcp4.socket"; option domain-name "${domainName}";
}; option domain-name-servers 172.20.73.8, 9.9.9.9;
dhcp6 = { ddns-domainname "${domainName}";
socket-type = "unix";
socket-name = "/run/kea/dhcp6.socket";
};
d2 = {
socket-type = "unix";
socket-name = "/run/kea/dhcp-ddns.socket";
};
};
};
# Increase reliablity next-server ${config.site.net.serv.hosts4.netboot};
# (mostly for kea-dhcp-ddns-server.service) if option arch = 00:00 {
systemd.services = filename "netboot.xyz.kpxe";
let } else {
restartService.serviceConfig = { filename "netboot.xyz.efi";
RestartSec = 4; }
Restart = "always";
}; subnet ${subnet4Net} netmask ${lib.netmasks.${toString subnet4Len}} {
in { range ${dhcp.start} ${dhcp.end};
kea-dhcp4-server = restartService; }
kea-dhcp6-server = restartService;
kea-dhcp-ddns-server = restartService; update-static-leases on;
${builtins.concatStringsSep "\n" (
builtins.attrValues (
builtins.mapAttrs (addr: hwaddr:
''
host ${addr} {
hardware ethernet ${hwaddr};
fixed-address ${addr};
}
''
) dhcp.fixed-hosts
)
)}
}
''
) dhcpNets
)
)}
'';
}; };
} }

View File

@ -1,30 +1,33 @@
{ config, dns-nix, hostName, lib, pkgs, self, ... }: { hostName, config, lib, pkgs, self, inputs, ... }:
let let
serial = builtins.substring 0 10 self.lastModifiedDate; serial =
let
generateZoneFile = let timestamp = toString self.lastModified;
util = dns-nix.util.${pkgs.system}; datePkg = pkgs.runCommandLocal "date-${timestamp}" {} ''
in { name, ns, records, ... }: (util.writeZone name { date -d @${timestamp} +%Y%m%d%H > $out
TTL = 60*60; '';
SOA = { in
nameServer = "${lib.dns.ns}."; toString (import datePkg);
adminEmail = "astro@spaceboyz.net";
serial = lib.toInt serial; generateZoneFile = { name, ns, records, dynamic }:
refresh = 1*60*60; builtins.toFile "${name}.zone" ''
retry = 5*60; $ORIGIN ${name}.
expire = 2*60*60; $TTL 1h
minimum = 1*60;
}; @ IN SOA ${lib.dns.ns}. astro.spaceboyz.net. (
NS = map (a: a+".") ns; ${serial} ; serial
subdomains = lib.foldl (a: b: lib.recursiveUpdate a b) { } (map ({ name, type, data }: { 1h ; refresh
${name}.${type} = [ data ]; 1m ; retry
}) records); 2h ; expire
}).overrideAttrs (_: { 1m ; minimum
checkPhase = '' )
${pkgs.knot-dns}/bin/kzonecheck "$target" ${lib.concatMapStrings (ns: " IN NS ${ns}.\n") ns}
${lib.concatMapStrings ({ name, type, data }:
"${name} IN ${type} ${data}\n"
) records}
''; '';
});
in in
{ {
options = options =
@ -39,7 +42,7 @@ in
type = types.enum [ "A" "AAAA" "MX" "SRV" "CNAME" "TXT" "PTR" ]; type = types.enum [ "A" "AAAA" "MX" "SRV" "CNAME" "TXT" "PTR" ];
}; };
data = mkOption { data = mkOption {
type = types.oneOf [ types.str (types.attrsOf (types.oneOf [ types.int types.str ]))]; type = types.str;
}; };
}; };
@ -73,169 +76,90 @@ in
config = { config = {
site.dns.localZones = lib.dns.localZones; site.dns.localZones = lib.dns.localZones;
services.knot = lib.mkIf config.site.hosts.${hostName}.services.dns.enable ( services.bind = lib.mkIf config.site.hosts.${hostName}.services.dns.enable (
let let
generateZone = zone@{ name, dynamic, ... }: { generateZone = zone@{ name, dynamic, ... }: {
domain = name; inherit name;
template = "zentralwerk"; master = true;
acl = [ "zone_xfr" ] # allowed for zone-transfer
++ lib.optional (lib.hasSuffix ".arpa" name) "dn42" slaves = [
++ lib.optional dynamic "dyndns"; # ns.c3d2.de
file = if dynamic "217.197.84.53" "2001:67c:1400:2240::a"
then "/var/lib/knot/zones/${name}.zone" config.site.net.serv.hosts4.bind
config.site.net.serv.hosts6.dn42.bind
config.site.net.serv.hosts6.up4.bind
# ns.spaceboyz.net
"172.22.24.4" "2a01:4f9:4b:39ec::4"
];
file =
if dynamic
then "/var/db/bind/${name}.zone"
else generateZoneFile zone; else generateZoneFile zone;
notify = [ "all" ]; extraConfig = ''
also-notify {
# ns.c3d2.de
217.197.84.53;
2001:67c:1400:2240::a;
${config.site.net.serv.hosts4.bind};
${config.site.net.serv.hosts6.dn42.bind};
${config.site.net.serv.hosts6.up4.bind};
# ns.spaceboyz.net
172.22.24.4;
95.217.229.209;
2a01:4f9:4b:39ec::4;
};
notify-source ${config.site.net.serv.hosts4.dns};
notify-source-v6 ${config.site.net.serv.hosts6.up4.dns};
'' + lib.optionalString dynamic ''
allow-update { key "dyndns"; };
'';
}; };
in { in {
enable = true; enable = true;
settings = { zones = map generateZone config.site.dns.localZones;
acl = [
{
id = "dyndns";
action = "update";
key = "dyndns";
}
{
id = "zone_xfr";
address = with config.site.net.serv; [
# ns.c3d2.de
hosts4.knot hosts6.dn42.knot hosts6.up4.knot
"2a00:8180:2c00:282:2041:cbff:fe0c:8516"
"fd23:42:c3d2:582:2041:cbff:fe0c:8516"
# ns.spaceboyz.net
"172.22.24.4" "37.27.116.148" "2a01:4f9:3070:2728::4"
# ns1.supersandro.de
"188.34.196.104" "2a01:4f8:1c1c:1d38::1"
];
action = "transfer";
}
{
id = "dn42";
address = [ "172.22.24.4" "fd42:180:3de0:30::1" ];
}
];
key = [ { extraConfig = ''
id = "dyndns"; key "dyndns" {
algorithm = "hmac-sha256"; algorithm hmac-sha256;
secret = config.site.dyndnsKey; secret "${config.site.dyndnsKey}";
} ];
log = [ {
target = "syslog";
any = "info";
} ];
mod-stats = [ {
id = "default";
query-type = "on";
} ];
remote = let
via = with config.site.net.serv; [ hosts4.dns hosts6.up4.dns ];
in [
{
id = "ns.c3d2.de";
address = with config.site.net.serv; [ hosts4.knot hosts6.dn42.knot hosts6.up4.knot ];
inherit via;
} {
id = "ns.spaceboyz.net";
address = [
"172.22.24.4"
"37.27.116.148" "2a01:4f9:3070:2728::4"
];
inherit via;
} {
id = "ns1.supersandro.de";
address = [ /*"188.34.196.104"*/ "2a01:4f8:1c1c:1d38::1" ];
inherit via;
} {
id = "b.master.delegation-servers.dn42";
address = [ "172.22.24.4" "fd42:180:3de0:30::1" ];
}
];
remotes = [
{
id = "all";
remote = [ "ns.c3d2.de" "ns.spaceboyz.net" "ns1.supersandro.de" ];
}
{
id = "dn42";
remote = [ "b.master.delegation-servers.dn42" ];
}
];
server = {
answer-rotation = true;
automatic-acl = true;
identity = "dns.serv.zentralwerk.org";
listen = with config.site.net; [
"127.0.0.1" "::1"
serv.hosts4.dns serv.hosts6.up4.dns serv.hosts6.dn42.dns
];
tcp-fastopen = true;
version = null;
};
template = [
{
# default is a magic name and is always loaded.
# Because we want to use catalog-role/catalog-zone settings for all zones *except* the catalog zone itself, we must split the templates
id = "default";
global-module = [ "mod-stats" ];
}
{
id = "zentralwerk";
catalog-role = "member";
catalog-zone = "zentralwerk.";
dnssec-signing = true;
journal-content = "all"; # required for zonefile-load=difference-no-serial and makes cold starts like zone reloads
module = "mod-stats/default";
semantic-checks = true;
serial-policy = "increment";
storage = "/var/lib/knot/zones";
zonefile-load = "difference-no-serial";
}
];
zone = [ {
acl = "zone_xfr";
catalog-role = "generate";
domain = "zentralwerk.";
notify = [ "ns1.supersandro.de" "ns.spaceboyz.net" ];
storage = "/var/lib/knot/catalog";
} ] ++ map generateZone config.site.dns.localZones;
}; };
'';
extraOptions = ''
# allow underscores in dynamic hostnames
${lib.concatMapStringsSep "\n" (type: ''
check-names ${type} ignore;
'') [ "master" "slave" "response" ]}
'';
}); });
systemd.services = { systemd.services.create-dynamic-zones = {
create-dynamic-zones = {
description = "Creates dynamic zone files"; description = "Creates dynamic zone files";
requiredBy = [ "knot.service" ]; requiredBy = [ "bind.service" ];
before = [ "knot.service" ]; before = [ "bind.service" ];
serviceConfig.Type = "oneshot"; serviceConfig.Type = "oneshot";
script = '' script = ''
mkdir -p /var/lib/knot/zones mkdir -p /var/db/bind
${lib.concatMapStringsSep "\n" (zone@{ name, ... }: '' ${lib.concatMapStringsSep "\n" (zone@{ name, ... }: ''
[ -e /var/lib/knot/zones/${name}.zone ] || \ [ -e /var/db/bind/${name}.zone ] || \
cp ${generateZoneFile zone} /var/lib/knot/zones/${name}.zone cp ${generateZoneFile zone} /var/db/bind/${name}.zone
chown -R knot /var/lib/knot/zones chown -R named /var/db/bind
chmod -R u+rwX /var/lib/knot/zones chmod -R u+rwX /var/db/bind
'') (builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones)} '') (
builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones
)}
''; '';
}; };
systemd.services.update-dynamic-zones = {
update-dynamic-zones = {
description = "Creates initial records in dynamic zone files"; description = "Creates initial records in dynamic zone files";
requiredBy = [ "knot.service" ]; requiredBy = [ "bind.service" ];
after = [ "knot.service" ]; after = [ "bind.service" ];
serviceConfig.Type = "oneshot"; serviceConfig.Type = "oneshot";
path = [ pkgs.dnsutils ]; path = [ pkgs.dnsutils ];
script = lib.concatMapStrings (zone: '' script = ''
nsupdate -v -y "hmac-sha256:dyndns:${config.site.dyndnsKey}" <<EOF ${lib.concatMapStrings (zone: ''
nsupdate -y "hmac-sha256:dyndns:${config.site.dyndnsKey}" <<EOF
server localhost server localhost
${lib.concatMapStringsSep "\n" ({ name, type, data }: '' ${lib.concatMapStringsSep "\n" ({ name, type, data }: ''
@ -245,8 +169,10 @@ in
send send
EOF EOF
'') (builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones); '') (
}; builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones
)}
'';
}; };
}; };
} }

View File

@ -1,99 +1,105 @@
{ hostName, config, lib, pkgs, ... }: { hostName, config, lib, pkgs, ... }:
lib.mkIf config.site.hosts.${hostName}.services.dnscache.enable { lib.mkIf config.site.hosts.${hostName}.services.dnscache.enable {
services.kresd = { services.unbound = {
enable = true; enable = true;
instances = 4; settings = {
listenPlain = [ "0.0.0.0:53" "[::0]:53" ]; remote-control = {
package = pkgs.knot-resolver.override { extraFeatures = true; }; control-enable = true;
extraConfig = /* lua */ '' control-use-cert = false;
modules = { };
'http', server = {
'policy', num-threads = 4;
'predict', verbosity = 1;
'prefill', prefetch = true;
'serve_stale < cache', -- servce stail records while refreshing the record serve-expired = true;
'workarounds < iterate', -- solve problems around specific broken subdomains, mainly disables case randomization cache-min-ttl = 60;
'view' cache-max-ttl = 3600;
}
cache.size = 500 * MB interface = [ "0.0.0.0" "'::0'" ];
cache.min_ttl(60) # TODO: generate
access-control = [
"fd23:42:c3d2:500::/56 allow"
# TODO: remove
"2a02:8106:208:5200::/56 allow"
# TODO: remove
"2a02:8106:211:e900::/56 allow"
"2a00:8180:2000:37::1/128 allow"
"2a00:8180:2c00:200::/56 allow"
"::172.20.72.0/117 allow"
"::172.22.99.0/120 allow"
"::1/128 allow"
"172.20.72.0/21 allow"
"10.0.0.0/24 allow"
"10.200.0.0/15 allow"
"172.22.99.0/24 allow"
"127.0.0.0/8 allow"
"0.0.0.0/0 deny"
"::/0 deny"
];
# For DNS over TLS
tls-cert-bundle = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
net.listen('127.0.0.1', 8453, { kind = 'webmgmt' }) # allow reverse lookup of rfc1918 space, which includes the DN42 address space
http.prometheus.namespace = 'resolver_' unblock-lan-zones = true;
insecure-lan-zones = true;
-- dns42 domain-insecure = [
policy.add(policy.suffix( "dn42"
policy.STUB({'fd42:d42:d42:54::1', 'fd42:d42:d42:53::1', '172.20.0.53', '172.23.0.53'}), "d.f.ip6.arpa"
policy.todnames({'dn42.', 'd.f.ip6.arpa', '20.172.in-addr.arpa', '21.172.in-addr.arpa', '22.172.in-addr.arpa', '23.172.in-addr.arpa'}) "ffdd"
)) ];
};
-- freifunk forward-zone = let
policy.add(policy.suffix( mkFfddZone = name: {
policy.STUB({'10.200.0.4', '10.200.0.16'}), inherit name;
policy.todnames({'ffdd.', '200.10.in-addr.arpa', '201.10.in-addr.arpa'}) forward-addr = [ "10.200.0.4" "10.200.0.16" ];
)) };
in [ {
-- size.dns.localZones name = ".";
policy.add(policy.suffix( forward-tls-upstream = true;
policy.STUB({'${config.site.net.serv.hosts4.dns}', ${lib.concatStringsSep ", " (map (hosts6: "'${hosts6.dns}'") (builtins.attrValues config.site.net.serv.hosts6))}}), forward-addr = [
policy.todnames({${lib.concatStringsSep ", " (map (zone: "'${zone.name}'") config.site.dns.localZones)}}) # Quad9
)) "2620:fe::fe@853#dns.quad9.net"
"9.9.9.9@853#dns.quad9.net"
-- forward to dns caches "2620:fe::9@853#dns.quad9.net"
policy.add(policy.slice( "149.112.112.112@853#dns.quad9.net"
policy.slice_randomize_psl(), # Cloudflare DNS
-- quad9 "2606:4700:4700::1111@853#cloudflare-dns.com"
policy.TLS_FORWARD({ "1.1.1.1@853#cloudflare-dns.com"
{'2620:fe::fe', hostname='dns.quad9.net'}, "2606:4700:4700::1001@853#cloudflare-dns.com"
{'2620:fe::9', hostname='dns.quad9.net'}, "1.0.0.1@853#cloudflare-dns.com"
{'9.9.9.9', hostname='dns.quad9.net'}, ];
{'149.112.112.112', hostname='dns.quad9.net'} } ] ++
}), # Local networks
-- cloudflare map ({ name, ... }: {
policy.TLS_FORWARD({ name = "${name}";
{'2606:4700:4700::1111', hostname='cloudflare-dns.com'}, forward-addr = [ "${config.site.net.serv.hosts4.dns}" ] ++
{'2606:4700:4700::1001', hostname='cloudflare-dns.com'}, map (hosts6: hosts6.dns)
{'1.1.1.1', hostname='cloudflare-dns.com'}, (builtins.attrValues config.site.net.serv.hosts6);
{'1.0.0.1', hostname='cloudflare-dns.com'} }) config.site.dns.localZones
}) # Freifunk
)) ++ (map mkFfddZone [
"ffdd"
-- allow access from our networks "200.10.in-addr.arpa"
'' + lib.concatMapStringsSep "\n" (cidr: "view:addr('${cidr}', policy.all(policy.PASS))") [ "201.10.in-addr.arpa"
# localhost ]);
"::1/128" "127.0.0.0/8" # DN42
# mgmt stub-zone = let
"${config.site.net.mgmt.subnet4}" mkDn42Zone = name: {
# dn42 inherit name;
"fd23:42:c3d2:500::/56" "::172.20.72.0/117" "::172.22.99.0/120" stub-prime = true;
"172.20.72.0/21" "172.22.99.0/24" stub-addr = [
# freifunk "172.20.0.53" "fd42:d42:d42:54::1"
"10.200.0.0/15" "172.23.0.53" "fd42:d42:d42:53::1"
# DSI ];
"2a00:8180:2000:37::1/128" "2a00:8180:2c00:200::/56" };
# flpk in map mkDn42Zone [
"${config.site.net.flpk.subnet4}" "2a0f:5382:acab:1400::/56 allow" "dn42" "d.f.ip6.arpa"
] + "\n" + /* lua */ '' "20.172.in-addr.arpa" "21.172.in-addr.arpa"
"22.172.in-addr.arpa" "23.172.in-addr.arpa"
-- drop everything that hasn't matched ];
view:addr('0.0.0.0/0', policy.all(policy.DROP)) };
view:addr('::/0', policy.all(policy.DROP))
predict = {
window = 15, -- sampling window
period = 24*(60/15) -- track last X hours, divide through sampling window
}
prefill.config({
['.'] = {
url = 'https://www.internic.net/domain/root.zone',
interval = 86400, -- seconds
}
})
trust_anchors.set_insecure({'dn42', 'd.f.ip6.arpa', 'ffdd'})
'';
}; };
} }

View File

@ -1,114 +0,0 @@
{ config, lib, ... }:
let
inherit (config.networking) hostName;
interfaces = config.site.hosts.${hostName}.physicalInterfaces;
# linux iface name max length = 15
shortenNetName = name:
if builtins.match "priv(.*)" name != null
then "p" + builtins.substring 4 9 name
else if name == "coloradio"
then "cr"
else if name == "coloradio-gw"
then "cr-gw"
else name;
checkIfname = ifname: let
len = builtins.stringLength ifname;
in if len > 15
then throw "Interface name ${ifname} is ${toString (len - 15)} chars too long."
else ifname;
# `lxc.net.*` formatter for lxc.container.conf files
netConfig =
let
attrNamesOrdered = attrs:
if attrs ? type
then [ "type" ] ++ lib.remove "type" (builtins.attrNames attrs)
else builtins.attrNames attrs;
serialize = name: x:
if builtins.isString x
then "${name} = ${x}\n"
else if builtins.isAttrs x
then builtins.concatStringsSep "" (
map (n: serialize "${name}.${n}" x.${n}) (attrNamesOrdered x)
)
else if builtins.isList x
then
let
enumerate = xs: n:
if xs == []
then []
else [ {
e = builtins.head xs;
i = n;
} ] ++ enumerate (builtins.tail xs) (n + 1);
in
builtins.concatStringsSep "" (
map ({ e, i }: serialize "${name}.${toString i}" e) (enumerate x 0)
)
else throw "Invalid data in lxc net config for ${name}: ${lib.generators.toPretty {} x}";
in
serialize "lxc.net" (
map (netName:
let
ifData = interfaces.${netName};
in {
type = ifData.type;
name = checkIfname netName;
flags = "up";
hwaddr = if ifData ? hwaddr && ifData.hwaddr != null
then ifData.hwaddr
else "0A:14:48:xx:xx:xx";
} // (lib.optionalAttrs (ifData.type == "veth") {
veth.pair = checkIfname "${shortenNetName hostName}-${shortenNetName netName}";
veth.mode = checkIfname "bridge";
link = checkIfname netName;
}) // (lib.optionalAttrs (ifData.type == "phys") {
link = checkIfname "ext-${netName}";
})
) (builtins.attrNames interfaces)
);
in
{
system.build.lxcConfig = builtins.toFile "${hostName}.conf" ''
# For lxcfs and sane defaults
lxc.include = /etc/lxc/common.conf
lxc.uts.name = ${hostName}
# Handled by lxc@.service
lxc.start.auto = 0
lxc.rootfs.path = /var/lib/lxc/${hostName}/rootfs
lxc.init.cmd = "/init"
lxc.mount.entry = /nix/store nix/store none bind,ro 0 0
lxc.mount.entry = none tmp tmpfs defaults 0 0
lxc.mount.auto = proc:mixed sys:ro cgroup:mixed
lxc.autodev = 1
lxc.tty.max = 0
lxc.pty.max = 8
lxc.cap.drop = sys_module sys_time sys_nice sys_pacct sys_rawio
security.privileged = false
lxc.apparmor.profile = lxc-container-default-with-mounting
lxc.cgroup.memory.limit_in_bytes = 1G
lxc.cgroup.memory.kmem.tcp.limit_in_bytes = 128M
# tuntap
lxc.cgroup.devices.allow = c 10:200 rw
lxc.cgroup2.devices.allow = c 10:200 rw
# ppp
lxc.cgroup.devices.allow = c 108:0 rwm
lxc.cgroup2.devices.allow = c 108:0 rwm
${netConfig}
'';
}

View File

@ -0,0 +1,22 @@
{ lib, pkgs, ... }:
let
netboot_xyz_efi = pkgs.fetchurl {
url = "https://github.com/netbootxyz/netboot.xyz/releases/download/2.0.40/netboot.xyz.efi";
sha256 = "1gvgvlaxhjkr9i0b2bjq85h12ni9h5fn6r8nphsag3il9kificcc";
};
netboot_xyz_kpxe = pkgs.fetchurl {
url = "https://github.com/netbootxyz/netboot.xyz/releases/download/2.0.40/netboot.xyz.kpxe";
sha256 = "1crkr995i1hv3q548gx2xan1ymxmzcnr7mxaf77s2410mpqfcx82";
};
tftpRoot = pkgs.runCommand "tftproot" {} ''
mkdir -p $out
ln -s ${netboot_xyz_efi} $out/netboot.xyz.efi
ln -s ${netboot_xyz_kpxe} $out/netboot.xyz.kpxe
'';
in
{
services.atftpd = {
enable = true;
root = tftpRoot;
};
}

View File

@ -1,4 +1,4 @@
{ hostName, config, lib, pkgs, ... }: { hostName, config, lib, ... }:
let let
hostConf = config.site.hosts.${hostName}; hostConf = config.site.hosts.${hostName};
@ -15,8 +15,6 @@ let
else null; else null;
enabled = firstUpstreamInterface != null; enabled = firstUpstreamInterface != null;
inherit (upstreamInterfaces.${firstUpstreamInterface}.upstream) staticIpv4Address;
in in
{ {
systemd.network.networks = { systemd.network.networks = {
@ -24,23 +22,19 @@ in
# systemd-networkd only requests Prefix Delegation via DHCPv6 on # systemd-networkd only requests Prefix Delegation via DHCPv6 on
# the upstream interface if another interface is configured for it. # the upstream interface if another interface is configured for it.
# without this, the static ipv6 subnet won't be routed to us. # without this, the static ipv6 subnet won't be routed to us.
networkConfig.DHCPPrefixDelegation = true; networkConfig.DHCPv6PrefixDelegation = true;
dhcpV6PrefixDelegationConfig = { dhcpV6PrefixDelegationConfig = {
SubnetId = "81"; SubnetId = "81";
# because we have static addresses, we don't actually use this # because we have static addresses, we don't actually use this
Assign = false; Assign = false;
}; };
}; };
} // builtins.mapAttrs (_: { upstream, ... }: } // builtins.mapAttrs (_: { upstream, ... }: {
# DHCP
lib.optionalAttrs (hostName != "flpk-gw") {
DHCP = "yes"; DHCP = "yes";
networkConfig.IPv6AcceptRA = true; networkConfig.IPv6AcceptRA = true;
dhcpV6Config.PrefixDelegationHint = "::/56"; dhcpV6Config.PrefixDelegationHint = "::/56";
}
//
# Traffic Shaping # Traffic Shaping
{
extraConfig = '' extraConfig = ''
[CAKE] [CAKE]
Parent = root Parent = root
@ -56,100 +50,36 @@ in
Bandwidth = ${toString upstream.upBandwidth}K Bandwidth = ${toString upstream.upBandwidth}K
''} ''}
''; '';
} }) upstreamInterfaces;
) upstreamInterfaces;
networking.nat = lib.optionalAttrs enabled { networking.nat = lib.optionalAttrs enabled {
enable = true; enable = true;
enableIPv6 = true;
internalInterfaces = [ "core" ]; internalInterfaces = [ "core" ];
externalInterface = firstUpstreamInterface; externalInterface = firstUpstreamInterface;
externalIP = staticIpv4Address; externalIP = upstreamInterfaces.${firstUpstreamInterface}.upstream.staticIpv4Address;
extraCommands = '' extraCommands =
# Add workaround for upstreams with wonky MTU
iptables -t mangle -A FORWARD \
-p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
ip6tables -t mangle -A FORWARD \
-p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
# Prohibit SMTP except for servers
iptables -N fwd_smtp || \
iptables -F fwd_smtp
iptables -A fwd_smtp --source ${config.site.net.serv.subnet4} -j RETURN
iptables -A fwd_smtp --dest ${config.site.net.serv.subnet4} -j RETURN
iptables -A fwd_smtp --source ${config.site.net.flpk.subnet4} -j RETURN
iptables -A fwd_smtp --dest ${config.site.net.flpk.subnet4} -j RETURN
iptables -A fwd_smtp -j REJECT
iptables -I FORWARD -p tcp --dport 25 -j fwd_smtp
ip6tables -N fwd_smtp || \
ip6tables -F fwd_smtp
${lib.concatMapStrings (subnet6: ''
ip6tables -A fwd_smtp --source ${subnet6} -j RETURN
ip6tables -A fwd_smtp --dest ${subnet6} -j RETURN
'') (builtins.concatMap builtins.attrValues [
config.site.net.serv.subnets6
config.site.net.flpk.subnets6
])}
ip6tables -A fwd_smtp -j REJECT
ip6tables -I FORWARD -p tcp --dport 25 -j fwd_smtp
${lib.optionalString (staticIpv4Address != null) ''
# Allow connections to ${staticIpv4Address} from other hosts behind NAT
${lib.concatMapStrings (fwd: let
m = builtins.match "([0-9.]+):([0-9-]+)" fwd.destination;
destinationIP = if m == null then throw "bad ip:ports `${fwd.destination}'" else lib.elemAt m 0;
destinationPorts = if m == null then throw "bad ip:ports `${fwd.destination}'" else builtins.replaceStrings ["-"] [":"] (lib.elemAt m 1);
in ''
iptables -t nat -A nixos-nat-pre \
-d ${staticIpv4Address} -p ${fwd.proto} \
--dport ${builtins.toString fwd.sourcePort} \
-j DNAT --to-destination ${fwd.destination}
iptables -t nat -A nixos-nat-post \
-d ${destinationIP} -p ${fwd.proto} \
--dport ${destinationPorts} \
-s 172.20.72.0/21 -j MASQUERADE
iptables -t nat -A nixos-nat-post \
-d ${destinationIP} -p ${fwd.proto} \
--dport ${destinationPorts} \
-s ${config.site.net.c3d2.subnet4} -j MASQUERADE
'') config.networking.nat.forwardPorts}
''}
# Do not NAT our public IPv4 addresses
${lib.concatMapStringsSep "\n" (net:
lib.concatMapStrings (subnet: ''
iptables -t nat -I nixos-nat-post \
-o ${net} \
-s ${subnet} \
-j RETURN
'') upstreamInterfaces.${net}.upstream.noNat.subnets4 or []
) (builtins.attrNames hostConf.interfaces)}
# Provide IPv6 upstream for everyone, using NAT66 when not from # Provide IPv6 upstream for everyone, using NAT66 when not from
# our static prefixes # our static prefixes
${lib.concatMapStringsSep "\n" (net: lib.concatMapStringsSep "\n" (net: ''
lib.concatMapStrings (subnet: '' ip6tables -t nat -N ${net}_nat || \
ip6tables -t nat -I nixos-nat-post \ ip6tables -t nat -F ${net}_nat
-o ${net} \ ${lib.concatMapStringsSep "\n" (subnet: ''
ip6tables -t nat -A ${net}_nat \
-s ${subnet} \ -s ${subnet} \
-j RETURN -j RETURN
'') upstreamInterfaces.${net}.upstream.noNat.subnets6 '') upstreamInterfaces.${net}.upstream.noNat.subnets6}
) (builtins.attrNames upstreamInterfaces)} ip6tables -t nat -A ${net}_nat -j MASQUERADE
# There just have been moments without a complete ruleset. Flush
# out invalid conntrack states!
${pkgs.conntrack-tools}/bin/conntrack -F
'';
extraStopCommands = ''
iptables -F FORWARD 2>/dev/null || true
ip6tables -F FORWARD 2>/dev/null || true
ip6tables -t nat -A POSTROUTING \
-o ${net} \
-j ${net}_nat
'') (builtins.attrNames upstreamInterfaces);
extraStopCommands =
lib.concatMapStringsSep "\n" (net: ''
ip6tables -t nat -F POSTROUTING 2>/dev/null || true ip6tables -t nat -F POSTROUTING 2>/dev/null || true
''; ip6tables -t nat -F ${net}_nat 2>/dev/null || true
ip6tables -t nat -X ${net}_nat 2>/dev/null || true
'') (builtins.attrNames upstreamInterfaces);
forwardPorts = map ({ destination, sourcePort, reflect, ... }@forwardedPort: forwardPorts = map ({ destination, sourcePort, reflect, ... }@forwardedPort:
removeAttrs forwardedPort ["reflect"] // { removeAttrs forwardedPort ["reflect"] // {
@ -159,7 +89,11 @@ in
else "${destination}:${toString sourcePort}"; else "${destination}:${toString sourcePort}";
loopbackIPs = loopbackIPs =
if reflect if reflect
then [ config.site.net.core.hosts4.${hostName} ] then builtins.filter (ip: ip != null) (
map (net:
upstreamInterfaces.${net}.upstream.staticIpv4Address
) (builtins.attrNames upstreamInterfaces)
)
else []; else [];
} }
) hostConf.forwardPorts; ) hostConf.forwardPorts;

View File

@ -1,4 +1,4 @@
{ hostName, config, lib, ... }: { hostName, inputs, config, lib, ... }:
let let
hostConf = config.site.hosts.${hostName}; hostConf = config.site.hosts.${hostName};
@ -26,7 +26,7 @@ in lib.mkIf (pppoeInterfaces != {}) {
enable = true; enable = true;
autostart = true; autostart = true;
config = '' config = ''
plugin pppoe.so plugin rp-pppoe.so
nic-${upstream.link} nic-${upstream.link}
ifname ${ifName} ifname ${ifName}
# Login settings. (PAP) # Login settings. (PAP)
@ -64,17 +64,14 @@ in lib.mkIf (pppoeInterfaces != {}) {
in networks // { in networks // {
"${ifName}" = { "${ifName}" = {
matchConfig.Name = "${ifName}"; matchConfig.Name = "${ifName}";
linkConfig = lib.optionalAttrs (ifName == "core") {
# interface is stuck in "routable (configuring)" and blocks systemd-networkd-wait-online
# TODO: figure out why exactly
RequiredForOnline = false;
};
networkConfig = { networkConfig = {
DHCP = lib.mkForce "ipv6"; DHCP = lib.mkOverride 900 "ipv6";
# accept config set by pppd # accept config set by pppd
KeepConfiguration = "yes"; KeepConfiguration = "yes";
}; };
dhcpV6Config = { dhcpV6Config = {
RapidCommit = true;
ForceDHCPv6PDOtherInformation = true;
PrefixDelegationHint = "::/56"; PrefixDelegationHint = "::/56";
}; };
}; };
@ -84,4 +81,11 @@ in lib.mkIf (pppoeInterfaces != {}) {
}; };
}) {} (builtins.attrNames pppoeInterfaces); }) {} (builtins.attrNames pppoeInterfaces);
# TODO: needed?
networking.nat.extraCommands = ''
iptables -A FORWARD \
-p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
'';
} }

View File

@ -1,58 +0,0 @@
{ config, pkgs, ... }:
let
privateKeyFile = ifName:
"/run/wireguard-keys/${ifName}.key";
ifName = "vpn";
in
{
systemd.services = {
"wireguard-key-${ifName}" = {
description = "Create key file for wireguard interface '${ifName}'";
requiredBy = [ "systemd-networkd.service" ];
before = [ "systemd-networkd.service" ];
serviceConfig.Type = "oneshot";
script = ''
#! ${pkgs.runtimeShell} -e
F=${privateKeyFile ifName}
mkdir -p -m 0700 $(dirname $F)
chown systemd-network:systemd-network $(dirname $F)
rm -f $F
cat >$F <<EOF
${config.site.vpn.wireguard.privateKey}
EOF
chmod 0400 $F
chown systemd-network:systemd-network $F
'';
};
};
systemd.network.netdevs.vpn = {
netdevConfig = {
Name = ifName;
Kind = "wireguard";
};
wireguardConfig = {
PrivateKeyFile = privateKeyFile ifName;
ListenPort = config.site.vpn.wireguard.port;
};
wireguardPeers = map ({ publicKey, allowedIPs }: {
wireguardPeerConfig = {
PublicKey = publicKey;
AllowedIPs = allowedIPs ++ [ "fe80::/64" "ff02::/16" ];
};
}) config.site.vpn.wireguard.peers;
};
systemd.network.networks.vpn.addresses = [ {
addressConfig = {
Address = "fe80::1/64";
Scope = "link";
};
} ];
environment.systemPackages = [
pkgs.wireguard-tools
];
}

View File

@ -1,7 +1,7 @@
# wireguard upstreams (like njalla and flpk, not like vpn dialup. see vpn-gw)
{ hostName, config, lib, pkgs, ... }: { hostName, config, lib, pkgs, ... }:
let let
gateway = "upstream1";
tunnels = lib.filterAttrs (_: { wireguard, ... }: tunnels = lib.filterAttrs (_: { wireguard, ... }:
wireguard != null wireguard != null
@ -16,7 +16,7 @@ let
"/run/wireguard-keys/${ifName}.key"; "/run/wireguard-keys/${ifName}.key";
wireguardMark = 3; wireguardMark = 3;
vpnTable = 100; vpn4Table = 100;
in in
{ {
systemd.services = builtins.foldl' (services: ifName: services // { systemd.services = builtins.foldl' (services: ifName: services // {
@ -52,6 +52,7 @@ in
}; };
wireguardConfig = { wireguardConfig = {
PrivateKeyFile = privateKeyFile ifName; PrivateKeyFile = privateKeyFile ifName;
# Mark for routing with another routing table
FirewallMark = wireguardMark; FirewallMark = wireguardMark;
}; };
wireguardPeers = [ { wireguardPeers = [ {
@ -67,10 +68,10 @@ in
# Wireguard transported through another routing table # Wireguard transported through another routing table
# (containing upstream by bird ospf) # (containing upstream by bird ospf)
core.routingPolicyRules = [ { core.routingPolicyRules = [ {
# Marked wireguard packets take the vpn routing table # Marked wireguard packets take the vpn4 routing table
routingPolicyRuleConfig = { routingPolicyRuleConfig = {
Table = vpn4Table;
FirewallMark = wireguardMark; FirewallMark = wireguardMark;
Table = vpnTable;
}; };
} ]; } ];
} // builtins.mapAttrs (ifName: { wireguard, upstream, ... }: { } // builtins.mapAttrs (ifName: { wireguard, upstream, ... }: {
@ -83,12 +84,12 @@ in
# IPv4 default route # IPv4 default route
networkConfig.DefaultRouteOnDevice = true; networkConfig.DefaultRouteOnDevice = true;
routes = [ {
# IPv6 default route # IPv6 default route
routes = [ {
routeConfig.Destination = "::/0"; routeConfig.Destination = "::/0";
} ]; } ];
extraConfig = lib.mkIf (upstream.upBandwidth != null) '' extraConfig = ''
[CAKE] [CAKE]
Parent = root Parent = root
# DOCSIS overhead # DOCSIS overhead
@ -109,7 +110,7 @@ in
networking.iproute2 = lib.mkIf enabled { networking.iproute2 = lib.mkIf enabled {
enable = true; enable = true;
rttablesExtraConfig = '' rttablesExtraConfig = ''
${toString vpnTable} vpn ${toString vpn4Table} vpn4
''; '';
}; };

View File

@ -0,0 +1,57 @@
{ pkgs, lib, config, hostName, ... }:
let
hostConf = config.site.hosts.${hostName};
cfg = hostConf.services.yggdrasil;
in lib.mkIf cfg.enable {
networking.firewall.enable = false;
boot.postBootCommands = ''
if [ ! -c /dev/net/tun ]; then
mkdir -p /dev/net
mknod -m 666 /dev/net/tun c 10 200
fi
'';
# Forward traffic under the prefix.
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
networking.nat = {
enable = true;
# Provide NAT66 for everyone with addresses foreign to Yggdrasil
extraCommands = ''
ip6tables -t nat -A POSTROUTING ! --src 200::/7 -o ygg -j MASQUERADE
'';
};
systemd.tmpfiles.rules = [
"d /var/lib/yggdrasil 0700 root root -"
"L+ /var/lib/yggdrasil/keys.json - - - - ${builtins.toFile "keys.json" cfg.keys}"
];
services.yggdrasil = {
enable = true;
persistentKeys = true;
config = {
IfName = "ygg";
Peers = # https://publicpeers.neilalexander.dev/
[
# czechia
"tcp://[2a03:3b40:fe:ab::1]:46370" # emery vpsfree.cz
# poland
"tls://[2001:41d0:601:1100::cf2]:11129"
];
Listen = [
"tcp://[::]:1337"
# Not needed as `sysctl net.ipv6.bindv6only=0` by default
# "tcp://0.0.0.0:1337"
];
NodeInfo = {
# This information is visible to the network.
name = "y.c3d2.de";
location = "Dresden";
email = "ehmry@c3d2.de";
};
};
};
}

View File

@ -1,13 +1,13 @@
# Pulls together NixOS configuration modules according to the # Pulls together NixOS configuration modules according to the
# name/role of the host to be built. # name/role of the host to be built.
{ hostName, lib, ... }: { hostName, config, lib, pkgs, ... }:
let let
inherit (lib) optionals; inherit (lib) optionals;
hostConfig = lib.config.site.hosts.${hostName}; hostConfig = lib.config.site.hosts.${hostName};
in { in {
inherit (lib.config) site; site = lib.config.site;
imports = [ imports = [
../lib/config/options.nix ../lib/config/options.nix
@ -20,27 +20,24 @@ in {
./server/default.nix ./server/default.nix
] ++ ] ++
optionals (hostConfig.role == "container") [ optionals (hostConfig.role == "container") [
./container/lxc-config.nix
./container/defaults.nix ./container/defaults.nix
./container/dhcp-server.nix ./container/dhcp-server.nix
./container/wireguard.nix ./container/wireguard.nix
./container/dns.nix ./container/dns.nix
./container/dnscache.nix ./container/dnscache.nix
./container/yggdrasil.nix
] ++ ] ++
optionals lib.config.site.hosts.${hostName}.isRouter [ optionals lib.config.site.hosts.${hostName}.isRouter [
./container/bird.nix ./container/bird.nix
] ++ ] ++
optionals ( optionals (builtins.match "upstream.*" hostName != null) [
builtins.match "upstream.*" hostName != null ||
hostName == "flpk-gw"
) [
./container/upstream.nix ./container/upstream.nix
./container/upstream/pppoe.nix ./container/upstream/pppoe.nix
] ++ ] ++
optionals (hostName == "mgmt-gw") [ optionals (hostName == "mgmt-gw") [
./container/mgmt-gw.nix ./container/mgmt-gw.nix
] ++ ] ++
optionals (hostName == "vpn-gw") [ optionals (hostName == "netboot") [
./container/vpn.nix ./container/netboot.nix
]; ];
} }

View File

@ -1,4 +1,4 @@
{ hostName, inputs, config, lib, pkgs, ... }: { hostName, inputs, pkgs, config, options, lib, ... }:
{ {
boot.kernelParams = [ boot.kernelParams = [
@ -7,9 +7,11 @@
# Prevents automatic creation of interface bond0 by the kernel # Prevents automatic creation of interface bond0 by the kernel
"bonding.max_bonds=0" "bonding.max_bonds=0"
]; ];
boot.tmp.useTmpfs = true; boot.tmpOnTmpfs = true;
# Includes wireguard # Includes wireguard
boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages; boot.kernelPackages = pkgs.linuxPackages_latest;
# Keep building
boot.zfs.enableUnstable = true;
# no persistent logs # no persistent logs
services.journald.extraConfig = '' services.journald.extraConfig = ''
@ -23,18 +25,11 @@
registry = { registry = {
nixpkgs.flake = inputs.nixpkgs; nixpkgs.flake = inputs.nixpkgs;
}; };
settings = {
substituters = lib.mkBefore [ "https://hydra.hq.c3d2.de" ];
trusted-public-keys = [
"nix-serve.hq.c3d2.de:KZRGGnwOYzys6pxgM8jlur36RmkJQ/y8y62e52fj1ps=%"
];
};
}; };
documentation = { documentation = {
enable = lib.mkForce false; enable = false;
nixos.enable = lib.mkForce false; nixos.enable = false;
}; };
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
@ -42,8 +37,6 @@
bridge-utils bridge-utils
conntrack-tools conntrack-tools
dhcpcd dhcpcd
dhcpdump
dig
ethtool ethtool
git git
iftop iftop
@ -56,7 +49,6 @@
screen screen
speedtest-cli speedtest-cli
tcpdump tcpdump
tmux
traceroute traceroute
vim vim
wget wget
@ -64,25 +56,6 @@
networking.hostName = hostName; networking.hostName = hostName;
programs = {
fzf.keybindings = true;
git = {
enable = true;
config = {
alias = {
co = "checkout";
lg = "log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold y
ow)%d%C(reset)'";
remote = "remote -v";
st = "status";
undo = "reset --soft HEAD^";
};
pull.rebase = true;
rebase.autoStash = true;
};
};
};
users.users.root.initialHashedPassword = ""; users.users.root.initialHashedPassword = "";
system.stateVersion = "20.09"; system.stateVersion = "20.09";

View File

@ -1,18 +1,11 @@
{ hostName, config, lib, ... }: { hostName, config, lib, ... }:
let lib.mkIf config.site.hosts.${hostName}.firewall.enable {
hostConfig = config.site.hosts.${hostName}; networking.firewall = {
in {
networking.firewall = lib.mkIf hostConfig.firewall.enable {
enable = true; enable = true;
extraCommands = '' extraCommands = ''
${lib.optionalString hostConfig.isRouter ''
ip46tables -I nixos-fw -p ospfigp -j ACCEPT
''}
ip46tables -A FORWARD -i core -m state --state ESTABLISHED,RELATED -j ACCEPT ip46tables -A FORWARD -i core -m state --state ESTABLISHED,RELATED -j ACCEPT
ip46tables -A FORWARD -i core -j REJECT ip46tables -A FORWARD -i core -j REJECT --reject-with net-unreach
''; '';
extraStopCommands = '' extraStopCommands = ''
ip46tables -F FORWARD ip46tables -F FORWARD

View File

@ -1,4 +1,4 @@
{ hostName, config, lib, ... }: { hostName, config, lib, pkgs, ... }:
let let
# pick an address for a net's gateway # pick an address for a net's gateway

View File

@ -1,4 +1,4 @@
{ pkgs, ... }: { pkgs, nixpkgs-master, ... }:
{ {
boot.kernelModules = [ "kvm-intel" "pppoe" ]; boot.kernelModules = [ "kvm-intel" "pppoe" ];
boot.kernelParams = [ "nomodeset" ]; boot.kernelParams = [ "nomodeset" ];
@ -8,20 +8,16 @@
time.timeZone = "Europe/Berlin"; time.timeZone = "Europe/Berlin";
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git wget vim git screen
inetutils # telnet
ipmitool ipmitool
liboping # noping
screen
vim
wget
]; ];
services.openssh.enable = true;
services.openssh = { services.openssh.permitRootLogin = "prohibit-password";
enable = true;
settings.PermitRootLogin = "prohibit-password";
};
# additional config for bare metal # additional config for bare metal
services.collectd.plugins.ipmi = ""; services.collectd = {
plugins.ipmi = "";
# FIXME: IPMI is only available with nixpkgs-21.11 onwards
package = nixpkgs-master.legacyPackages.${pkgs.system}.collectd;
};
} }

View File

@ -1,4 +1,4 @@
{ self, config, lib, pkgs, ... }: { hostName, self, config, lib, pkgs, ... }:
let let
# Containers that are run on this host # Containers that are run on this host
@ -10,6 +10,70 @@ let
enabled = containers != {}; enabled = containers != {};
# linux iface name max length = 15
shortenNetName = name:
if builtins.match "priv(.*)" name != null
then "p" + builtins.substring 4 9 name
else name;
checkIfname = ifname: let
len = builtins.stringLength ifname;
in if len > 15
then throw "Interface name ${ifname} is ${toString (len - 15)} chars too long."
else ifname;
# `lxc.net.*` formatter for lxc.container.conf files
netConfig = ctName: interfaces:
let
config = map (netName:
let
ifData = interfaces.${netName};
in {
type = ifData.type;
name = checkIfname netName;
flags = "up";
hwaddr = if ifData ? hwaddr && ifData.hwaddr != null
then ifData.hwaddr
else "0A:14:48:xx:xx:xx";
} // (lib.optionalAttrs (ifData.type == "veth") {
veth.pair = checkIfname "${shortenNetName ctName}-${shortenNetName netName}";
veth.mode = checkIfname "bridge";
link = checkIfname netName;
}) // (lib.optionalAttrs (ifData.type == "phys") {
link = checkIfname "ext-${netName}";
})
) (builtins.attrNames interfaces);
attrNamesOrdered = attrs:
if attrs ? type
then [ "type" ] ++ lib.remove "type" (builtins.attrNames attrs)
else builtins.attrNames attrs;
serialize = name: x:
if builtins.isString x
then "${name} = ${x}\n"
else if builtins.isAttrs x
then builtins.concatStringsSep "" (
map (n: serialize "${name}.${n}" x.${n}) (attrNamesOrdered x)
)
else if builtins.isList x
then
let
enumerate = xs: n:
if xs == []
then []
else [ {
e = builtins.head xs;
i = n;
} ] ++ enumerate (builtins.tail xs) (n + 1);
in
builtins.concatStringsSep "" (
map ({ e, i }: serialize "${name}.${toString i}" e) (enumerate x 0)
)
else throw "Invalid data in lxc net config for ${name}: ${lib.generators.toPretty {} x}";
in
serialize "lxc.net" config;
# User-facing script to build/update container NixOS systems # User-facing script to build/update container NixOS systems
build-script = pkgs.writeScriptBin "build-container" '' build-script = pkgs.writeScriptBin "build-container" ''
#! ${pkgs.runtimeShell} -e #! ${pkgs.runtimeShell} -e
@ -30,7 +94,6 @@ let
${ctName}) ${ctName})
echo Using prebuilt system for container $c echo Using prebuilt system for container $c
SYSTEM=${self.packages.x86_64-linux."${ctName}-rootfs"} SYSTEM=${self.packages.x86_64-linux."${ctName}-rootfs"}
CONFIG=${self.packages.x86_64-linux."${ctName}-lxc-config"}
;; ;;
'') ( '') (
builtins.attrNames ( builtins.attrNames (
@ -42,8 +105,6 @@ let
echo Building $c echo Building $c
nix build -o /nix/var/nix/gcroots/lxc/$c zentralwerk-network#$c-rootfs nix build -o /nix/var/nix/gcroots/lxc/$c zentralwerk-network#$c-rootfs
SYSTEM=$(readlink /nix/var/nix/gcroots/lxc/$c) SYSTEM=$(readlink /nix/var/nix/gcroots/lxc/$c)
nix build -o /nix/var/nix/gcroots/lxc/$c.config zentralwerk-network#$c-lxc-config
CONFIG=$(readlink /nix/var/nix/gcroots/lxc/$c.config)
;; ;;
esac esac
@ -56,7 +117,6 @@ let
mkdir -p /var/lib/lxc/$c/rootfs/$d mkdir -p /var/lib/lxc/$c/rootfs/$d
done done
ln -fs $SYSTEM/init /var/lib/lxc/$c/rootfs/init ln -fs $SYSTEM/init /var/lib/lxc/$c/rootfs/init
ln -fs $CONFIG /var/lib/lxc/$c/config
done done
# Activate all the desired container after all of them are # Activate all the desired container after all of them are
@ -102,8 +162,10 @@ in
virtualisation.lxc = lib.mkIf enabled { virtualisation.lxc = lib.mkIf enabled {
enable = true; enable = true;
# Container configs live in /etc so that they can be created
# through `environment.etc`.
systemConfig = '' systemConfig = ''
lxc.lxcpath = /var/lib/lxc lxc.lxcpath = /etc/lxc/containers
''; '';
}; };
@ -114,7 +176,50 @@ in
enable-script disable-script enable-script disable-script
]; ];
environment.etc."lxc/common.conf".source = "${pkgs.lxc}/share/lxc/config/common.conf"; # Create lxc.container.conf files
environment.etc =
builtins.foldl' (etc: ctName: etc // {
"lxc/containers/${ctName}/config" = {
enable = true;
source =
builtins.toFile "${ctName}.conf" ''
# For lxcfs and sane defaults
lxc.include = /etc/lxc/common.conf
lxc.uts.name = ${ctName}
# Handled by lxc@.service
lxc.start.auto = 0
lxc.rootfs.path = /var/lib/lxc/${ctName}/rootfs
lxc.init.cmd = "/init"
lxc.mount.entry = /nix/store nix/store none bind,ro 0 0
lxc.mount.entry = none tmp tmpfs defaults 0 0
lxc,mount.auto = proc:mixed sys:ro cgroup:mixed
lxc.autodev = 1
lxc.tty.max = 0
lxc.pty.max = 8
lxc.cap.drop = sys_module sys_time sys_nice sys_pacct sys_rawio
security.privileged = false
lxc.apparmor.profile = lxc-container-default-with-mounting
lxc.cgroup.memory.limit_in_bytes = 1G
lxc.cgroup.memory.kmem.tcp.limit_in_bytes = 128M
# tuntap
lxc.cgroup.devices.allow = c 10:200 rw
lxc.cgroup2.devices.allow = c 10:200 rw
# ppp
lxc.cgroup.devices.allow = c 108:0 rwm
lxc.cgroup2.devices.allow = c 108:0 rwm
${netConfig ctName containers.${ctName}.physicalInterfaces}
'';
};
}) {
"lxc/common.conf".source = "${pkgs.lxc}/share/lxc/config/common.conf";
} (builtins.attrNames containers);
# Systemd service template for LXC containers # Systemd service template for LXC containers
systemd.services."lxc@" = { systemd.services."lxc@" = {
@ -143,8 +248,6 @@ in
Restart = "always"; Restart = "always";
RestartSec = "1s"; RestartSec = "1s";
}; };
# Prevent restart on host nixos-rebuild switch
restartIfChanged = false;
}; };
# Starts all the containers after boot # Starts all the containers after boot

View File

@ -1,5 +1,5 @@
# Server network configuration # Server network configuration
{ config, lib, ... }: { hostName, self, config, lib, pkgs, ... }:
let let
# LXC containers on this host # LXC containers on this host
@ -114,7 +114,5 @@ in
networkConfig.Bridge = net; networkConfig.Bridge = net;
}; };
}) {} ctNets; }) {} ctNets;
wait-online.anyInterface = true;
}; };
} }

View File

@ -1,17 +1,21 @@
{ config, ... }: { config, pkgs, ... }:
{ {
# Use the systemd-boot EFI boot loader. boot.loader.grub.enable = true;
boot.loader.systemd-boot.enable = true; boot.loader.grub.version = 2;
boot.loader.efi.canTouchEfiVariables = true; boot.loader.grub.devices = [
"/dev/disk/by-path/pci-0000:05:00.0-scsi-0:1:0:0"
"/dev/disk/by-path/pci-0000:05:00.0-scsi-0:1:0:1"
];
networking.hostName = "server1"; # Define your hostname. networking.hostName = "server1"; # Define your hostname.
networking.hostId = "01010101"; networking.hostId = "12345678";
boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ata_piix" "hpsa" "usb_storage" "usbhid" "sd_mod" "sr_mod" ]; boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ata_piix" "hpsa" "usb_storage" "usbhid" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
nixpkgs.config.allowBroken = true; nixpkgs.config.allowBroken = true;
boot.zfs.enableUnstable = true;
boot.supportedFilesystems = [ "zfs" ]; boot.supportedFilesystems = [ "zfs" ];
boot.initrd.supportedFilesystems = [ "zfs" ]; boot.initrd.supportedFilesystems = [ "zfs" ];
# Required for Broadcom NICs # Required for Broadcom NICs
@ -43,8 +47,8 @@
}; };
fileSystems."/boot" = fileSystems."/boot" =
{ device = "/dev/disk/by-label/ESP"; { device = "/dev/disk/by-uuid/23f17e88-ab7e-4dcc-a119-2ed1b9c2c91d";
fsType = "vfat"; fsType = "ext2";
}; };
swapDevices = [ ]; swapDevices = [ ];

View File

@ -1,9 +1,10 @@
{ ... }: { pkgs, ... }:
{ {
boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ahci" "usbhid" "sd_mod" "sr_mod" ]; boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ahci" "usbhid" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
nixpkgs.config.allowBroken = true; nixpkgs.config.allowBroken = true;
boot.zfs.enableUnstable = true;
boot.supportedFilesystems = [ "zfs" ]; boot.supportedFilesystems = [ "zfs" ];
boot.initrd.supportedFilesystems = [ "zfs" ]; boot.initrd.supportedFilesystems = [ "zfs" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
@ -38,6 +39,7 @@
}; };
boot.loader.grub.enable = true; boot.loader.grub.enable = true;
boot.loader.grub.version = 2;
boot.loader.grub.device = "/dev/sda"; boot.loader.grub.device = "/dev/sda";
networking.hostName = "server2"; # Define your hostname. networking.hostName = "server2"; # Define your hostname.

View File

@ -1,38 +1,31 @@
{ self, pkgs, hostName }: { self, pkgs, hostName, config, hostConfig, ... }:
with pkgs; with pkgs;
with lib; with lib;
let let
inherit (self.lib) config;
hostConfig = config.site.hosts.${hostName};
ports = self.lib.getOpenwrtPorts hostConfig.model; ports = self.lib.getOpenwrtPorts hostConfig.model;
uciDeleteAll = key: '' uciDeleteAll = key: ''
while uci -q delete ${key}[-1]; do :; done while uci -q delete ${key}[-1]; do :; done
''; '';
# hostBridgedNets =
# self.lib.unique (
# builtins.concatMap ({ ssids, ... }:
# map ({ net, ... }:
# net
# ) (builtins.attrValues ssids)
# ) (builtins.attrValues hostConfig.wifi)
# );
openwrtModel = self.lib.getOpenwrtModel hostConfig.model; openwrtModel = self.lib.getOpenwrtModel hostConfig.model;
hasSwitch = hasSwitch =
if hostConfig.model == "ubnt_unifiac-mesh" if hostConfig.model == "unifiac-mesh"
# ours don't come with a switch. # ours don't come with a switch.
then false then false
else else
openwrtModel ? ports
&&
any ({ switch ? null, ... }: switch != null) any ({ switch ? null, ... }: switch != null)
(builtins.attrValues openwrtModel.ports); (builtins.attrValues openwrtModel.ports);
hasDSA = (
all ({ switch ? null, ... }:
switch == null
) (builtins.attrValues openwrtModel.ports or {})
&&
any ({ port ? null, interface ? null, ... }:
port != null &&
interface != null &&
port == interface
) (builtins.attrValues openwrtModel.ports or {})
) || hostConfig.model == "ubnt_unifi-usg";
portsDoc = portsDoc =
let let
@ -42,7 +35,7 @@ let
then port.index then port.index
else if port ? interface else if port ? interface
then port.interface then port.interface
else "How to identify port ${generators.toPretty {} port}?"; else "How to identify port ${lib.generators.toPretty {} port}?";
in result // { in result // {
"${key}" = port; "${key}" = port;
} }
@ -54,7 +47,7 @@ let
then portByIndex.${index}.port then portByIndex.${index}.port
else if portByIndex.${index} ? interface else if portByIndex.${index} ? interface
then portByIndex.${index}.interface then portByIndex.${index}.interface
else throw "${hostName}: What is port ${generators.toPretty {} portByIndex.${index}.port}?" else throw "${hostName}: What is port ${lib.generators.toPretty {} portByIndex.${index}.port}?"
}" }"
) ( ) (
builtins.sort builtins.lessThan ( builtins.sort builtins.lessThan (
@ -112,20 +105,6 @@ let
) )
); );
dsaPorts = net:
unique (
concatMap ({ ports, ... }: ports) (
builtins.filter ({ nets, ... }: builtins.elem net nets)
(builtins.attrValues hostConfig.links)
));
dsaPortType = net: port:
if any ({ ports, trunk, ... }: trunk && builtins.elem port ports) (
builtins.attrValues hostConfig.links
) || hostConfig.links.${net}.trunk or true
then "t"
else "u*";
networkInterfaces = net: networkInterfaces = net:
let let
inherit (config.site.net.${net}) vlan; inherit (config.site.net.${net}) vlan;
@ -148,7 +127,7 @@ let
else [] else []
) (builtins.attrValues openwrtModel.ports) ) (builtins.attrValues openwrtModel.ports)
++ ++
optionals (hostConfig.interfaces ? ${port} && vlan != null) [ "${port}.${toString vlan}" ] lib.optionals (hostConfig.interfaces ? ${port} && vlan != null) [ "${port}.${toString vlan}" ]
) ports ) ports
) ( ) (
builtins.attrValues ( builtins.attrValues (
@ -159,18 +138,19 @@ let
) )
); );
mgmtInterface = in ''
if hasDSA #! ${pkgs.runtimeShell} -e
then "br0.${toString config.site.net.mgmt.vlan}"
else ${if hostConfig.firstboot
let then ''
mgmtInterfaces = networkInterfaces "mgmt"; ssh-keygen -R 192.168.1.1
in if builtins.length mgmtInterfaces == 1 ssh root@192.168.1.1 \
then builtins.head mgmtInterfaces "ash -e -x" <<__SSH__
else "br-mgmt"; '' else ''
ssh root@${config.site.net.mgmt.hosts4.${hostName}} \
"ash -e -x" <<__SSH__
''}
in
''
# Set root password # Set root password
echo -e '${hostConfig.password}\n${hostConfig.password}' | passwd echo -e '${hostConfig.password}\n${hostConfig.password}' | passwd
@ -188,8 +168,8 @@ in
uci set system.@system[0].log_ip=${config.site.net.mgmt.hosts4.logging} uci set system.@system[0].log_ip=${config.site.net.mgmt.hosts4.logging}
uci set system.@system[0].log_proto=udp uci set system.@system[0].log_proto=udp
${optionalString hasSwitch ''
# Switch config # Switch config
${optionalString hasSwitch ''
# Ports ${portsDoc} # Ports ${portsDoc}
${concatMapStrings (net: '' ${concatMapStrings (net: ''
uci add network switch_vlan uci add network switch_vlan
@ -198,42 +178,7 @@ in
uci set network.@switch_vlan[-1].vlan='${toString config.site.net.${net}.vlan}' uci set network.@switch_vlan[-1].vlan='${toString config.site.net.${net}.vlan}'
uci set network.@switch_vlan[-1].ports='${switchPortsConfig net}' uci set network.@switch_vlan[-1].ports='${switchPortsConfig net}'
uci set network.@switch_vlan[-1].comment='${net}' uci set network.@switch_vlan[-1].comment='${net}'
'') (
sort (net1: net2:
config.site.net.${net1}.vlan < config.site.net.${net2}.vlan
) (
unique (
builtins.concatMap ({ nets, ... }: nets)
(builtins.attrValues hostConfig.links)
)
)
)}
''}
${optionalString hasDSA ''
# DSA
${uciDeleteAll "network.@device"}
uci add network device
uci set network.@device[-1].name='br0'
uci set network.@device[-1].type='bridge'
${concatMapStrings (port: ''
uci add_list network.@device[-1].ports='${port}'
'') (
unique (
builtins.concatMap ({ ports, ... }: ports)
(builtins.attrValues hostConfig.links)
)
)}
uci set network.br0='interface'
uci set network.br0.proto='none'
uci set network.br0.device='br0'
${concatMapStrings (net: ''
uci add network bridge-vlan
uci set network.@bridge-vlan[-1].device='br0'
uci set network.@bridge-vlan[-1].vlan='${toString config.site.net.${net}.vlan}'
${concatMapStrings (port: ''
uci add_list network.@bridge-vlan[-1].ports='${port}:${dsaPortType net port}'
'') (dsaPorts net)}
'') ( '') (
sort (net1: net2: sort (net1: net2:
config.site.net.${net1}.vlan < config.site.net.${net2}.vlan config.site.net.${net1}.vlan < config.site.net.${net2}.vlan
@ -248,18 +193,13 @@ in
# mgmt network # mgmt network
uci set network.mgmt=interface uci set network.mgmt=interface
${if hasDSA
then ''
uci set network.mgmt.device='br0.${toString config.site.net.mgmt.vlan}'
'' else ''
uci set network.mgmt.ifname='${ uci set network.mgmt.ifname='${
if builtins.length (networkInterfaces "mgmt") > 0 if builtins.length (networkInterfaces "mgmt") > 0
then concatStringsSep " " (networkInterfaces "mgmt") then lib.concatStringsSep " " (networkInterfaces "mgmt")
else throw "${hostName}: No interface for mgmt" else throw "${hostName}: No interface for mgmt"
}' }'
''}
uci set network.mgmt.proto=static uci set network.mgmt.proto=static
${optionalString (hostConfig.interfaces.mgmt.type == "bridge") '' ${lib.optionalString (hostConfig.interfaces.mgmt.type == "bridge") ''
uci set network.mgmt.type=bridge uci set network.mgmt.type=bridge
''} ''}
uci set network.mgmt.ipaddr=${config.site.net.mgmt.hosts4.${hostName}} uci set network.mgmt.ipaddr=${config.site.net.mgmt.hosts4.${hostName}}
@ -274,7 +214,7 @@ in
uci -q delete network.globals.ula_prefix || true uci -q delete network.globals.ula_prefix || true
# delete unused networks # delete unused networks
${concatMapStrings (net: ${concatMapStrings (net:
optionalString (! hostConfig.interfaces ? ${net}) '' lib.optionalString (! hostConfig.interfaces ? ${net}) ''
uci -q delete network.${net} || true uci -q delete network.${net} || true
'' ''
) ([ "lan" "wan" "wan6" ] ++ builtins.attrNames config.site.net)} ) ([ "lan" "wan" "wan6" ] ++ builtins.attrNames config.site.net)}
@ -285,30 +225,22 @@ in
iface = hostConfig.interfaces.${net}; iface = hostConfig.interfaces.${net};
in optionalString (net != "mgmt" && builtins.elem iface.type ["bridge" "phys"]) '' in optionalString (net != "mgmt" && builtins.elem iface.type ["bridge" "phys"]) ''
uci set network.${net}=interface uci set network.${net}=interface
${optionalString (iface.type == "bridge") '' ${lib.optionalString (iface.type == "bridge") ''
uci set network.${net}.type=bridge uci set network.${net}.type=bridge
uci add network device
uci set network.@device[-1].name='${net}'
uci set network.@device[-1].type='bridge'
''} ''}
uci set network.${net}.proto=static uci set network.${net}.proto=static
${if hasDSA
then ''
uci set network.${net}.device='br0.${toString config.site.net.${net}.vlan}'
'' else ''
uci set network.${net}.ifname='${concatStringsSep " " (networkInterfaces net)}' uci set network.${net}.ifname='${concatStringsSep " " (networkInterfaces net)}'
''} ${lib.optionalString (config.site.net.${net}.mtu != null) ''
${optionalString (config.site.net.${net}.mtu != null) ''
uci set network.${net}.mtu=${toString config.site.net.${net}.mtu} uci set network.${net}.mtu=${toString config.site.net.${net}.mtu}
''} ''}
${optionalString (config.site.net.${net}.hosts4 ? ${hostName}) '' ${lib.optionalString (config.site.net.${net}.hosts4 ? ${hostName}) ''
# address in net # address in net
uci set network.${net}.ipaddr=${config.site.net.${net}.hosts4.${hostName}} uci set network.${net}.ipaddr=${config.site.net.${net}.hosts4.${hostName}}
uci set network.${net}.netmask=${self.lib.netmasks.${toString config.site.net.${net}.subnet4Len}} uci set network.${net}.netmask=${self.lib.netmasks.${toString config.site.net.${net}.subnet4Len}}
''} ''}
${concatMapStrings (hosts6: optionalString (hosts6 ? ${hostName}) '' ${lib.concatMapStrings (hosts6: lib.optionalString (hosts6 ? ${hostName}) ''
uci set network.${net}.ip6addr=${hosts6.${hostName}}/64 uci set network.${net}.ip6addr=${hosts6.${hostName}}/64
'') (builtins.attrValues config.site.net.${net}.hosts6)} '') (builtins.attrValues config.site.net.${net}.hosts6)}
'') (builtins.attrNames hostConfig.interfaces) '') (builtins.attrNames hostConfig.interfaces)
@ -323,13 +255,14 @@ in
uci set network.${name}.proto=vxlan6 uci set network.${name}.proto=vxlan6
uci set network.${name}.peer6addr='${iface.vxlan.peer}' uci set network.${name}.peer6addr='${iface.vxlan.peer}'
uci set network.${name}.port=4789 uci set network.${name}.port=4789
uci set network.${name}.mtu=1600
uci set network.${name}.rxcsum=0 uci set network.${name}.rxcsum=0
uci set network.${name}.txcsum=0 uci set network.${name}.txcsum=0
uci set network.${name}.delegate=0 uci set network.${name}.delegate=0
'') (builtins.attrNames hostConfig.interfaces) '') (builtins.attrNames hostConfig.interfaces)
} }
${uciDeleteAll "wireless.radio"}
uci -q delete wireless.default_radio0 || true uci -q delete wireless.default_radio0 || true
uci -q delete wireless.default_radio1 || true uci -q delete wireless.default_radio1 || true
${concatStrings (imap0 (index: path: ${concatStrings (imap0 (index: path:
@ -342,7 +275,6 @@ in
uci set wireless.radio${toString index}=wifi-device uci set wireless.radio${toString index}=wifi-device
uci set wireless.radio${toString index}.type=mac80211 uci set wireless.radio${toString index}.type=mac80211
uci set wireless.radio${toString index}.country=DE uci set wireless.radio${toString index}.country=DE
uci set wireless.radio${toString index}.band=${radioConfig.band}
uci set wireless.radio${toString index}.channel=${toString radioConfig.channel} uci set wireless.radio${toString index}.channel=${toString radioConfig.channel}
uci set wireless.radio${toString index}.path=${path} uci set wireless.radio${toString index}.path=${path}
uci set wireless.radio${toString index}.htmode=${radioConfig.htmode} uci set wireless.radio${toString index}.htmode=${radioConfig.htmode}
@ -352,118 +284,34 @@ in
${concatMapStrings (ssid: ${concatMapStrings (ssid:
let let
ssidConfig = radioConfig.ssids.${ssid}; ssidConfig = radioConfig.ssids.${ssid};
netConfig = config.site.net.${ssidConfig.net};
# mapping our option to openwrt/hostapd setting
encryption = {
none = "none";
owe = "owe";
wpa2 = "psk2";
wpa3 = "sae-mixed";
}.${ssidConfig.encryption};
ifname =
if ssidConfig.ifname != null
then ssidConfig.ifname
else "${ifPrefix}-${ssidConfig.net}";
pad = len: prefix: s:
if builtins.stringLength s < len
then pad len prefix "${prefix}${s}"
else s;
in '' in ''
uci add wireless wifi-iface uci add wireless wifi-iface
uci set wireless.@wifi-iface[-1].ifname=${ifname} uci set wireless.@wifi-iface[-1].ifname=${ifPrefix}-${ssidConfig.net}
uci set wireless.@wifi-iface[-1].device=radio${toString index} uci set wireless.@wifi-iface[-1].device=radio${toString index}
uci set wireless.@wifi-iface[-1].ssid='${ssid}' uci set wireless.@wifi-iface[-1].ssid='${ssid}'
uci set wireless.@wifi-iface[-1].mode=${ssidConfig.mode} uci set wireless.@wifi-iface[-1].mode=${ssidConfig.mode}
uci set wireless.@wifi-iface[-1].network=${ssidConfig.net} uci set wireless.@wifi-iface[-1].network=${ssidConfig.net}
uci set wireless.@wifi-iface[-1].mcast_rate=18000 uci set wireless.@wifi-iface[-1].mcast_rate=18000
uci set wireless.@wifi-iface[-1].hidden=${if ssidConfig.hidden then "1" else "0"}
uci set wireless.@wifi-iface[-1].encryption='${encryption}'
${if (ssidConfig.psk != null) ${if (ssidConfig.psk != null)
then '' then ''
uci set wireless.@wifi-iface[-1].encryption=psk2
uci set wireless.@wifi-iface[-1].key='${ssidConfig.psk}' uci set wireless.@wifi-iface[-1].key='${ssidConfig.psk}'
'' ''
else '' else ''
uci set wireless.@wifi-iface[-1].encryption=none
uci -q delete wireless.@wifi-iface[-1].key || true uci -q delete wireless.@wifi-iface[-1].key || true
''} ''}
${lib.optionalString (!ssidConfig.disassocLowAck) ''
uci set wireless.@wifi-iface[-1].disassoc_low_ack='0'
''}
${lib.optionalString (netConfig.wifi.ieee80211rKey != null) ''
# for usteerd
# see https://www.libe.net/en-wlan-roaming#client-steering
# https://openwrt.org/docs/guide-user/network/wifi/usteer#configure_80211k_and_80211v_on_all_ap-nodes
uci set wireless.@wifi-iface[-1].bss_transition=1
uci set wireless.@wifi-iface[-1].wnm_sleep_mode=1
uci set wireless.@wifi-iface[-1].time_advertisement=2
uci set wireless.@wifi-iface[-1].time_zone=GMT0
uci set wireless.@wifi-iface[-1].ieee80211k=1
uci set wireless.@wifi-iface[-1].rrm_neighbor_report=1
uci set wireless.@wifi-iface[-1].rrm_beacon_report=1
# breaks Apple devices connecting to wifi when used together with wpa2/wpa3 mixed mode (sae-mixed)
# uci set wireless.@wifi-iface[-1].ieee80211r=1
# when unset derived from interface MAC
uci set wireless.@wifi-iface[-1].nasid=${pad 12 "0" (toString ((lib.toInt (lib.removePrefix "ap" hostName)) * 65536 + index))}
# when unset derived from the first 4 chars of the md5 hashed SSID
uci set wireless.@wifi-iface[-1].mobility_domain=${pad 4 "0" (lib.toHexString (49920 + netConfig.vlan))}
# https://github.com/openwrt/openwrt/issues/7907
# https://github.com/openwrt/openwrt/commit/2984a0420649733662ff95b0aff720b8c2c19f8a
uci set wireless.@wifi-iface[-1].ft_over_ds=0
# as recommend in 7907 and seems to fairly often trigger while testing
uci set wireless.@wifi-iface[-1].reassociation_deadline=20000
# might be unused if ft_over_ds is not used
uci set wireless.@wifi-iface[-1].ft_bridge=${mgmtInterface}
# otherwise the r0kh/r1kh options below are not applied
uci set wireless.@wifi-iface[-1].ft_psk_generate_local=0
# do not just rely on the monility domain for increased security
# https://forum.openwrt.org/t/802-11r-fast-transition-how-to-understand-that-ft-works/110920/81
uci set wireless.@wifi-iface[-1].r0kh=ff:ff:ff:ff:ff:ff,\*,${netConfig.wifi.ieee80211rKey}
uci set wireless.@wifi-iface[-1].r1kh=00:00:00:00:00:00,00:00:00:00:00:00,${netConfig.wifi.ieee80211rKey}
uci set wireless.@wifi-iface[-1].pmk_r1_push=1
''}
'' ''
) (builtins.attrNames radioConfig.ssids)} ) (builtins.attrNames radioConfig.ssids)}
'') (builtins.attrNames hostConfig.wifi))} '') (builtins.attrNames hostConfig.wifi))}
uci set usteer.@usteer[0].network=mgmt
uci set usteer.@usteer[0].load_kick_enabled=1
uci set usteer.@usteer[0].load_kick_threshold=67
uci set usteer.@usteer[0].signal_diff_threshold=15
uci set usteer.@usteer[0].load_balancing_threshold=8
uci set usteer.@usteer[0].band_steering_threshold=16
uci commit uci commit
# Add hotfixes for MTU settings ${lib.optionalString hostConfig.wifiOnLink.enable ''
cat >/etc/hotplug.d/iface/99-mtu <<__MTU__
#!/bin/sh
${concatMapStrings (net:
optionalString (config.site.net ? ${net} &&
config.site.net.${net}.mtu != null) ''
if [ "\\\$ACTION" = ifup -a "\\\$INTERFACE" = ${net} ]; then
ip link set \\\$DEVICE mtu ${toString config.site.net.${net}.mtu}
fi
'') (builtins.attrNames hostConfig.interfaces)
}
__MTU__
${optionalString hostConfig.wifiOnLink.enable ''
# Cronjob that makes sure WiFi is only visible when server with all # Cronjob that makes sure WiFi is only visible when server with all
# the gateways is reachable # the gateways is reachable
cat >/etc/crontabs/root <<__CRON__ cat >/etc/crontabs/root <<__CRON__
* * * * * /usr/sbin/wifi-on-link.sh #* * * * * /usr/sbin/wifi-on-link.sh
* * * * * /usr/sbin/usteer-info.sh
__CRON__ __CRON__
cat >/usr/sbin/wifi-on-link.sh <<__SH__ cat >/usr/sbin/wifi-on-link.sh <<__SH__
#!/bin/sh #!/bin/sh
@ -493,36 +341,16 @@ in
__SH__ __SH__
chmod a+rx /usr/sbin/wifi-on-link.sh chmod a+rx /usr/sbin/wifi-on-link.sh
/etc/init.d/cron restart /etc/init.d/cron restart
cat > /etc/collectd.conf <<COLLECTD
Hostname "${hostName}"
FQDNLookup false
Interval 10
BaseDir "/var/run/collectd"
Include "/etc/collectd/conf.d"
PIDFile "/var/run/collectd.pid"
PluginDir "/usr/lib/collectd"
TypesDB "/usr/share/collectd/types.db"
LoadPlugin cpu
LoadPlugin load
LoadPlugin interface
LoadPlugin iwinfo
LoadPlugin network
LoadPlugin exec
<Plugin network>
Server "${config.site.net.serv.hosts6.dn42.stats}" "25826"
</Plugin>
<Plugin exec>
Exec "nobody" "/usr/bin/usteer-stats.sh"
</Plugin>
COLLECTD
''} ''}
chmod +x /usr/bin/usteer-stats.sh /usr/sbin/usteer-info.sh
for svc in dnsmasq uhttpd ; do for svc in dnsmasq uhttpd ; do
rm -f /etc/rc.d/*\$svc rm -f /etc/rc.d/*\$svc
/etc/init.d/\$svc stop || true /etc/init.d/\$svc stop || true
done done
${lib.optionalString hostConfig.firstboot "reboot"}
__SSH__
echo "Base configuration done \\o/"
echo "Later run: ap_install_collectd.sh ${config.site.net.mgmt.hosts4.${hostName}}"
'' ''

View File

@ -1,20 +1,16 @@
{ self, nixpkgs, system, openwrt-imagebuilder }: { self, nixpkgs, system }:
let let
inherit (self.lib) config; inherit (self.lib) config;
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
inherit (pkgs) lib;
export-openwrt-models = pkgs.writeText "openwrt-models.nix" ( export-openwrt-models = pkgs.writeText "openwrt-models.nix" (
lib.generators.toPretty {} self.lib.openwrtModels nixpkgs.lib.generators.toPretty {} self.lib.openwrtModels
); );
export-config = pkgs.writeText "config.nix" ( export-config = pkgs.writeText "config.nix" (
lib.generators.toPretty {} ( nixpkgs.lib.generators.toPretty {} config
lib.recursiveUpdate );
config
{ site.dns.localZones = self.lib.dns.localZones; }
));
encrypt-secrets = pkgs.writeScriptBin "encrypt-secrets" '' encrypt-secrets = pkgs.writeScriptBin "encrypt-secrets" ''
#! ${pkgs.runtimeShell} -e #! ${pkgs.runtimeShell} -e
@ -45,7 +41,7 @@ let
''; '';
network-cypher-graphs = import ./network-cypher-graphs.nix { inherit config pkgs; }; network-cypher-graphs = import ./network-cypher-graphs.nix { inherit config pkgs; };
network-graphs = import ./network-graphs.nix { inherit config lib pkgs; }; network-graphs = import ./network-graphs.nix { inherit config pkgs; };
mkRootfs = hostName: mkRootfs = hostName:
self.nixosConfigurations.${hostName}.config.system.build.toplevel; self.nixosConfigurations.${hostName}.config.system.build.toplevel;
@ -55,20 +51,7 @@ let
"${hostName}-rootfs" = mkRootfs hostName; "${hostName}-rootfs" = mkRootfs hostName;
}) {} ( }) {} (
builtins.attrNames ( builtins.attrNames (
lib.filterAttrs (_: { role, ... }: builtins.elem role ["server" "container"]) nixpkgs.lib.filterAttrs (_: { role, ... }: builtins.elem role ["server" "container"])
config.site.hosts
)
);
mkLxcConfig = hostName:
self.nixosConfigurations.${hostName}.config.system.build.lxcConfig;
lxc-configs =
builtins.foldl' (rootfs: hostName: rootfs // {
"${hostName}-lxc-config" = mkLxcConfig hostName;
}) {} (
builtins.attrNames (
lib.filterAttrs (_: { role, ... }: role == "container")
config.site.hosts config.site.hosts
) )
); );
@ -76,33 +59,26 @@ let
vm-packages = vm-packages =
builtins.foldl' (rootfs: hostName: rootfs // { builtins.foldl' (rootfs: hostName: rootfs // {
"${hostName}-vm" = self.nixosConfigurations.${hostName}.config.system.build.vm "${hostName}-vm" = self.nixosConfigurations.${hostName}.config.system.build.vm
.overrideAttrs (_oa: { .overrideAttrs (oa: {
meta.mainProgram = "run-${hostName}-vm"; meta.mainProgram = "run-${hostName}-vm";
}); });
}) {} ( }) {} (
builtins.attrNames ( builtins.attrNames (
lib.filterAttrs (_: { role, ... }: role == "server") nixpkgs.lib.filterAttrs (_: { role, ... }: role == "server")
config.site.hosts config.site.hosts
) )
); );
openwrt = import ./openwrt { inherit self nixpkgs system openwrt-imagebuilder; }; all-rootfs = with pkgs;
runCommand "all-rootfs" {} ''
openwrt-packages = builtins.foldl' (images: hostName: images // { mkdir -p $out
${hostName} = pkgs.writeScriptBin "${hostName}.sh" ( ${lib.concatMapStrings (pkg: ''
openwrt.sshScript hostName ln -s ${pkg} $out/${pkg.name}
); '') (builtins.attrValues rootfs-packages)}
"${hostName}-image" = openwrt.buildImage hostName; '';
}) {} (
builtins.attrNames (
lib.filterAttrs (_: { role, ... }:
role == "ap"
) config.site.hosts
)
);
device-templates = import ./device-templates.nix { device-templates = import ./device-templates.nix {
inherit self nixpkgs system openwrt; inherit self nixpkgs system;
}; };
dns-slaves = import ./dns-slaves.nix { dns-slaves = import ./dns-slaves.nix {
@ -117,25 +93,13 @@ let
inherit self nixpkgs system; inherit self nixpkgs system;
}; };
gateway-report = import ./gateway-report.nix {
inherit self nixpkgs system;
};
switch-report = import ./switch-report.nix {
inherit self nixpkgs system;
};
vlan-report = import ./vlan-report.nix { vlan-report = import ./vlan-report.nix {
inherit self nixpkgs system; inherit self nixpkgs system;
}; };
homepage = pkgs.callPackage ./homepage {
inherit self;
};
in in
rootfs-packages // lxc-configs // vm-packages // device-templates // openwrt-packages // network-graphs // network-cypher-graphs // starlink // subnetplans // { rootfs-packages // vm-packages // device-templates // network-graphs // network-cypher-graphs // starlink // subnetplans // {
inherit export-openwrt-models export-config dns-slaves inherit all-rootfs export-openwrt-models export-config dns-slaves
encrypt-secrets decrypt-secrets switch-to-production encrypt-secrets decrypt-secrets switch-to-production
homepage gateway-report switch-report vlan-report vlan-report
; ;
} }

View File

@ -1,4 +1,4 @@
{ self, nixpkgs, system, openwrt }: { self, nixpkgs, system }:
with nixpkgs.lib; with nixpkgs.lib;
let let
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
@ -11,13 +11,18 @@ let
args = { args = {
inherit self hostName config hostConfig pkgs; inherit self hostName config hostConfig pkgs;
}; };
in import (./switches + "/${model}.nix") ( in {
args // import ./switches/shared.nix args ap = import ./ap.nix args;
) switch = import (./switches + "/${model}.nix")
(args //
import ./switches/shared.nix args
);
}.${role}
) )
) ( ) (
filterAttrs (_: { role, model, ... }: filterAttrs (_: { role, model, ... }:
role == "switch" && model != "dumb" role == "ap" ||
(role == "switch" && model != "dumb")
) config.site.hosts ) config.site.hosts
); );

View File

@ -15,12 +15,12 @@ let
in in
writeText "named.slave.conf" ( writeText "named.slave.conf" (
lib.concatMapStringsSep "\n" ({ name, ... }: '' lib.concatMapStringsSep "\n" ({ name, ns, ... }: ''
zone "${name}" IN { zone "${name}" IN {
type slave; type slave;
masters {${mastersStr} }; masters {${mastersStr} };
file "/var/lib/bind/slave/${name}.zone"; file "/var/lib/bind/slave/${name}.zone";
allow-notify { ${mastersStr} }; allow-notify {${mastersStr} };
allow-query { any; }; allow-query { any; };
}; };
'') ( '') (

View File

@ -1,120 +0,0 @@
{ self, nixpkgs, system }:
with nixpkgs.legacyPackages.${system};
let
config = self.lib.config;
in
writeText "gateway-report.md" ''
# Gateway Report
${lib.concatMapStrings (net:
let
netConfig = config.site.net.${net};
routers4 = builtins.filter (hostName:
config.site.hosts ? ${hostName} &&
config.site.hosts.${hostName}.isRouter
) (
builtins.attrNames netConfig.hosts4
);
routers6 = builtins.filter (hostName:
config.site.hosts ? ${hostName} &&
config.site.hosts.${hostName}.isRouter
) (lib.unique (
builtins.concatMap builtins.attrNames (builtins.attrValues netConfig.hosts6)
));
upstreamAt = l: n:
if n < builtins.length l
then
let
hostName = builtins.elemAt l n;
hostConfig = config.site.hosts.${hostName};
providers =
map ({ upstream, ... }: upstream.provider) (
builtins.filter ({ upstream, ... }:
upstream.provider or null != null
) (builtins.attrValues hostConfig.interfaces)
);
in
"${hostName}${
lib.optionalString (providers != []) " (${lib.concatStringsSep ", " providers})"
}"
else "";
in
lib.optionalString (net != "core" && (routers4 != [] || routers6 != [])) ''
## Network ${net}
${lib.optionalString (routers4 != []) ''
### IPv4 `${netConfig.subnet4}`
| Address | Name | Primary Uplink | Fallback Uplink |
|-|-|-|-|
${lib.concatMapStrings (hostName:
let
hostConfig = config.site.hosts.${hostName};
isDhcpDefault = hostName == netConfig.dhcp.router or null;
emphasize = s:
if isDhcpDefault
then "**${s}**"
else s;
upstream4a = upstreamAt hostConfig.ospf.allowedUpstreams 0;
upstream4b = upstreamAt hostConfig.ospf.allowedUpstreams 1;
in ''
|${
emphasize netConfig.hosts4.${hostName}
}|${
emphasize hostName
}|${
upstream4a
}|${
upstream4b
}|
''
) (lib.naturalSort routers4)}
''}
${lib.optionalString (routers6 != {}) ''
### IPv6 ${lib.concatStringsSep " " (
map (s: "`${s}`") (
builtins.attrValues netConfig.subnets6
)
)}
| Address | Name | Primary Uplink | Fallback Uplink |
|-|-|-|-|
${lib.concatMapStrings (hostName:
let
hostConfig = config.site.hosts.${hostName};
isIpv6Router = hostName == netConfig.ipv6Router;
emphasize = s:
if isIpv6Router
then "**${s}**"
else s;
upstream6a = upstreamAt hostConfig.ospf.allowedUpstreams6 0;
upstream6b = upstreamAt hostConfig.ospf.allowedUpstreams6 1;
in ''
|${
emphasize (
lib.concatMapStringsSep " " (ctx:
"`${netConfig.hosts6.${ctx}.${hostName}}`"
) (builtins.filter (ctx:
netConfig.hosts6.${ctx} ? ${hostName}
) (builtins.attrNames netConfig.hosts6))
)
}|${
emphasize hostName
}|${
upstream6a
}|${
upstream6b
}|
''
) (lib.naturalSort routers6)}
''}
''
) (lib.naturalSort (builtins.attrNames config.site.net))}
''

View File

@ -1,5 +0,0 @@
{
"captive": false,
"user-portal-url": "https://zentralwerk.org/",
"venue-info-url": "https://zentralwerk.org/"
}

View File

@ -1,75 +0,0 @@
{ self
, system
, substituteAll
, stdenv
, pandoc
, bat
, ansi2html
}:
let
inherit (self.packages.${system})
export-config
gateway-report network-graphs
subnetplans switch-report vlan-report;
in
stdenv.mkDerivation {
pname = "zentralwerk-network-homepage";
version = self.lastModifiedDate;
src = ./src;
nativeBuildInputs = [
pandoc
bat
ansi2html
];
buildPhase = ''
pandoc -t html ${../../../doc/hello.md} > index.html
cat ${./linked-data.html} >> index.html
pandoc -t html ${../../../doc/vpn.md} > vpn.html
pandoc -t html ${gateway-report} > gateway-report.html
cat ${../../../cabling.md} ${switch-report} >> switch-report.md
pandoc -t html switch-report.md > switch-report.html
pandoc -t html ${vlan-report} > vlan-report.html
echo '<pre>' > config.html
bat --color=always --theme=GitHub -p ${export-config} | \
ansi2html -il >> config.html
echo '</pre>' >> config.html
ln -s ${substituteAll {
src = ./figure.html;
img = "physical.png";
caption = "Physikalische Netzwerkstruktur";
}} physical.html
ln -s ${substituteAll {
src = ./figure.html;
img = "logical.png";
caption = "Logische Netzwerkstruktur";
}} logical.html
ln -s ${subnetplans}/share/doc/zentralwerk/* .
for F in *.html; do
cat ${./header.html} "$F" ${./footer.html} > "$F.new"
rm "$F"
mv "$F.new" "$F"
done
'';
installPhase = ''
DIR=$out/share/doc/zentralwerk/www
mkdir -p $DIR
ln -s ${network-graphs}/share/doc/zentralwerk/* $DIR/
ln -s ${../../../doc/core.png} $DIR/core.png
ln -s ${./security.txt} $DIR/security.txt
ln -s ${./captive.json} $DIR/captive.json
cp *.{html,css,png,svg} $DIR/
mkdir -p $out/nix-support
echo doc homepage $DIR index.html >> $out/nix-support/hydra-build-products
'';
}

View File

@ -1,4 +0,0 @@
<figure>
<img src="@img@" alt="@caption@">
<figcaption>@caption@</figcaption>
</figure>

View File

@ -1,14 +0,0 @@
</main>
<footer>
<p>
<a href="https://gitea.c3d2.de/zentralwerk/network">git</a>
vom
<a href="https://www.c3d2.de/">C3D2</a>
im
<a href="https://www.zentralwerk.de/">Zentralwerk</a>
</p>
</footer>
</body>
</html>

View File

@ -1,35 +0,0 @@
<!DOCTYPE html>
<html lang="de" xml:lang="de">
<head>
<title>zentralwerk.org</title>
<meta charset="utf-8"/>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<meta name="robots" content="index,follow"/>
<meta name="description" content="zentralwerk-network"/>
<meta name="keywords" content="c3d2 ccc zentralwerk network"/>
<meta name="generator" content="zentralwerk-network"/>
<meta name="language" content="de"/>
<meta name="author" content="Astro"/>
<link rel="icon" type="image/png" href="zw.png"/>
<link rel="stylesheet" title="Default" type="text/css" href="style.css"/>
</head>
<body>
<header>
<h1>zentralwerk-network</h1>
<nav>
<ul>
<li><a href=".">Willkommen</a></li>
<li><a href="gateway-report.html">Router</a></li>
<li><a href="subnetplan4.html">IPv4</a></li>
<li><a href="subnetplan6.html">IPv6</a></li>
<li><a href="vlan-report.html">VLAN</a></li>
<li><a href="logical.html">Logisch</a></li>
<li><a href="physical.html">Physisch</a></li>
<li><a href="switch-report.html">Ports</a></li>
<li><a href="vpn.html">VPN</a></li>
<li><a href="config.html">Config</a></li>
</ul>
</nav>
</header>
<main>

View File

@ -1,30 +0,0 @@
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Project",
"name": "zentralwerk-network",
"image": "https://www.zentralwerk.org/zw.png",
"logo": "https://www.zentralwerk.org/zw.png",
"@id": "https://www.zentralwerk.org/",
"url": "https://www.zentralwerk.org/",
"sameAs": "https://gitea.c3d2.de/zentralwerk/network",
"address": {
"@type": "PostalAddress",
"streetAddress": "Riesaer Str. 32",
"addressLocality": "Dresden",
"postalCode": "01127",
"addressCountry": "DE"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 51.0811716,
"longitude": 13.7285633
},
"parentOrganization": {
"@type": "NGO",
"name": "Chaos Computer Club Dresden",
"@id": "https://www.c3d2.de/whois.html",
"url": "https://www.c3d2.de/whois.html"
}
}
</script>

View File

@ -1,3 +0,0 @@
Contact: mailto:astro@spaceboyz.net
Preferred-Languages: en, de
Hiring: https://www.c3d2.de/space.html

View File

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="1920"
height="1080"
viewBox="0 0 507.99999 285.75"
version="1.1"
id="svg5"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="background.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#af1f00"
bordercolor="#cccccc"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="1"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.23657384"
inkscape:cx="1470.9995"
inkscape:cy="762.97531"
inkscape:window-width="1916"
inkscape:window-height="1057"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
sodipodi:type="star"
style="opacity:0.349515;fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#ffff00;stroke-width:1.21295;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
id="path163"
inkscape:flatsided="false"
sodipodi:sides="48"
sodipodi:cx="266.05429"
sodipodi:cy="144.57217"
sodipodi:r1="179.29391"
sodipodi:r2="44.823479"
sodipodi:arg1="0.36233915"
sodipodi:arg2="0.427789"
inkscape:rounded="-2.4286129e-17"
inkscape:randomized="0"
d="m 433.7067,208.12514 -126.86819,-44.95749 117.13857,66.29681 -119.91468,-61.13249 107.48296,81.01929 -110.9094,-76.26151 95.98829,94.3555 -100.00643,-90.08565 82.85123,106.07726 -87.39232,-102.36842 68.29656,115.98401 -73.28291,-112.89964 52.57333,123.90625 -57.9196,-121.4991 35.95054,129.7084 -41.56528,-128.01968 18.71264,133.29122 -24.49976,-132.34982 1.15456,134.59339 -7.01505,-134.41541 -16.42328,133.59262 10.5897,-134.18111 -33.72012,130.30605 28.01326,-131.65094 -50.43999,124.7899 44.95749,-126.86818 -66.29682,117.13856 61.1325,-119.91468 -81.01929,107.48296 76.2615,-110.9094 -94.3555,95.98829 90.08566,-100.00643 -106.07726,82.85123 102.36842,-87.39232 -115.98401,68.29657 112.89963,-73.28291 -123.90624,52.57332 121.4991,-57.9196 L 94.358103,196.21253 222.37779,154.64726 89.086568,173.35989 221.43638,148.86013 86.843,150.01469 221.2584,142.99964 87.665786,126.57636 221.8469,137.16606 91.54085,103.44594 223.19179,131.4592 98.401887,81.01921 225.27007,125.9767 108.1315,59.679885 228.04618,120.81238 120.56322,39.79309 231.47262,116.0546 135.48433,21.699094 235.49076,111.78475 152.63953,5.7074906 240.03185,108.07591 171.73529,-7.9080994 245.0182,104.99153 192.44487,-18.91471 250.36448,102.58439 214.41393,-27.124014 255.97921,100.89567 237.26657,-32.395549 261.76633,99.954267 260.61178,-34.639117 267.62682,99.776288 284.0501,-33.81633 273.4604,100.36478 307.18052,-29.941267 279.16727,101.70967 329.60725,-23.08023 284.64976,103.78795 350.94658,-13.350614 289.81408,106.56406 370.83338,-0.91889557 294.57187,109.9905 388.92737,14.002216 298.84171,114.00865 404.91897,31.157415 302.55055,118.54974 418.53456,50.253172 305.63493,123.53608 429.54117,70.962754 308.04207,128.88236 437.75048,92.931813 309.73079,134.49709 443.02201,115.78445 310.6722,140.28421 445.26558,139.12966 310.85018,146.1447 444.4428,162.56799 310.26169,151.97829 440.56773,185.6984 308.91679,157.68515 Z"
inkscape:transform-center-x="-1.5557927e-05"
inkscape:transform-center-y="1.8543187e-05"
transform="matrix(3.4901017,0,0,3.4901017,-674.55653,24.83979)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,108 +0,0 @@
body {
margin: 0;
padding: 0;
background: #AF1F00 url('background.svg') fixed no-repeat center/100%;
color: #FFEF00;
font-family: sans-serif;
display: flex;
flex-direction: column;
justify-content: space-between;
min-height: 100vh;
}
a {
text-decoration: none;
font-weight: bold;
color: #CF3F1F;
}
a:visited {
color: #AF1F00;
}
header, footer {
background-color: #FFEF00;
color: #AF1F00;
text-align: center;
}
header {
margin: 0 0 3rem;
border-bottom: 1rem solid #DFCF00;
}
header h1 {
margin: 0.5rem 0;
padding: 0rem 2rem;
font-family: serif;
}
footer {
margin: 3rem 0 0;
}
footer p {
margin: 0.3rem 0;
}
nav ul {
margin: 0.3rem 0;
padding: 0;
list-style-type: none;
}
nav ul li {
display: inline-block;
margin: 0 2rem;
padding: 0;
}
main {
min-width: 50vh;
max-width: 60rem;
margin: 1rem auto;
padding: 1.5rem 4rem;
background: #FFF;
color: #111;
border-top: 1rem solid #EFDF00;
border-left: 1rem solid #EFDF00;
border-right: 1.5rem solid #DFCF00;
border-bottom: 1.5rem solid #DFCF00;
overflow: auto;
}
main figure {
text-align: center;
}
main figure img {
max-width: 100%;
}
main table {
font-size: 75%;
border-collapse: collapse;
border: 1px solid #555;
}
main table th {
background-color: #555;
color: #FFF;
padding: 0.4rem;
}
main table td {
border: 1px solid #555;
padding: 0.2rem 0.4rem;
}
main h3 code {
margin-left: 0.6rem;
}
.sourceCode .kw {
font-weight: bold;
color: #1F2F6F;
}
.sourceCode .dt {
font-weight: bold;
color: #1F5F2F;
}
.sourceCode .ot {
color: #666;
}
.sourceCode .st {
color: #007F00;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@ -138,7 +138,7 @@ in rec {
logical-cypher-graph = logical-cypher-graph =
let let
containers = containers =
lib.filterAttrs (_: { role, ... }: lib.filterAttrs (_: { isRouter, role, ... }:
role == "container" role == "container"
) config.site.hosts; ) config.site.hosts;
in in

View File

@ -1,14 +1,12 @@
{ config, lib, pkgs, ... }: { config, pkgs, ... }:
let let
inherit (pkgs) lib runCommand graphviz;
netColor = net: netColor = net:
if net == "core" if net == "core"
then "grey" then "grey"
else if net == "mgmt" else if net == "mgmt"
then "brown" then "brown"
else if net == "roof"
then "orange"
else if net == "flpk"
then "yellow"
else if builtins.elem net [ "c3d2" "serv" "cluster" ] else if builtins.elem net [ "c3d2" "serv" "cluster" ]
then "green" then "green"
else if builtins.match "up.+" net != null || else if builtins.match "up.+" net != null ||
@ -80,13 +78,13 @@ let
} }
''; '';
renderGraph = args@{ name, engine, ... }: renderGraph = args@{ name, engine, ... }:
pkgs.runCommand "${name}.png" { runCommand "${name}.png" {
src = builtins.toFile "${name}.dot" ( src = builtins.toFile "${name}.dot" (
toDot args toDot args
); );
} '' } ''
echo $src echo $src
${pkgs.graphviz-nox}/bin/${engine} -Tpng $src > $out ${graphviz}/bin/${engine} -Tpng $src > $out
''; '';
in rec { in rec {
@ -136,7 +134,7 @@ in rec {
logical-graph = logical-graph =
let let
containers = containers =
lib.filterAttrs (_: { role, ... }: lib.filterAttrs (_: { isRouter, role, ... }:
role == "container" role == "container"
) config.site.hosts; ) config.site.hosts;
in in
@ -160,7 +158,7 @@ in rec {
) (builtins.attrNames containers); ) (builtins.attrNames containers);
}; };
network-graphs = pkgs.runCommand "network-graphs" {} '' network-graphs = runCommand "network-graphs" {} ''
DIR=$out/share/doc/zentralwerk DIR=$out/share/doc/zentralwerk
mkdir -p $DIR mkdir -p $DIR
ln -s ${physical-graph} $DIR/physical.png ln -s ${physical-graph} $DIR/physical.png

View File

@ -1,144 +0,0 @@
{ self, nixpkgs, system, openwrt-imagebuilder }:
let
inherit (self.lib) config;
pkgs = nixpkgs.legacyPackages.${system};
uciConfig = hostName: import ./uci-config.nix { inherit self pkgs hostName; };
modelPackages = {
"tplink_archer-c7-v2" = [
"-kmod-ath10k-ct" "-ath10k-firmware-qca988x-ct-full-htt" "-ath10k-firmware-qca988x-ct"
"kmod-ath10k" "ath10k-firmware-qca988x"
];
"tplink_archer-c7-v5" = [
"-kmod-ath10k-ct" "-ath10k-firmware-qca988x-ct" "-ath10k-firmware-qca988x-ct-full-htt"
"kmod-ath10k" "ath10k-firmware-qca988x"
];
"ubnt_unifiac-lite" = [
"-kmod-ath10k-ct" "-ath10k-firmware-qca988x-ct"
"kmod-ath10k" "ath10k-firmware-qca988x"
];
"ubnt_unifiac-mesh" = [
"-kmod-ath10k-ct" "-ath10k-firmware-qca988x-ct"
"kmod-ath10k" "ath10k-firmware-qca988x"
];
"dir-615-d" = [
# flash size reasons
"-wpad-openssl"
"-tcpdump"
"wpad-wolfssl"
];
};
in rec {
sshScript = hostName:
let
address = config.site.net.mgmt.hosts4.${hostName};
in ''
#! ${pkgs.runtimeShell} -e
ssh root@${address} "cat > /tmp/openwrt-image" < ${buildImage hostName}/openwrt-*-${hostName}-*-sysupgrade.bin
ssh root@${address} "sysupgrade -n /tmp/openwrt-image" || true
# ssh hostkey will have changed after boot
ssh-keygen -R ${address}
'';
buildImage = hostName:
let
hostConfig = config.site.hosts.${hostName};
hasVxlan = builtins.any ({ type, ... }:
type == "vxlan"
) (builtins.attrValues hostConfig.interfaces);
inherit (hostConfig) model;
matches = (openwrt-imagebuilder.lib.profiles {
inherit pkgs;
}).identifyProfiles model;
fallbackProfile =
if model == "dir-615-d"
then (openwrt-imagebuilder.lib.profiles {
inherit pkgs;
release = "19.07.10";
}).identifyProfile model
else if builtins.match "tl-wr[78].*" model != null
then {
release = "18.06.9";
packagesArch = "mips_24kc";
target = "ar71xx";
variant = "tiny";
profile = model;
sha256 = "sha256-P7BJI6n6s53szYXKshnJRKL2fLIYgJLPiq/yd0oRKoE=";
feedsSha256 = {
base.sha256 = "sha256-IbND2snJ1UrDRhvGQIRxzGuSpftQ+AyiWqaVZqbGdHY=";
packages.sha256 = "sha256-18UvzdUL98CranBtzAY7hoUlEvafUdssAQOuqDQi4BU=";
};
}
else null;
build = args:
openwrt-imagebuilder.lib.build (args // {
extraImageName = "zw-${hostName}";
packages = [
# remove unused default .ipk
"-dnsmasq" "-firewall" "-firewall4"
"-ppp" "-ppp-mod-pppoe" "-kmod-ppp" "-kmod-pppoe" "-kmod-pppox"
"-iptables" "-ip6tables" "-kmod-ipt-offload"
"-odhcp6c" "-odhcpd-ipv6only"
"-wpad-basic-mbedtls"
# monitoring
"collectd"
"collectd-mod-iwinfo" "collectd-mod-network"
"collectd-mod-interface" "collectd-mod-load" "collectd-mod-cpu"
"collectd-mod-exec"
] ++ (
if args.variant != "tiny"
then [
# debugging
"htop"
"tcpdump"
# wpa3
"-wpad-basic-wolfssl" "-wpad-mini"
"wpad-openssl"
"usteer"
] else [
# debugging
"tcpdump-mini"
# wpa3
"-wpad-openssl" "-wpad-mini"
"wpad-wolfssl"
]
) ++ nixpkgs.lib.optionals hasVxlan [
"vxlan" "kmod-vxlan"
] ++ modelPackages.${model} or [];
disabledServices = [ "dnsmasq" "uhttpd" ];
files = pkgs.runCommandNoCC "image-files" {} ''
mkdir -p $out/etc/uci-defaults
cat > $out/etc/uci-defaults/99-zentralwerk <<EOF
${uciConfig hostName}
EOF
mkdir -p $out/usr/{bin,sbin}
cp ${./usteer-info.sh} $out/usr/sbin/usteer-info.sh
cp ${./usteer-stats.sh} $out/usr/bin/usteer-stats.sh
chmod +x $out/usr/bin/*.sh $out/usr/sbin/*.sh
'';
});
in
if matches == [] && fallbackProfile != null
then build fallbackProfile
else if matches == []
then builtins.trace "${hostName} (${model}) not supported by OpenWRT"
null
else if builtins.length matches == 1
then build (builtins.elemAt matches 0)
else builtins.trace "${hostName} (${model}) has multiple models!" (
build (builtins.elemAt matches 0)
);
}

View File

@ -1,3 +0,0 @@
#! /bin/sh
[ -p /tmp/usteer-info ] || exit 0
exec /bin/ubus call usteer local_info > /tmp/usteer-info

View File

@ -1,32 +0,0 @@
#! /bin/sh
HOSTNAME=`cat /proc/sys/kernel/hostname`
INTERVAL=60
[ -p /tmp/usteer-info ] || mkfifo /tmp/usteer-info
while true; do
if [ ! -p /tmp/usteer-info ]; then
echo "/tmp/usteer-info went missing!"
exit 1
fi
DATA="$(cat /tmp/usteer-info)"
cd /sys/class/net
for iface in wlan*; do
eval $( echo "$DATA" | jsonfilter \
-e 'LOAD=@["hostapd.'$iface'"].load' \
-e 'NOISE=@["hostapd.'$iface'"].noise' \
-e 'N_ASSOC=@["hostapd.'$iface'"].n_assoc' \
-e 'FREQ=@["hostapd.'$iface'"].freq' \
-e 'ROAM_SOURCE=@["hostapd.'$iface'"].roam_events.source' \
-e 'ROAM_TARGET=@["hostapd.'$iface'"].roam_events.target'
)
echo "PUTVAL \"$HOSTNAME/usteer_local_info-$iface/stations-load\" interval=$INTERVAL N:$LOAD"
echo "PUTVAL \"$HOSTNAME/usteer_local_info-$iface/signal_noise-noise\" interval=$INTERVAL N:$NOISE"
echo "PUTVAL \"$HOSTNAME/usteer_local_info-$iface/stations-n_assoc\" interval=$INTERVAL N:$N_ASSOC"
echo "PUTVAL \"$HOSTNAME/usteer_local_info-$iface/frequency-freq\" interval=$INTERVAL N:$FREQ"
echo "PUTVAL \"$HOSTNAME/usteer_local_info-$iface/transitions-roam_source\" interval=$INTERVAL N:$ROAM_SOURCE"
echo "PUTVAL \"$HOSTNAME/usteer_local_info-$iface/transitions-roam_target\" interval=$INTERVAL N:$ROAM_TARGET"
done
done

View File

@ -57,14 +57,10 @@ nets.each do |net|
end end
exit 1 if collisions > 0 exit 1 if collisions > 0
GROUP_PREFIX = 19 GROUP_PREFIX = 16
groups = {} groups = {}
nets.each do |net| nets.each do |net|
if net.addr.prefix > GROUP_PREFIX
group = net.addr.supernet(GROUP_PREFIX).to_s group = net.addr.supernet(GROUP_PREFIX).to_s
else
group = net.addr.to_s
end
(groups[group] ||= []) << net (groups[group] ||= []) << net
end end
@ -105,9 +101,7 @@ def background_color desc
"#9F9F9F" "#9F9F9F"
when "mgmt" when "mgmt"
"#FF3F3F" "#FF3F3F"
when "roof" when "c3d2"
"#FF4F2F"
when "c3d2", "flpk"
"yellow" "yellow"
when "serv", "cluster" when "serv", "cluster"
"orange" "orange"

View File

@ -1,97 +0,0 @@
{ self, nixpkgs, system }:
with nixpkgs.legacyPackages.${system};
let
config = self.lib.config;
reportHosts = lib.concatMapStrings (hostName:
let
inherit (config.site.hosts.${hostName}) links model location;
linksByPorts = builtins.foldl' (linksByPorts: linkName:
if links.${linkName}.group != null
then
# group ports
linksByPorts // {
${lib.concatMapStringsSep "<br>" (port:
"`${port}`"
) links.${linkName}.ports} = linkName;
}
else
# expand lists of access ports to seperate rows
builtins.foldl' (linksByPorts': port:
linksByPorts' // {
"`${port}`" = linkName;
}
) linksByPorts links.${linkName}.ports
) {} (builtins.attrNames links);
in ''
## ${hostName}
`${model}` @ **${location}**
|Ports|Target|Networks|
|-:|:-:|:-|
${lib.concatMapStrings (ports:
let
linkName = linksByPorts.${ports};
link = links.${linkName};
in ''
|${
lib.optionalString (link.group != null)
"**Group ${toString link.group}**<br>"
}${
ports
}|**${
linkName
}**|${
if link.trunk
then "**Trunk:** "
else "**Access:** "
}${
lib.concatStringsSep ", " (
map (net:
if config.site.net.${net}.vlan != null
then "${net}&nbsp;(`${toString config.site.net.${net}.vlan}`)"
else net
) (builtins.sort (a: b:
let
vlanA = config.site.net.${a}.vlan;
vlanB = config.site.net.${b}.vlan;
in
(
if vlanA == null
then 4096
else vlanA
) < (
if vlanB == null
then 4096
else vlanB
)
) link.nets)
)
}|
'') (lib.naturalSort (
builtins.attrNames linksByPorts
))}
'');
reportRole = role:
reportHosts (
lib.naturalSort (
builtins.filter (hostName:
config.site.hosts.${hostName}.role == role
) (builtins.attrNames config.site.hosts)
)
);
in
writeText "switch-report.md" ''
# Switch Report
${reportRole "switch"}
# Access Point Report
${reportRole "ap"}
''

View File

@ -1,180 +0,0 @@
{ self, pkgs, hostName, config, hostConfig
, sort, sortBy, sortNetsByVlan
, ... }:
with pkgs;
with lib;
''
#! ${expect}/bin/expect -f
${if hostConfig.firstboot
then ''
spawn sudo ${uucp}/bin/cu -s 19200 -l /dev/ttyUSB0
send "\r"
''
else ''
spawn ${inetutils}/bin/telnet ${config.site.net.mgmt.hosts4.${hostName}}
expect "Password:"
send "${hostConfig.password}\r"
''
}
expect ">"
send "system-view\r"
expect "]"
send "sysname ${hostName}\r"
expect "]"
send "user-interface vty 0 4\r"
expect "ui-vty0-4]"
send "screen-length 0\r"
expect "ui-vty0-4]"
send "user privilege level 3\r"
expect "ui-vty0-4]"
send "set authentication password simple ${hostConfig.password}\r"
expect "ui-vty0-4]"
send "quit\r"
expect "${hostName}]"
send "local-user admin\r"
expect -- "-luser-admin]"
send "password simple ${hostConfig.password}\r"
expect -- "-luser-admin]"
send "quit\r"
expect "${hostName}]"
# Enable logging
send "info-center enable\r"
expect "]"
send "info-center loghost ${config.site.net.mgmt.hosts4.logging} channel loghost facility local6\r"
expect "]"
send "info-center source default channel loghost log level informational\r"
expect "]"
${concatMapStrings (net:
let
netConfig = config.site.net.${net};
vlan = toString netConfig.vlan;
inherit (config.site.net.${net}) hosts4;
hostAddr4 = hosts4.${hostName};
prefixLength = elemAt (
builtins.split "/" netConfig.subnet4
) 2;
netmask = self.lib.netmasks.${prefixLength};
in
if netConfig.vlan != null
then ''
send "vlan ${vlan}\r"
expect -- "-vlan${vlan}]"
send "name ${net}\r"
expect -- "-vlan${vlan}]"
${optionalString (net == "mgmt") ''
# Actually only used for mgmt_vlan, switches are not routers
send "interface Vlan-interface ${vlan}\r"
expect "]"
${optionalString (hosts4 ? ${hostName}) ''
send "ip address ${hostAddr4} ${netmask}\r"
expect "]"
''}
''}
send "quit\r"
expect "${hostName}]"
''
else ""
) (sortNetsByVlan (builtins.attrNames config.site.net))
}
${concatMapStrings (name:
let
linkConfig = hostConfig.links.${name};
isAccess = config.site.net ? ${name};
netConfig = config.site.net.${name};
isTrunk = !isAccess;
isBond = isTrunk && builtins.length linkConfig.ports > 1;
in
if isTrunk
then ''
${optionalString isBond ''
send "link-aggregation group ${linkConfig.group} mode static\r"
expect {
"This aggregation will be modified to static mode. Continue ?" {
send "Y\r"
}
"]" {}
}
send "link-aggregation group ${linkConfig.group} description ${name}\r"
expect "]"
''}
${concatMapStrings (port: ''
send "interface ${port}\r"
expect "]"
send "undo stp edged-port\r"
expect "]"
${if isBond
then ''
send "lacp enable\r"
expect "]"
send "undo port link-aggregation group\r"
expect "]"
send "port link-aggregation group ${linkConfig.group}\r"
'' else ''
send "undo lacp enable\r"
''}
expect "]"
send "jumboframe enable\r"
expect "]"
send "port link-type trunk\r"
expect "]"
# Set dummy default vlan
send "port trunk pvid vlan 4094\r"
expect "]"
# Deconfigure all but mgmt vlan
send "undo port trunk permit vlan 2 to 4094\r"
expect "]"
${concatMapStrings (vlan: ''
send "port trunk permit vlan ${toString vlan}\r"
expect "]"
'') (sort linkConfig.vlans)}
send "undo shutdown\r"
expect "]"
send "quit\r"
expect "${hostName}]"
'') (sort linkConfig.ports)}
'' else
concatMapStrings (port: ''
send "interface ${port}\r"
expect "]"
send "undo port link-aggregation group\r"
expect "]"
send "port link-type access\r"
expect "]"
${if name == "mgmt"
then ''
send "undo port access vlan\r"
expect "]"
'' else ''
send "port access vlan ${toString netConfig.vlan}\r"
expect "]"
''}
send "undo shutdown\r"
expect "]"
send "quit\r"
expect "${hostName}]"
'') (sort linkConfig.ports)
) (sortBy (link: hostConfig.links.${link}.ports)
(builtins.attrNames hostConfig.links)
)}
send "save main\r"
expect "Y/N]"
send "YES\r"
expect "press the enter key):"
send "\r"
expect "]"
send "quit\r"
expect ">"
send "quit\r"
''

View File

@ -122,7 +122,7 @@ with lib;
send "exit\r" send "exit\r"
expect "(config)#" expect "(config)#"
'' else '' '' else ''
send "interface range gigabitEthernet ${ports}\r" send "interface range gigabitEthernet 1/0/${ports}\r"
expect "(config-if-range)#" expect "(config-if-range)#"
send "switchport mode access\r" send "switchport mode access\r"
expect "(config-if-range)#" expect "(config-if-range)#"

View File

@ -1,134 +0,0 @@
{ pkgs, hostName, config, hostConfig
, sortBy, sortNetsByVlan
, ... }:
with pkgs;
with lib;
let
configFile = builtins.toFile "junos.config" ''
system {
host-name ${hostName};
time-zone Europe/Berlin;
root-authentication {
encrypted-password "%%HASH%%"; ## SECRET-DATA
ssh-ed25519 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHGgoLzQMeyX1wjsX/hgVkN//zyfOQPiBRYgO2ajEGH6 root@server2";
}
services {
ssh {
root-login allow;
}
netconf {
ssh;
}
web-management {
http {
interface [ vme.0 vlan.1 ];
}
}
}
}
protocols {
lldp {
interface all;
}
}
virtual-chassis {
no-split-detection;
member 0 {
mastership-priority 255;
}
member 1 {
mastership-priority 255;
}
}
chassis { aggregated-devices { ethernet { device-count 32; } } }
vlans {
${concatMapStrings (net:
let
netName = if net == "mgmt"
then "mgmt-vlan"
else net;
netConfig = config.site.net.${net};
vlan = toString netConfig.vlan;
in
lib.optionalString (netConfig.vlan != null) ''
${netName} {
vlan-id ${vlan};
${lib.optionalString (net == "mgmt") ''
l3-interface vlan.${vlan};
''}
}
''
) (sortNetsByVlan (builtins.attrNames config.site.net))}
}
interfaces {
vlan {
unit ${toString config.site.net.mgmt.vlan} {
family inet {
address ${mgmtAddress}/${toString config.site.net.mgmt.subnet4Len};
}
}
}
${concatMapStrings (name:
let
linkConfig = hostConfig.links.${name};
group = linkConfig.group;
isBond = linkConfig.group != null &&
builtins.length linkConfig.ports > 1;
nets = map (net:
if net == "mgmt"
then "mgmt-vlan"
else net
) linkConfig.nets;
vlanConfig = ''
unit 0 {
family ethernet-switching {
port-mode ${if linkConfig.trunk then "trunk" else "access"};
vlan { members [ ${concatStringsSep " " nets} ]; }
}
}
'';
in
if isBond
then concatMapStrings (port: ''
${port} {
ether-options { 802.3ad ae${group}; }
}
'') (linkConfig.ports) + ''
ae${group} {
aggregated-ether-options { lacp { active; } }
${vlanConfig}
}
''
else concatMapStrings (port: ''
${port} {
${vlanConfig}
}
'') (linkConfig.ports)
) (sortBy (link: hostConfig.links.${link}.ports)
(builtins.attrNames hostConfig.links)
)}
}
'';
configFileWithHash = runCommand "junos.config" {
nativeBuildInputs = [ mkpasswd ];
} ''
HASH=$(echo "${hostConfig.password}" | mkpasswd --method=SHA-512 --stdin)
substitute ${configFile} $out \
--replace "%%HASH%%" "$HASH"
'';
mgmtAddress = config.site.net.mgmt.hosts4.${hostName};
in ''
#! ${runtimeShell} -e
scp ${configFileWithHash} root@${mgmtAddress}:/tmp/junos.config
ssh root@${mgmtAddress} cli <<EOF
configure
load override /tmp/junos.config
commit
EOF
''

View File

@ -1,5 +1,5 @@
# https://www.crc.id.au/real-console-on-linksys-srw2024-switch/ # https://www.crc.id.au/real-console-on-linksys-srw2024-switch/
{ pkgs, hostName, config, hostConfig { self, pkgs, hostName, config, hostConfig
, sort, sortBy, sortNetsByVlan , sort, sortBy, sortNetsByVlan
, ... }: , ... }:
with pkgs; with pkgs;
@ -66,11 +66,10 @@ with lib;
${concatMapStrings (name: ${concatMapStrings (name:
let let
linkConfig = hostConfig.links.${name}; linkConfig = hostConfig.links.${name};
isAccess = config.site.net ? ${name};
netConfig = config.site.net.${name}; netConfig = config.site.net.${name};
isTrunk = linkConfig.trunk; isTrunk = !isAccess;
isBond = builtins.length linkConfig.ports > 1 && isBond = isTrunk && builtins.length linkConfig.ports > 1;
# not named like a net
(!config.site.net ? ${name});
vlans = concatStringsSep "," (map toString (sort linkConfig.vlans)); vlans = concatStringsSep "," (map toString (sort linkConfig.vlans));
ports = concatStringsSep "," linkConfig.ports; ports = concatStringsSep "," linkConfig.ports;
in in
@ -109,31 +108,6 @@ with lib;
send "exit\r" send "exit\r"
expect "(config)#" expect "(config)#"
'') linkConfig.ports '') linkConfig.ports
else if isBond
then
if builtins.length linkConfig.vlans != 1
then throw "Cannot configure non-trunked port with multiple vlans"
else ''
send "interface range ethernet ${ports}\r"
expect "(config-if)#"
send "channel-group ${linkConfig.group} mode auto\r"
expect "(config-if)#"
send "interface port-channel ${linkConfig.group}\r"
expect "(config-if)#"
send "exit\r"
send "interface port-channel ${linkConfig.group}\r"
expect "(config-if)#"
send "switchport trunk allowed vlan remove all\r"
expect "(config-if)#"
send "switchport mode access\r"
expect "(config-if)#"
send "switchport access vlan ${toString (builtins.head linkConfig.vlans)}\r"
expect "(config-if)#"
send "exit\r"
expect "(config)#"
''
else concatMapStrings (port: '' else concatMapStrings (port: ''
send "interface ethernet ${port}\r" send "interface ethernet ${port}\r"
expect "(config-if)#" expect "(config-if)#"

View File

@ -3,10 +3,8 @@ with nixpkgs.legacyPackages.${system};
let let
config = self.lib.config; config = self.lib.config;
in in
writeText "vlan-report.md" '' writeText "vlan-report.txt" (
# VLAN Report lib.concatMapStrings (net: ''
${lib.concatMapStrings (net: ''
## ${net}${lib.optionalString (config.site.net.${net}.vlan != null) " (VLAN ${toString config.site.net.${net}.vlan})"} ## ${net}${lib.optionalString (config.site.net.${net}.vlan != null) " (VLAN ${toString config.site.net.${net}.vlan})"}
${lib.concatStringsSep "\n" ( ${lib.concatStringsSep "\n" (
lib.concatMap (host: lib.concatMap (host:
@ -20,5 +18,5 @@ writeText "vlan-report.md" ''
) (lib.attrNames config.site.hosts) ) (lib.attrNames config.site.hosts)
)} )}
'') (lib.attrNames config.site.net)} '') (lib.attrNames config.site.net)
'' )

5985
openwrt/tl-wr841-v10.config Normal file

File diff suppressed because it is too large Load Diff

5849
openwrt/tl-wr841-v11.config Normal file

File diff suppressed because it is too large Load Diff

6002
openwrt/tl-wr841-v8.config Normal file

File diff suppressed because it is too large Load Diff