Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Astro | 4260ec2405 |
|
@ -1,3 +1 @@
|
|||
/contact.md
|
||||
/config/secrets-production.nix
|
||||
/config/secrets-production.nix.old
|
||||
contact.md
|
||||
|
|
48
README.md
48
README.md
|
@ -23,11 +23,20 @@ Wir, ein kleiner Kreis von Menschen die das Netzwerk im Zentralwerk betreuen, ha
|
|||
|
||||
* [Verkabelung Patchpanel Haus B](cabling.md)
|
||||
* TODO: tuerme, saal
|
||||
* [Planung der IP-Adressbereiche](subnets.md)
|
||||
* (verschlüsselte) [Kontakte zu den Personen mit den einzelnen Anschlüssen](contact.md.gpg)
|
||||
* Dokumentation
|
||||
* [WiFi-Provisionierung](doc/wifi-provisioning.md) und Erstellung von Privatnetzen
|
||||
* `flake.nix` und Unterverzeichnis [nix/](nix): Konfigurationsskripte
|
||||
|
||||
### Nixification Roadmap
|
||||
|
||||
- [x] Einlesen der Salt-Daten in Nix
|
||||
- [x] Containererstellung
|
||||
- [x] Migration der Container
|
||||
- [ ] device-scripts auf Site Config umstellen
|
||||
- [ ] Site Config ohne Entschlüsselung dumpen, Salt-Daten löschen
|
||||
|
||||
### Development Setup
|
||||
|
||||
Get Nix with Flakes first:
|
||||
|
@ -52,16 +61,11 @@ set.
|
|||
|
||||
#### Gerätekonfigurationen
|
||||
|
||||
```bash
|
||||
```
|
||||
nix build .#all-device-scripts
|
||||
./result/bin/...
|
||||
```
|
||||
|
||||
Oder direkt:
|
||||
```bash
|
||||
nix run .#switch-b2 && nix run .#ap3
|
||||
```
|
||||
|
||||
### Server Setup
|
||||
|
||||
```
|
||||
|
@ -73,15 +77,11 @@ auch `/etc/nixos` so dass `nixos-rebuild switch` problemlos
|
|||
klappt. Ausserdem ist dieser lokale Checkout in der `nix registry`
|
||||
eingetragen, was von bspw. von `build-container` verwendet wird.
|
||||
|
||||
Ausserdem werden dort immer wieder `nix run .#switch-to-production`
|
||||
ausgeführt.
|
||||
Der Flake-input `zentralwerk-network-key` ist mit einem lokalen
|
||||
Repository überschrieben, weshalb die `flake.lock` dirty ist.
|
||||
|
||||
### 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
|
||||
Container. systemd versucht sie zu starten. Das wird erst nach
|
||||
`build-container` funktionieren, welches das Rootfs anlegt.
|
||||
|
@ -100,6 +100,9 @@ Innerhalb eines Containers gibts erneut `systemctl`, `journalctl`,
|
|||
|
||||
### Nix Flake
|
||||
|
||||
[Segfaulting nix?](https://github.com/NixOS/nix/issues/4178) Until
|
||||
resolved, `export GC_DONT_GC=1`
|
||||
|
||||
#### Site Config
|
||||
|
||||
Wir verwenden das Module-System von NixOS eigenständig in
|
||||
|
@ -119,14 +122,6 @@ Systemkonfigurationen für alle Hosts mit der `role` `"server"` oder
|
|||
|
||||
Alle NixOS-Einstellungen
|
||||
|
||||
#### Secrets
|
||||
|
||||
```bash
|
||||
nix run .#decrypt-secrets
|
||||
$EDITOR config/secrets-production.nix
|
||||
nix run .#encrypt-secrets
|
||||
```
|
||||
|
||||
### server1 als Cold Standby
|
||||
|
||||
Was ein Server kann, kann ein anderer auch. Er sollte gelegentlich
|
||||
|
@ -137,14 +132,11 @@ werden, muss die Datei `/etc/start-containers` *vorhanden* sein. Zum
|
|||
Umgang damit gibt es die zwei handlichen Befehle `enable-containers`
|
||||
und `disable-containers`.
|
||||
|
||||
### Dinge die stets schieflaufen
|
||||
|
||||
#### IP Subnet Plans
|
||||
#### pub-Netz läuft, aber kein DHCP+Internet darüber verfügbar
|
||||
|
||||
`nix build .#`[subnetplan4](https://hydra.hq.c3d2.de/job/c3d2/zentralwerk-network/subnetplans/latest/download/1)
|
||||
Eventuell hat `uci` bei der ap-Konfiguration die Switch-Konfiguration
|
||||
für dieses VLAN nicht in `/etc/config/network` angelegt.
|
||||
|
||||
`nix build .#`[subnetplan6](https://hydra.hq.c3d2.de/job/c3d2/zentralwerk-network/subnetplans/latest/download/2)
|
||||
|
||||
#### Network Maps
|
||||
|
||||
![Physikalische Vernetzung](https://hydra.hq.c3d2.de/job/c3d2/zentralwerk-network/network-graphs/latest/download/2)
|
||||
![Logische Vernetzung](https://hydra.hq.c3d2.de/job/c3d2/zentralwerk-network/network-graphs/latest/download/1)
|
||||
* **Überprüfen**: `swconfig dev switch0 show`
|
||||
|
|
|
@ -26,11 +26,11 @@ Alle Stecker im Haus sind in Schema A gecrimpt.
|
|||
| | ![][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.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.05.02 *v* | ![][gi] B 2.06 | | | 19 |
|
||||
| ![][ri] B 4.06.01 *v* | ![][ri] B 2.07 | | | 20 |
|
||||
| ![][ri] B 4.07.05 *v* | | | | 21 |
|
||||
| ![][ri] B 4.06.01 | ![][ri] B 2.07 | | | 20 |
|
||||
| ![][ri] B 4.07.05 | | | | 21 |
|
||||
| ![][ri] B 4.08.01 | | | | 22 |
|
||||
| ![][ri] B 4.09.01 *v* | | | | 23 |
|
||||
| ![][ri] B 4.10.01 *v* | | | | 24 |
|
||||
|
|
2425
config/ap.nix
2425
config/ap.nix
File diff suppressed because it is too large
Load Diff
|
@ -1,21 +0,0 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
# https://github.com/NixOS/nixpkgs/pull/206965
|
||||
concatMapAttrsRecursive = with lib; f: flip pipe [ (mapAttrs f) attrValues (foldl' recursiveUpdate { }) ];
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
# Secrets
|
||||
./secrets.nix
|
||||
|
||||
# Hardware
|
||||
./vlan.nix
|
||||
./switch.nix
|
||||
./ap.nix
|
||||
./server.nix
|
||||
]
|
||||
# IP networks
|
||||
++ lib.filesystem.listFilesRecursive ./net;
|
||||
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
{ lib, ... }:
|
||||
{
|
||||
site.net.c3d2 = {
|
||||
dhcp = {
|
||||
server = "c3d2-gw3";
|
||||
start = "172.22.99.100";
|
||||
end = "172.22.99.199";
|
||||
fixed-hosts = {
|
||||
"172.22.99.96" = "08:00:27:bb:8c:b3";
|
||||
"172.22.99.98" = "08:00:27:aa:90:e2";
|
||||
# "astrom" = "aa:00:5b:08:f0:5c";
|
||||
# "astron" = "aa:00:5b:08:f0:5b";
|
||||
# "batman" = "5c:cf:7f:c0:05:28";
|
||||
# "beere" = "b8:27:eb:ac:65:d2";
|
||||
# "beere2" = "b8:27:eb:53:0b:27";
|
||||
# "bender.hq.c3de.de" = "00:23:df:7e:c8:0a";
|
||||
# "cider" = "00:0d:93:75:ee:fa";
|
||||
"dacbert" = "dc:a6:32:e0:46:bf";
|
||||
"dn42" = "aa:00:42:7a:32:46";
|
||||
# "drucker" = "00:23:c3:d2:12:0f";
|
||||
# "feile" = "aa:00:5b:12:c1:f7";
|
||||
# "fernandopoo" = "aa:00:f7:52:85:27";
|
||||
# "fhem" = "b8:27:eb:9e:8b:db";
|
||||
# "git" = "aa:00:47:d8:57:10";
|
||||
"glotzbert" = "90:1b:0e:88:da:0a";
|
||||
# "wled-nix-snowflake" = "44:17:93:10:77:e8";
|
||||
# "wled-fairy-dust" = "3c:61:05:e3:2f:ad";
|
||||
# "wled-warnbert" = "3c:61:05:fc:21:37";
|
||||
# "wled-matrix" = "e8:db:84:e4:f4:30";
|
||||
# "ledball1" = "b8:27:eb:53:0b:27";
|
||||
# Beleuchtungskiste auf Traverse über Fernseher
|
||||
# "ledbeere" = "b8:27:eb:60:99:59";
|
||||
# "leviathan" = "00:ff:08:31:db:e5";
|
||||
# "lisbeth" = "b8:27:eb:a5:ee:5c";
|
||||
# "marenz-build" = "44:1e:a1:59:2e:e8";
|
||||
# "matemat" = "a2:1b:7c:e8:19:72";
|
||||
# "minecraft" = "4a:57:d3:64:fe:e9";
|
||||
# "moleflap" = "aa:00:0d:b1:6c:67";
|
||||
# "monit" = "00:23:ae:94:e7:19";
|
||||
"pipebert" = "ec:a8:6b:fe:b4:cb";
|
||||
# "public-access-proxy" = "12:24:5f:bd:9b:e7";
|
||||
"pulsebert" = "b8:27:eb:16:31:61";
|
||||
# "ruststripe1" = "06:32:0e:39:21:69";
|
||||
"schalter" = "b8:27:eb:ac:65:d2";
|
||||
# "semanta" = "00:ff:e4:bb:ea:2a";
|
||||
# "server2" = "d0:67:e5:f3:57:10";
|
||||
# "server3" = "e4:1f:13:2e:4f:c0";
|
||||
# "server4" = "00:9c:02:a9:26:01";
|
||||
# "sharing" = "00:23:c3:d2:75:18";
|
||||
# "sofafon" = "b8:27:eb:23:8d:01";
|
||||
# "storage2" = "42:5e:0f:4e:f3:cc";
|
||||
# "ustriper" = "aa:bb:95:33:bb:aa";
|
||||
# "wiefelspuetz" = "aa:00:7f:01:8a:d0";
|
||||
# "wormhole" = "00:23:c3:d2:00:76";
|
||||
# "www1" = "aa:00:13:8b:03:47";
|
||||
# "riscbert" = "6c:cf:39:00:05:95";
|
||||
};
|
||||
time = 300;
|
||||
max-time = 30 * 24 * 3600;
|
||||
router = "c3d2-gw3";
|
||||
};
|
||||
domainName = "c3d2.zentralwerk.org";
|
||||
dynamicDomain = true;
|
||||
subnet4 = "172.22.99.0/24";
|
||||
hosts4 = {
|
||||
c3d2-anon = "172.22.99.1";
|
||||
c3d2-gw1 = "172.22.99.2";
|
||||
c3d2-gw2 = "172.22.99.3";
|
||||
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";
|
||||
};
|
||||
ipv6Router = "c3d2-gw3";
|
||||
hosts6.dn42 = {
|
||||
bgp = "fd23:42:c3d2:523::c3d2:ff0b";
|
||||
c3d2-anon = "fd23:42:c3d2:523::c3d2:1";
|
||||
c3d2-gw1 = "fd23:42:c3d2:523::c3d2:2";
|
||||
c3d2-gw2 = "fd23:42:c3d2:523::c3d2:3";
|
||||
c3d2-gw3 = "fd23:42:c3d2:523::c3d2:4";
|
||||
};
|
||||
hosts6.up4 = {
|
||||
bgp = "2a00:8180:2c00:223::c3d2:ff0b";
|
||||
c3d2-anon = "2a00:8180:2c00:223::c3d2:1";
|
||||
c3d2-gw1 = "2a00:8180:2c00:223::c3d2:2";
|
||||
c3d2-gw2 = "2a00:8180:2c00:223::c3d2:3";
|
||||
c3d2-gw3 = "2a00:8180:2c00:223::c3d2:4";
|
||||
pipebert = "2a00:8180:2c00:223:eea8:6bff:fefe:b4cb";
|
||||
};
|
||||
subnets6 = {
|
||||
dn42 = "fd23:42:c3d2:523::/64";
|
||||
up4 = "2a00:8180:2c00:223::/64";
|
||||
};
|
||||
};
|
||||
|
||||
site.hosts =
|
||||
let
|
||||
makeGateway = lib.recursiveUpdate {
|
||||
interfaces = {
|
||||
c3d2.type = "veth";
|
||||
core.type = "veth";
|
||||
};
|
||||
role = "container";
|
||||
};
|
||||
in
|
||||
{
|
||||
c3d2-anon = makeGateway {
|
||||
interfaces = {
|
||||
c3d2.hwaddr = "0A:14:48:01:07:05";
|
||||
core.hwaddr = "0A:14:48:01:07:04";
|
||||
};
|
||||
ospf.allowedUpstreams = [ "anon1" "freifunk" ];
|
||||
};
|
||||
c3d2-gw1 = makeGateway {
|
||||
interfaces = {
|
||||
c3d2.hwaddr = "0A:14:48:01:21:01";
|
||||
core.hwaddr = "0A:14:48:01:21:00";
|
||||
};
|
||||
ospf.allowedUpstreams = [ "flpk-gw" "freifunk" "upstream4" "upstream3" "anon1" ];
|
||||
};
|
||||
c3d2-gw2 = makeGateway {
|
||||
interfaces = {
|
||||
c3d2.hwaddr = "0A:14:48:01:21:03";
|
||||
core.hwaddr = "0A:14:48:01:21:02";
|
||||
};
|
||||
ospf.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ];
|
||||
};
|
||||
c3d2-gw3 = makeGateway {
|
||||
interfaces = {
|
||||
c3d2.hwaddr = "0A:14:48:01:21:05";
|
||||
core.hwaddr = "0A:14:48:01:21:04";
|
||||
};
|
||||
ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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";
|
||||
};
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
{ lib, ... }:
|
||||
let
|
||||
cephMonServers = [ "server5" "server6" "server8" ];
|
||||
in
|
||||
{
|
||||
site.net.cluster = {
|
||||
ipv6Router = "cls-gw";
|
||||
domainName = "cluster.zentralwerk.org";
|
||||
extraRecords = map (host: {
|
||||
data = {
|
||||
service = "ceph-mon";
|
||||
proto = "tcp";
|
||||
priority = 1;
|
||||
weight = 1;
|
||||
port = 6789;
|
||||
target = host;
|
||||
};
|
||||
name = "@";
|
||||
type = "SRV";
|
||||
}) cephMonServers
|
||||
++
|
||||
lib.lists.imap0 (i: host: {
|
||||
name = "mon${toString i}";
|
||||
type = "CNAME";
|
||||
data = "${host}";
|
||||
}) cephMonServers;
|
||||
hosts4 = {
|
||||
cls-gw = "172.20.77.1";
|
||||
server1 = "172.20.77.30";
|
||||
server2 = "172.20.77.2";
|
||||
server3 = "172.20.77.3";
|
||||
server4 = "172.20.77.4";
|
||||
server5 = "172.20.77.5";
|
||||
server6 = "172.20.77.6";
|
||||
server7 = "172.20.77.7";
|
||||
server8 = "172.20.77.8";
|
||||
server9 = "172.20.77.9";
|
||||
server10 = "172.20.77.10";
|
||||
server11 = "172.20.77.11";
|
||||
server12 = "172.20.77.12";
|
||||
server13 = "172.20.77.13";
|
||||
server14 = "172.20.77.14";
|
||||
server15 = "172.20.77.15";
|
||||
server16 = "172.20.77.16";
|
||||
server17 = "172.20.77.17";
|
||||
server18 = "172.20.77.18";
|
||||
server19 = "172.20.77.19";
|
||||
server20 = "172.20.77.20";
|
||||
server21 = "172.20.77.21";
|
||||
server22 = "172.20.77.22";
|
||||
server23 = "172.20.77.23";
|
||||
server24 = "172.20.77.24";
|
||||
server25 = "172.20.77.25";
|
||||
server26 = "172.20.77.26";
|
||||
server27 = "172.20.77.27";
|
||||
server28 = "172.20.77.28";
|
||||
server29 = "172.20.77.29";
|
||||
};
|
||||
hosts6 = {
|
||||
dn42 = {
|
||||
cls-gw = "fd23:42:c3d2:586::1";
|
||||
server1 = "fd23:42:c3d2:586::11";
|
||||
server2 = "fd23:42:c3d2:586::12";
|
||||
server3 = "fd23:42:c3d2:586::13";
|
||||
server4 = "fd23:42:c3d2:586::14";
|
||||
server5 = "fd23:42:c3d2:586::15";
|
||||
server6 = "fd23:42:c3d2:586::16";
|
||||
server7 = "fd23:42:c3d2:586::17";
|
||||
server8 = "fd23:42:c3d2:586::18";
|
||||
server9 = "fd23:42:c3d2:586::19";
|
||||
server10 = "fd23:42:c3d2:586::1a";
|
||||
server11 = "fd23:42:c3d2:586::1b";
|
||||
server12 = "fd23:42:c3d2:586::1c";
|
||||
server13 = "fd23:42:c3d2:586::1d";
|
||||
server14 = "fd23:42:c3d2:586::1e";
|
||||
server15 = "fd23:42:c3d2:586::1f";
|
||||
server16 = "fd23:42:c3d2:586::20";
|
||||
server17 = "fd23:42:c3d2:586::21";
|
||||
server18 = "fd23:42:c3d2:586::22";
|
||||
server19 = "fd23:42:c3d2:586::23";
|
||||
server20 = "fd23:42:c3d2:586::24";
|
||||
server21 = "fd23:42:c3d2:586::25";
|
||||
server22 = "fd23:42:c3d2:586::26";
|
||||
server23 = "fd23:42:c3d2:586::27";
|
||||
server24 = "fd23:42:c3d2:586::28";
|
||||
server25 = "fd23:42:c3d2:586::29";
|
||||
server26 = "fd23:42:c3d2:586::2a";
|
||||
server27 = "fd23:42:c3d2:586::2b";
|
||||
server28 = "fd23:42:c3d2:586::2c";
|
||||
server29 = "fd23:42:c3d2:586::2d";
|
||||
};
|
||||
up4 = {
|
||||
cls-gw = "2a00:8180:2c00:284::1";
|
||||
server1 = "2a00:8180:2c00:284::11";
|
||||
server2 = "2a00:8180:2c00:284::12";
|
||||
server3 = "2a00:8180:2c00:284::13";
|
||||
server4 = "2a00:8180:2c00:284::14";
|
||||
server5 = "2a00:8180:2c00:284::15";
|
||||
server6 = "2a00:8180:2c00:284::16";
|
||||
server7 = "2a00:8180:2c00:284::17";
|
||||
server8 = "2a00:8180:2c00:284::18";
|
||||
server9 = "2a00:8180:2c00:284::19";
|
||||
server10 = "2a00:8180:2c00:284::1a";
|
||||
server11 = "2a00:8180:2c00:284::1b";
|
||||
server12 = "2a00:8180:2c00:284::1c";
|
||||
server13 = "2a00:8180:2c00:284::1d";
|
||||
server14 = "2a00:8180:2c00:284::1e";
|
||||
server15 = "2a00:8180:2c00:284::1f";
|
||||
server16 = "2a00:8180:2c00:284::20";
|
||||
server17 = "2a00:8180:2c00:284::21";
|
||||
server18 = "2a00:8180:2c00:284::22";
|
||||
server19 = "2a00:8180:2c00:284::23";
|
||||
server20 = "2a00:8180:2c00:284::24";
|
||||
server21 = "2a00:8180:2c00:284::25";
|
||||
server22 = "2a00:8180:2c00:284::26";
|
||||
server23 = "2a00:8180:2c00:284::27";
|
||||
server24 = "2a00:8180:2c00:284::28";
|
||||
server25 = "2a00:8180:2c00:284::29";
|
||||
server26 = "2a00:8180:2c00:284::2a";
|
||||
server27 = "2a00:8180:2c00:284::2b";
|
||||
server28 = "2a00:8180:2c00:284::2c";
|
||||
server29 = "2a00:8180:2c00:284::2d";
|
||||
};
|
||||
};
|
||||
subnet4 = "172.20.77.0/27";
|
||||
subnets6 = {
|
||||
dn42 = "fd23:42:c3d2:586::/64";
|
||||
up4 = "2a00:8180:2c00:284::/64";
|
||||
};
|
||||
};
|
||||
|
||||
site.hosts =
|
||||
let
|
||||
makeServer = {
|
||||
role = "client";
|
||||
model = "nixos";
|
||||
interfaces = builtins.foldl' (interfaces: net:
|
||||
interfaces // {
|
||||
"${net}".type = "bridge";
|
||||
}
|
||||
) {} [
|
||||
"cluster"
|
||||
"core"
|
||||
"mgmt"
|
||||
"serv"
|
||||
"c3d2"
|
||||
"c3d2iot"
|
||||
"pub"
|
||||
"priv23"
|
||||
"priv31"
|
||||
"priv45"
|
||||
"bmx"
|
||||
"flpk"
|
||||
];
|
||||
};
|
||||
in {
|
||||
cls-gw = {
|
||||
role = "container";
|
||||
interfaces = {
|
||||
cluster = {
|
||||
hwaddr = "0A:14:48:01:06:02";
|
||||
type = "veth";
|
||||
};
|
||||
core = {
|
||||
hwaddr = "0A:14:48:01:06:03";
|
||||
type = "veth";
|
||||
};
|
||||
};
|
||||
ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ];
|
||||
};
|
||||
server3 = makeServer;
|
||||
server5 = makeServer;
|
||||
server6 = makeServer;
|
||||
server7 = makeServer;
|
||||
server8 = makeServer;
|
||||
server9 = makeServer;
|
||||
server10 = makeServer;
|
||||
};
|
||||
}
|
|
@ -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" ];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,249 +0,0 @@
|
|||
{
|
||||
site.net.core = {
|
||||
domainName = "core.zentralwerk.org";
|
||||
hosts4 = {
|
||||
anon1 = "172.20.72.7";
|
||||
bgp = "172.20.72.27";
|
||||
c3d2-anon = "172.20.72.9";
|
||||
c3d2-gw1 = "172.20.72.8";
|
||||
c3d2-gw2 = "172.20.72.63";
|
||||
c3d2-gw3 = "172.20.72.64";
|
||||
cls-gw = "172.20.72.29";
|
||||
freifunk = "172.20.72.40";
|
||||
mgmt-gw = "172.20.72.28";
|
||||
priv1-gw = "172.20.72.4";
|
||||
priv10-gw = "172.20.72.20";
|
||||
priv11-gw = "172.20.72.21";
|
||||
priv12-gw = "172.20.72.22";
|
||||
priv13-gw = "172.20.72.23";
|
||||
priv14-gw = "172.20.72.24";
|
||||
priv15-gw = "172.20.72.25";
|
||||
priv16-gw = "172.20.72.26";
|
||||
priv17-gw = "172.20.72.30";
|
||||
priv17-gw-up3 = "172.20.72.66";
|
||||
priv18-gw = "172.20.72.31";
|
||||
priv19-gw = "172.20.72.32";
|
||||
priv2-gw = "172.20.72.5";
|
||||
priv20-gw = "172.20.72.33";
|
||||
priv21-gw = "172.20.72.34";
|
||||
priv22-gw = "172.20.72.35";
|
||||
priv23-gw = "172.20.72.36";
|
||||
priv24-gw = "172.20.72.37";
|
||||
priv25-gw = "172.20.72.38";
|
||||
priv26-gw = "172.20.72.39";
|
||||
priv27-gw = "172.20.72.41";
|
||||
priv28-gw = "172.20.72.42";
|
||||
priv29-gw = "172.20.72.43";
|
||||
priv3-gw = "172.20.72.13";
|
||||
priv30-gw = "172.20.72.44";
|
||||
priv31-gw = "172.20.72.45";
|
||||
priv32-gw = "172.20.72.46";
|
||||
priv33-gw = "172.20.72.47";
|
||||
priv34-gw = "172.20.72.48";
|
||||
priv35-gw = "172.20.72.49";
|
||||
priv36-gw = "172.20.72.50";
|
||||
priv37-gw = "172.20.72.51";
|
||||
priv38-gw = "172.20.72.52";
|
||||
priv39-gw = "172.20.72.60";
|
||||
priv4-gw = "172.20.72.14";
|
||||
priv40-gw = "172.20.72.61";
|
||||
priv41-gw = "172.20.72.65";
|
||||
priv42-gw = "172.20.72.67";
|
||||
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";
|
||||
priv6-gw = "172.20.72.16";
|
||||
priv7-gw = "172.20.72.17";
|
||||
priv8-gw = "172.20.72.18";
|
||||
priv9-gw = "172.20.72.19";
|
||||
pub-gw = "172.20.72.3";
|
||||
serv-gw = "172.20.72.2";
|
||||
server3 = "172.20.72.53";
|
||||
server4 = "172.20.72.54";
|
||||
server5 = "172.20.72.55";
|
||||
server6 = "172.20.72.56";
|
||||
server7 = "172.20.72.57";
|
||||
server8 = "172.20.72.58";
|
||||
upstream3 = "172.20.72.11";
|
||||
upstream4 = "172.20.72.12";
|
||||
coloradio-gw = "172.20.72.62";
|
||||
vpn-gw = "172.20.72.69";
|
||||
flpk-gw = "172.20.72.71";
|
||||
iot-gw = "172.20.72.77";
|
||||
};
|
||||
hosts6 = {
|
||||
dn42 = {
|
||||
anon1 = "fd23:42:c3d2:581::9:1";
|
||||
bgp = "fd23:42:c3d2:581::c3d2:b";
|
||||
c3d2-anon = "fd23:42:c3d2:581::c3d2:a";
|
||||
c3d2-gw1 = "fd23:42:c3d2:581::c3d2:1";
|
||||
c3d2-gw2 = "fd23:42:c3d2:581::c3d2:2";
|
||||
c3d2-gw3 = "fd23:42:c3d2:581::c3d2:3";
|
||||
cls-gw = "fd23:42:c3d2:581::c3d2:4";
|
||||
freifunk = "fd23:42:c3d2:581:8000::1";
|
||||
mgmt-gw = "fd23:42:c3d2:581::8:3";
|
||||
iot-gw = "fd23:42:c3d2:581::8:7";
|
||||
priv1-gw = "fd23:42:c3d2:581::c:0";
|
||||
priv10-gw = "fd23:42:c3d2:581::c:9";
|
||||
priv11-gw = "fd23:42:c3d2:581::c:a";
|
||||
priv12-gw = "fd23:42:c3d2:581::c:b";
|
||||
priv13-gw = "fd23:42:c3d2:581::c:c";
|
||||
priv14-gw = "fd23:42:c3d2:581::c:d";
|
||||
priv15-gw = "fd23:42:c3d2:581::c:e";
|
||||
priv16-gw = "fd23:42:c3d2:581::c:f";
|
||||
priv17-gw = "fd23:42:c3d2:581::c:10";
|
||||
priv18-gw = "fd23:42:c3d2:581::c:11";
|
||||
priv19-gw = "fd23:42:c3d2:581::c:12";
|
||||
priv2-gw = "fd23:42:c3d2:581::c:1";
|
||||
priv20-gw = "fd23:42:c3d2:581::c:13";
|
||||
priv21-gw = "fd23:42:c3d2:581::c:14";
|
||||
priv22-gw = "fd23:42:c3d2:581::c:15";
|
||||
priv23-gw = "fd23:42:c3d2:581::c:16";
|
||||
priv24-gw = "fd23:42:c3d2:581::c:17";
|
||||
priv25-gw = "fd23:42:c3d2:581::c:18";
|
||||
priv26-gw = "fd23:42:c3d2:581::c:19";
|
||||
priv27-gw = "fd23:42:c3d2:581::c:1a";
|
||||
priv28-gw = "fd23:42:c3d2:581::c:1b";
|
||||
priv29-gw = "fd23:42:c3d2:581::c:1c";
|
||||
priv3-gw = "fd23:42:c3d2:581::c:2";
|
||||
priv30-gw = "fd23:42:c3d2:581::c:1d";
|
||||
priv31-gw = "fd23:42:c3d2:581::c:1e";
|
||||
priv32-gw = "fd23:42:c3d2:581::c:1f";
|
||||
priv33-gw = "fd23:42:c3d2:581::c:20";
|
||||
priv34-gw = "fd23:42:c3d2:581::c:21";
|
||||
priv35-gw = "fd23:42:c3d2:581::c:22";
|
||||
priv36-gw = "fd23:42:c3d2:581::c:23";
|
||||
priv37-gw = "fd23:42:c3d2:581::c:24";
|
||||
priv38-gw = "fd23:42:c3d2:581::c:25";
|
||||
priv39-gw = "fd23:42:c3d2:581::c:26";
|
||||
priv4-gw = "fd23:42:c3d2:581::c:3";
|
||||
priv40-gw = "fd23:42:c3d2:581::c:27";
|
||||
priv41-gw = "fd23:42:c3d2:581::c:28";
|
||||
priv42-gw = "fd23:42:c3d2:581::c:29";
|
||||
priv43-gw = "fd23:42:c3d2:581::c:2a";
|
||||
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";
|
||||
priv6-gw = "fd23:42:c3d2:581::c:5";
|
||||
priv7-gw = "fd23:42:c3d2:581::c:6";
|
||||
priv8-gw = "fd23:42:c3d2:581::c:7";
|
||||
priv9-gw = "fd23:42:c3d2:581::c:8";
|
||||
pub-gw = "fd23:42:c3d2:581::8:2";
|
||||
serv-gw = "fd23:42:c3d2:581::8:1";
|
||||
upstream3 = "fd23:42:c3d2:581::b:2";
|
||||
upstream4 = "fd23:42:c3d2:581::b:3";
|
||||
vpn-gw = "fd23:42:c3d2:581:9001::1";
|
||||
coloradio-gw = "fd23:42:c3d2:581:9009::1";
|
||||
};
|
||||
up4 = {
|
||||
anon1 = "2a00:8180:2c00:281::9:1";
|
||||
bgp = "2a00:8180:2c00:281::c3d2:b";
|
||||
c3d2-anon = "2a00:8180:2c00:281::c3d2:a";
|
||||
c3d2-gw1 = "2a00:8180:2c00:281::c3d2:1";
|
||||
c3d2-gw2 = "2a00:8180:2c00:281::c3d2:2";
|
||||
c3d2-gw3 = "2a00:8180:2c00:281::c3d2:3";
|
||||
cls-gw = "2a00:8180:2c00:281::8:4";
|
||||
freifunk = "2a00:8180:2c00:281:8000::1";
|
||||
mgmt-gw = "2a00:8180:2c00:281::8:3";
|
||||
iot-gw = "2a00:8180:2c00:281::8:7";
|
||||
priv1-gw = "2a00:8180:2c00:281::c:0";
|
||||
priv10-gw = "2a00:8180:2c00:281::c:9";
|
||||
priv11-gw = "2a00:8180:2c00:281::c:a";
|
||||
priv12-gw = "2a00:8180:2c00:281::c:b";
|
||||
priv13-gw = "2a00:8180:2c00:281::c:c";
|
||||
priv14-gw = "2a00:8180:2c00:281::c:d";
|
||||
priv15-gw = "2a00:8180:2c00:281::c:e";
|
||||
priv16-gw = "2a00:8180:2c00:281::c:f";
|
||||
priv17-gw = "2a00:8180:2c00:281::c:10";
|
||||
priv18-gw = "2a00:8180:2c00:281::c:11";
|
||||
priv19-gw = "2a00:8180:2c00:281::c:12";
|
||||
priv2-gw = "2a00:8180:2c00:281::c:1";
|
||||
priv20-gw = "2a00:8180:2c00:281::c:13";
|
||||
priv21-gw = "2a00:8180:2c00:281::c:14";
|
||||
priv22-gw = "2a00:8180:2c00:281::c:15";
|
||||
priv23-gw = "2a00:8180:2c00:281::c:16";
|
||||
priv24-gw = "2a00:8180:2c00:281::c:17";
|
||||
priv25-gw = "2a00:8180:2c00:281::c:18";
|
||||
priv26-gw = "2a00:8180:2c00:281::c:19";
|
||||
priv27-gw = "2a00:8180:2c00:281::c:1a";
|
||||
priv28-gw = "2a00:8180:2c00:281::c:1b";
|
||||
priv29-gw = "2a00:8180:2c00:281::c:1c";
|
||||
priv3-gw = "2a00:8180:2c00:281::c:2";
|
||||
priv30-gw = "2a00:8180:2c00:281::c:1d";
|
||||
priv31-gw = "2a00:8180:2c00:281::c:1e";
|
||||
priv32-gw = "2a00:8180:2c00:281::c:1f";
|
||||
priv33-gw = "2a00:8180:2c00:281::c:20";
|
||||
priv34-gw = "2a00:8180:2c00:281::c:21";
|
||||
priv35-gw = "2a00:8180:2c00:281::c:22";
|
||||
priv36-gw = "2a00:8180:2c00:281::c:23";
|
||||
priv37-gw = "2a00:8180:2c00:281::c:24";
|
||||
priv38-gw = "2a00:8180:2c00:281::c:25";
|
||||
priv39-gw = "2a00:8180:2c00:281::c:26";
|
||||
priv4-gw = "2a00:8180:2c00:281::c:3";
|
||||
priv40-gw = "2a00:8180:2c00:281::c:27";
|
||||
priv41-gw = "2a00:8180:2c00:281::c:28";
|
||||
priv42-gw = "2a00:8180:2c00:281::c:29";
|
||||
priv43-gw = "2a00:8180:2c00:281::c:2a";
|
||||
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";
|
||||
priv6-gw = "2a00:8180:2c00:281::c:5";
|
||||
priv7-gw = "2a00:8180:2c00:281::c:6";
|
||||
priv8-gw = "2a00:8180:2c00:281::c:7";
|
||||
priv9-gw = "2a00:8180:2c00:281::c:8";
|
||||
serv-gw = "2a00:8180:2c00:281::8:1";
|
||||
upstream4 = "2a00:8180:2c00:281::b:1";
|
||||
vpn-gw = "2a00:8180:2c00:281:9001::1";
|
||||
coloradio-gw = "2a00:8180:2c00:281:9009::1";
|
||||
};
|
||||
};
|
||||
subnet4 = "172.20.72.0/25";
|
||||
subnets6 = {
|
||||
dn42 = "fd23:42:c3d2:581::/64";
|
||||
up4 = "2a00:8180:2c00:281::/64";
|
||||
};
|
||||
};
|
||||
|
||||
site.hosts = {
|
||||
bgp = {
|
||||
bgp = {
|
||||
asn = 4242421127;
|
||||
peers = {
|
||||
"172.22.99.253" = { asn = 64699; };
|
||||
"fe80::a800:42ff:fe7a:3246%c3d2" = { asn = 64699; };
|
||||
};
|
||||
};
|
||||
interfaces = {
|
||||
c3d2 = {
|
||||
hwaddr = "0A:14:48:01:22:01";
|
||||
type = "veth";
|
||||
};
|
||||
core = {
|
||||
hwaddr = "0A:14:48:01:22:00";
|
||||
type = "veth";
|
||||
};
|
||||
};
|
||||
ospf = {
|
||||
allowedUpstreams =
|
||||
[ "upstream4" "upstream3" "anon1" "freifunk" ];
|
||||
stubNets4 = [ "172.20.0.0/14" "10.0.0.0/8" ];
|
||||
stubNets6 =
|
||||
[ "fd00::/8" "2a00:8180:2c00:200::/56" ];
|
||||
};
|
||||
role = "container";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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";
|
||||
};
|
||||
}
|
|
@ -1,218 +0,0 @@
|
|||
{
|
||||
site.net.mgmt = {
|
||||
domainName = "mgmt.zentralwerk.org";
|
||||
hosts4 = {
|
||||
ap1 = "10.0.0.41";
|
||||
ap10 = "10.0.0.50";
|
||||
ap11 = "10.0.0.51";
|
||||
ap12 = "10.0.0.52";
|
||||
ap13 = "10.0.0.53";
|
||||
ap14 = "10.0.0.54";
|
||||
ap15 = "10.0.0.55";
|
||||
ap16 = "10.0.0.56";
|
||||
ap17 = "10.0.0.57";
|
||||
ap18 = "10.0.0.58";
|
||||
ap19 = "10.0.0.59";
|
||||
ap2 = "10.0.0.42";
|
||||
ap20 = "10.0.0.60";
|
||||
ap21 = "10.0.0.61";
|
||||
ap22 = "10.0.0.62";
|
||||
ap23 = "10.0.0.63";
|
||||
ap24 = "10.0.0.64";
|
||||
ap25 = "10.0.0.65";
|
||||
ap26 = "10.0.0.66";
|
||||
ap27 = "10.0.0.67";
|
||||
ap28 = "10.0.0.68";
|
||||
ap29 = "10.0.0.69";
|
||||
ap3 = "10.0.0.43";
|
||||
ap30 = "10.0.0.70";
|
||||
ap31 = "10.0.0.71";
|
||||
ap32 = "10.0.0.72";
|
||||
ap33 = "10.0.0.73";
|
||||
ap34 = "10.0.0.74";
|
||||
ap35 = "10.0.0.75";
|
||||
ap36 = "10.0.0.76";
|
||||
ap37 = "10.0.0.77";
|
||||
ap38 = "10.0.0.78";
|
||||
ap39 = "10.0.0.79";
|
||||
ap4 = "10.0.0.44";
|
||||
ap40 = "10.0.0.80";
|
||||
ap41 = "10.0.0.81";
|
||||
ap42 = "10.0.0.82";
|
||||
ap43 = "10.0.0.83";
|
||||
ap44 = "10.0.0.84";
|
||||
ap45 = "10.0.0.85";
|
||||
ap46 = "10.0.0.86";
|
||||
ap47 = "10.0.0.87";
|
||||
ap48 = "10.0.0.88";
|
||||
ap49 = "10.0.0.89";
|
||||
ap5 = "10.0.0.45";
|
||||
ap50 = "10.0.0.90";
|
||||
ap51 = "10.0.0.91";
|
||||
ap52 = "10.0.0.92";
|
||||
ap53 = "10.0.0.93";
|
||||
ap54 = "10.0.0.94";
|
||||
ap55 = "10.0.0.95";
|
||||
ap56 = "10.0.0.96";
|
||||
ap57 = "10.0.0.97";
|
||||
ap58 = "10.0.0.98";
|
||||
ap59 = "10.0.0.99";
|
||||
ap6 = "10.0.0.46";
|
||||
ap60 = "10.0.0.100";
|
||||
ap61 = "10.0.0.101";
|
||||
ap62 = "10.0.0.102";
|
||||
ap63 = "10.0.0.103";
|
||||
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";
|
||||
ap70 = "10.0.0.110";
|
||||
ap71 = "10.0.0.111";
|
||||
ap72 = "10.0.0.112";
|
||||
ap8 = "10.0.0.48";
|
||||
ap9 = "10.0.0.49";
|
||||
logging = "10.0.0.251";
|
||||
mgmt-gw = "10.0.0.254";
|
||||
monit = "10.0.0.250";
|
||||
server1 = "10.0.0.1";
|
||||
server1-ipmi = "10.0.0.201";
|
||||
server2 = "10.0.0.2";
|
||||
server2-ipmi = "10.0.0.202";
|
||||
server3 = "10.0.0.3";
|
||||
server3-ipmi = "10.0.0.203";
|
||||
server4 = "10.0.0.4";
|
||||
server4-ipmi = "10.0.0.204";
|
||||
server5 = "10.0.0.5";
|
||||
server5-ipmi = "10.0.0.205";
|
||||
server6 = "10.0.0.6";
|
||||
server6-ipmi = "10.0.0.206";
|
||||
server7 = "10.0.0.7";
|
||||
server7-ipmi = "10.0.0.207";
|
||||
server8 = "10.0.0.8";
|
||||
server8-ipmi = "10.0.0.208";
|
||||
server9 = "10.0.0.9";
|
||||
server9-ipmi = "10.0.0.209";
|
||||
switch-a1 = "10.0.0.15";
|
||||
switch-a1-cpe = "10.0.0.16";
|
||||
switch-b1 = "10.0.0.10";
|
||||
switch-b2 = "10.0.0.11";
|
||||
switch-c1 = "10.0.0.12";
|
||||
switch-c3d2-main = "10.0.0.14";
|
||||
switch-d1 = "10.0.0.13";
|
||||
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 = {
|
||||
dn42 = {
|
||||
ap1 = "fd23:42:c3d2:580::4:1";
|
||||
ap10 = "fd23:42:c3d2:580::4:a";
|
||||
ap11 = "fd23:42:c3d2:580::4:b";
|
||||
ap12 = "fd23:42:c3d2:580::4:c";
|
||||
ap13 = "fd23:42:c3d2:580::4:d";
|
||||
ap14 = "fd23:42:c3d2:580::4:e";
|
||||
ap15 = "fd23:42:c3d2:580::4:f";
|
||||
ap16 = "fd23:42:c3d2:580::4:10";
|
||||
ap17 = "fd23:42:c3d2:580::4:11";
|
||||
ap18 = "fd23:42:c3d2:580::4:12";
|
||||
ap19 = "fd23:42:c3d2:580::4:13";
|
||||
ap2 = "fd23:42:c3d2:580::4:2";
|
||||
ap20 = "fd23:42:c3d2:580::4:14";
|
||||
ap21 = "fd23:42:c3d2:580::4:15";
|
||||
ap22 = "fd23:42:c3d2:580::4:16";
|
||||
ap23 = "fd23:42:c3d2:580::4:17";
|
||||
ap24 = "fd23:42:c3d2:580::4:18";
|
||||
ap25 = "fd23:42:c3d2:580::4:19";
|
||||
ap26 = "fd23:42:c3d2:580::4:1a";
|
||||
ap27 = "fd23:42:c3d2:580::4:1b";
|
||||
ap28 = "fd23:42:c3d2:580::4:1c";
|
||||
ap29 = "fd23:42:c3d2:580::4:1d";
|
||||
ap3 = "fd23:42:c3d2:580::4:3";
|
||||
ap30 = "fd23:42:c3d2:580::4:1e";
|
||||
ap31 = "fd23:42:c3d2:580::4:1f";
|
||||
ap32 = "fd23:42:c3d2:580::4:20";
|
||||
ap33 = "fd23:42:c3d2:580::4:21";
|
||||
ap34 = "fd23:42:c3d2:580::4:22";
|
||||
ap35 = "fd23:42:c3d2:580::4:23";
|
||||
ap36 = "fd23:42:c3d2:580::4:24";
|
||||
ap37 = "fd23:42:c3d2:580::4:25";
|
||||
ap38 = "fd23:42:c3d2:580::4:26";
|
||||
ap39 = "fd23:42:c3d2:580::4:27";
|
||||
ap4 = "fd23:42:c3d2:580::4:4";
|
||||
ap40 = "fd23:42:c3d2:580::4:28";
|
||||
ap41 = "fd23:42:c3d2:580::4:29";
|
||||
ap42 = "fd23:42:c3d2:580::4:2a";
|
||||
ap43 = "fd23:42:c3d2:580::4:2b";
|
||||
ap44 = "fd23:42:c3d2:580::4:2c";
|
||||
ap45 = "fd23:42:c3d2:580::4:2d";
|
||||
ap46 = "fd23:42:c3d2:580::4:2e";
|
||||
ap47 = "fd23:42:c3d2:580::4:2f";
|
||||
ap48 = "fd23:42:c3d2:580::4:30";
|
||||
ap49 = "fd23:42:c3d2:580::4:31";
|
||||
ap5 = "fd23:42:c3d2:580::4:5";
|
||||
ap50 = "fd23:42:c3d2:580::4:32";
|
||||
ap51 = "fd23:42:c3d2:580::4:33";
|
||||
ap52 = "fd23:42:c3d2:580::4:34";
|
||||
ap53 = "fd23:42:c3d2:580::4:35";
|
||||
ap54 = "fd23:42:c3d2:580::4:36";
|
||||
ap55 = "fd23:42:c3d2:580::4:37";
|
||||
ap56 = "fd23:42:c3d2:580::4:38";
|
||||
ap57 = "fd23:42:c3d2:580::4:39";
|
||||
ap58 = "fd23:42:c3d2:580::4:3a";
|
||||
ap59 = "fd23:42:c3d2:580::4:3b";
|
||||
ap6 = "fd23:42:c3d2:580::4:6";
|
||||
ap60 = "fd23:42:c3d2:580::4:3c";
|
||||
ap61 = "fd23:42:c3d2:580::4:3d";
|
||||
ap62 = "fd23:42:c3d2:580::4:3e";
|
||||
ap63 = "fd23:42:c3d2:580::4:3f";
|
||||
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";
|
||||
ap70 = "fd23:42:c3d2:580::4:46";
|
||||
ap71 = "fd23:42:c3d2:580::4:47";
|
||||
ap72 = "fd23:42:c3d2:580::4:48";
|
||||
ap8 = "fd23:42:c3d2:580::4:8";
|
||||
ap9 = "fd23:42:c3d2:580::4:9";
|
||||
mgmt-gw = "fd23:42:c3d2:580:ffff:ffff:ffff:ffff";
|
||||
monit = "fd23:42:c3d2:580::250";
|
||||
server1 = "fd23:42:c3d2:580::1";
|
||||
server2 = "fd23:42:c3d2:580::2";
|
||||
switch-b1 = "fd23:42:c3d2:580::10";
|
||||
switch-b2 = "fd23:42:c3d2:580::11";
|
||||
switch-c1 = "fd23:42:c3d2:580::12";
|
||||
switch-c3d2-main = "fd23:42:c3d2:580::14";
|
||||
switch-d1 = "fd23:42:c3d2:580::13";
|
||||
};
|
||||
};
|
||||
subnet4 = "10.0.0.0/24";
|
||||
subnets6 = { dn42 = "fd23:42:c3d2:580::/64"; };
|
||||
};
|
||||
|
||||
site.hosts.mgmt-gw = {
|
||||
firewall.enable = true;
|
||||
interfaces = {
|
||||
core = {
|
||||
hwaddr = "0A:14:48:01:24:01";
|
||||
type = "veth";
|
||||
};
|
||||
mgmt = {
|
||||
hwaddr = "0A:14:48:01:24:00";
|
||||
type = "veth";
|
||||
};
|
||||
};
|
||||
ospf = {
|
||||
allowedUpstreams =
|
||||
[ "upstream4" "upstream3" "anon1" "freifunk" ];
|
||||
};
|
||||
role = "container";
|
||||
};
|
||||
}
|
|
@ -1,773 +0,0 @@
|
|||
{ lib, ... }:
|
||||
let
|
||||
privCount = 49;
|
||||
seq = n: max:
|
||||
if n <= max
|
||||
then [ n ] ++ seq (n + 1) max
|
||||
else [];
|
||||
in
|
||||
lib.mkMerge (
|
||||
map (n:
|
||||
let
|
||||
toHex = n: with lib; toLower (toHexString n);
|
||||
subnetUp4 = "2a00:8180:2c00:${toHex (703 + n)}::";
|
||||
subnetDn42 = "fd23:42:c3d2:${toHex (1471 + n)}::";
|
||||
in {
|
||||
site.net."priv${toString n}" = {
|
||||
dhcp = {
|
||||
server = "priv${toString n}-gw";
|
||||
time = 300;
|
||||
max-time = 60 * 24 * 3600;
|
||||
router = "priv${toString n}-gw";
|
||||
};
|
||||
domainName = "priv${toString n}.zentralwerk.org";
|
||||
dynamicDomain = true;
|
||||
hosts6 = {
|
||||
dn42 = { "priv${toString n}-gw" = "${subnetDn42}1"; };
|
||||
up4 = { "priv${toString n}-gw" = "${subnetUp4}1"; };
|
||||
};
|
||||
subnets6 = {
|
||||
dn42 = "${subnetDn42}/64";
|
||||
up4 = "${subnetUp4}/64";
|
||||
};
|
||||
};
|
||||
|
||||
site.hosts."priv${toString n}-gw" = {
|
||||
role = "container";
|
||||
interfaces = {
|
||||
core.type = "veth";
|
||||
"priv${toString n}".type = "veth";
|
||||
};
|
||||
ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ];
|
||||
};
|
||||
}
|
||||
) (seq 1 privCount)
|
||||
++
|
||||
[ {
|
||||
site.net = {
|
||||
priv1 = {
|
||||
subnet4 = "172.20.74.0/28";
|
||||
hosts4 = { priv1-gw = "172.20.74.1"; };
|
||||
dhcp = {
|
||||
end = "172.20.74.14";
|
||||
start = "172.20.74.2";
|
||||
};
|
||||
};
|
||||
priv2 = {
|
||||
hosts4 = { priv2-gw = "172.20.75.1"; };
|
||||
subnet4 = "172.20.75.0/27";
|
||||
dhcp = {
|
||||
start = "172.20.75.2";
|
||||
end = "172.20.75.30";
|
||||
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";
|
||||
};
|
||||
};
|
||||
};
|
||||
priv3 = {
|
||||
hosts4 = { priv3-gw = "172.20.74.129"; };
|
||||
subnet4 = "172.20.74.128/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.130";
|
||||
end = "172.20.74.142";
|
||||
};
|
||||
};
|
||||
priv4 = {
|
||||
hosts4 = { priv4-gw = "172.20.75.129"; };
|
||||
subnet4 = "172.20.75.128/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.130";
|
||||
end = "172.20.75.142";
|
||||
};
|
||||
};
|
||||
priv5 = {
|
||||
hosts4 = { priv5-gw = "172.20.74.65"; };
|
||||
subnet4 = "172.20.74.64/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.66";
|
||||
end = "172.20.74.78";
|
||||
};
|
||||
};
|
||||
priv6 = {
|
||||
hosts4 = { priv6-gw = "172.20.74.193"; };
|
||||
subnet4 = "172.20.74.192/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.194";
|
||||
end = "172.20.74.206";
|
||||
};
|
||||
};
|
||||
priv7 = {
|
||||
hosts4 = { priv7-gw = "172.20.75.65"; };
|
||||
subnet4 = "172.20.75.64/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.66";
|
||||
end = "172.20.75.78";
|
||||
};
|
||||
};
|
||||
priv8 = {
|
||||
hosts4 = { priv8-gw = "172.20.75.193"; };
|
||||
subnet4 = "172.20.75.192/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.194";
|
||||
end = "172.20.75.206";
|
||||
};
|
||||
};
|
||||
priv9 = {
|
||||
hosts4 = { priv9-gw = "172.20.74.33"; };
|
||||
subnet4 = "172.20.74.32/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.34";
|
||||
end = "172.20.74.46";
|
||||
};
|
||||
};
|
||||
priv10 = {
|
||||
hosts4 = { priv10-gw = "172.20.74.97"; };
|
||||
subnet4 = "172.20.74.96/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.98";
|
||||
end = "172.20.74.110";
|
||||
};
|
||||
};
|
||||
priv11 = {
|
||||
hosts4 = { priv11-gw = "172.20.74.161"; };
|
||||
subnet4 = "172.20.74.160/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.162";
|
||||
end = "172.20.74.174";
|
||||
};
|
||||
};
|
||||
priv12 = {
|
||||
hosts4 = { priv12-gw = "172.20.74.225"; };
|
||||
subnet4 = "172.20.74.224/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.226";
|
||||
end = "172.20.74.238";
|
||||
};
|
||||
};
|
||||
priv13 = {
|
||||
hosts4 = { priv13-gw = "172.20.75.33"; };
|
||||
subnet4 = "172.20.75.32/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.34";
|
||||
end = "172.20.75.46";
|
||||
};
|
||||
};
|
||||
priv14 = {
|
||||
hosts4 = { priv14-gw = "172.20.75.97"; };
|
||||
subnet4 = "172.20.75.96/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.98";
|
||||
end = "172.20.75.110";
|
||||
};
|
||||
};
|
||||
priv15 = {
|
||||
hosts4 = { priv15-gw = "172.20.75.161"; };
|
||||
subnet4 = "172.20.75.160/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.162";
|
||||
end = "172.20.75.174";
|
||||
};
|
||||
};
|
||||
priv16 = {
|
||||
hosts4 = { priv16-gw = "172.20.75.225"; };
|
||||
subnet4 = "172.20.75.224/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.226";
|
||||
end = "172.20.75.238";
|
||||
};
|
||||
};
|
||||
priv17 = {
|
||||
hosts4 = {
|
||||
priv17-gw = "172.20.73.129";
|
||||
priv17-gw-up3 = "172.20.73.130";
|
||||
};
|
||||
subnet4 = "172.20.73.128/27";
|
||||
dhcp = {
|
||||
start = "172.20.73.131";
|
||||
end = "172.20.73.158";
|
||||
};
|
||||
};
|
||||
priv18 = {
|
||||
hosts4 = { priv18-gw = "172.20.74.49"; };
|
||||
subnet4 = "172.20.74.48/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.50";
|
||||
end = "172.20.74.62";
|
||||
};
|
||||
};
|
||||
priv19 = {
|
||||
hosts4 = { priv19-gw = "172.20.73.193"; };
|
||||
subnet4 = "172.20.73.192/26";
|
||||
dhcp = {
|
||||
start = "172.20.73.194";
|
||||
end = "172.20.73.254";
|
||||
};
|
||||
};
|
||||
priv20 = {
|
||||
hosts4 = { priv20-gw = "172.20.74.113"; };
|
||||
subnet4 = "172.20.74.112/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.114";
|
||||
end = "172.20.74.126";
|
||||
};
|
||||
};
|
||||
priv21 = {
|
||||
hosts4 = { priv21-gw = "172.20.74.145"; };
|
||||
subnet4 = "172.20.74.144/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.146";
|
||||
end = "172.20.74.158";
|
||||
};
|
||||
};
|
||||
priv22 = {
|
||||
hosts4 = { priv22-gw = "172.20.74.177"; };
|
||||
subnet4 = "172.20.74.176/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.178";
|
||||
end = "172.20.74.190";
|
||||
};
|
||||
};
|
||||
priv23 = {
|
||||
hosts4 = { priv23-gw = "172.20.73.161"; };
|
||||
subnet4 = "172.20.73.160/27";
|
||||
dhcp = {
|
||||
start = "172.20.73.165";
|
||||
end = "172.20.73.190";
|
||||
fixed-hosts = {
|
||||
"172.20.73.162" = "da:2c:3a:2c:87:22";
|
||||
"172.20.73.163" = "b8:27:eb:16:31:61";
|
||||
"172.20.73.164" = "ca:71:c4:90:3e:c7";
|
||||
};
|
||||
time = lib.mkForce 900;
|
||||
};
|
||||
};
|
||||
priv24 = {
|
||||
hosts4 = { priv24-gw = "172.20.74.241"; };
|
||||
subnet4 = "172.20.74.240/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.242";
|
||||
end = "172.20.74.254";
|
||||
};
|
||||
};
|
||||
priv25 = {
|
||||
hosts4 = { priv25-gw = "172.20.74.81"; };
|
||||
subnet4 = "172.20.74.80/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.82";
|
||||
end = "172.20.74.94";
|
||||
};
|
||||
};
|
||||
priv26 = {
|
||||
hosts4 = { priv26-gw = "172.20.75.49"; };
|
||||
subnet4 = "172.20.75.48/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.50";
|
||||
end = "172.20.75.62";
|
||||
};
|
||||
};
|
||||
priv27 = {
|
||||
hosts4 = { priv27-gw = "172.20.75.81"; };
|
||||
subnet4 = "172.20.75.80/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.82";
|
||||
end = "172.20.75.94";
|
||||
};
|
||||
};
|
||||
priv28 = {
|
||||
hosts4 = { priv28-gw = "172.20.75.113"; };
|
||||
subnet4 = "172.20.75.112/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.114";
|
||||
end = "172.20.75.126";
|
||||
};
|
||||
};
|
||||
priv29 = {
|
||||
hosts4 = { priv29-gw = "172.20.75.145"; };
|
||||
subnet4 = "172.20.75.144/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.146";
|
||||
end = "172.20.75.158";
|
||||
};
|
||||
};
|
||||
priv30 = {
|
||||
hosts4 = { priv30-gw = "172.20.75.177"; };
|
||||
subnet4 = "172.20.75.176/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.178";
|
||||
end = "172.20.75.190";
|
||||
};
|
||||
};
|
||||
priv31 = {
|
||||
hosts4 = { priv31-gw = "172.20.75.209"; };
|
||||
subnet4 = "172.20.75.208/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.210";
|
||||
end = "172.20.75.221";
|
||||
fixed-hosts = {
|
||||
# zw-ev-vm
|
||||
"172.20.75.222" = "92:a8:00:49:a6:61";
|
||||
};
|
||||
};
|
||||
};
|
||||
priv32 = {
|
||||
hosts4 = { priv32-gw = "172.20.75.241"; };
|
||||
subnet4 = "172.20.75.240/28";
|
||||
dhcp = {
|
||||
start = "172.20.75.242";
|
||||
end = "172.20.75.254";
|
||||
};
|
||||
};
|
||||
priv33 = {
|
||||
hosts4 = { priv33-gw = "172.20.74.17"; };
|
||||
subnet4 = "172.20.74.16/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.18";
|
||||
end = "172.20.74.30";
|
||||
};
|
||||
};
|
||||
priv34 = {
|
||||
hosts4 = { priv34-gw = "172.20.74.209"; };
|
||||
subnet4 = "172.20.74.208/28";
|
||||
dhcp = {
|
||||
start = "172.20.74.210";
|
||||
end = "172.20.74.222";
|
||||
};
|
||||
};
|
||||
priv35 = {
|
||||
hosts4 = { priv35-gw = "172.20.76.1"; };
|
||||
subnet4 = "172.20.76.0/28";
|
||||
dhcp = {
|
||||
start = "172.20.76.2";
|
||||
end = "172.20.76.14";
|
||||
};
|
||||
};
|
||||
priv36 = {
|
||||
hosts4 = { priv36-gw = "172.20.76.65"; };
|
||||
subnet4 = "172.20.76.64/28";
|
||||
dhcp = {
|
||||
start = "172.20.76.66";
|
||||
end = "172.20.76.78";
|
||||
};
|
||||
};
|
||||
priv37 = {
|
||||
hosts4 = { priv37-gw = "172.20.76.129"; };
|
||||
subnet4 = "172.20.76.128/28";
|
||||
dhcp = {
|
||||
start = "172.20.76.130";
|
||||
end = "172.20.76.142";
|
||||
};
|
||||
};
|
||||
priv38 = {
|
||||
hosts4 = { priv38-gw = "172.20.76.193"; };
|
||||
subnet4 = "172.20.76.192/28";
|
||||
dhcp = {
|
||||
start = "172.20.76.194";
|
||||
end = "172.20.76.206";
|
||||
};
|
||||
};
|
||||
priv39 = {
|
||||
hosts4 = { priv39-gw = "172.20.77.129"; };
|
||||
subnet4 = "172.20.77.128/28";
|
||||
dhcp = {
|
||||
start = "172.20.77.130";
|
||||
end = "172.20.77.142";
|
||||
};
|
||||
};
|
||||
priv40 = {
|
||||
hosts4 = { priv40-gw = "172.20.77.65"; };
|
||||
subnet4 = "172.20.77.64/28";
|
||||
dhcp = {
|
||||
start = "172.20.77.66";
|
||||
end = "172.20.77.78";
|
||||
};
|
||||
};
|
||||
priv41 = {
|
||||
hosts4 = { priv41-gw = "172.20.77.193"; };
|
||||
subnet4 = "172.20.77.192/28";
|
||||
dhcp = {
|
||||
start = "172.20.77.194";
|
||||
end = "172.20.77.206";
|
||||
};
|
||||
};
|
||||
priv42 = {
|
||||
hosts4 = { priv42-gw = "172.20.76.33"; };
|
||||
subnet4 = "172.20.76.32/28";
|
||||
dhcp = {
|
||||
start = "172.20.76.34";
|
||||
end = "172.20.76.46";
|
||||
};
|
||||
};
|
||||
priv43 = {
|
||||
hosts4 = { priv43-gw = "172.20.76.97"; };
|
||||
subnet4 = "172.20.76.96/28";
|
||||
dhcp = {
|
||||
start = "172.20.76.98";
|
||||
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 = {
|
||||
priv1-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:19:00";
|
||||
priv1.hwaddr = "0A:14:48:01:19:01";
|
||||
};
|
||||
};
|
||||
priv2-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:18:00";
|
||||
priv2.hwaddr = "0A:14:48:01:18:01";
|
||||
};
|
||||
};
|
||||
priv3-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:08:00";
|
||||
priv3.hwaddr = "0A:14:48:01:08:01";
|
||||
};
|
||||
};
|
||||
priv4-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:17:01";
|
||||
priv4.hwaddr = "0A:14:48:01:17:00";
|
||||
};
|
||||
};
|
||||
priv5-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:12:00";
|
||||
priv5.hwaddr = "0A:14:48:01:12:01";
|
||||
};
|
||||
};
|
||||
priv6-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:11:00";
|
||||
priv6.hwaddr = "0A:14:48:01:11:01";
|
||||
};
|
||||
};
|
||||
priv7-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:10:00";
|
||||
priv7.hwaddr = "0A:14:48:01:10:01";
|
||||
};
|
||||
};
|
||||
priv8-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:09:00";
|
||||
priv8.hwaddr = "0A:14:48:01:09:01";
|
||||
};
|
||||
};
|
||||
priv9-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:20:00";
|
||||
priv9.hwaddr = "0A:14:48:01:20:01";
|
||||
};
|
||||
};
|
||||
priv10-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:13:02";
|
||||
priv10.hwaddr = "0A:14:48:01:13:03";
|
||||
};
|
||||
};
|
||||
priv11-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:29:00";
|
||||
priv11.hwaddr = "0A:14:48:01:29:01";
|
||||
};
|
||||
};
|
||||
priv12-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:00";
|
||||
priv12.hwaddr = "0A:14:48:01:2A:01";
|
||||
};
|
||||
};
|
||||
priv13-gw = {
|
||||
firewall.enable = true;
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:10";
|
||||
priv13.hwaddr = "0A:14:48:01:2A:11";
|
||||
};
|
||||
};
|
||||
priv14-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:12";
|
||||
priv14.hwaddr = "0A:14:48:01:2A:13";
|
||||
};
|
||||
};
|
||||
priv15-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:14";
|
||||
priv15.hwaddr = "0A:14:48:01:2A:15";
|
||||
};
|
||||
};
|
||||
priv16-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:16";
|
||||
priv16.hwaddr = "0A:14:48:01:2A:17";
|
||||
};
|
||||
};
|
||||
priv17-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:18";
|
||||
priv17.hwaddr = "0A:14:48:01:2A:19";
|
||||
};
|
||||
};
|
||||
priv17-gw-up3 = {
|
||||
role = "container";
|
||||
interfaces = {
|
||||
core = {
|
||||
type = "veth";
|
||||
hwaddr = "0A:14:47:02:2A:18";
|
||||
};
|
||||
priv17 = {
|
||||
type = "veth";
|
||||
hwaddr = "0A:14:47:02:2A:19";
|
||||
};
|
||||
};
|
||||
ospf.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ];
|
||||
};
|
||||
priv18-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:1A";
|
||||
priv18.hwaddr = "0A:14:48:01:2A:1B";
|
||||
};
|
||||
};
|
||||
priv19-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:1C";
|
||||
priv19.hwaddr = "0A:14:48:01:2A:1D";
|
||||
};
|
||||
};
|
||||
priv20-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:1E";
|
||||
priv20.hwaddr = "0A:14:48:01:2A:1F";
|
||||
};
|
||||
};
|
||||
priv21-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:20";
|
||||
priv21.hwaddr = "0A:14:48:01:2A:21";
|
||||
};
|
||||
};
|
||||
priv22-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:24";
|
||||
priv22.hwaddr = "0A:14:48:01:2A:25";
|
||||
};
|
||||
};
|
||||
priv23-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:22";
|
||||
priv23.hwaddr = "0A:14:48:01:2A:23";
|
||||
};
|
||||
};
|
||||
priv24-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:26";
|
||||
priv24.hwaddr = "0A:14:48:01:2A:27";
|
||||
};
|
||||
};
|
||||
priv25-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:28";
|
||||
priv25.hwaddr = "0A:14:48:01:2A:29";
|
||||
};
|
||||
};
|
||||
priv26-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:2A";
|
||||
priv26.hwaddr = "0A:14:48:01:2A:2B";
|
||||
};
|
||||
};
|
||||
priv27-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:2C";
|
||||
priv27.hwaddr = "0A:14:48:01:2A:2D";
|
||||
};
|
||||
};
|
||||
priv28-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:2E";
|
||||
priv28.hwaddr = "0A:14:48:01:2A:2F";
|
||||
};
|
||||
};
|
||||
priv29-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:30";
|
||||
priv29.hwaddr = "0A:14:48:01:2A:31";
|
||||
};
|
||||
};
|
||||
priv30-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:32";
|
||||
priv30.hwaddr = "0A:14:48:01:2A:33";
|
||||
};
|
||||
};
|
||||
priv31-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:34";
|
||||
priv31.hwaddr = "0A:14:48:01:2A:35";
|
||||
};
|
||||
};
|
||||
priv32-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:36";
|
||||
priv32.hwaddr = "0A:14:48:01:2A:37";
|
||||
};
|
||||
};
|
||||
priv33-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:38";
|
||||
priv33.hwaddr = "0A:14:48:01:2A:39";
|
||||
};
|
||||
};
|
||||
priv34-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:40";
|
||||
priv34.hwaddr = "0A:14:48:01:2A:41";
|
||||
};
|
||||
};
|
||||
priv35-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:42";
|
||||
priv35.hwaddr = "0A:14:48:01:2A:43";
|
||||
};
|
||||
};
|
||||
priv36-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:44";
|
||||
priv36.hwaddr = "0A:14:48:01:2A:45";
|
||||
};
|
||||
};
|
||||
priv37-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:46";
|
||||
priv37.hwaddr = "0A:14:48:01:2A:47";
|
||||
};
|
||||
};
|
||||
priv38-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:48";
|
||||
priv38.hwaddr = "0A:14:48:01:2A:49";
|
||||
};
|
||||
};
|
||||
priv39-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:4A";
|
||||
priv39.hwaddr = "0A:14:48:01:2A:4B";
|
||||
};
|
||||
};
|
||||
priv40-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:4C";
|
||||
priv40.hwaddr = "0A:14:48:01:2A:4D";
|
||||
};
|
||||
};
|
||||
priv41-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:4E";
|
||||
priv41.hwaddr = "0A:14:48:01:2A:4F";
|
||||
};
|
||||
};
|
||||
priv42-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:50";
|
||||
priv42.hwaddr = "0A:14:48:01:2A:51";
|
||||
};
|
||||
};
|
||||
priv43-gw = {
|
||||
interfaces = {
|
||||
core.hwaddr = "0A:14:48:01:2A:52";
|
||||
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";
|
||||
};
|
||||
};
|
||||
};
|
||||
} ]
|
||||
)
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
site.net.pub = {
|
||||
dhcp = {
|
||||
start = "172.20.78.2";
|
||||
end = "172.20.79.253";
|
||||
router = "pub-gw";
|
||||
server = "pub-gw";
|
||||
time = 120;
|
||||
max-time = 12 * 3600;
|
||||
};
|
||||
domainName = "pub.zentralwerk.org";
|
||||
dynamicDomain = true;
|
||||
hosts4 = {
|
||||
pub-gw = "172.20.78.1";
|
||||
};
|
||||
hosts6 = {
|
||||
dn42 = {
|
||||
pub-gw = "fd23:42:c3d2:583::1";
|
||||
};
|
||||
flpk = {
|
||||
pub-gw = "2a0f:5382:acab:1403::1";
|
||||
};
|
||||
};
|
||||
subnet4 = "172.20.78.0/23";
|
||||
subnets6 = {
|
||||
dn42 = "fd23:42:c3d2:583::/64";
|
||||
flpk = "2a0f:5382:acab:1403::/64";
|
||||
};
|
||||
};
|
||||
|
||||
site.hosts.pub-gw = {
|
||||
interfaces = {
|
||||
core = {
|
||||
hwaddr = "0A:14:48:01:16:00";
|
||||
type = "veth";
|
||||
};
|
||||
pub = {
|
||||
hwaddr = "0A:14:48:01:16:01";
|
||||
type = "veth";
|
||||
};
|
||||
};
|
||||
ospf = {
|
||||
allowedUpstreams = [ "anon1" "freifunk" ];
|
||||
allowedUpstreams6 = [ "flpk-gw" "anon1" "freifunk" ];
|
||||
};
|
||||
role = "container";
|
||||
};
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
site.net.roof = {
|
||||
# not switched, only a wifi
|
||||
vlan = null;
|
||||
# leave space for vxlan
|
||||
mtu = 1574;
|
||||
subnet4 = "10.0.57.0/24";
|
||||
hosts4 = {
|
||||
ap57 = "10.0.57.1";
|
||||
ap58 = "10.0.57.2";
|
||||
};
|
||||
hosts6.dn42 = {
|
||||
ap57 = "fd23:42:c3d2:584::39";
|
||||
ap58 = "fd23:42:c3d2:584::40";
|
||||
};
|
||||
subnets6.dn42 = "fd23:42:c3d2:584::/64";
|
||||
};
|
||||
}
|
|
@ -1,190 +0,0 @@
|
|||
{ lib, ... }:
|
||||
{
|
||||
site.net.serv = {
|
||||
domainName = "serv.zentralwerk.org";
|
||||
subnet4 = "172.20.73.0/25";
|
||||
hosts4 = {
|
||||
serv-gw = "172.20.73.1";
|
||||
dns = "172.20.73.2";
|
||||
stats = "172.20.73.3";
|
||||
dresden-zone = "172.20.73.4";
|
||||
tlms-elastic = "172.20.73.7"; # tlms
|
||||
dnscache = "172.20.73.8";
|
||||
tlms-ctfd = "172.20.73.9"; # tlms
|
||||
buzzrelay = "172.20.73.15";
|
||||
matemat = "172.20.73.21";
|
||||
spaceapi = "172.20.73.25";
|
||||
mucbot = "172.20.73.27";
|
||||
scrape = "172.20.73.32";
|
||||
pretalx = "172.20.73.33";
|
||||
vaultwarden = "172.20.73.34";
|
||||
uranus = "172.20.73.37"; # tlms
|
||||
tram-borzoi = "172.20.73.38"; # tlms
|
||||
borken-data-hoarder = "172.20.73.39"; # tlms
|
||||
matrix = "172.20.73.40";
|
||||
activity-relay = "172.20.73.41";
|
||||
luulaatsch-asterisk = "172.20.73.42";
|
||||
grafana = "172.20.73.43";
|
||||
public-access-proxy = "172.20.73.45";
|
||||
marenz = "172.20.73.46";
|
||||
network-homepage = "172.20.73.47";
|
||||
home-assistant = "172.20.73.48";
|
||||
hydra = "172.20.73.49";
|
||||
owncast = "172.20.73.50";
|
||||
nfsroot = "172.20.73.51";
|
||||
ticker = "172.20.73.52";
|
||||
gitea = "172.20.73.53";
|
||||
stream = "172.20.73.54";
|
||||
jabber = "172.20.73.55";
|
||||
mobilizon = "172.20.73.56";
|
||||
radiobert = "172.20.73.57";
|
||||
# mail = "172.20.73.58";
|
||||
sdrweb = "172.20.73.60";
|
||||
knot = "172.20.73.61";
|
||||
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.up4 = "2a00:8180:2c00:282::/64";
|
||||
hosts6.dn42 = {
|
||||
knot = "fd23:42:c3d2:582:cd7:56ff:fe69:6366";
|
||||
blogs = "fd23:42:c3d2:582:b8a8:7dff:fee8:5ac2";
|
||||
dns = "fd23:42:c3d2:582:2:0:0:2";
|
||||
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";
|
||||
hydra = "fd23:42:c3d2:582:e2cb:4eff:fe3b:f94b";
|
||||
jabber = "fd23:42:c3d2:582:b869:ccff:fe46:902a";
|
||||
# mail = "fd23:42:c3d2:582:88c0:41ff:fe70:d6cd";
|
||||
matemat = "fd23:42:c3d2:582:f82b:1bff:fedc:8572";
|
||||
mobilizon = "fd23:42:c3d2:582:48d1:5cff:fea7:1676";
|
||||
mongo = "fd23:42:c3d2:582:14ec:c8ff:fe0a:fc5c";
|
||||
mucbot = "fd23:42:c3d2:582:28db:dff:fe6b:e89a";
|
||||
radiobert = "fd23:42:c3d2:582:e65f:1ff:fe5d:1679";
|
||||
radius = "fd23:42:c3d2:582:2:0:0:4";
|
||||
sdrweb = "fd23:42:c3d2:582:3078:bbff:fe76:e9ef";
|
||||
serv-gw = "fd23:42:c3d2:582::1";
|
||||
spaceapi = "fd23:42:c3d2:582:1457:adff:fe93:62e9";
|
||||
stats = "fd23:42:c3d2:582:2:0:0:3";
|
||||
staging-data-hoarder = "fd23:42:c3d2:582:2de:5bff:fef9:e23d";
|
||||
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 = {
|
||||
knot = "2a00:8180:2c00:282:cd7:56ff:fe69:6366";
|
||||
blogs = "2a00:8180:2c00:282:b8a8:7dff:fee8:5ac2";
|
||||
dns = "2a00:8180:2c00:282:2:0:0:2";
|
||||
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";
|
||||
hydra = "2a00:8180:2c00:282:e2cb:4eff:fe3b:f94b";
|
||||
jabber = "2a00:8180:2c00:282:b869:ccff:fe46:902a";
|
||||
# mail = "2a00:8180:2c00:282:88c0:41ff:fe70:d6cd";
|
||||
matemat = "2a00:8180:2c00:282:f82b:1bff:fedc:8572";
|
||||
mobilizon = "2a00:8180:2c00:282:48d1:5cff:fea7:1676";
|
||||
mucbot = "2a00:8180:2c00:282:28db:dff:fe6b:e89a";
|
||||
public-access-proxy = "2a00:8180:2c00:282:1024:5fff:febd:9be7";
|
||||
radiobert = "2a00:8180:2c00:282:e65f:1ff:fe5d:1679";
|
||||
radius = "2a00:8180:2c00:282:2:0:0:4";
|
||||
scrape = "2a00:8180:2c00:282:e073:50ff:fef5:eb6e";
|
||||
sdrweb = "2a00:8180:2c00:282:3078:bbff:fe76:e9ef";
|
||||
spaceapi = "2a00:8180:2c00:282:1457:adff:fe93:62e9";
|
||||
stats = "2a00:8180:2c00:282:2:0:0:3";
|
||||
stream = "2a00:8180:2c00:282:dc91:c7ff:fe51:d1c5";
|
||||
ticker = "2a00:8180:2c00:282:b407:40ff:fec1:81f2";
|
||||
staging-data-hoarder = "2a00:8180:2c00:282:2de:5bff:fef9:e23d";
|
||||
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";
|
||||
};
|
||||
};
|
||||
|
||||
site.hosts =
|
||||
let
|
||||
makeContainer = lib.recursiveUpdate {
|
||||
role = "container";
|
||||
interfaces = {
|
||||
serv = {
|
||||
gw4 = "serv-gw";
|
||||
gw6 = "serv-gw";
|
||||
type = "veth";
|
||||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
dns = makeContainer {
|
||||
interfaces.serv.hwaddr = "0A:14:48:01:23:00";
|
||||
services.dns.enable = true;
|
||||
};
|
||||
dnscache = makeContainer {
|
||||
services.dnscache.enable = true;
|
||||
};
|
||||
serv-gw = makeContainer {
|
||||
interfaces = {
|
||||
core = {
|
||||
type = "veth";
|
||||
hwaddr = "0A:14:48:01:06:01";
|
||||
gw4 = null;
|
||||
gw6 = null;
|
||||
};
|
||||
serv = {
|
||||
hwaddr = "0A:14:48:01:06:00";
|
||||
gw4 = null;
|
||||
gw6 = null;
|
||||
};
|
||||
};
|
||||
ospf.allowedUpstreams =
|
||||
[ "upstream4" "upstream3" "anon1" "freifunk" ];
|
||||
};
|
||||
stats = makeContainer {
|
||||
interfaces.serv.hwaddr = "0A:14:48:01:15:00";
|
||||
};
|
||||
|
||||
hydra = {
|
||||
role = "client";
|
||||
model = "nixos";
|
||||
interfaces.serv.type = "phys";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,273 +0,0 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
servHosts = config.site.net.serv.hosts4;
|
||||
inherit (config.site.net.c3d2.hosts4) dn42;
|
||||
inherit (config.site.net.flpk.hosts4) c3d2-web;
|
||||
in
|
||||
{
|
||||
site.hosts = {
|
||||
upstream3 = {
|
||||
interfaces = {
|
||||
core = {
|
||||
hwaddr = "0A:14:48:01:28:00";
|
||||
type = "veth";
|
||||
};
|
||||
up3 = {
|
||||
hwaddr = "00:23:74:D7:42:7D";
|
||||
type = "veth";
|
||||
upstream = {
|
||||
link = null;
|
||||
noNat = { subnets6 = [ ]; };
|
||||
provider = "starlink";
|
||||
staticIpv4Address = null;
|
||||
upBandwidth = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
ospf.upstreamInstance = 7;
|
||||
role = "container";
|
||||
};
|
||||
|
||||
upstream4 = rec {
|
||||
forwardPorts = [
|
||||
{ # http
|
||||
destination = servHosts.public-access-proxy;
|
||||
proto = "tcp";
|
||||
sourcePort = 80;
|
||||
}
|
||||
{ # https
|
||||
destination = servHosts.public-access-proxy;
|
||||
proto = "tcp";
|
||||
sourcePort = 443;
|
||||
}
|
||||
{ # gemini
|
||||
destination = "${c3d2-web}:1965";
|
||||
proto = "tcp";
|
||||
sourcePort = 1965;
|
||||
}
|
||||
{
|
||||
destination = servHosts.knot;
|
||||
proto = "tcp";
|
||||
sourcePort = 53;
|
||||
}
|
||||
{
|
||||
destination = servHosts.knot;
|
||||
proto = "udp";
|
||||
sourcePort = 53;
|
||||
}
|
||||
{
|
||||
destination = dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2325;
|
||||
}
|
||||
{
|
||||
destination = dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2327;
|
||||
}
|
||||
{
|
||||
destination = dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2337;
|
||||
}
|
||||
{
|
||||
destination = dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2338;
|
||||
}
|
||||
{
|
||||
destination = dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2339;
|
||||
}
|
||||
{
|
||||
destination = dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2340;
|
||||
}
|
||||
{
|
||||
destination = dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2342;
|
||||
}
|
||||
{
|
||||
destination = dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2399;
|
||||
}
|
||||
{
|
||||
destination = dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 24699;
|
||||
}
|
||||
{
|
||||
destination = dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 64699;
|
||||
}
|
||||
# ?
|
||||
{
|
||||
destination = "172.22.99.175:22";
|
||||
proto = "tcp";
|
||||
sourcePort = 2224;
|
||||
}
|
||||
{
|
||||
destination = servHosts.gitea;
|
||||
proto = "tcp";
|
||||
sourcePort = 22;
|
||||
}
|
||||
{
|
||||
destination = servHosts.jabber;
|
||||
proto = "tcp";
|
||||
sourcePort = 5222;
|
||||
}
|
||||
{
|
||||
destination = servHosts.jabber;
|
||||
proto = "tcp";
|
||||
sourcePort = 5223;
|
||||
}
|
||||
{
|
||||
destination = servHosts.jabber;
|
||||
proto = "tcp";
|
||||
sourcePort = 5269;
|
||||
}
|
||||
{
|
||||
destination = servHosts.jabber;
|
||||
proto = "tcp";
|
||||
sourcePort = 3478;
|
||||
}
|
||||
{
|
||||
destination = servHosts.jabber;
|
||||
proto = "tcp";
|
||||
sourcePort = 3479;
|
||||
}
|
||||
{
|
||||
destination = servHosts.jabber;
|
||||
proto = "udp";
|
||||
sourcePort = 3478;
|
||||
}
|
||||
{
|
||||
destination = servHosts.jabber;
|
||||
proto = "udp";
|
||||
sourcePort = 3479;
|
||||
}
|
||||
# poelzi
|
||||
{
|
||||
destination = "172.20.73.162:22";
|
||||
proto = "tcp";
|
||||
sourcePort = 2323;
|
||||
}
|
||||
# jan
|
||||
{
|
||||
destination = "172.20.75.3:51820";
|
||||
proto = "udp";
|
||||
sourcePort = 30057;
|
||||
}
|
||||
# zw-ev RDP
|
||||
{
|
||||
destination = "172.20.75.222:3389";
|
||||
proto = "tcp";
|
||||
sourcePort = 45000;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.core.hosts4.vpn-gw;
|
||||
proto = "udp";
|
||||
sourcePort = config.site.vpn.wireguard.port;
|
||||
reflect = true;
|
||||
}
|
||||
{
|
||||
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 = {
|
||||
core = {
|
||||
hwaddr = "0A:14:48:01:28:01";
|
||||
type = "veth";
|
||||
};
|
||||
up4 = {
|
||||
hwaddr = "00:23:74:D7:42:7E";
|
||||
type = "veth";
|
||||
};
|
||||
up4-pppoe = {
|
||||
type = "pppoe";
|
||||
upstream = {
|
||||
link = "up4";
|
||||
noNat = {
|
||||
subnets6 =
|
||||
[ "2a00:8180:2000:37::1/128" "2a00:8180:2c00:200::/56" ];
|
||||
};
|
||||
provider = "dsi";
|
||||
staticIpv4Address = "81.201.149.152";
|
||||
upBandwidth = 98000;
|
||||
};
|
||||
};
|
||||
};
|
||||
ospf = {
|
||||
upstreamInstance = 8;
|
||||
stubNets4 = [
|
||||
"${interfaces.up4-pppoe.upstream.staticIpv4Address}/32"
|
||||
];
|
||||
};
|
||||
role = "container";
|
||||
};
|
||||
|
||||
freifunk.ospf.upstreamInstance = 6;
|
||||
|
||||
anon1 = {
|
||||
interfaces = {
|
||||
core = {
|
||||
hwaddr = "0A:14:48:01:14:00";
|
||||
type = "veth";
|
||||
};
|
||||
njalla = {
|
||||
type = "wireguard";
|
||||
upstream = {
|
||||
provider = "njal.la";
|
||||
upBandwidth = 45000;
|
||||
};
|
||||
};
|
||||
};
|
||||
ospf = {
|
||||
allowedUpstreams = [ "upstream3" "upstream4" "freifunk" ];
|
||||
upstreamInstance = 5;
|
||||
};
|
||||
role = "container";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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" ];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQEMA2PKcvDMvlKLAQf9H11MeVsKpyi49/f8YxayUL8mbu8FEuUEW2F4N6MbThXz
|
||||
/kEweXTs3m9KywyieiF17S2UE/02b5E2533sn41mRa5Jo3vmGPb6WANRkoB7YLOO
|
||||
T770KStpvdIH8vljhGj3eFrNk64POch9fPrGMt8pz4uYcmKgjYhKNb4iUqFj8ZIi
|
||||
RsdheQ78MnY37df7IzLQmFGZs1jIA773rHN6aVomOqNBTzfVTQO41zKATzbrKpW4
|
||||
qqau3kn1fbQTab1FedJMEqk1YPhD1H8Pyhib3ff7JpPeWxkUzuZt+grAUD59aJsr
|
||||
ZX93USKoHSuJ5tUCY3dfmpiaetH2qjOmjI2ysCYGENLqAW440k/1U/Z58B0/ezTZ
|
||||
RTyU2GPbf7kpC2VL8EDZSTwLkDMB+mmXlZffF3bB1rdmZCahzjk4X9awKSXLIVTV
|
||||
ShGx2z9sI1pjmtz5CzXA7Ry0wmfJJ8gFM4DUaPCs2KghHVurGY4lmn1VWw80VtXn
|
||||
+u2dqhYTtdgxArwGV4EsKYBqRRAjsKn9NWXRo+WXIhH9EPzHioJGwKgbDw/n69Qa
|
||||
zMBNfePDj1HapEILaTq7jL/K67+07hDMVOnkUJL/lE2yzwCKkb0PnWAGgzXyOCQG
|
||||
p4ih9+samGMM7rIjxM1eI892MuAlrf+awkHY6P4cwU9vKxKHbqmqeRbOe8wUBuqg
|
||||
kmF9MCOPsCrS/5Dtr0JoR9WTnByLvekPbChW3ANMzAuHtKrjE7H583Z+ql52iYcj
|
||||
cLqlDP/1XzXu7dwfm3VcY0VD73Qy9gAHaOXcMHk6nOFzPiiAjVuqrw+pC7qS3SxJ
|
||||
pnzbyRz4ourfMymsfGj0aMlZknCcWidR366gnVLVDw19hWQ+s76cBJ1sKh/dNpUo
|
||||
d9h5qC7mlZ1RTHZFS8RKF1WODcq9h9W+CkQUg0y2R6EztEdVnc263fgwJH1VFAZW
|
||||
vsYhFehx1TJ/X/miMvScUDedrA1xcD+gs2zhXi5lYpk2U3HpfvGpEkLJaTzAXQiX
|
||||
7MxTBjnWviHv0s4ozeLICQDp81QqPNgCskaWf2I+9tYjU0Ob2I2ZqQ4LCx4UAraV
|
||||
iHmrszgP3OvkqRnidX1sYxwu7NUxZQK+Nmpb+N0+PyDErZdHNfpgl0erh0YswPOf
|
||||
Cc6WLsp9B2YkLNNGLxJnpYJEccE3I23JJ5/2A/4ZbfUZnDA6jKTx4qXj4ScygY0S
|
||||
kBiCwIaX2xEPOpQ61fE0xzV2xXnfGBT7IgcTwjL1ilOIWrWRbCad1wIlaL1c5lfv
|
||||
chCdv3ItWL9rwQvv3aiFm1oq3PL0Tp5qdth5ylmcyFwLRNVJKmZC79tD9/XYx1LG
|
||||
NTAWtMqR2dsz44nTPvn3x+HI08Ll3UbGK64hKlfjUjjYUUMCDwXXSl1HiunzZVa9
|
||||
5aVMD/Eg5TzzuS1aL1y01cfBhjZH5guFRxl6KUuNzIjAWh4rScCplTWfKtSQVhTO
|
||||
ZwAAuY3TZ5R4M/PFNLXCByUMI+nivKazVhVZSVMPTU1ENYrSFVKURsvuLwju8Pan
|
||||
K026oBtPdnaetOkERZJzayiPA2KCqN/LkPNMsmfniAZedj+7SUmyYigwMVRWFuB+
|
||||
HLPzZSDb4WJD53OiJhYdFlblEtTATZ2JdOBEATHB7wQqxBTNKheYTKV3ALZnu0d/
|
||||
6jOlRNHeAD6XlyAvTyuMFiU1qHEACmFN4EQ2y7yR9TI8KmCKkP6wXPzavtVjB/ll
|
||||
qeozsjD1BDhHhQLmOra8yXuZ9NoWkgNUtn9HRhbMlv0XjrPerkJ+xv0HQudI6Hyy
|
||||
sEj3fJY5l47CauUOaMmzSf/+ONSE5YQ6eh8Q6RNqpjKJ7HKJqgBDsVCcfkbA6Dtp
|
||||
KaQcUr4Q8cGoYejqUt9glVnmJDYicebdZFt9BA8i/mCykKvPpsGc/oFyh+u5lFjd
|
||||
GiFr4QlULSZsO3Yfv4xeFPWqkJ7xMeX65zPc+q5MH2+8pYXL6l/7U3yFI4gEXACX
|
||||
xiWrnvi8KWhju0GMHji/obUHuaudzYRaWdQWb7ga/xw2Q3UagXZxvM0arOliQT1P
|
||||
1EvHdN8U7xahKo9kGYAn2sgbOEMuoLC+MRkBE2PocC1TqU8LRootXXah4oJMglvu
|
||||
80MJYCZ5AvbMeW/lpnrtx9v9gbumP1bl/fxzi+fksMJzjwrQlgjdTM2peNVRP2OT
|
||||
EQFQm3jtqLqtKo0Oc7BtExevVzb0eGH8L/3Y2NUZCsLkY+KvIZe6O+8nBOcX4GeU
|
||||
nxSypDDTNxP0bhjMYaSI+eIVFRhEvCHdtscbtzpiOdsAUq9C20HDNTjeJ4QlpP4t
|
||||
/8nfywmBvgQ3ddujkRX7iGYzGebHOKfJwSXksT+md2wslx/CvMumEvK3CRN2OLK/
|
||||
dS3deYWLy3DLRJA5bgcp/OAnVKNGt3EGQq11ucup23Fm3jINCgEVzccW/X2AP0uV
|
||||
cyEFudLnMuHERcjcAHfXHqPCqqohSo+MNGZwoKLjXWSctY7dlofILlwShauBR/Gb
|
||||
HnArSBPuQaWQRX8gtWIwwjUmy2a63cgKIrvhtSGQO7JY32/omZjAYSGJQ2zppZh+
|
||||
aluD1TMos69ThHITEaLApO18xzWHlHFxdP0v9sPx1BUhd6NaZiXvjWQnTjBlepjn
|
||||
xntPyEsM4xypmEAViQeWz7WJdm5O7NhafoFQyn1i+fVysO/ru+LBRFmXp2xwfVUw
|
||||
Z8m1bCNAZ3ZOro2VIztQsgO9Zv1tycteII+wP+RicDIYaaHnLYbGznbuTtYNAyqb
|
||||
rBd2uHwlUjVqEfSMlnmdsOcF34ssGF6hU8bBgU3d44BeQCzYpCaxN0MQCCPK/d+V
|
||||
R/KDe1C1QkDEifDL0wvAZ6uyPPakpQlPi0pTA/20Vfc16LQiCISWBrLWoE3MmtGV
|
||||
ocAQe1M+xt+1pjOMlv7vPJ5Wfb3zeQ3yL/+d+qL54kr0cHSAF5mE6GjMYscWjott
|
||||
Vz81RjFgt8ci3pdzDK3W1Zt97qUcFBG+4liQpJZVB3we/v6mhJaQ9lcyb/G1Urk1
|
||||
GynGtWzzk8aXHMeVi5cfNAGqigxuwl8lMDYlCRoT+q6lzCFqIk+P9avoCZRXCS62
|
||||
FzVz8lwhDaslYoC+SdWQl7hq6gdxdRFvx+n+nHWcKprGVJ82f9wVid7fqwKh++2P
|
||||
bNequ4JORLCofyJ1QWYTv/Ep/RQW1rNdgrEf+SUXtK+HSxz6ZwRYCyz2OdBqJgLt
|
||||
df6s3ivk4ekkowF0h+8a62+aQpHmW9rWVFdP1ibUeThxsyLu41Y4/6LG8FhKxn8U
|
||||
Qyz9xJvP3QhSrf4LgY8hDb4I8YbZFYrNqlkaeT9ulcbR9bilNJJ8vbpPt0/gsDNx
|
||||
hbkaL6grhoyva/dDbnUIuYoSRJUCp4I6lBczyYXBtP900jSNH4ezJS0HRarRHf1V
|
||||
vn5J2xWQnFzbbYAlY4wbzjDRqKwShx/koe9q4JSvs2cYc6tg7Aw1cjJcrmo+TORo
|
||||
cdoN4S5iL3babk788B8FHjZJeMnoEyqFzzHgq+bSzR4RrhIUVPf6PTIiMMcUt20j
|
||||
seYUAwZC0I4cJU81Y+ok8nVuOHxRucr9A0MWhjaY05+rdM+TmwFVHDuPGoy0fKOQ
|
||||
Acj1EAPhhAQGQRXlq7tlbPrsJCHxHpQvCcawIGVYf9Ci0QwDd4q3s5nR5rSW2LUy
|
||||
+MJh57Rutd7H0Exgj7+KDkEoBxAJMMYuiOm9FJBZ7rxBe9dYjih0vv0ORsMjWTgW
|
||||
Jr5IxxXuLgIHsMOIL/Z3TS+omXqia6SAWcEogh6QwXdKrt/HZnKJIpUF5roTPmFK
|
||||
iFTMh3brwkJ2FF8Xgf3MYKnb5WHplQvK8hkLb98rz7J2YqwPY52vaNPQInnocfEs
|
||||
pYTQTVb2OhRop/nMSr/77vNirnGocySg6IWpQnwU8pc4evtdmX6G0Q4rdHpwy3DE
|
||||
21w7SOIYAaDKJj9gmsUiik8lCIn58xL+lgZjt1OuB1LP3P5OZ8rZ7Ff+S6Cdltyy
|
||||
Gn/Q0YBFRD1JtM2anXOGhX/bqsJyvmqD4NsO1dogT8GDd9TJLSbUFdY0zoCk6xfJ
|
||||
BKQ/IwN7mfXMRmqlJaZgGwzywPpoViQ6iHHIfGNGnqjNwltGHJDefGMLPos03c40
|
||||
fHqsfCJfseTEUZtreKp/B2RiZeqYg72emcpqWs+q9C2Warrn52GeKpFzKJlELeTL
|
||||
WpIhuaYI1WEbeoMdBJrV7207U4Ufd4sHTC2QOQOXoRCNMBUHF77vMvgaPHPVETTg
|
||||
fEzpuDpoTnU79LMWdME0MkGvsCudbBrupNwC15ULt7mNuA2SalfrYxkNskvPKYAh
|
||||
sg87w/zkl/IVIk5tvSdN44Gvji7vVZvMkfVcyk5o8OU4IZUxy/iRTZUzvBZrqzaA
|
||||
CFHl+QwXLgApwphApTBEZGWZMCdP1FD21QXNUt4sXWB8eW419p0a6oJFwGPEkRMD
|
||||
XTJMjhCqP7SJUDPWIS1CuI33bdOuyjGeUSeb0Xe1IYuxWqPBI0oNJL3s6K+V98Ut
|
||||
meIVIUCOo+sOS64UqdBmcbAkFSnE04xxiFN7jOd3Bfr+2aRDOMYlozM2j+H2oDBF
|
||||
JyMEZAY2Nn7s2iqyK66q70DLku2x9kmuuY1U6jUxuvYn3id6D5tk4+BhvbSXpvHo
|
||||
a0pGupBsx2pIY+uHQafwErqGNoH6BAhARq8aeRzNZrPlcfyTiTZ2xYsh40AVYx0S
|
||||
fNcWNhi4/ZVamjveZD1Gg/w6u4ouzrrBS3PeOebuBrVkUExitZ4QnvZe8Vda/YcY
|
||||
miV13I66Ks6ZTALSeZ4Hd0b7yjsZnNiBkmAMCClYM8qcrOfGJsAGhi/V4uIzrz0Z
|
||||
LAMMX5Il3xwDhN/463hP89GTWymwQ2s6R2Y5e4TNUzt/2fajPy7ENDT1htnObeIR
|
||||
cEsjz7vCkMplEK6tVNbfp7PxfOrH3SnBkkG1A+QlWPrHL3J8Ck4hVq6XKhRwPRgM
|
||||
8ERpyTgTRmwvPEGXQptVsStFKvqhS8jsJDkxadGFJaOhgqzysIhJUgbO8335oW6M
|
||||
efyeKPih0zwr2RUq1sKE9KW9T8vnwT2V5BRw3LjZ99NP3ONiuhXflVyLevnGLkmY
|
||||
7VScu8rGlKij6jW9mIiAL/UA0nt9Dh/vJZGDTh4bMHVwJb0yFMfsbw==
|
||||
=EhAz
|
||||
-----END PGP MESSAGE-----
|
|
@ -1,343 +0,0 @@
|
|||
# Dummy secrets for testing
|
||||
{
|
||||
site.net = {
|
||||
core.ospf.secret = "encrypted";
|
||||
pub.wifi.ieee80211rKey = "2dc40abba46da9490ea0e00f93f18ce5";
|
||||
c3d2.wifi.ieee80211rKey = "d1b1fa2461efc0df9e2d96579607b7f6";
|
||||
};
|
||||
|
||||
site.hosts = {
|
||||
ap1.password = "encrypted";
|
||||
ap2.password = "encrypted";
|
||||
ap3.password = "encrypted";
|
||||
ap4.password = "encrypted";
|
||||
ap5.password = "encrypted";
|
||||
ap6.password = "encrypted";
|
||||
ap7.password = "encrypted";
|
||||
ap8.password = "encrypted";
|
||||
ap9.password = "encrypted";
|
||||
ap10.password = "encrypted";
|
||||
ap11.password = "encrypted";
|
||||
ap12.password = "encrypted";
|
||||
ap15.password = "encrypted";
|
||||
ap17.password = "encrypted";
|
||||
ap18.password = "encrypted";
|
||||
ap19.password = "encrypted";
|
||||
ap21.password = "encrypted";
|
||||
ap22.password = "encrypted";
|
||||
ap23.password = "encrypted";
|
||||
ap24.password = "encrypted";
|
||||
ap25.password = "encrypted";
|
||||
ap26.password = "encrypted";
|
||||
ap27.password = "encrypted";
|
||||
ap28.password = "encrypted";
|
||||
ap29.password = "encrypted";
|
||||
ap30.password = "encrypted";
|
||||
ap31.password = "encrypted";
|
||||
ap32.password = "encrypted";
|
||||
ap33.password = "encrypted";
|
||||
ap34.password = "encrypted";
|
||||
ap35.password = "encrypted";
|
||||
ap36.password = "encrypted";
|
||||
ap37.password = "encrypted";
|
||||
ap38.password = "encrypted";
|
||||
ap39.password = "encrypted";
|
||||
ap40.password = "encrypted";
|
||||
ap41.password = "encrypted";
|
||||
ap42.password = "encrypted";
|
||||
ap44.password = "encrypted";
|
||||
ap45.password = "encrypted";
|
||||
ap46.password = "encrypted";
|
||||
ap47.password = "encrypted";
|
||||
ap48.password = "encrypted";
|
||||
ap49.password = "encrypted";
|
||||
ap50.password = "encrypted";
|
||||
ap51.password = "encrypted";
|
||||
ap52.password = "encrypted";
|
||||
ap53.password = "encrypted";
|
||||
ap54.password = "encrypted";
|
||||
ap55.password = "encrypted";
|
||||
ap56.password = "encrypted";
|
||||
ap57.password = "encrypted";
|
||||
ap58.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";
|
||||
switch-a1.password = "encrypted";
|
||||
switch-b1.password = "encrypted";
|
||||
switch-b2.password = "encrypted";
|
||||
switch-b3.password = "encrypted";
|
||||
switch-c1.password = "encrypted";
|
||||
switch-c3d2-main.password = "encrypted";
|
||||
switch-d1.password = "encrypted";
|
||||
switch-dach.password = "encrypted";
|
||||
switch-ds1.password = "encrypted";
|
||||
switch-ds2.password = "encrypted";
|
||||
switch-ds3.password = "encrypted";
|
||||
|
||||
upstream4.interfaces.up4-pppoe.upstream = {
|
||||
user = "encrypted";
|
||||
password = "encrypted";
|
||||
};
|
||||
|
||||
anon1.interfaces.njalla.wireguard = {
|
||||
addresses = [ "fec0::1/64" "192.168.0.1/24" ];
|
||||
endpoint = "0.0.0.1";
|
||||
privateKey = "encrypted";
|
||||
publicKey = "encrypted";
|
||||
};
|
||||
flpk-gw.interfaces.up-flpk.wireguard = {
|
||||
addresses = [ "fec0::1/64" "192.168.0.1/24" ];
|
||||
endpoint = "0.0.0.1";
|
||||
privateKey = "encrypted";
|
||||
publicKey = "encrypted";
|
||||
};
|
||||
|
||||
ap1.wifi."platform/qca953x_wmac".ssids."uebergangsnetz".psk = "encrypted";
|
||||
ap10.wifi."platform/qca953x_wmac".ssids = {
|
||||
"iz-dresden.org".psk = "encrypted";
|
||||
};
|
||||
ap11.wifi."platform/ahb/18100000.wmac".ssids."braeunigkoschnik".psk = "encrypted";
|
||||
ap12.wifi."platform/ar934x_wmac".ssids = {
|
||||
"IrèneMélix".psk = "encrypted";
|
||||
"paperheart".psk = "encrypted";
|
||||
};
|
||||
ap15.wifi."platform/ahb/18100000.wmac".ssids."etz250".psk = "encrypted";
|
||||
ap17.wifi."platform/ahb/18100000.wmac".ssids = {
|
||||
"EDUB".psk = "encrypted";
|
||||
"Zweitwohnsitz".psk = "encrypted";
|
||||
"e-Stuetzpunkt".psk = "encrypted";
|
||||
};
|
||||
ap18.wifi."platform/qca953x_wmac".ssids."Restaurierung Wolff/Kober".psk = "encrypted";
|
||||
ap19.wifi."platform/qca953x_wmac".ssids = {
|
||||
"Bockwurst".psk = "encrypted";
|
||||
"Walter".psk = "encrypted";
|
||||
};
|
||||
ap2.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids = {
|
||||
"C3D2 legacy".psk = "encrypted";
|
||||
"C3D2 IoT".psk = "encrypted";
|
||||
};
|
||||
};
|
||||
ap23.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."LBK Network".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."LBK Network".psk = "encrypted";
|
||||
};
|
||||
ap24.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";
|
||||
ap29.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."jungnickel-fotografie".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."jungnickel-fotografie".psk = "encrypted";
|
||||
};
|
||||
ap3.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted";
|
||||
"platform/ar934x_wmac".ssids."C3D2 legacy".psk = "encrypted";
|
||||
};
|
||||
ap30.wifi."platform/ahb/18100000.wmac".ssids."WLANb0402".psk = "encrypted";
|
||||
ap31.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids = {
|
||||
"C3D2 legacy" = { "psk" = "encrypted"; };
|
||||
"C3D2 IoT" = { "psk" = "encrypted"; };
|
||||
"FOTOAKADEMIEdd" = { "psk" = "encrypted"; };
|
||||
};
|
||||
};
|
||||
ap32.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."ZW stage".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."ZW stage legacy".psk = "encrypted";
|
||||
};
|
||||
ap33.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."C3D2 legacy".psk = "encrypted";
|
||||
};
|
||||
ap34.wifi."pci0000:00/0000:00:00.0".ssids."etz250".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";
|
||||
ap37.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."hechtfilm.de".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."hechtfilm.de legacy".psk = "encrypted";
|
||||
};
|
||||
ap38.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids = {
|
||||
"ZW heinrichsgarten" = { "psk" = "encrypted"; };
|
||||
"plop" = { "psk" = "encrypted"; };
|
||||
};
|
||||
"platform/ahb/18100000.wmac".ssids = {
|
||||
"ZW heinrichsgarten" = { "psk" = "encrypted"; };
|
||||
"plop" = { "psk" = "encrypted"; };
|
||||
"millimeter" = { "psk" = "encrypted"; };
|
||||
};
|
||||
};
|
||||
ap39.wifi."platform/10180000.wmac".ssids."EckiTino".psk = "encrypted";
|
||||
ap4.wifi."platform/ahb/18100000.wmac".ssids."jam-circle.de".psk = "encrypted";
|
||||
ap40.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."M".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."M legacy".psk = "encrypted";
|
||||
};
|
||||
ap41.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."Walter".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."Walter".psk = "encrypted";
|
||||
};
|
||||
ap42.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."jam-circle.de".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."jam-circle.de legacy".psk = "encrypted";
|
||||
};
|
||||
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:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted";
|
||||
};
|
||||
ap45.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:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted";
|
||||
};
|
||||
ap46.wifi = {
|
||||
"1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids = {
|
||||
"EWW".psk = "encrypted";
|
||||
"ZW stage legacy".psk = "encrypted";
|
||||
};
|
||||
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids = {
|
||||
"EWW".psk = "encrypted";
|
||||
"ZW stage".psk = "encrypted";
|
||||
};
|
||||
};
|
||||
ap47.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:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted";
|
||||
};
|
||||
ap48.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:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted";
|
||||
};
|
||||
ap49.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:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted";
|
||||
};
|
||||
ap5.wifi."platform/ahb/18100000.wmac".ssids."verbalwerk.de".psk = "encrypted";
|
||||
ap50.wifi = {
|
||||
"1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0".ssids = {
|
||||
"ZW stage legacy".psk = "encrypted";
|
||||
"gerdwork".psk = "encrypted";
|
||||
};
|
||||
"1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted";
|
||||
};
|
||||
ap51.wifi = {
|
||||
"pci0000:01/0000:01:00.0".ssids."antrares".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."antrares".psk = "encrypted";
|
||||
};
|
||||
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:01.0/0000:02:00.0".ssids."ZW stage".psk = "encrypted";
|
||||
};
|
||||
ap53.wifi."platform/qca953x_wmac".ssids."Karen Koschnick".psk = "encrypted";
|
||||
ap54.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."Abyssinia".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."Abyssinia".psk = "encrypted";
|
||||
};
|
||||
ap55.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."MagLAN".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."MagLAN (legacy)".psk = "encrypted";
|
||||
};
|
||||
ap56.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."MagLAN".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."MagLAN (legacy)".psk = "encrypted";
|
||||
};
|
||||
ap57.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."Zentralwerk".psk = "encrypted";
|
||||
};
|
||||
ap58.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."Zentralwerk".psk = "encrypted";
|
||||
"platform/ahb/18100000.wmac".ssids."LIZA".psk = "encrypted";
|
||||
};
|
||||
ap59.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."Ebs 5000".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";
|
||||
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";
|
||||
};
|
||||
ap8.wifi = {
|
||||
"pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted";
|
||||
"platform/ar934x_wmac".ssids = {
|
||||
"C3D2 legacy".psk = "encrypted";
|
||||
"teknologi".psk = "encrypted";
|
||||
};
|
||||
};
|
||||
ap9.wifi."platform/qca953x_wmac".ssids."Herzzbuehne".psk = "encrypted";
|
||||
};
|
||||
|
||||
site.dyndnsKey = "oYmxXCIa0nArp0679L6v+y/UfnhripOudLv+R5Cop8I=";
|
||||
|
||||
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"
|
||||
];
|
||||
} ];
|
||||
};
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
{ config, lib, ... }:
|
||||
let
|
||||
containers = lib.filterAttrs (_: { role, ... }:
|
||||
role == "container"
|
||||
) config.site.hosts;
|
||||
|
||||
bridgeInterfaces = builtins.foldl' (result: { interfaces, ... }:
|
||||
result // builtins.mapAttrs (_: _: {
|
||||
type = "bridge";
|
||||
}) (
|
||||
lib.filterAttrs (_: { type, ... }:
|
||||
builtins.elem type [ "veth" "bridge" ]
|
||||
) interfaces
|
||||
)
|
||||
) {} (builtins.attrValues containers);
|
||||
|
||||
makeServer = _name: {
|
||||
role = "server";
|
||||
model = "pc";
|
||||
interfaces = bridgeInterfaces // {
|
||||
cluster = {
|
||||
type = "bridge";
|
||||
gw4 = "cls-gw";
|
||||
gw6 = "cls-gw";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
site = {
|
||||
hosts = {
|
||||
server1 = makeServer "server1";
|
||||
server2 = makeServer "server2";
|
||||
};
|
||||
|
||||
sshPubKeys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDOFs2LdK23ysS0SSkXZuULUOCZHe1ZxvfOKj002J6rkvAaDLar9g5aKuiIV70ZR33A2rchoLMiM4pLLwoSAPJg1FgIgJjU+DFoWtiW+IjzKXdHHVspb2iOIhpfbfk8WC5HZ/6fPz4RUqadGQ43ImnMhSN0ge3s/oM48hpc96ne6tH+mGiugdPx8097NE9yTqJHi8deBhi3daeJH4eQeg66Fi+kDIAZv5TJ0Oca5h7PBd253/vf3l21jRH8u1D1trALv9KStGycTk5Nwih+OHx+Rnvue/B/nxgAz4I3mmQa+jhRlGaQVG0MtOBRY3Ae7ZNqhjuefDUCM2hwG70toU9xDUw0AihC2ownY+P2PjssoG1O8f/D7ilw7qrXJHEeM8HwzqMH8X4ELYHaHTwjeWfZTTFev1Djr969LjdS1UZzqCZHO0jmQ5Pa3eXw8xcoprtt620kYLTKSMs6exLstE48o57Yqfn+eTJDy7EkcjiLN6GNIi42b9Z73xXNpZx1WR9O6OulJf/6pWgrApasvxiGmxxILq98s1/VnZkOFXR8JXnpvKHEIOIr3bFQu3GLCrzY2Yuh4NL5wy6lcZNTr/0rr6AO24IbEWM7TApbXnKA5XQhAbThrVsuFBdT3+bBP2nedvWQ0W+Q6SUf+8T2o5InnFqs5ABnTixBItiWw+9BiQ== root@server1"
|
||||
];
|
||||
};
|
||||
}
|
|
@ -1,469 +0,0 @@
|
|||
{
|
||||
site.hosts = {
|
||||
switch-a1 = {
|
||||
role = "switch";
|
||||
model = "TL-SG3210";
|
||||
location = "Saal A";
|
||||
interfaces = { mgmt.type = "phys"; };
|
||||
|
||||
links = {
|
||||
switch-a2.ports = [ "7" ];
|
||||
priv25.ports = [
|
||||
# A6: Kleiner Saal Schaltschrank
|
||||
"1"
|
||||
# Kabinett A10
|
||||
"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 = {
|
||||
role = "switch";
|
||||
model = "dumb";
|
||||
location = "Saal A";
|
||||
|
||||
links = {
|
||||
switch-c1.ports = [ "1" ];
|
||||
switch-a1.ports = [ "2" ];
|
||||
switch-ds1.ports = [ "3" ];
|
||||
switch-ds2.ports = [ "4" ];
|
||||
switch-ds3.ports = [ "5" ];
|
||||
ap44.ports = [ "10" ];
|
||||
ap45.ports = [ "11" ];
|
||||
ap46.ports = [ "12" ];
|
||||
ap47.ports = [ "13" ];
|
||||
ap48.ports = [ "14" ];
|
||||
ap49.ports = [ "15" ];
|
||||
ap50.ports = [ "16" ];
|
||||
ap52.ports = [ "17" ];
|
||||
};
|
||||
};
|
||||
|
||||
switch-b3 = {
|
||||
role = "switch";
|
||||
model = "junos";
|
||||
location = "Haus B Souterrain";
|
||||
interfaces = { mgmt.type = "phys"; };
|
||||
|
||||
# Ports 1-19 ungerade oben
|
||||
# Ports 2-20 gerade unten
|
||||
# (15, 16 gehen aktuell nach Haus A)
|
||||
# Ports 21-24 unten seitlich (optional optisch)
|
||||
# Port 7 geht aktuell nach Turm C Erdgeschoss und dadurch zur Ecce
|
||||
links = {
|
||||
ap23.ports = [ "ge-0/0/10" ];
|
||||
ap8.ports = [ "ge-0/0/16" ];
|
||||
iso1.ports = [ "ge-0/0/2" ];
|
||||
iso2.ports = [ "ge-0/0/3" ];
|
||||
iso3.ports = [ "ge-0/0/4" ];
|
||||
coloradio.ports = [
|
||||
# Patchpanel C8
|
||||
"ge-0/0/22"
|
||||
];
|
||||
c3d2.ports = [
|
||||
"ge-0/0/5"
|
||||
"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 = {
|
||||
group = "1";
|
||||
ports = [
|
||||
"ge-0/0/38" "ge-0/0/39"
|
||||
"ge-1/0/32" "ge-1/0/33"
|
||||
];
|
||||
};
|
||||
hydra = {
|
||||
group = "7";
|
||||
trunk = false;
|
||||
ports = [
|
||||
"ge-0/0/14" "ge-0/0/15"
|
||||
"ge-1/0/14" "ge-1/0/15"
|
||||
];
|
||||
};
|
||||
server10 = {
|
||||
group = "5";
|
||||
ports = [
|
||||
"ge-0/0/36" "ge-0/0/37"
|
||||
"ge-1/0/36" "ge-1/0/37"
|
||||
];
|
||||
};
|
||||
switch-c1 = {
|
||||
group = "2";
|
||||
ports = [ "ge-0/0/30" "ge-0/0/31" "ge-1/0/30" "ge-1/0/31" ];
|
||||
};
|
||||
switch-c3d2-main = {
|
||||
group = "4";
|
||||
ports = [
|
||||
"ge-0/0/26"
|
||||
"ge-0/0/27"
|
||||
"ge-1/0/26"
|
||||
"ge-1/0/27"
|
||||
];
|
||||
};
|
||||
switch-d1.ports = [ "ge-0/0/34" ];
|
||||
|
||||
ap1.ports = [ "ge-1/0/8" ];
|
||||
ap11.ports = [ "ge-1/0/10" ];
|
||||
ap34.ports = [ "ge-1/0/12" ];
|
||||
ap18.ports = [ "ge-1/0/18" ];
|
||||
ap29.ports = [ "ge-0/0/46" ];
|
||||
ap30.ports = [ "ge-1/0/22" ];
|
||||
ap35.ports = [ "ge-1/0/23" ];
|
||||
ap37.ports = [ "ge-1/0/39" ];
|
||||
ap63.ports = [ "ge-1/0/17" ];
|
||||
ap40.ports = [ "ge-1/0/21" ];
|
||||
ap41.ports = [ "ge-0/0/47" ];
|
||||
ap42.ports = [ "ge-1/0/6" ];
|
||||
ap5.ports = [ "ge-1/0/7" ];
|
||||
ap51.ports = [ "ge-1/0/13" ];
|
||||
ap53.ports = [ "ge-0/0/7" ];
|
||||
ap72.ports = [ "ge-1/0/38" ];
|
||||
ap55.ports = [ "ge-1/0/19" ];
|
||||
ap56.ports = [ "ge-1/0/9" ];
|
||||
ap60.ports = [ "ge-1/0/20" ];
|
||||
ap62.ports = [ "ge-0/0/11" ];
|
||||
ap65.ports = [ "ge-0/0/9" ];
|
||||
ap66.ports = [ "ge-1/0/43" ];
|
||||
mgmt.ports = [
|
||||
"ge-0/0/0"
|
||||
"ge-0/0/1"
|
||||
"ge-1/0/44"
|
||||
# server7
|
||||
"ge-1/0/45"
|
||||
"ge-1/0/46"
|
||||
# server8
|
||||
"ge-1/0/47"
|
||||
# server9
|
||||
"ge-1/0/48"
|
||||
];
|
||||
flpk.ports = [
|
||||
# server7
|
||||
"ge-0/0/40"
|
||||
];
|
||||
priv1.ports = [ "ge-1/0/3" ];
|
||||
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" ];
|
||||
ap64.ports = [ "ge-0/0/45" ];
|
||||
pub.ports = [
|
||||
"ge-1/0/11"
|
||||
];
|
||||
server9 = {
|
||||
group = "10";
|
||||
ports = [
|
||||
"ge-0/0/28"
|
||||
"ge-0/0/29"
|
||||
"ge-1/0/28"
|
||||
"ge-1/0/29"
|
||||
];
|
||||
};
|
||||
server8 = {
|
||||
group = "6";
|
||||
ports = [
|
||||
"ge-0/0/41"
|
||||
"ge-0/0/42"
|
||||
"ge-1/0/41"
|
||||
"ge-1/0/42"
|
||||
];
|
||||
};
|
||||
server6 = {
|
||||
group = "9";
|
||||
ports = [
|
||||
"ge-0/0/18"
|
||||
"ge-0/0/19"
|
||||
"ge-1/0/0"
|
||||
"ge-1/0/2"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
switch-c1 = {
|
||||
role = "switch";
|
||||
model = "HP-procurve-2824";
|
||||
location = "Turm C Keller, bei Kabelanschluessen";
|
||||
interfaces = { mgmt.type = "phys"; };
|
||||
|
||||
links = {
|
||||
# Saal A: durch dummen PoE-Switch mit Aggregation an ap44-50,52 + switch-a1
|
||||
switch-a2 = {
|
||||
group = "1";
|
||||
ports = [ "15-16" ];
|
||||
};
|
||||
switch-b3 = {
|
||||
group = "2";
|
||||
ports = [ "21-24" ];
|
||||
};
|
||||
switch-dach.ports = [ "6" ];
|
||||
# Vodafone Modems
|
||||
up1.ports = [ "1" ];
|
||||
up2.ports = [ "2" ];
|
||||
# DSI
|
||||
up4.ports = [ "4" ];
|
||||
# Turm C APs
|
||||
ap17.ports = [ "19" ];
|
||||
ap19.ports = [ "17" ];
|
||||
ap26.ports = [ "18" ];
|
||||
ap38.ports = [ "7" ];
|
||||
ap61.ports = [ "13" ];
|
||||
# Iso nets
|
||||
iso1.ports = [ "9" ];
|
||||
iso2.ports = [ "10" ];
|
||||
iso3.ports = [ "11" ];
|
||||
iso4.ports = [ "12" ];
|
||||
iso6.ports = [ "14" ];
|
||||
# Saal Foyer
|
||||
priv25.ports = [ "20" ];
|
||||
};
|
||||
};
|
||||
|
||||
switch-c3d2-main = {
|
||||
role = "switch";
|
||||
model = "HP-procurve-2824";
|
||||
location = "C3D2";
|
||||
interfaces = { mgmt.type = "phys"; };
|
||||
|
||||
links = {
|
||||
mgmt.ports = [ "1" ];
|
||||
switch-b3 = {
|
||||
group = "1";
|
||||
ports = [ "21-24" ];
|
||||
};
|
||||
# Kammer
|
||||
ap2.ports = [ "3" ];
|
||||
# Decke
|
||||
ap31.ports = [ "2" ];
|
||||
# Fenster
|
||||
ap33.ports = [ "5" ];
|
||||
c3d2.ports = [ "8-20" ];
|
||||
# tmp Datenspuren: VOC
|
||||
iso4.ports = [ "4" "6" "7" ];
|
||||
};
|
||||
};
|
||||
|
||||
switch-d1 = {
|
||||
role = "switch";
|
||||
model = "TL-SG3210";
|
||||
location = "Turm D Elektroraum";
|
||||
interfaces = { mgmt.type = "phys"; };
|
||||
|
||||
links = {
|
||||
switch-b3 = {
|
||||
group = "1";
|
||||
ports = [ "1" ];
|
||||
};
|
||||
switch-d2.ports = [ "3" ];
|
||||
|
||||
# Turm D APs
|
||||
ap7.ports = [ "8" ];
|
||||
ap9.ports = [ "5" ];
|
||||
ap10.ports = [ "4" ];
|
||||
ap12.ports = [ "7" ];
|
||||
ap22.ports = [ "2" ];
|
||||
};
|
||||
};
|
||||
|
||||
switch-d2 = {
|
||||
role = "switch";
|
||||
model = "dumb";
|
||||
location = "Turm D Durchgang 1. Etage";
|
||||
|
||||
links = {
|
||||
switch-d1 = {
|
||||
group = "1";
|
||||
ports = [ "12" ];
|
||||
};
|
||||
ap3.ports = [ "1" ];
|
||||
ap59.ports = [ "2" ];
|
||||
};
|
||||
};
|
||||
|
||||
switch-dach = {
|
||||
role = "switch";
|
||||
model = "HP-procurve-2824";
|
||||
location = "Dach";
|
||||
interfaces = { mgmt.type = "phys"; };
|
||||
|
||||
links = {
|
||||
mgmt.ports = [ "1" ];
|
||||
switch-c1.ports = [ "24" ];
|
||||
# Freifunk nodes
|
||||
bmx.ports = [ "12,14,16" ];
|
||||
# radiobert
|
||||
serv.ports = [ "7" ];
|
||||
# Starlink
|
||||
up3.ports = [ "3" ];
|
||||
# unifiac-mesh
|
||||
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" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
let
|
||||
range = cur: max:
|
||||
if cur <= max
|
||||
then [ cur ] ++ range (cur + 1) max
|
||||
else [];
|
||||
in
|
||||
{
|
||||
site.net = builtins.mapAttrs (_: vlan: { inherit vlan; }) {
|
||||
# switches and CPE only have IP addresses configured in the management vlan
|
||||
mgmt = 1;
|
||||
# routers, OSPF area 0
|
||||
core = 2;
|
||||
# servers...
|
||||
serv = 3;
|
||||
# ZW public
|
||||
pub = 4;
|
||||
# C3D2 home network
|
||||
c3d2 = 5;
|
||||
cluster = 6;
|
||||
bmx = 7;
|
||||
flpk = 8;
|
||||
coloradio = 9;
|
||||
# Modems
|
||||
up1 = 10;
|
||||
up2 = 11;
|
||||
up3 = 12;
|
||||
up4 = 13;
|
||||
# Isolated other stuff
|
||||
c3d2iot = 20;
|
||||
# Isolated neighbors directly connectied with their modems
|
||||
iso1 = 101;
|
||||
iso2 = 102;
|
||||
iso3 = 103;
|
||||
iso4 = 104;
|
||||
iso5 = 105;
|
||||
iso6 = 106;
|
||||
} // builtins.foldl' (result: i:
|
||||
# Neighbor subnets
|
||||
result // {
|
||||
"priv${toString i}".vlan = i + 39;
|
||||
}
|
||||
) {} (range 1 61);
|
||||
}
|
BIN
contact.md.asc
BIN
contact.md.asc
Binary file not shown.
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIID6DCCAtCgAwIBAgIJALTDMS9sfATBMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD
|
||||
VQQGEwJERTEQMA4GA1UECAwHU2FjaHNlbjEQMA4GA1UEBwwHRHJlc2RlbjEUMBIG
|
||||
A1UECgwLWmVudHJhbHdlcmsxEDAOBgNVBAsMB05ldHdvcmsxEDAOBgNVBAMMB0Yu
|
||||
IE5vcmQxGzAZBgkqhkiG9w0BCQEWDHJvb3RAYzNkMi5kZTAeFw0xNzAyMDYyMzE1
|
||||
MDRaFw0yNzAyMDQyMzE1MDRaMIGIMQswCQYDVQQGEwJERTEQMA4GA1UECAwHU2Fj
|
||||
aHNlbjEQMA4GA1UEBwwHRHJlc2RlbjEUMBIGA1UECgwLWmVudHJhbHdlcmsxEDAO
|
||||
BgNVBAsMB05ldHdvcmsxEDAOBgNVBAMMB0YuIE5vcmQxGzAZBgkqhkiG9w0BCQEW
|
||||
DHJvb3RAYzNkMi5kZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKyk
|
||||
jWtecgb49vxmmOyw0Lno91HjJ8n75/jb27KaE1eqib0vFL1G7qZeaR1IKdceCXE+
|
||||
umieBpK0g83Bb01V9Vsg1vHC5hLq5u0bqbITpU5jtVRdO003GFa9yrtrvBsyw7tH
|
||||
cR4cewWaewNzZPFuvb/dgzqSOAoxKg4gjsUKM+0TJN2Zz5Zqat4aks1Jig/EKjDl
|
||||
zXIA3NkuzdUTmDB4JpYOOR+WZGKVAO9s6eFJ8AoJZRzSqlIonYjQCvRL02vCztIO
|
||||
+BEgj3ezP6kuAaNcnifoS3APIBil2jfQB7+pl9XmxeOK/BKghOjOUypgcQVAgC/J
|
||||
HM1tEJKm6goXKUrf428CAwEAAaNTMFEwHQYDVR0OBBYEFOfykHof0NOzWSZUORJh
|
||||
wNjZAx/hMB8GA1UdIwQYMBaAFOfykHof0NOzWSZUORJhwNjZAx/hMA8GA1UdEwEB
|
||||
/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAASFNwwW5Xtf0ZkeAGhzi/Pnm2eu
|
||||
pp2GyRHkvar8s/gYX7STqDkqxOtVcySHYxDELaw0BP4b71VkthmdxJXLdDDI5Zqg
|
||||
zjttxfWGnRH6jvYEvFMWS3h6fBKZpkpNcg2tZ549uuFjdyqaDp+EYM82kT+HkRCP
|
||||
hWQSHEW9uXi7wMd9dtz9rJV/wfClDQJp6GeKIoXHBJIb9PyQb0yoAjIw7XHGPkr/
|
||||
MTxv6RKAGgxtmEAHLu8DeF9R8Z/r6kU2OVcq+xK90mp6zzV233lorlSDtQfev1kn
|
||||
NG4kc8M9YiI0xCfNKJCkQMdZbxZ58uuAbF39ID9vyfyf6eVqQp8VxlvdJrI=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,5 @@
|
|||
# Encrypting salt-pillar/ values
|
||||
|
||||
```shell
|
||||
echo -n $SECRET | gpg --armor --batch --trust-model always --encrypt -r 1F0F221A7483B5EF5D103D8B32EBADE870BAF886
|
||||
```
|
11
doc/hello.md
11
doc/hello.md
|
@ -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
|
||||
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))
|
||||
* 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)
|
||||
|
||||
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)
|
||||
|
||||
### 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.
|
||||
|
||||
|
||||
---
|
||||
# Sprechstunden
|
||||
|
||||
Dienstags und Donnerstags 16:00-18:00 Uhr
|
||||
|
||||
[C3D2](https://www.c3d2.de/space.html), Haus B Souterrain, genau in der Mitte
|
||||
|
||||
|
||||
![Kernnetz visualisiert von eri!](core.png)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
Manchmal ist es notwendig einen Port auf dem Switch auf einen anderen zu duplizieren. Es kann auch über vlan ganz woanders hingeschickt werden, aber hier ist die Variante um es auf einen anderen Port auf demselben Switch zu legen:
|
||||
|
||||
#XX: eine numerische id
|
||||
#YY: das interface was monitored werden soll
|
||||
mirroring-group XX mirroring-port GigabitEthernet 1/0/YY both
|
||||
|
||||
#ZZ: ist das interface auf dem der traffic des anderen ports erscheinen soll
|
||||
mirroring-group YY monitor-port GigabitEthernet 1/0/ZZ
|
||||
|
||||
#ggfs. stp ausmachen
|
||||
interface GigabitEthernet 1/0/ZZ stp disable
|
||||
|
||||
#danach aufräumen
|
||||
undo mirroring-group XX
|
||||
|
||||
|
||||
Der monitor-port ist an sich noch funktional, er empfängt zB broadcasts der vlans, die auf ihm konfiguriert sind. Ggfs. die vlans deaktivieren, falls wirklich nur der Traffic des mirroring-port gesehen werden soll.
|
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDhDCCAmwCAQEwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAkRFMRAwDgYD
|
||||
VQQIDAdTYWNoc2VuMRAwDgYDVQQHDAdEcmVzZGVuMRQwEgYDVQQKDAtaZW50cmFs
|
||||
d2VyazEQMA4GA1UECwwHTmV0d29yazEQMA4GA1UEAwwHRi4gTm9yZDEbMBkGCSqG
|
||||
SIb3DQEJARYMcm9vdEBjM2QyLmRlMB4XDTE3MDIwNjIzMTUzMFoXDTI3MDIwNDIz
|
||||
MTUzMFowgYYxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdTYWNoc2VuMRAwDgYDVQQH
|
||||
DAdEcmVzZGVuMRQwEgYDVQQKDAtaZW50cmFsd2VyazEQMA4GA1UECwwHTmV0d29y
|
||||
azEOMAwGA1UEAwwFRmlvbmExGzAZBgkqhkiG9w0BCQEWDHJvb3RAYzNkMi5kZTCC
|
||||
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOOE2AI7JlSS+o8ll85Bz4Gy
|
||||
Uv+/I0bJOTOCRWYBuXIJV7eAHczpdlPoCz+SiTt5MNMalCAmme9SChrS7H4CFCBs
|
||||
RNmMkgMiM0khUN6/EW+QaL3TdAwbcJFPGEhD/6HoJli5fvfsHV2sy1/Un+fr5ZDK
|
||||
uv1xjeOzQaaMqATkIPhuvWHIRO6vUBGyepyssTKZbwdlwecAuTuAs/2UAO2j8ANs
|
||||
hWJ+Ns7naZPzJ8YjyAYAoLcxHzOwz0cgtI7oveeudWGW6SX/U+pQyNMciQ6bv8f7
|
||||
A9PAfX3d5oyy6UQp2gqUKEbSpRxa0I0ZO8hseLz70UnhDcQuuRnlr/pOFCKhDEkC
|
||||
AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAFqgRx/mqcqTdob3OJXIWIRXzcQP1YYLO
|
||||
As3K485qo9e2b28TfrHdHuXWRvR5k7kbtbfqnRLhlfrXQtwYC/9//WzO51LbmKiE
|
||||
gnteG6M/bOelxTsOcuvYL8prTcNxgkRUcVOxwm5rtLDhhc4Ibp/ciNzVNk0+9sTF
|
||||
kYqy2qUuqAscyU5EpSrZ8SPUbK1Pf1Q6x3qU30xkyE5IPIv3sGx6VTwEJBWhyVw5
|
||||
FLtpk/zc9768R/MKxe/WAtuK02x8i8oLb4WtqjSPcuUpo6GUXy3pvKskboJVrPbD
|
||||
4Kn3vZqtKwxPv4HZ40abzMAq/0QOkUFGkWLJcVlyVegZEQE+O8DIwg==
|
||||
-----END CERTIFICATE-----
|
16
doc/vpn.md
16
doc/vpn.md
|
@ -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
|
||||
```
|
|
@ -0,0 +1,58 @@
|
|||
# Provisionierung eines WLAN-Routers
|
||||
|
||||
TODO: nixify
|
||||
|
||||
Sofern der Router durch uns provisioniert wird (ansonsten siehe unten)
|
||||
|
||||
1. Kontaktdaten und Dosennummer in `contacts.md` vermerken
|
||||
2. Nachbar will Privatnetz (verschlüsseltes WLAN)?
|
||||
|
||||
1. privX allokieren
|
||||
2. `privX-gw` in `salt-pillar/lxc-containers` anlegen
|
||||
3. Erweitere `salt-pillar/dhcp/init.sls` um das Netz anhand [der
|
||||
Subnets](../subnets.md). Erste IPv4-Adresse muss für den `privX-gw`
|
||||
frei bleiben, siehe `salt-pillar/hosts/init.sls`
|
||||
4. `salt server1 state.apply lxc-containers`
|
||||
5. `salt-key -A`
|
||||
6. `salt privX-gw state.apply`
|
||||
|
||||
3. AP provisionieren in `salt-pillar/cpe/aps`
|
||||
|
||||
1. Frisches OpenWRT/LEDE? `firstboot: True`
|
||||
2. Feld `model`
|
||||
3. Feld `location`
|
||||
4. LAN-Dosen in `lan-access` auf *privX* legen
|
||||
5. WLANs anpassen:
|
||||
1. SSID festlegen
|
||||
2. `net` auf *privX*
|
||||
3. `psk` vom Benutzer eingeben lassen, verschlüsselt
|
||||
abspeichern
|
||||
6. Kanäle je nach Umgebung des Nachbars optimieren
|
||||
* Ist der Nachbar auf Kanal 1 mag man eher zum Kanal 6
|
||||
* als weitere Option gibt es noch Kanal 11
|
||||
7. mit root@server1 `salt server1 state.apply cpe` ausführen
|
||||
* das generiert `/root/apX.sh`
|
||||
8. mit root@server1 `/root/apX.sh` ausführen zum Anwenden des Konfigurationsskripts
|
||||
9. Wenn Fehler gezeigt werden
|
||||
* `entry not found` ist nicht schlimm
|
||||
* `invalid` hingegen schon!
|
||||
* dann "commit" entfernen und den Fehler suchen.
|
||||
10. collectd installieren wie beim Ende des letzten Skripts angezeigt
|
||||
11. Falls noch Platz ist, ist das Paket `tcpdump` pratisch
|
||||
12. EAP-Netze brauchen große Features: `opkg remove wpad-mini && opkg install wpad`
|
||||
|
||||
4. Switch-Port konfigurieren in `salt-pillar/switches`
|
||||
|
||||
1. Switch raussuchen, z.B. *switch-b1* oder *switch-b2* im Haus B
|
||||
2. Eintrag `apX` anlegen
|
||||
3. `mode: trunk`
|
||||
4. Der Port in welchen das Kabel gesteckt wird kommt unter `ports:`
|
||||
* z.B.: `- GigabitEthernet 1/0/36`
|
||||
5. `vlans:` immer *mgmt* und *pub*, sowie das *privX*
|
||||
6. `salt server1 state.apply switches`
|
||||
7. `/root/switch-X.sh` zum Anwenden des Konfigurationsskripts
|
||||
|
||||
Wenn wir nicht provisionieren, sondern ein mitgebrachter Router verwendet wird:
|
||||
* kein ZW public konfigurieren!
|
||||
* bridge-mode verwenden, dhcpd aus
|
||||
* wenn VLAN möglich: switchport mode auf "trunk"; wenn VLAN nicht möglich: switchport mode auf "access"
|
108
flake.lock
108
flake.lock
|
@ -1,100 +1,58 @@
|
|||
{
|
||||
"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": {
|
||||
"locked": {
|
||||
"lastModified": 1713634877,
|
||||
"narHash": "sha256-+tmLKU8N+YMIIBRPmWFueaytsbSDu4wqGnxc3RKYZwk=",
|
||||
"owner": "SuperSandro2000",
|
||||
"lastModified": 1631792076,
|
||||
"narHash": "sha256-dBRsZ3JB6i53nzC30SsltdwrzjIr8e0zU/y8HitKpT8=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "84f20dcf85434cd2e2a163ec3a30937c78cc26b2",
|
||||
"rev": "4d7170376374e74c7aa52938004e354de1947373",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "SuperSandro2000",
|
||||
"ref": "nixos-23.11",
|
||||
"owner": "NixOS",
|
||||
"ref": "release-21.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"openwrt": {
|
||||
"flake": false,
|
||||
"nixpkgs-master": {
|
||||
"locked": {
|
||||
"lastModified": 1713442482,
|
||||
"narHash": "sha256-OAcv1qiM2V6wPQm4Tz2QnnDpw34pifG6QRDZea7AP9o=",
|
||||
"ref": "openwrt-23.05",
|
||||
"rev": "9b33b74ef71225442361d5192d3a727be212c3cd",
|
||||
"revCount": 58296,
|
||||
"type": "git",
|
||||
"url": "https://git.openwrt.org/openwrt/openwrt.git"
|
||||
},
|
||||
"original": {
|
||||
"ref": "openwrt-23.05",
|
||||
"type": "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",
|
||||
"lastModified": 1631810187,
|
||||
"narHash": "sha256-GHEpi5KiRo8fT9Oma5AFWAZVbP/C/ZnENnsdK++dNEU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a8c43f8eb7ad74d8fa784d12a789195fdd8120f6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "astro",
|
||||
"repo": "nix-openwrt-imagebuilder",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"dns-nix": "dns-nix",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"openwrt": "openwrt",
|
||||
"openwrt-imagebuilder": "openwrt-imagebuilder"
|
||||
"nixpkgs-master": "nixpkgs-master",
|
||||
"zentralwerk-network-key": "zentralwerk-network-key"
|
||||
}
|
||||
},
|
||||
"zentralwerk-network-key": {
|
||||
"locked": {
|
||||
"dir": "nix/key",
|
||||
"lastModified": 1631808463,
|
||||
"narHash": "sha256-5xMZkqqQbpXECnKEK2THT7u4+/vL7SPp3Jvoicm1Moc=",
|
||||
"ref": "master",
|
||||
"rev": "e4a5aee0e44ca058d2f12d6c6f34db6d484187fc",
|
||||
"revCount": 1172,
|
||||
"type": "git",
|
||||
"url": "https://gitea.c3d2.de/zentralwerk/network.git?dir=nix%2fkey"
|
||||
},
|
||||
"original": {
|
||||
"dir": "nix/key",
|
||||
"type": "git",
|
||||
"url": "https://gitea.c3d2.de/zentralwerk/network.git?dir=nix%2fkey"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
50
flake.nix
50
flake.nix
|
@ -2,22 +2,14 @@
|
|||
description = "Zentralwerk network";
|
||||
|
||||
inputs = {
|
||||
dns-nix = {
|
||||
url = "github:SuperSandro2000/dns.nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
nixpkgs.url = "github:SuperSandro2000/nixpkgs/nixos-23.11";
|
||||
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";
|
||||
};
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/release-21.05";
|
||||
nixpkgs-master.url = "github:NixOS/nixpkgs";
|
||||
# `nix flake update --override-flake zentralwerk-network-key git+file:///...`
|
||||
# to provide the GPG secret key
|
||||
zentralwerk-network-key.url = "git+https://gitea.c3d2.de/zentralwerk/network.git?dir=nix/key";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, dns-nix, nixpkgs, openwrt, openwrt-imagebuilder }:
|
||||
outputs = inputs@{ self, nixpkgs, nixpkgs-master, zentralwerk-network-key }:
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
systems = [ system ];
|
||||
|
@ -27,28 +19,31 @@
|
|||
self.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [ self.nixosModule ];
|
||||
specialArgs = {
|
||||
hostName = name;
|
||||
inherit (self) lib;
|
||||
inherit inputs dns-nix self;
|
||||
};
|
||||
specialArgs.hostName = name;
|
||||
specialArgs.lib = self.lib;
|
||||
specialArgs.self = self;
|
||||
specialArgs.inputs = inputs;
|
||||
specialArgs.nixpkgs-master = nixpkgs-master;
|
||||
};
|
||||
in {
|
||||
# Config, and utilities
|
||||
lib = nixpkgs.lib.extend (_final: _prev:
|
||||
lib = nixpkgs.lib.extend (final: prev:
|
||||
import ./nix/lib {
|
||||
inherit self openwrt;
|
||||
inherit (nixpkgs.legacyPackages.x86_64-linux) lib pkgs;
|
||||
inherit self;
|
||||
inherit (zentralwerk-network-key.lib) gpgKey;
|
||||
pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
||||
});
|
||||
|
||||
# Everything that can be built locally outside of NixOS
|
||||
packages = forAllSystems (system:
|
||||
import ./nix/pkgs { inherit self nixpkgs system openwrt-imagebuilder; }
|
||||
import ./nix/pkgs { inherit self nixpkgs system; }
|
||||
);
|
||||
|
||||
# Configuration for nixosConfigurations
|
||||
# (see nix/nixos-module/default.nix)
|
||||
nixosModule = import ./nix/nixos-module;
|
||||
nixosModule = { ... }: {
|
||||
imports = [ ./nix/nixos-module ];
|
||||
};
|
||||
|
||||
# NixOS host systems (servers, and containers)
|
||||
nixosConfigurations =
|
||||
|
@ -76,10 +71,13 @@
|
|||
''
|
||||
);
|
||||
wrappers = {
|
||||
"all-device-scripts" = hydraJob;
|
||||
"all-device-scripts" = pkg:
|
||||
hydraJob pkg;
|
||||
|
||||
"export-config" = exportFileWrapper;
|
||||
".*-pillar" = exportFileWrapper;
|
||||
"switch-.*" = exportFileWrapper;
|
||||
"ap.*-image" = exportFileWrapper;
|
||||
"ap.*" = exportFileWrapper;
|
||||
};
|
||||
in
|
||||
builtins.mapAttrs (name: pkg:
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
description = "Zentralwerk network secret GPG key";
|
||||
|
||||
outputs = { ... }: {
|
||||
lib.gpgKey = null;
|
||||
# test key
|
||||
lib.dyndnsKey = "Dr1QHSfNtAwgbdoNBtCgl5NxsSXlaw9+qo7juiVTv58=";
|
||||
# test credentials
|
||||
lib.pppoe.upstream4 = {
|
||||
user = "test@example.com";
|
||||
password = "secret";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,60 +1,34 @@
|
|||
{ self
|
||||
, pkgs ? import <nixpkgs> {}
|
||||
, gpgKey
|
||||
}:
|
||||
|
||||
let
|
||||
result = pkgs.lib.evalModules {
|
||||
args = {
|
||||
inherit self pkgs;
|
||||
};
|
||||
modules = [
|
||||
(
|
||||
{ lib, ... }:
|
||||
with lib;
|
||||
{
|
||||
config._module.args = {
|
||||
inherit self pkgs;
|
||||
};
|
||||
options.assertions = mkOption {
|
||||
type = with types; listOf unspecified;
|
||||
internal = true;
|
||||
};
|
||||
options.warnings = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
internal = true;
|
||||
};
|
||||
options.gpgKey = mkOption {
|
||||
type = with types; nullOr path;
|
||||
};
|
||||
config = {
|
||||
inherit gpgKey;
|
||||
};
|
||||
}
|
||||
)
|
||||
./options.nix
|
||||
../../../config
|
||||
./legacy.nix
|
||||
];
|
||||
};
|
||||
|
||||
inherit (result) config;
|
||||
|
||||
warn = result:
|
||||
if builtins.length config.warnings > 0
|
||||
then builtins.trace ''
|
||||
Warnings:
|
||||
|
||||
${self.lib.concatStringsSep "\n" config.warnings}
|
||||
'' result
|
||||
else result;
|
||||
|
||||
error = result:
|
||||
let
|
||||
failed = builtins.filter ({ assertion, ... }:
|
||||
!assertion
|
||||
) config.assertions;
|
||||
in
|
||||
if failed != []
|
||||
then throw ''
|
||||
Errors:
|
||||
|
||||
${self.lib.concatMapStringsSep "\n" ({ message, ... }: message) failed}
|
||||
''
|
||||
else result;
|
||||
|
||||
in warn (error ({
|
||||
inherit (result) options;
|
||||
|
||||
config = builtins.removeAttrs config [ "assertions" "warnings" ];
|
||||
}))
|
||||
in
|
||||
result.config
|
||||
|
|
|
@ -0,0 +1,435 @@
|
|||
{ config, pkgs, lib, self, ... }:
|
||||
|
||||
let
|
||||
mainServers = [ "server1" "server2" ];
|
||||
pillar = self.lib.saltPillarFor "*";
|
||||
|
||||
renameAttr = from: to: attrset:
|
||||
builtins.foldl' (result: name:
|
||||
if name == from
|
||||
then result // { "${to}" = attrset.${name}; }
|
||||
else result // { "${name}" = attrset.${name}; }
|
||||
) {} (builtins.attrNames attrset);
|
||||
|
||||
# HACK: `type = "phys"` works but once an LXC container is stopped
|
||||
# the VLAN interface is not moved back.
|
||||
forceVeth = interface: interface // {
|
||||
type = "veth";
|
||||
};
|
||||
|
||||
netHasDHCP = net:
|
||||
net == "pub" ||
|
||||
net == "serv" ||
|
||||
builtins.match "priv[[:digit:]]+" net != null;
|
||||
in
|
||||
{
|
||||
options.salt-pillar = lib.mkOption {};
|
||||
config.salt-pillar = pillar;
|
||||
|
||||
config.site.net = lib.mkMerge ([
|
||||
(builtins.mapAttrs (_: vlan: { vlan = vlan; }) pillar.vlans)
|
||||
(builtins.mapAttrs (_: subnet4: { inherit subnet4; }) pillar.subnets-inet)
|
||||
(builtins.mapAttrs (_: hosts4: { inherit hosts4; }) pillar.hosts-inet)
|
||||
(builtins.mapAttrs (net: dhcpData: {
|
||||
dhcp = {
|
||||
inherit (dhcpData) start end time max-time;
|
||||
server =
|
||||
if netHasDHCP net
|
||||
then "${net}-gw"
|
||||
else null;
|
||||
fixed-hosts =
|
||||
if dhcpData ? fixed-hosts
|
||||
then dhcpData.fixed-hosts
|
||||
else {};
|
||||
router = dhcpData.host-opts.routers;
|
||||
};
|
||||
domainName = dhcpData.string-opts.domain-name;
|
||||
}) pillar.dhcp)
|
||||
{
|
||||
core.ospf.secret = pillar.ospf.secret;
|
||||
pub.dynamicDomain = true;
|
||||
|
||||
c3d2.dynamicDomain = true;
|
||||
c3d2.dhcp = {
|
||||
server = "c3d2-gw3";
|
||||
router = "c3d2-anon";
|
||||
start = "172.22.99.100";
|
||||
end = "172.22.99.199";
|
||||
fixed-hosts = {
|
||||
"astron.hq.c3d2.de" = "aa:00:5b:08:f0:5b";
|
||||
"astrom.hq.c3d2.de" = "aa:00:5b:08:f0:5c";
|
||||
"www1.hq.c3d2.de" = "aa:00:13:8b:03:47";
|
||||
"dn42.hq.c3d2.de" = "aa:00:42:7a:32:46";
|
||||
"icq.hq.c3d2.de" = "aa:00:30:f6:27:89";
|
||||
"jabber1.hq.c3d2.de" = "aa:00:0b:19:8f:14";
|
||||
"jabber2.hq.c3d2.de" = "aa:00:3d:6a:23:b8";
|
||||
"wiefelspuetz.hq.c3d2.de" = "aa:00:7f:01:8a:d0";
|
||||
"git.hq.c3d2.de" = "aa:00:47:d8:57:10";
|
||||
"fernandopoo.hq.c3d2.de" = "aa:00:f7:52:85:27";
|
||||
"moleflap.hq.c3d2.de" = "aa:00:0d:b1:6c:67";
|
||||
"wormhole.hq.c3d2.de" = "00:23:c3:d2:00:76";
|
||||
"sharing.hq.c3d2.de" = "00:23:c3:d2:75:18";
|
||||
"drucker.hq.c3d2.de" = "00:23:c3:d2:12:0f";
|
||||
"knot.hq.c3d2.de" = "52:54:cf:fd:ce:3f";
|
||||
"bender.hq.c3de.de" = "00:23:df:7e:c8:0a";
|
||||
"sofafon.hq.c3d2.de" = "b8:27:eb:23:8d:01";
|
||||
"schalter.hq.c3d2.de" = "b8:27:eb:4c:be:ff";
|
||||
"beere.hq.c3d2.de" = "b8:27:eb:ac:65:d2";
|
||||
"ledball1.hq.c3d2.de" = "b8:27:eb:53:0b:27";
|
||||
"cider.hq.c3d2.de" = "00:0d:93:75:ee:fa";
|
||||
"semanta.hq.c3d2.de" = "00:ff:e4:bb:ea:2a";
|
||||
"leviathan.hq.c3d2.de" = "00:ff:08:31:db:e5";
|
||||
"beere2.hq.c3d2.de" = "b8:27:eb:53:0b:27";
|
||||
"feile.hq.c3d2.de" = "aa:00:5b:12:c1:f7";
|
||||
"matemat.hq.c3d2.de" = "a2:1b:7c:e8:19:72";
|
||||
"172.22.99.98" = "08:00:27:aa:90:e2";
|
||||
"172.22.99.96" = "08:00:27:bb:8c:b3";
|
||||
"batman.hq.c3d2.de" = "5c:cf:7f:c0:05:28";
|
||||
"monit.hq.c3d2.de" = "00:23:ae:94:e7:19";
|
||||
"storage2.hq.c3d2.de" = "42:5e:0f:4e:f3:cc";
|
||||
"server2.hq.c3d2.de" = "d0:67:e5:f3:57:10";
|
||||
"server3.hq.c3d2.de" = "e4:1f:13:2e:4f:c0";
|
||||
"server4.hq.c3d2.de" = "00:9c:02:a9:26:01";
|
||||
"minecraft.hq.c3d2.de" = "4a:57:d3:64:fe:e9";
|
||||
"ustriper.hq.c3d2.de" = "aa:bb:95:33:bb:aa";
|
||||
"lisbeth.hq.c3d2.de" = "b8:27:eb:a5:ee:5c";
|
||||
"ruststripe1.hq.c3d2.de" = "06:32:0e:39:21:69";
|
||||
"fhem.hq.c3d2.de" = "b8:27:eb:9e:8b:db";
|
||||
"glotzbert.hq.c3d2.de" = "ec:a8:6b:fe:b4:cb";
|
||||
"pulsebert.hq.c3d2.de" = "b8:27:eb:16:31:61";
|
||||
"dacbert.hq.c3d2.de" = "dc:a6:32:31:b6:32";
|
||||
"public-access-proxy.hq.c3d2.de" = "12:24:5f:bd:9b:e7";
|
||||
"marenz-build.hq.c3d2.de" = "44:1e:a1:59:2e:e8";
|
||||
"ledbeere.hq.c3d2.de" = "b8:27:eb:60:99:59";
|
||||
};
|
||||
time = 86400;
|
||||
max-time = 30 * 86400;
|
||||
};
|
||||
}
|
||||
|
||||
# net priv* settings
|
||||
(
|
||||
builtins.mapAttrs (netName: _: {
|
||||
dynamicDomain = true;
|
||||
}) (
|
||||
lib.filterAttrs (netName: _:
|
||||
builtins.match "priv[[:digit:]]+" netName != null
|
||||
) pillar.hosts-inet
|
||||
)
|
||||
)
|
||||
] ++ (
|
||||
map (ctx:
|
||||
builtins.mapAttrs (_: subnet: { subnets6.${ctx} = subnet; }) pillar.subnets-inet6.${ctx}
|
||||
) (builtins.attrNames pillar.subnets-inet6)
|
||||
) ++ (
|
||||
map (ctx:
|
||||
builtins.mapAttrs (_: subnet: { hosts6.${ctx} = subnet; }) pillar.hosts-inet6.${ctx}
|
||||
) (builtins.attrNames pillar.hosts-inet6)
|
||||
));
|
||||
|
||||
config.site.hosts = lib.mkMerge (
|
||||
[
|
||||
{ # Static definitions
|
||||
|
||||
mgmt-gw.firewall.enable = true;
|
||||
priv13-gw.firewall.enable = true;
|
||||
|
||||
dns.services.dns.enable = true;
|
||||
|
||||
dnscache = {
|
||||
role = "container";
|
||||
|
||||
interfaces.serv = {
|
||||
gw4 = "serv-gw";
|
||||
gw6 = "serv-gw";
|
||||
type = "veth";
|
||||
};
|
||||
|
||||
services.dnscache.enable = true;
|
||||
};
|
||||
|
||||
upstream1.interfaces.up1.upstream = {
|
||||
provider = "vodafone";
|
||||
staticIpv4Address = "24.134.104.53";
|
||||
noNat.subnets6 = [
|
||||
"2a02:8106:208:5200::/56"
|
||||
];
|
||||
};
|
||||
upstream2.interfaces.up2.upstream = {
|
||||
provider = "vodafone";
|
||||
noNat.subnets6 = [
|
||||
"2a02:8106:208:e900::/56"
|
||||
];
|
||||
};
|
||||
upstream3.interfaces.up3.upstream.provider = "starlink";
|
||||
upstream4.interfaces.up4-pppoe = {
|
||||
type = "pppoe";
|
||||
upstream = {
|
||||
provider = "dsi";
|
||||
link = "up4";
|
||||
staticIpv4Address = "81.201.149.152";
|
||||
upBandwidth = 98000;
|
||||
noNat.subnets6 = [
|
||||
"2a00:8180:2000:37::1/128"
|
||||
"2a00:8180:2c00:200::/56"
|
||||
];
|
||||
};
|
||||
};
|
||||
upstream1.ospf.upstreamInstance = 3;
|
||||
upstream2.ospf.upstreamInstance = 4;
|
||||
anon1.ospf.upstreamInstance = 5;
|
||||
freifunk.ospf.upstreamInstance = 6;
|
||||
upstream3.ospf.upstreamInstance = 7;
|
||||
upstream4.ospf.upstreamInstance = 8;
|
||||
c3d2-gw1.ospf.allowedUpstreams = [ "upstream3" "upstream4" "upstream1" "anon1" "freifunk" ];
|
||||
c3d2-gw2.ospf.allowedUpstreams = [ "upstream1" "upstream3" "upstream4" "anon1" "freifunk" ];
|
||||
c3d2-gw3.ospf.allowedUpstreams = [ "upstream4" "upstream3" "upstream1" "anon1" "freifunk" ];
|
||||
serv-gw.ospf.allowedUpstreams = [ "upstream4" "upstream1" "upstream3" "anon1" "freifunk" ];
|
||||
cls-gw.ospf.allowedUpstreams = [ "upstream4" "upstream1" "upstream3" "anon1" "freifunk" ];
|
||||
mgmt-gw.ospf.allowedUpstreams = [ "upstream4" "upstream1" "upstream3" "anon1" "freifunk" ];
|
||||
bgp.ospf.allowedUpstreams = [ "upstream4" "upstream1" "upstream3" "anon1" "freifunk" ];
|
||||
anon1.ospf.allowedUpstreams = [ "upstream1" "upstream3" "upstream4" "freifunk" ];
|
||||
priv17-gw-up3.ospf.allowedUpstreams = [ "upstream3" "upstream4" "upstream1" "anon1" "freifunk" ];
|
||||
|
||||
pub-gw.ospf.allowedUpstreams = [ "anon1" "freifunk" ];
|
||||
c3d2-anon.ospf.allowedUpstreams = [ "anon1" "freifunk" ];
|
||||
|
||||
upstream4.forwardPorts = [
|
||||
{
|
||||
destination = config.site.net.serv.hosts4.public-access-proxy;
|
||||
proto = "tcp";
|
||||
sourcePort = 80;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.serv.hosts4.public-access-proxy;
|
||||
proto = "tcp";
|
||||
sourcePort = 443;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.serv.hosts4.bind;
|
||||
proto = "tcp";
|
||||
sourcePort = 53;
|
||||
reflect = false;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.serv.hosts4.bind;
|
||||
proto = "udp";
|
||||
sourcePort = 53;
|
||||
reflect = false;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.c3d2.hosts4.dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2325;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.c3d2.hosts4.dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2399;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.c3d2.hosts4.dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2327;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.c3d2.hosts4.dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2338;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.c3d2.hosts4.dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 2339;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.c3d2.hosts4.dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 40533;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.c3d2.hosts4.dn42;
|
||||
proto = "udp";
|
||||
sourcePort = 61699;
|
||||
}
|
||||
{
|
||||
destination = "${config.site.net.serv.hosts4.leonos}:22";
|
||||
proto = "tcp";
|
||||
sourcePort = 2223;
|
||||
}
|
||||
{
|
||||
destination = config.site.net.serv.hosts4.minetest;
|
||||
proto = "udp";
|
||||
sourcePort = 30000;
|
||||
}
|
||||
{
|
||||
destination = "172.22.99.175:22";
|
||||
proto = "tcp";
|
||||
sourcePort = 2224;
|
||||
}
|
||||
{ # Gitea ssh
|
||||
destination = config.site.net.serv.hosts4.gitea;
|
||||
proto = "tcp";
|
||||
sourcePort = 22;
|
||||
}
|
||||
{ # Jabber C2S
|
||||
destination = config.site.net.serv.hosts4.jabber;
|
||||
proto = "tcp";
|
||||
sourcePort = 5222;
|
||||
}
|
||||
{ # Jabber C2S+SSL
|
||||
destination = config.site.net.serv.hosts4.jabber;
|
||||
proto = "tcp";
|
||||
sourcePort = 5223;
|
||||
}
|
||||
{ # Jabber S2S
|
||||
destination = config.site.net.serv.hosts4.jabber;
|
||||
proto = "tcp";
|
||||
sourcePort = 5269;
|
||||
}
|
||||
{ # Jabber TURN
|
||||
destination = config.site.net.serv.hosts4.jabber;
|
||||
proto = "tcp";
|
||||
sourcePort = 3478;
|
||||
}
|
||||
{ # Jabber TURN
|
||||
destination = config.site.net.serv.hosts4.jabber;
|
||||
proto = "tcp";
|
||||
sourcePort = 3479;
|
||||
}
|
||||
{ # Jabber TURN
|
||||
destination = config.site.net.serv.hosts4.jabber;
|
||||
proto = "udp";
|
||||
sourcePort = 3478;
|
||||
}
|
||||
{ # Jabber TURN
|
||||
destination = config.site.net.serv.hosts4.jabber;
|
||||
proto = "udp";
|
||||
sourcePort = 3479;
|
||||
}
|
||||
{
|
||||
destination = "${config.site.net.serv.hosts4.vps1}:22";
|
||||
proto = "tcp";
|
||||
sourcePort = 2225;
|
||||
}
|
||||
] ++ map (port: {
|
||||
destination = config.site.net.serv.hosts4.mail;
|
||||
proto = "tcp";
|
||||
sourcePort = port;
|
||||
}) [ 25 465 587 110 143 993 995 ];
|
||||
}
|
||||
|
||||
# host priv*-gw settings
|
||||
(
|
||||
builtins.mapAttrs (hostName: _: {
|
||||
ospf.allowedUpstreams = [ "upstream4" "upstream3" "upstream1" "anon1" "freifunk" ];
|
||||
}) (
|
||||
lib.filterAttrs (hostName: _:
|
||||
builtins.match "priv[[:digit:]]+-gw" hostName != null
|
||||
) pillar.containers
|
||||
)
|
||||
)
|
||||
|
||||
(builtins.foldl' (result: hostName: result // {
|
||||
"${hostName}" = {
|
||||
role = "server";
|
||||
interfaces = builtins.mapAttrs (net: _: {
|
||||
type = "phys";
|
||||
} // lib.optionalAttrs (net == "cluster") {
|
||||
gw4 = "cls-gw";
|
||||
gw6 = "cls-gw";
|
||||
}) (
|
||||
lib.filterAttrs (_: hosts: hosts ? ${hostName}) (
|
||||
pillar.hosts-inet // (
|
||||
builtins.foldl' (result: hosts: result // hosts) {} (builtins.attrValues pillar.hosts-inet6)
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
}) {} mainServers)
|
||||
|
||||
(builtins.mapAttrs (_: switch: {
|
||||
inherit (switch) model location password;
|
||||
role = "switch";
|
||||
}) pillar.switches)
|
||||
|
||||
(builtins.mapAttrs (_: ap: {
|
||||
inherit (ap) model location password;
|
||||
role = "ap";
|
||||
}) pillar.cpe)
|
||||
|
||||
(builtins.mapAttrs (name: container:
|
||||
let
|
||||
ctPillar = self.lib.saltPillarFor name;
|
||||
in {
|
||||
role = "container";
|
||||
|
||||
interfaces =
|
||||
builtins.mapAttrs (net: interface:
|
||||
renameAttr "gw" "gw4"
|
||||
(forceVeth interface) // (
|
||||
if ctPillar ? upstream &&
|
||||
ctPillar.upstream.interface == net
|
||||
then {
|
||||
upstream.upBandwidth = ctPillar.upstream.up-bandwidth;
|
||||
}
|
||||
else {}
|
||||
)
|
||||
) container.interfaces;
|
||||
|
||||
wireguard =
|
||||
lib.optionalAttrs (ctPillar ? wireguard-instances) (
|
||||
builtins.mapAttrs (net: wgData: {
|
||||
inherit (builtins.head wgData.peers) endpoint;
|
||||
publicKey = (builtins.head wgData.peers).public_key;
|
||||
privateKey = wgData.private_key;
|
||||
addresses = builtins.filter builtins.isString (
|
||||
builtins.split "[, ]+" wgData.addr
|
||||
);
|
||||
upBandwidth = ctPillar.upstream.up-bandwidth;
|
||||
}) ctPillar.wireguard-instances);
|
||||
|
||||
ospf =
|
||||
let
|
||||
ospfConf = ctPillar.ospf;
|
||||
in lib.optionalAttrs (ctPillar ? ospf && ospfConf ? stubnets-inet) {
|
||||
stubNets4 = ospfConf.stubnets-inet;
|
||||
} // lib.optionalAttrs (ctPillar ? ospf && ospfConf ? stubnets-inet6) {
|
||||
stubNets6 = ospfConf.stubnets-inet6;
|
||||
};
|
||||
|
||||
bgp =
|
||||
if ctPillar ? bgp
|
||||
then
|
||||
let
|
||||
bgpConf = ctPillar.bgp;
|
||||
in {
|
||||
inherit (bgpConf) asn;
|
||||
peers = bgpConf.peers-inet // bgpConf.peers-inet6;
|
||||
}
|
||||
else null;
|
||||
|
||||
forwardPorts =
|
||||
if ctPillar ? port-forwarding
|
||||
then map ({ proto, port, to }: {
|
||||
proto = proto;
|
||||
sourcePort = port;
|
||||
destination = to;
|
||||
}) ctPillar.port-forwarding
|
||||
else [];
|
||||
}) pillar.containers)
|
||||
] ++
|
||||
|
||||
(map (net:
|
||||
builtins.mapAttrs (_: addr4: {
|
||||
}) pillar.hosts-inet.${net}
|
||||
) (builtins.attrNames pillar.hosts-inet)) ++
|
||||
|
||||
(builtins.concatMap (ctx:
|
||||
map (net:
|
||||
builtins.mapAttrs (_: addr6: {
|
||||
}) pillar.hosts-inet6.${ctx}.${net}
|
||||
) (builtins.attrNames pillar.hosts-inet6.${ctx})
|
||||
) (builtins.attrNames pillar.hosts-inet6))
|
||||
);
|
||||
}
|
|
@ -2,71 +2,6 @@
|
|||
|
||||
with lib;
|
||||
let
|
||||
# A host needs to know a network if it
|
||||
# - is a configured interface, or
|
||||
# - is required behind at least two different links
|
||||
getHostLinkNetworks = hostName: link:
|
||||
let
|
||||
hostConfig = config.site.hosts.${hostName};
|
||||
# all the host's links
|
||||
hostLinkNetworks = builtins.mapAttrs (link: _:
|
||||
networksBehindLink hostName link
|
||||
) hostConfig.links;
|
||||
# how many links have a net in networksBehindLink
|
||||
networkLinkCount = net:
|
||||
builtins.length (
|
||||
builtins.filter (builtins.elem net)
|
||||
(builtins.attrValues hostLinkNetworks)
|
||||
);
|
||||
in
|
||||
# access port
|
||||
if config.site.net ? ${link}
|
||||
then [ link ]
|
||||
|
||||
# multiple vlans on this link
|
||||
else
|
||||
builtins.filter (net:
|
||||
# this port and local interface
|
||||
hostConfig.interfaces ? ${net}
|
||||
||
|
||||
# this port and another
|
||||
networkLinkCount net > 1
|
||||
) hostLinkNetworks.${link};
|
||||
|
||||
networksBehindLink = hostName: name:
|
||||
networksBehindLink' {
|
||||
"${hostName}" = true;
|
||||
} [ name ];
|
||||
|
||||
networksBehindLink' = seen: links:
|
||||
if links == []
|
||||
then
|
||||
# Done, result is the seen link names that are networks:
|
||||
builtins.filter (name:
|
||||
config.site.net ? ${name}
|
||||
) (builtins.attrNames seen)
|
||||
else
|
||||
let
|
||||
link = builtins.head links;
|
||||
seen' = seen // {
|
||||
"${link}" = true;
|
||||
};
|
||||
onlyUnseen = builtins.filter (link: ! seen' ? ${link});
|
||||
links' = builtins.tail links;
|
||||
in
|
||||
if config.site.hosts ? ${link}
|
||||
then networksBehindLink' seen' (builtins.filter (link: ! seen' ? ${link}) (
|
||||
links' ++ (
|
||||
builtins.attrNames config.site.hosts.${link}.interfaces
|
||||
) ++ (
|
||||
onlyUnseen (builtins.attrNames config.site.hosts.${link}.links)
|
||||
)
|
||||
))
|
||||
else if config.site.net ? ${link}
|
||||
then networksBehindLink' seen' links'
|
||||
|
||||
else throw "Link to invalid target ${link}";
|
||||
|
||||
dhcpOpts = {
|
||||
start = mkOption {
|
||||
description = "First IP address in pool";
|
||||
|
@ -102,7 +37,7 @@ let
|
|||
options = {
|
||||
vlan = mkOption {
|
||||
description = "VLAN tag number";
|
||||
type = with types; nullOr int;
|
||||
type = types.int;
|
||||
};
|
||||
subnet4 = mkOption {
|
||||
description = "v.w.x.y/z";
|
||||
|
@ -119,7 +54,6 @@ let
|
|||
if subnet4 != null && builtins.length s == 2
|
||||
then builtins.head s
|
||||
else null;
|
||||
description = "Don't set, use subnet4 instead!";
|
||||
};
|
||||
subnet4Len = mkOption {
|
||||
type = with types; nullOr types.int;
|
||||
|
@ -131,7 +65,6 @@ let
|
|||
if subnet4 != null && builtins.length s == 2
|
||||
then lib.toInt (elemAt s 1)
|
||||
else null;
|
||||
description = "Don't set, use subnet4 instead!";
|
||||
};
|
||||
subnets6 = mkOption {
|
||||
description = "IPv6 subnets w/o prefixlen (always 64)";
|
||||
|
@ -158,49 +91,16 @@ let
|
|||
type = with types; nullOr (submodule { options = dhcpOpts; });
|
||||
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 {
|
||||
description = "Domain name option";
|
||||
type = types.str;
|
||||
default = "${name}.zentralwerk.org";
|
||||
};
|
||||
extraRecords = mkOption {
|
||||
type = with types; listOf (submodule {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = str;
|
||||
};
|
||||
type = mkOption {
|
||||
type = enum [ "A" "AAAA" "MX" "SRV" "CNAME" "TXT" ];
|
||||
};
|
||||
data = mkOption {
|
||||
type = oneOf [ str (attrsOf (oneOf [ int str ])) ];
|
||||
};
|
||||
};
|
||||
});
|
||||
default = [];
|
||||
description = "Extraneous DNS records";
|
||||
default = "${name}.zentralwerk.dn42";
|
||||
};
|
||||
dynamicDomain = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Domain updated by DHCP server?";
|
||||
};
|
||||
mtu = mkOption {
|
||||
type = with types; nullOr int;
|
||||
default = null;
|
||||
};
|
||||
wifi.ieee80211rKey = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
Key between WiFi access points for Fast Transition
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -221,27 +121,14 @@ let
|
|||
type = with types; nullOr int;
|
||||
default = null;
|
||||
};
|
||||
noNat.subnets4 = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
description = "Do not NAT traffic from these public static subnets";
|
||||
};
|
||||
noNat.subnets6 = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
description = "Do not NAT66 traffic from these public static subnets";
|
||||
};
|
||||
user = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
};
|
||||
password = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
interfaceOpts = { ... }: {
|
||||
interfaceOpts = { name, ... }: {
|
||||
options = {
|
||||
hwaddr = mkOption {
|
||||
type = with types; nullOr str;
|
||||
|
@ -249,7 +136,7 @@ let
|
|||
description = "Static MAC address";
|
||||
};
|
||||
type = mkOption {
|
||||
type = types.enum [ "phys" "veth" "pppoe" "bridge" "wireguard" "vxlan" ];
|
||||
type = types.enum [ "phys" "veth" "pppoe" ];
|
||||
description = ''
|
||||
veth: Virtual ethernet to be attached to a bridge.
|
||||
|
||||
|
@ -273,35 +160,6 @@ let
|
|||
default = null;
|
||||
description = "Upstream interface configuration";
|
||||
};
|
||||
wireguard = mkOption {
|
||||
default = null;
|
||||
type = with types; nullOr (submodule {
|
||||
options = {
|
||||
endpoint = mkOption {
|
||||
type = str;
|
||||
};
|
||||
publicKey = mkOption {
|
||||
type = str;
|
||||
};
|
||||
privateKey = mkOption {
|
||||
type = str;
|
||||
};
|
||||
addresses = mkOption {
|
||||
type = listOf str;
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
vxlan = mkOption {
|
||||
default = null;
|
||||
type = with types; nullOr (submodule {
|
||||
options = {
|
||||
peer = mkOption {
|
||||
type = str;
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -314,13 +172,6 @@ let
|
|||
Include the container system in the server's `build-container` script.
|
||||
'';
|
||||
};
|
||||
firstboot = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
true if host is a newly flashed OpenWRT device with a default address
|
||||
'';
|
||||
};
|
||||
role = mkOption {
|
||||
type = types.enum [ "ap" "switch" "server" "container" "client" ];
|
||||
default = "client";
|
||||
|
@ -360,8 +211,7 @@ let
|
|||
# isRouter = Part of the core network?
|
||||
default =
|
||||
config.site.hosts.${name}.interfaces ? core &&
|
||||
config.site.net.core.hosts4 ? ${name} &&
|
||||
config.site.hosts.${name}.role == "container";
|
||||
config.site.net.core.hosts4 ? ${name};
|
||||
description = "Should this host route?";
|
||||
};
|
||||
firewall.enable = mkOption {
|
||||
|
@ -412,16 +262,35 @@ let
|
|||
default = [];
|
||||
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 {
|
||||
type = with types; nullOr int;
|
||||
default = null;
|
||||
description = "OSPF instance for advertising the default route";
|
||||
};
|
||||
wireguard = mkOption {
|
||||
default = {};
|
||||
type = with types; attrsOf (submodule (
|
||||
{ name, ... }: {
|
||||
options = {
|
||||
endpoint = mkOption {
|
||||
type = str;
|
||||
};
|
||||
publicKey = mkOption {
|
||||
type = str;
|
||||
};
|
||||
privateKey = mkOption {
|
||||
type = str;
|
||||
};
|
||||
addresses = mkOption {
|
||||
type = listOf str;
|
||||
};
|
||||
upBandwidth = mkOption {
|
||||
type = with types; nullOr int;
|
||||
};
|
||||
};
|
||||
}
|
||||
));
|
||||
};
|
||||
bgp = mkOption {
|
||||
default = null;
|
||||
type = with types; nullOr (submodule {
|
||||
|
@ -438,81 +307,6 @@ let
|
|||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
links = mkOption {
|
||||
description = "Which port is connected to what other device? Keys are either network names or known hostnames.";
|
||||
default = {};
|
||||
type = with types; attrsOf (submodule (linkOpts name));
|
||||
};
|
||||
wifi = mkOption {
|
||||
default = {};
|
||||
type = with types; attrsOf (submodule (
|
||||
{ config, ... }: {
|
||||
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 {
|
||||
type = enum [ "HT20" "HT40-" "HT40+" "HT40" "VHT80" ];
|
||||
};
|
||||
channel = mkOption {
|
||||
type = int;
|
||||
};
|
||||
ssids = mkOption {
|
||||
type = attrsOf (submodule ({ config, ... }: {
|
||||
options = {
|
||||
net = mkOption {
|
||||
type = str;
|
||||
};
|
||||
psk = mkOption {
|
||||
type = nullOr str;
|
||||
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 {
|
||||
type = enum [ "ap" "sta" ];
|
||||
default = "ap";
|
||||
};
|
||||
ifname = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
};
|
||||
disassocLowAck = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Disable for wireless bridges.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
}
|
||||
));
|
||||
};
|
||||
wifiOnLink.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Install the wifi-on-link.sh script on OpenWRT devices.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -521,7 +315,7 @@ let
|
|||
type = types.int;
|
||||
};
|
||||
peers = mkOption {
|
||||
type = with types; attrsOf (submodule ({ ... }: {
|
||||
type = with types; attrsOf (submodule ({ name, ... }: {
|
||||
options = {
|
||||
asn = mkOption {
|
||||
type = types.int;
|
||||
|
@ -531,70 +325,6 @@ let
|
|||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
linkOpts = hostName: { name, ... }: {
|
||||
options = {
|
||||
ports = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "Port names";
|
||||
};
|
||||
group = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = "Link aggregation group with a fixed number";
|
||||
};
|
||||
nets = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "Automatically generated";
|
||||
default = getHostLinkNetworks hostName name;
|
||||
};
|
||||
vlans = mkOption {
|
||||
type = with types; listOf int;
|
||||
description = "Automatically generated, do not set";
|
||||
default = builtins.concatMap (net:
|
||||
let
|
||||
inherit (config.site.net.${net}) vlan;
|
||||
in if vlan != null
|
||||
then [ vlan ]
|
||||
else []
|
||||
) config.site.hosts.${hostName}.links.${name}.nets;
|
||||
};
|
||||
trunk = mkOption {
|
||||
type = types.bool;
|
||||
description = "Trunk with tagged VLANs?";
|
||||
default =
|
||||
if config.site.net ? ${name}
|
||||
then false
|
||||
else if config.site.hosts ? ${name}
|
||||
then true
|
||||
else throw "Invalid link target: \"${name}\"";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
options.site = {
|
||||
|
@ -603,38 +333,11 @@ in
|
|||
default = {};
|
||||
type = with types; attrsOf (submodule netOpts);
|
||||
};
|
||||
|
||||
|
||||
hosts = mkOption {
|
||||
description = "All the static hosts";
|
||||
default = {};
|
||||
type = with types; attrsOf (submodule hostOpts);
|
||||
};
|
||||
|
||||
sshPubKeys = mkOption {
|
||||
type = with types; listOf str;
|
||||
};
|
||||
|
||||
dyndnsKey = mkOption {
|
||||
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 =
|
||||
|
@ -669,136 +372,8 @@ in
|
|||
else []
|
||||
) (builtins.attrNames config.site.hosts);
|
||||
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 "IPv6 subnet" (x: builtins.attrValues x.subnets6) config.site.net) ++
|
||||
ospfUpstreamXorGw;
|
||||
|
||||
config.assertions =
|
||||
# Duplicate host/net name check
|
||||
map (name: {
|
||||
assertion = ! config.site.net ? ${name};
|
||||
message = "Host \"${name}\" must be named differently if net \"${name}\" exists.";
|
||||
}) (builtins.attrNames config.site.hosts)
|
||||
++
|
||||
# Duplicate address check
|
||||
(let
|
||||
addrHosts =
|
||||
builtins.foldl' (result: { hosts4, ... }:
|
||||
builtins.foldl' (result: host:
|
||||
let
|
||||
addr = hosts4.${host};
|
||||
in
|
||||
if result ? ${addr}
|
||||
then result // {
|
||||
"${addr}" = result.${addr} ++ [ host ];
|
||||
}
|
||||
else result // {
|
||||
"${addr}" = [ host ];
|
||||
}
|
||||
) result (builtins.attrNames hosts4)
|
||||
) {} (builtins.attrValues config.site.net)
|
||||
//
|
||||
builtins.foldl' (result: net:
|
||||
builtins.foldl' (result: ctx:
|
||||
builtins.foldl' (result: host:
|
||||
let
|
||||
addr = config.site.net.${net}.hosts6.${ctx}.${host};
|
||||
in
|
||||
if result ? ${addr}
|
||||
then result // {
|
||||
"${addr}" = result.${addr} ++ [ host ];
|
||||
}
|
||||
else result // {
|
||||
"${addr}" = [ host ];
|
||||
}
|
||||
) result (builtins.attrNames config.site.net.${net}.hosts6.${ctx})
|
||||
) result (builtins.attrNames config.site.net.${net}.hosts6)
|
||||
) {} (builtins.attrNames config.site.net);
|
||||
in map (addr: {
|
||||
assertion = builtins.length addrHosts.${addr} == 1;
|
||||
message = "Address ${addr} is assigned to more than one host: ${lib.concatStringsSep " " addrHosts.${addr}}";
|
||||
}) (builtins.attrNames addrHosts))
|
||||
++
|
||||
# duplicate vlan check
|
||||
(let
|
||||
vlanNets =
|
||||
builtins.foldl' (result: net:
|
||||
let
|
||||
vlan = toString config.site.net.${net}.vlan;
|
||||
in
|
||||
if config.site.net.${net}.vlan != null && result ? ${vlan}
|
||||
then result // {
|
||||
"${vlan}" = result.${vlan} ++ [ net ];
|
||||
}
|
||||
else result // {
|
||||
"${vlan}" = [ net ];
|
||||
}
|
||||
) {} (builtins.attrNames config.site.net);
|
||||
in map (vlan: {
|
||||
assertion = builtins.length vlanNets.${vlan} == 1;
|
||||
message = "VLAN ${vlan} is used by more than one network: ${lib.concatStringsSep " " vlanNets.${vlan}}";
|
||||
}) (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);
|
||||
}
|
||||
|
|
|
@ -1,32 +1,17 @@
|
|||
{ self, lib, openwrt, pkgs }:
|
||||
{ self, gpgKey, pkgs }:
|
||||
|
||||
rec {
|
||||
inherit (import ./config { inherit self pkgs; }) config;
|
||||
config = import ./config { inherit self pkgs gpgKey; };
|
||||
|
||||
saltPillarFor = import ./salt-support/salt-pillar.nix {
|
||||
inherit pkgs gpgKey;
|
||||
};
|
||||
|
||||
expandSaltTemplate = import ./salt-support/expand-template.nix { inherit pkgs; };
|
||||
|
||||
netmasks = import ./netmasks.nix;
|
||||
|
||||
subnet = import ./subnet { inherit pkgs; };
|
||||
|
||||
dns = import ./dns.nix { inherit config lib; };
|
||||
|
||||
openwrtModels = import ./openwrt-models.nix { inherit self openwrt; };
|
||||
|
||||
getOpenwrtModel = wantedModel:
|
||||
let
|
||||
models =
|
||||
builtins.filter ({ models, ... }:
|
||||
self.lib.any ({ model, vendor, ... }:
|
||||
model == wantedModel ||
|
||||
"${vendor}_${model}" == wantedModel
|
||||
) models
|
||||
) openwrtModels;
|
||||
result =
|
||||
builtins.foldl' (result: { data, ... }:
|
||||
self.lib.recursiveUpdate result data
|
||||
) {} models;
|
||||
in
|
||||
if builtins.length models > 0
|
||||
then result
|
||||
else builtins.trace "No data found for OpenWRT model ${wantedModel}"
|
||||
{};
|
||||
dns = import ./dns.nix { inherit pkgs config; };
|
||||
}
|
||||
|
|
123
nix/lib/dns.nix
123
nix/lib/dns.nix
|
@ -1,18 +1,15 @@
|
|||
{ config, lib }:
|
||||
{ pkgs, config }:
|
||||
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
in
|
||||
rec {
|
||||
ns = "dns.serv.zentralwerk.org";
|
||||
internalNS = [ ns ];
|
||||
# public servers (slaves)
|
||||
publicNS = [
|
||||
"ns.c3d2.de"
|
||||
"ns.spaceboyz.net"
|
||||
"ns1.supersandro.de"
|
||||
];
|
||||
|
||||
publicIPv4 = config.site.hosts.upstream4.interfaces.up4-pppoe.upstream.staticIpv4Address;
|
||||
|
||||
dynamicReverseZones4 = [
|
||||
publicNS = [ "ns.c3d2.de" "ns.spaceboyz.net" ];
|
||||
|
||||
dynamicReverseZones = [
|
||||
"73.20.172.in-addr.arpa"
|
||||
"74.20.172.in-addr.arpa"
|
||||
"75.20.172.in-addr.arpa"
|
||||
|
@ -21,25 +18,7 @@ rec {
|
|||
"78.20.172.in-addr.arpa"
|
||||
"79.20.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 =
|
||||
let
|
||||
|
@ -64,9 +43,8 @@ rec {
|
|||
);
|
||||
|
||||
# generate zones only for nets with hosts
|
||||
namedNets = lib.filterAttrs (_name: { hosts4, hosts6, dynamicDomain, ... }:
|
||||
hosts4 != {} ||
|
||||
hosts6 != {} ||
|
||||
namedNets = lib.filterAttrs (name: { hosts4, hosts6, dynamicDomain, ... }:
|
||||
(hosts4 != [] && hosts6 != []) ||
|
||||
dynamicDomain
|
||||
) config.site.net;
|
||||
|
||||
|
@ -99,7 +77,7 @@ rec {
|
|||
"${zone}" = true;
|
||||
}
|
||||
) {} (builtins.attrNames reverseHosts4)
|
||||
) ++ dynamicReverseZones4
|
||||
) ++ dynamicReverseZones
|
||||
);
|
||||
|
||||
# turns `::` into `0000:0000:0000:0000:0000:0000:0000:0000`
|
||||
|
@ -149,8 +127,10 @@ rec {
|
|||
let
|
||||
domain =
|
||||
if ctx == "dn42"
|
||||
then "${net}.zentralwerk.dn42"
|
||||
else namedNets.${net}.domainName;
|
||||
then namedNets.${net}.domainName
|
||||
else if builtins.match "up.*" ctx != null
|
||||
then "${net}.zentralwerk.org"
|
||||
else throw "Invalid IPv6 context: ${ctx}";
|
||||
in
|
||||
lib.recursiveUpdate result {
|
||||
"${ipv6ToReverse hosts.${host}}" = "${host}.${domain}";
|
||||
|
@ -160,79 +140,60 @@ rec {
|
|||
)) {} (builtins.attrNames namedNets);
|
||||
|
||||
# `{ dn42 = [ "....ip6.arpa" ]; }`
|
||||
reverseZones6 = builtins.mapAttrs (_ctx: reverseHosts6ctx:
|
||||
reverseZones6 = builtins.mapAttrs (ctx: reverseHosts6ctx:
|
||||
builtins.attrNames (
|
||||
builtins.foldl' (result: rname:
|
||||
result // {
|
||||
"${builtins.substring ((128 - reverseZone6Size) / 2) (72 - ((128 - reverseZone6Size) / 2)) rname}" = true;
|
||||
}) {} (builtins.attrNames reverseHosts6ctx)
|
||||
)
|
||||
builtins.foldl' (result: rname: result // {
|
||||
"${builtins.substring ((128 - reverseZone6Size) / 2) (72 - ((128 - reverseZone6Size) / 2)) rname}" = true;
|
||||
}) {} (builtins.attrNames reverseHosts6ctx)
|
||||
)
|
||||
) reverseHosts6;
|
||||
|
||||
in [ {
|
||||
name = "zentralwerk.org";
|
||||
ns = publicNS;
|
||||
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;
|
||||
} ];
|
||||
records = [];
|
||||
} {
|
||||
name = "zentralwerk.dn42";
|
||||
ns = internalNS;
|
||||
records = [ ];
|
||||
records = [ {
|
||||
name = "ipa";
|
||||
type = "A";
|
||||
data = config.site.net.serv.hosts4.ipa;
|
||||
} ];
|
||||
} {
|
||||
name = "dyn.zentralwerk.org";
|
||||
ns = publicNS;
|
||||
records = [ {
|
||||
name = "upstream4";
|
||||
name = "upstream1";
|
||||
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.mapAttrs (net: { dynamicDomain, hosts4, hosts6, extraRecords, ... }: [
|
||||
builtins.mapAttrs (net: { dynamicDomain, hosts4, hosts6, ... }: [
|
||||
{
|
||||
name = "${net}.zentralwerk.dn42";
|
||||
ns = internalNS;
|
||||
records =
|
||||
lib.optionals (hosts6 ? dn42) (hosts6Records hosts6.dn42) ++
|
||||
extraRecords;
|
||||
lib.optionals (hosts6 ? dn42) (hosts6Records hosts6.dn42);
|
||||
}
|
||||
{
|
||||
name = "${net}.zentralwerk.org";
|
||||
ns = publicNS;
|
||||
records =
|
||||
hosts4Records hosts4 ++
|
||||
lib.optionals (hosts6 ? up4) (hosts6Records hosts6.up4) ++
|
||||
lib.optionals (hosts6 ? flpk) (hosts6Records hosts6.flpk) ++
|
||||
extraRecords;
|
||||
lib.optionals (hosts6 ? up4) (hosts6Records hosts6.up4);
|
||||
dynamic = dynamicDomain;
|
||||
}
|
||||
]) namedNets
|
||||
)
|
||||
)
|
||||
++
|
||||
map (zone: {
|
||||
) ++ map (zone: {
|
||||
name = zone;
|
||||
ns =
|
||||
if isRfc1918Reverse zone
|
||||
then internalNS
|
||||
else publicNS;
|
||||
ns = internalNS;
|
||||
records =
|
||||
map (reverse: {
|
||||
name = builtins.head (
|
||||
|
@ -244,16 +205,17 @@ rec {
|
|||
builtins.filter (lib.hasSuffix ".${zone}")
|
||||
(builtins.attrNames reverseHosts4)
|
||||
);
|
||||
dynamic = builtins.elem zone dynamicReverseZones4;
|
||||
dynamic = builtins.elem zone dynamicReverseZones;
|
||||
}) reverseZones4
|
||||
++
|
||||
builtins.concatMap (ctx:
|
||||
++ builtins.concatMap (ctx:
|
||||
map (zone: {
|
||||
name = zone;
|
||||
ns =
|
||||
if ctx == "dn42"
|
||||
then internalNS
|
||||
else publicNS;
|
||||
else if builtins.match "up.*" ctx != null
|
||||
then publicNS
|
||||
else throw "Invalid IPv6 context: ${ctx}";
|
||||
records =
|
||||
map (reverse: {
|
||||
name = builtins.substring 0 ((128 - reverseZone6Size) / 2 - 1) reverse;
|
||||
|
@ -263,7 +225,6 @@ rec {
|
|||
builtins.filter (lib.hasSuffix ".${zone}")
|
||||
(builtins.attrNames reverseHosts6.${ctx})
|
||||
);
|
||||
dynamic = builtins.elem zone dynamicReverseZones6;
|
||||
}) reverseZones6.${ctx}
|
||||
) (builtins.attrNames reverseZones6);
|
||||
}
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
{ self, openwrt }:
|
||||
let
|
||||
# the files that contain port definitions
|
||||
defFiles = builtins.filter
|
||||
(self.lib.hasSuffix "/etc/board.d/02_network")
|
||||
(self.lib.filesystem.listFilesRecursive "${openwrt}/target/linux");
|
||||
# files contents as one string
|
||||
defSource = builtins.concatStringsSep "\n" (
|
||||
map builtins.readFile defFiles
|
||||
);
|
||||
defSourceLines = builtins.filter (s: s != []) (
|
||||
builtins.split "\n" (
|
||||
builtins.replaceStrings
|
||||
[ "\\\n" ] [ "" ] defSource
|
||||
));
|
||||
|
||||
parseCommand = line:
|
||||
let
|
||||
tokens =
|
||||
builtins.concatMap (frag:
|
||||
if builtins.isString frag
|
||||
then builtins.split "[[:space:]]+" frag
|
||||
else frag
|
||||
) (
|
||||
builtins.split "\"([^\"]*)\"" line
|
||||
);
|
||||
words =
|
||||
builtins.filter (word:
|
||||
word != [] && word != ""
|
||||
) tokens;
|
||||
command =
|
||||
if words != []
|
||||
then builtins.head words
|
||||
else "-";
|
||||
args =
|
||||
if words != []
|
||||
then builtins.tail words
|
||||
else [];
|
||||
|
||||
makeLinkFromArg = port: arg:
|
||||
builtins.foldl' (result: interface:
|
||||
if port != []
|
||||
then result // {
|
||||
"${port}" = {
|
||||
type = "phys";
|
||||
inherit interface port;
|
||||
};
|
||||
}
|
||||
else result
|
||||
) {} (builtins.split "[[:space:]]+" arg);
|
||||
|
||||
commands = {
|
||||
ucidef_add_switch.ports = builtins.foldl' (ports: arg:
|
||||
let
|
||||
switch = builtins.head args;
|
||||
m1 = builtins.match "([[:digit:]]+):(.+)" arg;
|
||||
m2 = builtins.match "([[:digit:]]+)([ut]?)@(.+)" arg;
|
||||
m2flag = builtins.elemAt m2 1;
|
||||
port = if m1 != null
|
||||
then {
|
||||
inherit switch;
|
||||
type = "port";
|
||||
index = builtins.elemAt m1 0;
|
||||
port = builtins.elemAt m1 1;
|
||||
}
|
||||
else if m2 != null
|
||||
then {
|
||||
inherit switch;
|
||||
type = "host";
|
||||
index = builtins.elemAt m2 0;
|
||||
interface = builtins.elemAt m2 2;
|
||||
} // self.lib.optionalAttrs (m2flag == "u") {
|
||||
only = "untagged";
|
||||
} // self.lib.optionalAttrs (m2flag == "t") {
|
||||
only = "tagged";
|
||||
}
|
||||
else throw "Unimplemented port scheme: ${arg}";
|
||||
in if m1 != null || m2 != null
|
||||
then ports // {
|
||||
"${port.index}" = port;
|
||||
}
|
||||
else builtins.trace "Unimplemented port scheme: ${arg}" ports
|
||||
) {} (builtins.tail args);
|
||||
|
||||
ucidef_set_interface_wan.ports = {
|
||||
"${builtins.head args}" = {
|
||||
type = "phys";
|
||||
interface = builtins.head args;
|
||||
port = "wan";
|
||||
};
|
||||
};
|
||||
|
||||
ucidef_set_interface_lan.ports =
|
||||
makeLinkFromArg "lan" (builtins.elemAt args 0);
|
||||
|
||||
ucidef_set_interfaces_lan_wan.ports =
|
||||
makeLinkFromArg "lan" (builtins.elemAt args 0) //
|
||||
self.lib.optionalAttrs (builtins.length args > 1) (
|
||||
makeLinkFromArg "wan" (builtins.elemAt args 1)
|
||||
);
|
||||
};
|
||||
in
|
||||
if commands ? ${command}
|
||||
then commands.${command}
|
||||
else {
|
||||
unknown."${command}" = args;
|
||||
};
|
||||
|
||||
in (
|
||||
builtins.foldl' ({ state, result, models ? null, data ? {} }: line:
|
||||
if state == "start"
|
||||
then
|
||||
if builtins.match "[[:space:]]*case \"?\\$board\"? in" line != null
|
||||
then { state = "case"; inherit result; }
|
||||
else { inherit state result; }
|
||||
|
||||
else if state == "case"
|
||||
then
|
||||
if builtins.match "[[:space:]]*esac" line != null
|
||||
then { state = "start"; inherit result; }
|
||||
else
|
||||
let
|
||||
m = builtins.match "[[:space:]]*(.+)\\)" line;
|
||||
in
|
||||
if m == null
|
||||
then { inherit state result; }
|
||||
else {
|
||||
inherit result;
|
||||
state = "model";
|
||||
models =
|
||||
builtins.filter (m: m != null) (
|
||||
map (s:
|
||||
let
|
||||
m = builtins.split "," s;
|
||||
in
|
||||
if s != [] &&
|
||||
m != null &&
|
||||
builtins.length m == 3
|
||||
then {
|
||||
vendor = builtins.elemAt m 0;
|
||||
model = builtins.elemAt m 2;
|
||||
}
|
||||
else null
|
||||
) (
|
||||
builtins.split "[[:space:]]*\\|[[:space:]]*" (
|
||||
builtins.head m
|
||||
)));
|
||||
}
|
||||
|
||||
else if state == "model"
|
||||
then
|
||||
if builtins.match "[[:space:]]*;;" line != null
|
||||
then {
|
||||
state = "case";
|
||||
result = result ++ [ {
|
||||
inherit models data;
|
||||
} ];
|
||||
}
|
||||
else {
|
||||
inherit result state models;
|
||||
data = self.lib.recursiveUpdate data (parseCommand line);
|
||||
}
|
||||
|
||||
else throw "Invalid state ${state}"
|
||||
) { state = "start"; result = []; } defSourceLines
|
||||
).result
|
|
@ -0,0 +1,23 @@
|
|||
{ pkgs ? import <nixpkgs> {}
|
||||
}:
|
||||
|
||||
name: template: data:
|
||||
let
|
||||
jsonFile =
|
||||
builtins.toFile "data.json" (builtins.toJSON data);
|
||||
j2custom =
|
||||
builtins.toFile "j2custom.py" ''
|
||||
def j2_environment(env):
|
||||
env.globals.update(
|
||||
zip=zip
|
||||
)
|
||||
return env
|
||||
'';
|
||||
in
|
||||
pkgs.runCommandLocal name {
|
||||
nativeBuildInputs = with pkgs; [
|
||||
pythonPackages.j2cli yaml2json
|
||||
];
|
||||
} ''
|
||||
j2 --customize ${j2custom} -f json ${template} ${jsonFile} > $out
|
||||
''
|
|
@ -0,0 +1,47 @@
|
|||
{ pkgs ? import <nixpkgs> {}
|
||||
, gpgKey
|
||||
}:
|
||||
|
||||
with pkgs.lib;
|
||||
let
|
||||
loadYaml = import ./load-yaml.nix { inherit pkgs; };
|
||||
|
||||
decryptMessage = x:
|
||||
if gpgKey == null
|
||||
then "encrypted"
|
||||
else
|
||||
builtins.readFile (
|
||||
pkgs.runCommandLocal "decrypted-salt-value" {
|
||||
nativeBuildInputs = [ pkgs.gnupg ];
|
||||
} ''
|
||||
export GNUPGHOME=$(mktemp -d)
|
||||
gpg --import ${gpgKey}
|
||||
gpg -d > $out << EOF
|
||||
${x}
|
||||
EOF
|
||||
''
|
||||
);
|
||||
|
||||
decrypt = x:
|
||||
if builtins.isString x
|
||||
then if builtins.substring 0 27 x == "-----BEGIN PGP MESSAGE-----"
|
||||
then decryptMessage x
|
||||
else x
|
||||
else if builtins.isList x
|
||||
then map decrypt x
|
||||
else if builtins.isAttrs x
|
||||
then builtins.mapAttrs (_: decrypt) x
|
||||
else x;
|
||||
|
||||
loadSls = files:
|
||||
decrypt (
|
||||
builtins.foldl' (result: filename:
|
||||
recursiveUpdate result (loadYaml filename)
|
||||
) {} files
|
||||
);
|
||||
in
|
||||
|
||||
files:
|
||||
if builtins.isList files
|
||||
then loadSls files
|
||||
else loadSls [ files ]
|
|
@ -0,0 +1,17 @@
|
|||
{ pkgs ? import <nixpkgs> {}
|
||||
}:
|
||||
|
||||
path:
|
||||
let
|
||||
json = pkgs.runCommandLocal "desalinated-${builtins.baseNameOf path}" {
|
||||
nativeBuildInputs = with pkgs; [
|
||||
pythonPackages.j2cli ruby yaml2json
|
||||
];
|
||||
} ''
|
||||
j2 ${path} > expanded.yaml
|
||||
yaml2json < expanded.yaml > $out
|
||||
'';
|
||||
in
|
||||
builtins.fromJSON (
|
||||
builtins.readFile json
|
||||
)
|
|
@ -0,0 +1,66 @@
|
|||
{ pkgs ? import <nixpkgs> {}
|
||||
, ...
|
||||
}@args:
|
||||
|
||||
hostName:
|
||||
|
||||
let
|
||||
loadSls = import ./load-sls.nix args;
|
||||
|
||||
pillarBase = (loadSls ../../../salt-pillar/top.sls).base;
|
||||
|
||||
globToRegex = builtins.replaceStrings ["*"] [".*"];
|
||||
|
||||
baseMatches =
|
||||
if hostName == "*"
|
||||
then
|
||||
builtins.attrNames pillarBase
|
||||
else
|
||||
builtins.filter (patterns:
|
||||
pkgs.lib.any (pattern:
|
||||
builtins.match (globToRegex pattern) hostName != null
|
||||
) (
|
||||
builtins.filter builtins.isString (
|
||||
builtins.split " or " patterns
|
||||
)
|
||||
)
|
||||
) (builtins.attrNames pillarBase);
|
||||
|
||||
fileIds = builtins.foldl' (result: matchName:
|
||||
result ++ pillarBase.${matchName}
|
||||
) [] baseMatches;
|
||||
|
||||
allFilePaths = pkgs.lib.filesystem.listFilesRecursive ../../../salt-pillar;
|
||||
|
||||
files = map (fileId:
|
||||
let
|
||||
parts = builtins.filter builtins.isString (
|
||||
builtins.split "\\." fileId
|
||||
);
|
||||
matches = builtins.filter (filePath:
|
||||
let
|
||||
suffix1 = builtins.concatStringsSep "/" (parts ++ [ "init.sls" ]);
|
||||
suffix2 = (builtins.concatStringsSep "/" parts) + ".sls";
|
||||
check = suffix:
|
||||
endsWith suffix (builtins.toString filePath);
|
||||
in
|
||||
check suffix1 || check suffix2
|
||||
) allFilePaths;
|
||||
matchesLength = builtins.length matches;
|
||||
in
|
||||
if matchesLength == 0
|
||||
then throw "No pillar file for ${fileId}"
|
||||
else if matchesLength > 1
|
||||
then throw "Ambiguous choice of files for ${fileId}"
|
||||
else builtins.head matches
|
||||
) fileIds;
|
||||
|
||||
endsWith = suffix: s:
|
||||
let
|
||||
suffixLen = builtins.stringLength suffix;
|
||||
sLen = builtins.stringLength s;
|
||||
in
|
||||
builtins.substring (sLen - suffixLen) suffixLen s == suffix;
|
||||
|
||||
in
|
||||
loadSls files
|
|
@ -47,16 +47,7 @@ in
|
|||
Forward true
|
||||
Server "${config.site.net.serv.hosts4.spaceapi}" "${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") {
|
||||
plugins.network = ''
|
||||
Server "${config.site.net.serv.hosts6.dn42.stats}" "${toString networkPort}"
|
||||
|
@ -90,7 +81,7 @@ in
|
|||
Host "inbert.c3d2.de"
|
||||
Host "heise.de"
|
||||
'';
|
||||
}) (lib.optionalAttrs config.services.kea.dhcp4.enable {
|
||||
}) (lib.optionalAttrs config.services.dhcpd4.enable {
|
||||
plugins.exec =
|
||||
let
|
||||
maxTimeout = builtins.foldl' (maxTimeout: net:
|
||||
|
@ -104,8 +95,8 @@ in
|
|||
else maxTimeout
|
||||
) 180 (builtins.attrNames config.site.net);
|
||||
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 {
|
||||
plugins.exec = ''
|
||||
Exec "${execUser}" "${pkgs.ruby}/bin/ruby" "${./unbound.rb}"
|
||||
|
@ -115,29 +106,4 @@ in
|
|||
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";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,28 +1,36 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'csv'
|
||||
require 'date'
|
||||
|
||||
INTERVAL = 60
|
||||
TIMEOUT = ARGV[0].to_i # TODO: now unused
|
||||
hostname = CSV::readlines("/proc/sys/kernel/hostname").join.strip
|
||||
INTERVAL = 10
|
||||
TIMEOUT = ARGV[0].to_i
|
||||
hostname = IO::readlines("/proc/sys/kernel/hostname").join.strip
|
||||
STDOUT.sync = true
|
||||
|
||||
loop do
|
||||
seen = {}
|
||||
count = 0
|
||||
now = Time.now.to_i
|
||||
|
||||
CSV::readlines("/var/lib/kea/kea-leases4.csv", headers: true).each do |rec|
|
||||
h = rec.to_h
|
||||
addr = h["hwaddr"]
|
||||
next unless addr
|
||||
last = h["expire"].to_i
|
||||
elapsed = now - last
|
||||
next if elapsed >= TIMEOUT
|
||||
addr = nil
|
||||
starts = nil
|
||||
|
||||
unless seen[addr]
|
||||
count += 1
|
||||
seen[addr] = true
|
||||
IO::readlines("/var/lib/dhcp/dhcpd.leases").each do |line|
|
||||
if line =~ /^lease (.+) \{/
|
||||
addr = $1
|
||||
|
||||
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]
|
||||
count += 1
|
||||
seen[addr] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
puts "PUTVAL \"#{hostname}/exec-dhcpd/current_sessions-leases\" interval=#{INTERVAL} N:#{count}"
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# wireguard upstreams (like njalla and flpk, not like vpn dialup. see vpn-gw)
|
||||
{ hostName, config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
gateway = "upstream1";
|
||||
|
||||
tunnels = lib.filterAttrs (_: { wireguard, ... }:
|
||||
tunnels = lib.filterAttrs (_: wireguard:
|
||||
wireguard != null
|
||||
) config.site.hosts.${hostName}.interfaces;
|
||||
) config.site.hosts.${hostName}.wireguard;
|
||||
firstTunnel =
|
||||
if builtins.length (builtins.attrNames tunnels) > 0
|
||||
then builtins.head (builtins.attrNames tunnels)
|
||||
|
@ -16,7 +16,7 @@ let
|
|||
"/run/wireguard-keys/${ifName}.key";
|
||||
|
||||
wireguardMark = 3;
|
||||
vpnTable = 100;
|
||||
vpn4Table = 100;
|
||||
in
|
||||
{
|
||||
systemd.services = builtins.foldl' (services: ifName: services // {
|
||||
|
@ -33,7 +33,7 @@ in
|
|||
chown systemd-network:systemd-network $(dirname $F)
|
||||
rm -f $F
|
||||
cat >$F <<EOF
|
||||
${tunnels.${ifName}.wireguard.privateKey}
|
||||
${tunnels.${ifName}.privateKey}
|
||||
EOF
|
||||
chmod 0400 $F
|
||||
chown systemd-network:systemd-network $F
|
||||
|
@ -45,13 +45,14 @@ in
|
|||
pkgs.wireguard-tools
|
||||
];
|
||||
|
||||
systemd.network.netdevs = builtins.mapAttrs (ifName: { wireguard, ... }: {
|
||||
systemd.network.netdevs = builtins.mapAttrs (ifName: wireguard: {
|
||||
netdevConfig = {
|
||||
Name = ifName;
|
||||
Kind = "wireguard";
|
||||
};
|
||||
wireguardConfig = {
|
||||
PrivateKeyFile = privateKeyFile ifName;
|
||||
# Mark for routing with another routing table
|
||||
FirewallMark = wireguardMark;
|
||||
};
|
||||
wireguardPeers = [ {
|
||||
|
@ -67,13 +68,13 @@ in
|
|||
# Wireguard transported through another routing table
|
||||
# (containing upstream by bird ospf)
|
||||
core.routingPolicyRules = [ {
|
||||
# Marked wireguard packets take the vpn routing table
|
||||
# Marked wireguard packets take the vpn4 routing table
|
||||
routingPolicyRuleConfig = {
|
||||
Table = vpn4Table;
|
||||
FirewallMark = wireguardMark;
|
||||
Table = vpnTable;
|
||||
};
|
||||
} ];
|
||||
} // builtins.mapAttrs (ifName: { wireguard, upstream, ... }: {
|
||||
} // builtins.mapAttrs (ifName: wireguard: {
|
||||
# Wireguard interfaces
|
||||
matchConfig.Name = ifName;
|
||||
|
||||
|
@ -83,17 +84,17 @@ in
|
|||
|
||||
# IPv4 default route
|
||||
networkConfig.DefaultRouteOnDevice = true;
|
||||
# IPv6 default route
|
||||
routes = [ {
|
||||
# IPv6 default route
|
||||
routeConfig.Destination = "::/0";
|
||||
} ];
|
||||
|
||||
extraConfig = lib.mkIf (upstream.upBandwidth != null) ''
|
||||
extraConfig = ''
|
||||
[CAKE]
|
||||
Parent = root
|
||||
# DOCSIS overhead
|
||||
OverheadBytes = 18
|
||||
Bandwidth = ${toString upstream.upBandwidth}K
|
||||
Bandwidth = ${toString wireguard.upBandwidth}K
|
||||
'';
|
||||
}) tunnels);
|
||||
|
||||
|
@ -109,7 +110,7 @@ in
|
|||
networking.iproute2 = lib.mkIf enabled {
|
||||
enable = true;
|
||||
rttablesExtraConfig = ''
|
||||
${toString vpnTable} vpn
|
||||
${toString vpn4Table} vpn4
|
||||
'';
|
||||
};
|
||||
|
|
@ -1,22 +1,24 @@
|
|||
# Routing daemon configuration
|
||||
{ hostName, config, lib, pkgs, ... }:
|
||||
{ hostName, config, options, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
hostNameEscaped = builtins.replaceStrings [ "-" ] [ "_" ] hostName;
|
||||
|
||||
hostConf = config.site.hosts.${hostName};
|
||||
|
||||
upstreamInterfaces = lib.filterAttrs (_: { upstream, ... }:
|
||||
upstream != null
|
||||
) hostConf.interfaces;
|
||||
isUpstream =
|
||||
builtins.match "upstream.*" hostName != null ||
|
||||
builtins.match "anon.*" hostName != null;
|
||||
|
||||
isUpstream = upstreamInterfaces != {};
|
||||
|
||||
ipv6RouterNets = builtins.attrNames (
|
||||
lib.filterAttrs (net: { ipv6Router, ... }:
|
||||
ipv6Router == hostName
|
||||
) config.site.net
|
||||
);
|
||||
# Configuring a gateway? If so, this is the associated net.
|
||||
gatewayNet =
|
||||
let
|
||||
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:
|
||||
if list == []
|
||||
|
@ -59,111 +61,76 @@ in
|
|||
''
|
||||
else ''
|
||||
export all;
|
||||
''}
|
||||
''}
|
||||
};
|
||||
}
|
||||
protocol device {
|
||||
scan time 10;
|
||||
}
|
||||
# Import address ranges of upstream interfaces so that
|
||||
# internal traffic to local public services take no detours
|
||||
# if the default router takes another upstream gateway.
|
||||
protocol direct {
|
||||
ipv4 {
|
||||
${if isUpstream
|
||||
then ''
|
||||
# No RFC1918, RFC6598
|
||||
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 ];
|
||||
''
|
||||
else ""}
|
||||
};
|
||||
ipv6;
|
||||
interface ${lib.concatMapStringsSep ", " (iface:
|
||||
''"${iface}"''
|
||||
)(builtins.attrNames hostConf.interfaces)};
|
||||
check link yes;
|
||||
}
|
||||
|
||||
${lib.optionalString (
|
||||
builtins.match "anon.*" hostName != null ||
|
||||
hostName == "flpk-gw"
|
||||
) ''
|
||||
${lib.optionalString (builtins.match "anon.*" hostName != null) ''
|
||||
# BIRD routing table for Wireguard transport
|
||||
ipv4 table vpn_table;
|
||||
ipv4 table vpn4_table;
|
||||
|
||||
# Kernel routing table for Wireguard transport
|
||||
protocol kernel VPN {
|
||||
# "vpn_table" configured on anon routers
|
||||
protocol kernel VPN4 {
|
||||
# "vpn4_table" configured on anon routers
|
||||
kernel table 100;
|
||||
ipv4 {
|
||||
export all;
|
||||
table vpn_table;
|
||||
table vpn4_table;
|
||||
};
|
||||
}
|
||||
''}
|
||||
|
||||
${lib.optionalString (ipv6RouterNets != []) ''
|
||||
${lib.optionalString (gatewayNet != null) ''
|
||||
# Router advertisements
|
||||
protocol radv {
|
||||
rdnss ${config.site.net.serv.hosts6.dn42.dnscache};
|
||||
|
||||
${lib.concatMapStrings (net: ''
|
||||
interface "${net}" {
|
||||
min ra interval 10;
|
||||
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;
|
||||
''}
|
||||
interface "${gatewayNet}" {
|
||||
min ra interval 10;
|
||||
max ra interval 60;
|
||||
|
||||
${builtins.concatStringsSep "\n" (
|
||||
map (subnet6: ''
|
||||
prefix ${subnet6} {
|
||||
preferred lifetime 600;
|
||||
valid lifetime 1800;
|
||||
};
|
||||
'') (builtins.attrValues config.site.net.${net}.subnets6)
|
||||
)}
|
||||
${builtins.concatStringsSep "\n" (
|
||||
map (subnet6: ''
|
||||
prefix ${subnet6} {
|
||||
preferred lifetime 600;
|
||||
valid lifetime 1800;
|
||||
};
|
||||
'') (builtins.attrValues config.site.net.${gatewayNet}.subnets6)
|
||||
)}
|
||||
|
||||
dnssl "${config.site.net.${net}.domainName}";
|
||||
};
|
||||
'') ipv6RouterNets}
|
||||
dnssl "${config.site.net.${gatewayNet}.domainName}";
|
||||
};
|
||||
}
|
||||
''}
|
||||
|
||||
# OSPFv2 for site-local IPv4
|
||||
protocol ospf v2 ZW4 {
|
||||
ipv4 {
|
||||
import all;
|
||||
# OSPF is self-contained
|
||||
export none;
|
||||
export where net != 0.0.0.0/0 && source != RTS_BGP;
|
||||
};
|
||||
area 0 {
|
||||
${builtins.concatStringsSep "\n" (
|
||||
builtins.attrValues (
|
||||
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
|
||||
then ''
|
||||
interface "${net}" {
|
||||
hello 10;
|
||||
wait 20;
|
||||
|
||||
authentication cryptographic;
|
||||
password "${config.site.net.${net}.ospf.secret}";
|
||||
};
|
||||
''
|
||||
else ''
|
||||
interface "${net}" {
|
||||
stub yes;
|
||||
cost 10;
|
||||
};
|
||||
else if config.site.net ? "${net}" && config.site.net.${net}.subnet4 != null
|
||||
then ''
|
||||
# Advertise route of network ${net}
|
||||
stubnet ${config.site.net.${net}.subnet4} {};
|
||||
''
|
||||
else ""
|
||||
) hostConf.interfaces
|
||||
)
|
||||
)}
|
||||
|
@ -178,7 +145,7 @@ in
|
|||
|
||||
${lib.optionalString isUpstream ''
|
||||
# OSPFv2 to advertise my default route
|
||||
protocol ospf v2 ZW4_${hostNameEscaped} {
|
||||
protocol ospf v2 ZW4_${hostName} {
|
||||
ipv4 {
|
||||
export where net = 0.0.0.0/0;
|
||||
};
|
||||
|
@ -191,8 +158,6 @@ in
|
|||
interface "${net}" instance ${toString hostConf.ospf.upstreamInstance} {
|
||||
# Become the designated router
|
||||
priority 10;
|
||||
hello 10;
|
||||
wait 20;
|
||||
|
||||
authentication cryptographic;
|
||||
password "${config.site.net.${net}.ospf.secret}";
|
||||
|
@ -211,19 +176,14 @@ in
|
|||
${text}
|
||||
|
||||
# OSPFv2 to receive a default route from ${upstream}
|
||||
protocol ospf v2 ZW4_${
|
||||
builtins.replaceStrings [ "-" ] [ "_" ] upstream
|
||||
} {
|
||||
protocol ospf v2 ZW4_${upstream} {
|
||||
ipv4 {
|
||||
import filter {
|
||||
preference = preference + ${toString (100 - n)};
|
||||
accept;
|
||||
};
|
||||
${lib.optionalString (
|
||||
builtins.match "anon.*" hostName != null ||
|
||||
hostName == "flpk-gw"
|
||||
) ''
|
||||
table vpn_table;
|
||||
${lib.optionalString (builtins.match "anon.*" hostName != null) ''
|
||||
table vpn4_table;
|
||||
''}
|
||||
};
|
||||
area 0 {
|
||||
|
@ -232,13 +192,7 @@ in
|
|||
builtins.mapAttrs (net: _:
|
||||
# Enable OSPF only on interfaces with a secret.
|
||||
lib.optionalString (config.site.net.${net}.ospf.secret != null) ''
|
||||
interface "${net}" instance ${
|
||||
builtins.replaceStrings [ "-" ] [ "_" ] (
|
||||
toString config.site.hosts.${upstream}.ospf.upstreamInstance
|
||||
)
|
||||
} {
|
||||
hello 10;
|
||||
wait 20;
|
||||
interface "${net}" instance ${toString config.site.hosts.${upstream}.ospf.upstreamInstance} {
|
||||
authentication cryptographic;
|
||||
password "${config.site.net.${net}.ospf.secret}";
|
||||
};
|
||||
|
@ -256,31 +210,28 @@ in
|
|||
# OSPFv3 for site-local IPv6
|
||||
protocol ospf v3 ZW6 {
|
||||
ipv6 {
|
||||
import all;
|
||||
# OSPF is self-contained
|
||||
export none;
|
||||
export where net != ::/0 && source != RTS_BGP;
|
||||
};
|
||||
area 0 {
|
||||
${builtins.concatStringsSep "\n" (
|
||||
builtins.attrValues (
|
||||
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
|
||||
then ''
|
||||
interface "${net}" {
|
||||
hello 10;
|
||||
wait 20;
|
||||
|
||||
authentication cryptographic;
|
||||
password "${config.site.net.${net}.ospf.secret}";
|
||||
};
|
||||
''
|
||||
else ''
|
||||
interface "${net}" {
|
||||
stub yes;
|
||||
cost 10;
|
||||
};
|
||||
''
|
||||
else builtins.concatStringsSep "\n" (
|
||||
map (subnet6: ''
|
||||
# Advertise route of network ${net}
|
||||
stubnet ${subnet6} {};
|
||||
'') (builtins.attrValues config.site.net.${net}.subnets6)
|
||||
)
|
||||
) hostConf.physicalInterfaces
|
||||
)
|
||||
)}
|
||||
|
@ -296,7 +247,7 @@ in
|
|||
|
||||
${lib.optionalString isUpstream ''
|
||||
# OSPFv3 to advertise my default route
|
||||
protocol ospf v3 ZW6_${hostNameEscaped} {
|
||||
protocol ospf v3 ZW6_${hostName} {
|
||||
ipv6 {
|
||||
export where net = ::/0;
|
||||
};
|
||||
|
@ -309,8 +260,6 @@ in
|
|||
interface "${net}" instance ${toString hostConf.ospf.upstreamInstance} {
|
||||
# Become the designated router
|
||||
priority 10;
|
||||
hello 10;
|
||||
wait 20;
|
||||
|
||||
authentication cryptographic;
|
||||
password "${config.site.net.${net}.ospf.secret}";
|
||||
|
@ -329,9 +278,7 @@ in
|
|||
${text}
|
||||
|
||||
# OSPFv3 to receive a default route from ${upstream}
|
||||
protocol ospf v3 ZW6_${
|
||||
builtins.replaceStrings [ "-" ] [ "_" ] upstream
|
||||
} {
|
||||
protocol ospf v3 ZW6_${upstream} {
|
||||
ipv6 {
|
||||
import filter {
|
||||
preference = preference + ${toString (100 - n)};
|
||||
|
@ -344,13 +291,7 @@ in
|
|||
builtins.mapAttrs (net: _:
|
||||
# Enable OSPF only on interfaces with a secret.
|
||||
lib.optionalString (config.site.net.${net}.ospf.secret != null) ''
|
||||
interface "${net}" instance ${
|
||||
builtins.replaceStrings [ "-" ] [ "_" ] (
|
||||
toString config.site.hosts.${upstream}.ospf.upstreamInstance
|
||||
)
|
||||
} {
|
||||
hello 10;
|
||||
wait 20;
|
||||
interface "${net}" instance ${toString config.site.hosts.${upstream}.ospf.upstreamInstance} {
|
||||
authentication cryptographic;
|
||||
password "${config.site.net.${net}.ospf.secret}";
|
||||
};
|
||||
|
@ -362,7 +303,7 @@ in
|
|||
}
|
||||
'';
|
||||
n = n + 1;
|
||||
}) { text = ""; n = 0; } hostConf.ospf.allowedUpstreams6
|
||||
}) { text = ""; n = 0; } hostConf.ospf.allowedUpstreams
|
||||
).text}
|
||||
|
||||
# Zentralwerk DN42
|
||||
|
@ -373,8 +314,11 @@ in
|
|||
protocol static {
|
||||
ipv6;
|
||||
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 2a0f:5382:acab:1400::/56 unreachable;
|
||||
}
|
||||
|
||||
${lib.optionalString (hostConf.bgp != null) ''
|
||||
|
@ -436,8 +380,8 @@ in
|
|||
];
|
||||
};
|
||||
instance = {
|
||||
ipv4 = "ZW4_${hostNameEscaped}";
|
||||
ipv6 = "ZW6_${hostNameEscaped}";
|
||||
ipv4 = "ZW4_${hostName}";
|
||||
ipv6 = "ZW6_${hostName}";
|
||||
};
|
||||
checkService = addressFamily: {
|
||||
description = "Check connectivity for ${addressFamily}";
|
||||
|
@ -447,7 +391,7 @@ in
|
|||
User = "bird2";
|
||||
Group = "bird2";
|
||||
};
|
||||
path = with pkgs; [ bird2 iputils ];
|
||||
path = [ pkgs.bird2 "/run/wrappers" ];
|
||||
script = ''
|
||||
STATE=unknown
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, modulesPath, pkgs, ... }:
|
||||
{ config, lib, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
|
@ -6,19 +6,22 @@
|
|||
(modulesPath + "/virtualisation/lxc-container.nix")
|
||||
];
|
||||
|
||||
environment = {
|
||||
etc."machine-id".text = builtins.substring 0 8 (builtins.hashString "sha256" config.networking.hostName);
|
||||
systemPackages = with pkgs; [
|
||||
ripgrep
|
||||
];
|
||||
boot = {
|
||||
isContainer = true;
|
||||
loader = {
|
||||
initScript.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc."machine-id".text =
|
||||
builtins.substring 0 8 (
|
||||
builtins.hashString "sha256" config.networking.hostName
|
||||
);
|
||||
|
||||
nix = {
|
||||
settings = {
|
||||
sandbox = false;
|
||||
max-jobs = lib.mkDefault 4;
|
||||
cores = lib.mkDefault 4;
|
||||
};
|
||||
useSandbox = false;
|
||||
maxJobs = lib.mkDefault 1;
|
||||
buildCores = lib.mkDefault 1;
|
||||
};
|
||||
|
||||
systemd.services =
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# ISC DHCP/IPv4 server configuration
|
||||
{ hostName, config, lib, ... }:
|
||||
{ hostName, inputs, config, lib, ... }:
|
||||
|
||||
let
|
||||
dhcpNets =
|
||||
|
@ -8,331 +8,81 @@ let
|
|||
dhcp.server == hostName
|
||||
) 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;
|
||||
in
|
||||
{
|
||||
services.kea.dhcp4 = lib.mkIf enabled {
|
||||
services.dhcpd4 = lib.optionalAttrs enabled {
|
||||
enable = true;
|
||||
|
||||
settings = {
|
||||
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));
|
||||
interfaces = builtins.attrNames dhcpNets;
|
||||
|
||||
subnet4 = concatMapDhcpNets (net: { vlan, subnet4, hosts4, dhcp, domainName, ... }: {
|
||||
id = vlan;
|
||||
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";
|
||||
} ];
|
||||
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;
|
||||
extraConfig = ''
|
||||
${builtins.concatStringsSep "\n" (
|
||||
builtins.attrValues (
|
||||
builtins.mapAttrs (net: { dhcp, subnet4Net, subnet4Len, domainName, ...}:
|
||||
''
|
||||
ddns-update-style standard;
|
||||
key dyndns {
|
||||
algorithm hmac-sha256;
|
||||
secret ${inputs.zentralwerk-network-key.lib.dyndnsKey};
|
||||
};
|
||||
zone ${domainName}. {
|
||||
primary ${config.site.net.serv.hosts4.dns};
|
||||
primary6 ${config.site.net.serv.hosts6.dn42.dns};
|
||||
key dyndns;
|
||||
}
|
||||
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;
|
||||
${lib.concatMapStrings ({ name, dynamic, ... }:
|
||||
lib.optionalString (
|
||||
dynamic &&
|
||||
lib.hasSuffix ".in-addr.arpa" name
|
||||
) ''
|
||||
zone ${name}. {
|
||||
primary ${config.site.net.serv.hosts4.dns};
|
||||
primary6 ${config.site.net.serv.hosts6.dn42.dns};
|
||||
key dyndns;
|
||||
}
|
||||
''
|
||||
) config.site.dns.localZones}
|
||||
|
||||
option arch code 93 = unsigned integer 16;
|
||||
group {
|
||||
default-lease-time ${toString dhcp.time};
|
||||
max-lease-time ${toString dhcp.max-time};
|
||||
option routers ${config.site.net.${net}.hosts4.${builtins.replaceStrings [".${net}"] [""] dhcp.router}};
|
||||
option domain-name "${domainName}";
|
||||
option domain-name-servers 172.20.73.8, 9.9.9.9;
|
||||
ddns-domainname "${domainName}";
|
||||
|
||||
next-server ${config.site.net.serv.hosts4.netboot};
|
||||
if option arch = 00:00 {
|
||||
filename "netboot.xyz.kpxe";
|
||||
} else {
|
||||
filename "netboot.xyz.efi";
|
||||
}
|
||||
))
|
||||
builtins.attrValues
|
||||
(builtins.filter (r: r != null))
|
||||
];
|
||||
});
|
||||
|
||||
match-client-id = false;
|
||||
host-reservation-identifiers = [ "hw-address" ];
|
||||
subnet ${subnet4Net} netmask ${lib.netmasks.${toString subnet4Len}} {
|
||||
range ${dhcp.start} ${dhcp.end};
|
||||
}
|
||||
|
||||
# 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";
|
||||
} ];
|
||||
};
|
||||
update-static-leases on;
|
||||
|
||||
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.mapAttrs makePxe pxeClassData
|
||||
);
|
||||
|
||||
control-socket = {
|
||||
socket-type = "unix";
|
||||
socket-name = "/run/kea/dhcp4-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";
|
||||
} ];
|
||||
};
|
||||
${builtins.concatStringsSep "\n" (
|
||||
builtins.attrValues (
|
||||
builtins.mapAttrs (addr: hwaddr:
|
||||
''
|
||||
host ${addr} {
|
||||
hardware ethernet ${hwaddr};
|
||||
fixed-address ${addr};
|
||||
}
|
||||
''
|
||||
) dhcp.fixed-hosts
|
||||
)
|
||||
)}
|
||||
}
|
||||
''
|
||||
) dhcpNets
|
||||
)
|
||||
)}
|
||||
'';
|
||||
};
|
||||
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, ... }:
|
||||
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";
|
||||
} ];
|
||||
ddns-generated-prefix = "d";
|
||||
ddns-qualifying-suffix = domainName;
|
||||
}
|
||||
else []
|
||||
);
|
||||
|
||||
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 &&
|
||||
(lib.hasSuffix ".in-addr.arpa" name ||
|
||||
lib.hasSuffix ".ip6.arpa" name)
|
||||
) config.site.dns.localZones
|
||||
);
|
||||
control-socket = {
|
||||
socket-type = "unix";
|
||||
socket-name = "/run/kea/dhcp-ddns.socket";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.kea.ctrl-agent = lib.mkIf enabled {
|
||||
enable = true;
|
||||
settings.control-sockets = {
|
||||
dhcp4 = {
|
||||
socket-type = "unix";
|
||||
socket-name = "/run/kea/dhcp4.socket";
|
||||
};
|
||||
dhcp6 = {
|
||||
socket-type = "unix";
|
||||
socket-name = "/run/kea/dhcp6.socket";
|
||||
};
|
||||
d2 = {
|
||||
socket-type = "unix";
|
||||
socket-name = "/run/kea/dhcp-ddns.socket";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Increase reliablity
|
||||
# (mostly for kea-dhcp-ddns-server.service)
|
||||
systemd.services =
|
||||
let
|
||||
restartService.serviceConfig = {
|
||||
RestartSec = 4;
|
||||
Restart = "always";
|
||||
};
|
||||
in {
|
||||
kea-dhcp4-server = restartService;
|
||||
kea-dhcp6-server = restartService;
|
||||
kea-dhcp-ddns-server = restartService;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,26 +1,33 @@
|
|||
{ config, dns-nix, hostName, lib, pkgs, self, ... }:
|
||||
{ hostName, config, lib, pkgs, self, inputs, ... }:
|
||||
|
||||
let
|
||||
serial = builtins.substring 0 10 self.lastModifiedDate;
|
||||
serial =
|
||||
let
|
||||
timestamp = toString self.lastModified;
|
||||
datePkg = pkgs.runCommandLocal "date-${timestamp}" {} ''
|
||||
date -d @${timestamp} +%Y%m%d%H > $out
|
||||
'';
|
||||
in
|
||||
toString (import datePkg);
|
||||
|
||||
generateZoneFile = let
|
||||
util = dns-nix.util.${pkgs.system};
|
||||
in { name, ns, records, ... }: util.writeZone name {
|
||||
TTL = 60*60;
|
||||
SOA = {
|
||||
nameServer = "${lib.dns.ns}.";
|
||||
adminEmail = "astro@spaceboyz.net";
|
||||
serial = lib.toInt serial;
|
||||
refresh = 1*60*60;
|
||||
retry = 5*60;
|
||||
expire = 2*60*60;
|
||||
minimum = 1*60;
|
||||
};
|
||||
NS = map (a: a+".") ns;
|
||||
subdomains = lib.foldl (a: b: lib.recursiveUpdate a b) { } (map ({ name, type, data }: {
|
||||
${name}.${type} = [ data ];
|
||||
}) records);
|
||||
};
|
||||
generateZoneFile = { name, ns, records, dynamic }:
|
||||
builtins.toFile "${name}.zone" ''
|
||||
$ORIGIN ${name}.
|
||||
$TTL 1h
|
||||
|
||||
@ IN SOA ${lib.dns.ns}. astro.spaceboyz.net. (
|
||||
${serial} ; serial
|
||||
1h ; refresh
|
||||
1m ; retry
|
||||
2h ; expire
|
||||
1m ; minimum
|
||||
)
|
||||
${lib.concatMapStrings (ns: " IN NS ${ns}.\n") ns}
|
||||
|
||||
${lib.concatMapStrings ({ name, type, data }:
|
||||
"${name} IN ${type} ${data}\n"
|
||||
) records}
|
||||
'';
|
||||
in
|
||||
{
|
||||
options =
|
||||
|
@ -32,10 +39,10 @@ in
|
|||
type = types.str;
|
||||
};
|
||||
type = mkOption {
|
||||
type = types.enum [ "A" "AAAA" "MX" "SRV" "CNAME" "TXT" "PTR" ];
|
||||
type = types.enum [ "A" "AAAA" "PTR" ];
|
||||
};
|
||||
data = mkOption {
|
||||
type = types.oneOf [ types.str (types.attrsOf (types.oneOf [ types.int types.str ]))];
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -69,151 +76,90 @@ in
|
|||
config = {
|
||||
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
|
||||
generateZone = zone@{ name, dynamic, ... }: {
|
||||
domain = name;
|
||||
template = "zentralwerk";
|
||||
acl = [ "zone_xfr" ] ++ lib.optional dynamic "dyndns";
|
||||
file = if dynamic
|
||||
then "/var/lib/knot/zones/${name}.zone"
|
||||
inherit name;
|
||||
master = true;
|
||||
# allowed for zone-transfer
|
||||
slaves = [
|
||||
# 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" "2a01:4f9:4b:39ec::4"
|
||||
];
|
||||
file =
|
||||
if dynamic
|
||||
then "/var/db/bind/${name}.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 {
|
||||
enable = true;
|
||||
settings = {
|
||||
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" "95.217.229.209" "2a01:4f9:4b:39ec::4"
|
||||
# ns1.supersandro.de
|
||||
"188.34.196.104" "2a01:4f8:1c1c:1d38::1"
|
||||
];
|
||||
action = "transfer";
|
||||
}
|
||||
];
|
||||
zones = map generateZone config.site.dns.localZones;
|
||||
|
||||
key = [ {
|
||||
id = "dyndns";
|
||||
algorithm = "hmac-sha256";
|
||||
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" "95.217.229.209" "2a01:4f9:4b:39ec::4" ];
|
||||
inherit via;
|
||||
} {
|
||||
id = "ns1.supersandro.de";
|
||||
address = [ /*"188.34.196.104"*/ "2a01:4f8:1c1c:1d38::1" ];
|
||||
inherit via;
|
||||
}
|
||||
];
|
||||
|
||||
remotes = [ {
|
||||
id = "all";
|
||||
remote = [ "ns.c3d2.de" "ns.spaceboyz.net" "ns1.supersandro.de" ];
|
||||
} ];
|
||||
|
||||
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;
|
||||
extraConfig = ''
|
||||
key "dyndns" {
|
||||
algorithm hmac-sha256;
|
||||
secret "${inputs.zentralwerk-network-key.lib.dyndnsKey}";
|
||||
};
|
||||
|
||||
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" ];
|
||||
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 = {
|
||||
create-dynamic-zones = {
|
||||
description = "Creates dynamic zone files";
|
||||
requiredBy = [ "knot.service" ];
|
||||
before = [ "knot.service" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = ''
|
||||
mkdir -p /var/lib/knot/zones
|
||||
systemd.services.create-dynamic-zones = {
|
||||
description = "Creates dynamic zone files";
|
||||
requiredBy = [ "bind.service" ];
|
||||
before = [ "bind.service" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = ''
|
||||
mkdir -p /var/db/bind
|
||||
|
||||
${lib.concatMapStringsSep "\n" (zone@{ name, ... }: ''
|
||||
[ -e /var/lib/knot/zones/${name}.zone ] || \
|
||||
cp ${generateZoneFile zone} /var/lib/knot/zones/${name}.zone
|
||||
chown -R knot /var/lib/knot/zones
|
||||
chmod -R u+rwX /var/lib/knot/zones
|
||||
'') (builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones)}
|
||||
'';
|
||||
};
|
||||
|
||||
update-dynamic-zones = {
|
||||
description = "Creates initial records in dynamic zone files";
|
||||
requiredBy = [ "knot.service" ];
|
||||
after = [ "knot.service" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
path = [ pkgs.dnsutils ];
|
||||
script = lib.concatMapStrings (zone: ''
|
||||
nsupdate -v -y "hmac-sha256:dyndns:${config.site.dyndnsKey}" <<EOF
|
||||
${lib.concatMapStringsSep "\n" (zone@{ name, ... }: ''
|
||||
[ -e /var/db/bind/${name}.zone ] || \
|
||||
cp ${generateZoneFile zone} /var/db/bind/${name}.zone
|
||||
chown -R named /var/db/bind
|
||||
chmod -R u+rwX /var/db/bind
|
||||
'') (
|
||||
builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones
|
||||
)}
|
||||
'';
|
||||
};
|
||||
systemd.services.update-dynamic-zones = {
|
||||
description = "Creates initial records in dynamic zone files";
|
||||
requiredBy = [ "bind.service" ];
|
||||
after = [ "bind.service" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
path = [ pkgs.dnsutils ];
|
||||
script = ''
|
||||
${lib.concatMapStrings (zone: ''
|
||||
nsupdate -y "hmac-sha256:dyndns:${inputs.zentralwerk-network-key.lib.dyndnsKey}" <<EOF
|
||||
server localhost
|
||||
|
||||
${lib.concatMapStringsSep "\n" ({ name, type, data }: ''
|
||||
|
@ -223,8 +169,10 @@ in
|
|||
|
||||
send
|
||||
EOF
|
||||
'') (builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones);
|
||||
};
|
||||
'') (
|
||||
builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones
|
||||
)}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,99 +1,105 @@
|
|||
{ hostName, config, lib, pkgs, ... }:
|
||||
|
||||
lib.mkIf config.site.hosts.${hostName}.services.dnscache.enable {
|
||||
services.kresd = {
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
instances = 4;
|
||||
listenPlain = [ "0.0.0.0:53" "[::0]:53" ];
|
||||
package = pkgs.knot-resolver.override { extraFeatures = true; };
|
||||
extraConfig = /* lua */ ''
|
||||
modules = {
|
||||
'http',
|
||||
'policy',
|
||||
'predict',
|
||||
'prefill',
|
||||
'serve_stale < cache', -- servce stail records while refreshing the record
|
||||
'workarounds < iterate', -- solve problems around specific broken subdomains, mainly disables case randomization
|
||||
'view'
|
||||
}
|
||||
settings = {
|
||||
remote-control = {
|
||||
control-enable = true;
|
||||
control-use-cert = false;
|
||||
};
|
||||
server = {
|
||||
num-threads = 4;
|
||||
verbosity = 1;
|
||||
prefetch = true;
|
||||
serve-expired = true;
|
||||
cache-min-ttl = 60;
|
||||
cache-max-ttl = 3600;
|
||||
|
||||
cache.size = 500 * MB
|
||||
cache.min_ttl(60)
|
||||
interface = [ "0.0.0.0" "'::0'" ];
|
||||
# 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' })
|
||||
http.prometheus.namespace = 'resolver_'
|
||||
# allow reverse lookup of rfc1918 space, which includes the DN42 address space
|
||||
unblock-lan-zones = true;
|
||||
insecure-lan-zones = true;
|
||||
|
||||
-- dns42
|
||||
policy.add(policy.suffix(
|
||||
policy.STUB({'fd42:d42:d42:54::1', 'fd42:d42:d42:53::1', '172.20.0.53', '172.23.0.53'}),
|
||||
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'})
|
||||
))
|
||||
domain-insecure = [
|
||||
"dn42"
|
||||
"d.f.ip6.arpa"
|
||||
"ffdd"
|
||||
];
|
||||
};
|
||||
|
||||
-- freifunk
|
||||
policy.add(policy.suffix(
|
||||
policy.STUB({'10.200.0.4', '10.200.0.16'}),
|
||||
policy.todnames({'ffdd.', '200.10.in-addr.arpa', '201.10.in-addr.arpa'})
|
||||
))
|
||||
|
||||
-- size.dns.localZones
|
||||
policy.add(policy.suffix(
|
||||
policy.STUB({'${config.site.net.serv.hosts4.dns}', ${lib.concatStringsSep ", " (map (hosts6: "'${hosts6.dns}'") (builtins.attrValues config.site.net.serv.hosts6))}}),
|
||||
policy.todnames({${lib.concatStringsSep ", " (map (zone: "'${zone.name}'") config.site.dns.localZones)}})
|
||||
))
|
||||
|
||||
-- forward to dns caches
|
||||
policy.add(policy.slice(
|
||||
policy.slice_randomize_psl(),
|
||||
-- quad9
|
||||
policy.TLS_FORWARD({
|
||||
{'2620:fe::fe', hostname='dns.quad9.net'},
|
||||
{'2620:fe::9', hostname='dns.quad9.net'},
|
||||
{'9.9.9.9', hostname='dns.quad9.net'},
|
||||
{'149.112.112.112', hostname='dns.quad9.net'}
|
||||
}),
|
||||
-- cloudflare
|
||||
policy.TLS_FORWARD({
|
||||
{'2606:4700:4700::1111', hostname='cloudflare-dns.com'},
|
||||
{'2606:4700:4700::1001', hostname='cloudflare-dns.com'},
|
||||
{'1.1.1.1', hostname='cloudflare-dns.com'},
|
||||
{'1.0.0.1', hostname='cloudflare-dns.com'}
|
||||
})
|
||||
))
|
||||
|
||||
-- allow access from our networks
|
||||
'' + lib.concatMapStringsSep "\n" (cidr: "view:addr('${cidr}', policy.all(policy.PASS))") [
|
||||
# localhost
|
||||
"::1/128" "127.0.0.0/8"
|
||||
# mgmt
|
||||
"${config.site.net.mgmt.subnet4}"
|
||||
# dn42
|
||||
"fd23:42:c3d2:500::/56" "::172.20.72.0/117" "::172.22.99.0/120"
|
||||
"172.20.72.0/21" "172.22.99.0/24"
|
||||
# freifunk
|
||||
"10.200.0.0/15"
|
||||
# DSI
|
||||
"2a00:8180:2000:37::1/128" "2a00:8180:2c00:200::/56"
|
||||
# flpk
|
||||
"${config.site.net.flpk.subnet4}" "2a0f:5382:acab:1400::/56 allow"
|
||||
] + "\n" + /* lua */ ''
|
||||
|
||||
-- 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'})
|
||||
'';
|
||||
forward-zone = let
|
||||
mkFfddZone = name: {
|
||||
inherit name;
|
||||
forward-addr = [ "10.200.0.4" "10.200.0.16" ];
|
||||
};
|
||||
in [ {
|
||||
name = ".";
|
||||
forward-tls-upstream = true;
|
||||
forward-addr = [
|
||||
# Quad9
|
||||
"2620:fe::fe@853#dns.quad9.net"
|
||||
"9.9.9.9@853#dns.quad9.net"
|
||||
"2620:fe::9@853#dns.quad9.net"
|
||||
"149.112.112.112@853#dns.quad9.net"
|
||||
# Cloudflare DNS
|
||||
"2606:4700:4700::1111@853#cloudflare-dns.com"
|
||||
"1.1.1.1@853#cloudflare-dns.com"
|
||||
"2606:4700:4700::1001@853#cloudflare-dns.com"
|
||||
"1.0.0.1@853#cloudflare-dns.com"
|
||||
];
|
||||
} ] ++
|
||||
# Local networks
|
||||
map ({ name, ... }: {
|
||||
name = "${name}";
|
||||
forward-addr = [ "${config.site.net.serv.hosts4.dns}" ] ++
|
||||
map (hosts6: hosts6.dns)
|
||||
(builtins.attrValues config.site.net.serv.hosts6);
|
||||
}) config.site.dns.localZones
|
||||
# Freifunk
|
||||
++ (map mkFfddZone [
|
||||
"ffdd"
|
||||
"200.10.in-addr.arpa"
|
||||
"201.10.in-addr.arpa"
|
||||
]);
|
||||
# DN42
|
||||
stub-zone = let
|
||||
mkDn42Zone = name: {
|
||||
inherit name;
|
||||
stub-prime = true;
|
||||
stub-addr = [
|
||||
"172.20.0.53" "fd42:d42:d42:54::1"
|
||||
"172.23.0.53" "fd42:d42:d42:53::1"
|
||||
];
|
||||
};
|
||||
in map mkDn42Zone [
|
||||
"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"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
'';
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
{ hostName, config, lib, pkgs, ... }:
|
||||
{ hostName, config, lib, ... }:
|
||||
|
||||
let
|
||||
hostConf = config.site.hosts.${hostName};
|
||||
|
@ -15,8 +15,6 @@ let
|
|||
else null;
|
||||
|
||||
enabled = firstUpstreamInterface != null;
|
||||
|
||||
inherit (upstreamInterfaces.${firstUpstreamInterface}.upstream) staticIpv4Address;
|
||||
in
|
||||
{
|
||||
systemd.network.networks = {
|
||||
|
@ -24,132 +22,64 @@ in
|
|||
# systemd-networkd only requests Prefix Delegation via DHCPv6 on
|
||||
# the upstream interface if another interface is configured for it.
|
||||
# without this, the static ipv6 subnet won't be routed to us.
|
||||
networkConfig.DHCPPrefixDelegation = true;
|
||||
networkConfig.DHCPv6PrefixDelegation = true;
|
||||
dhcpV6PrefixDelegationConfig = {
|
||||
SubnetId = "81";
|
||||
# because we have static addresses, we don't actually use this
|
||||
Assign = false;
|
||||
};
|
||||
};
|
||||
} // builtins.mapAttrs (_: { upstream, ... }:
|
||||
# DHCP
|
||||
lib.optionalAttrs (hostName != "flpk-gw") {
|
||||
DHCP = "yes";
|
||||
networkConfig.IPv6AcceptRA = true;
|
||||
dhcpV6Config.PrefixDelegationHint = "::/56";
|
||||
}
|
||||
//
|
||||
} // builtins.mapAttrs (_: { upstream, ... }: {
|
||||
DHCP = "yes";
|
||||
networkConfig.IPv6AcceptRA = true;
|
||||
dhcpV6Config.PrefixDelegationHint = "::/56";
|
||||
|
||||
# Traffic Shaping
|
||||
{
|
||||
extraConfig = ''
|
||||
[CAKE]
|
||||
Parent = root
|
||||
${lib.optionalString (upstream.provider == "vodafone") ''
|
||||
# DOCSIS overhead
|
||||
OverheadBytes = 18
|
||||
''}
|
||||
${lib.optionalString (upstream.provider == "dsi") ''
|
||||
# PPPoE overhead
|
||||
OverheadBytes = 18
|
||||
''}
|
||||
${lib.optionalString (upstream.upBandwidth != null) ''
|
||||
Bandwidth = ${toString upstream.upBandwidth}K
|
||||
''}
|
||||
'';
|
||||
}
|
||||
) upstreamInterfaces;
|
||||
extraConfig = ''
|
||||
[CAKE]
|
||||
Parent = root
|
||||
${lib.optionalString (upstream.provider == "vodafone") ''
|
||||
# DOCSIS overhead
|
||||
OverheadBytes = 18
|
||||
''}
|
||||
${lib.optionalString (upstream.provider == "dsi") ''
|
||||
# PPPoE overhead
|
||||
OverheadBytes = 18
|
||||
''}
|
||||
${lib.optionalString (upstream.upBandwidth != null) ''
|
||||
Bandwidth = ${toString upstream.upBandwidth}K
|
||||
''}
|
||||
'';
|
||||
}) upstreamInterfaces;
|
||||
|
||||
networking.nat = lib.optionalAttrs enabled {
|
||||
enable = true;
|
||||
enableIPv6 = true;
|
||||
internalInterfaces = [ "core" ];
|
||||
externalInterface = firstUpstreamInterface;
|
||||
externalIP = staticIpv4Address;
|
||||
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)}
|
||||
|
||||
externalIP = upstreamInterfaces.${firstUpstreamInterface}.upstream.staticIpv4Address;
|
||||
extraCommands =
|
||||
# Provide IPv6 upstream for everyone, using NAT66 when not from
|
||||
# our static prefixes
|
||||
${lib.concatMapStringsSep "\n" (net:
|
||||
lib.concatMapStrings (subnet: ''
|
||||
ip6tables -t nat -I nixos-nat-post \
|
||||
-o ${net} \
|
||||
-s ${subnet} \
|
||||
-j RETURN
|
||||
'') upstreamInterfaces.${net}.upstream.noNat.subnets6
|
||||
) (builtins.attrNames upstreamInterfaces)}
|
||||
lib.concatMapStringsSep "\n" (net: ''
|
||||
ip6tables -t nat -N ${net}_nat || \
|
||||
ip6tables -t nat -F ${net}_nat
|
||||
${lib.concatMapStringsSep "\n" (subnet: ''
|
||||
ip6tables -t nat -A ${net}_nat \
|
||||
-s ${subnet} \
|
||||
-j RETURN
|
||||
'') upstreamInterfaces.${net}.upstream.noNat.subnets6}
|
||||
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 -F POSTROUTING 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 ${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:
|
||||
removeAttrs forwardedPort ["reflect"] // {
|
||||
|
@ -159,7 +89,11 @@ in
|
|||
else "${destination}:${toString sourcePort}";
|
||||
loopbackIPs =
|
||||
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 [];
|
||||
}
|
||||
) hostConf.forwardPorts;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ hostName, config, lib, ... }:
|
||||
{ hostName, inputs, config, lib, ... }:
|
||||
|
||||
let
|
||||
hostConf = config.site.hosts.${hostName};
|
||||
|
@ -7,6 +7,8 @@ let
|
|||
lib.filterAttrs (_: { type, ... }: type == "pppoe")
|
||||
hostConf.interfaces;
|
||||
|
||||
inherit (inputs.zentralwerk-network-key.lib.pppoe.${hostName}) user password;
|
||||
|
||||
in lib.mkIf (pppoeInterfaces != {}) {
|
||||
boot.postBootCommands = ''
|
||||
if [ ! -c /dev/ppp ]; then
|
||||
|
@ -14,23 +16,20 @@ in lib.mkIf (pppoeInterfaces != {}) {
|
|||
fi
|
||||
'';
|
||||
|
||||
environment.etc."ppp/pap-secrets".text = lib.concatMapStrings (ifName:
|
||||
let
|
||||
inherit (pppoeInterfaces.${ifName}.upstream) user password;
|
||||
in ''
|
||||
"${user}" * "${password}"
|
||||
'') (builtins.attrNames pppoeInterfaces);
|
||||
environment.etc."ppp/pap-secrets".text = ''
|
||||
"${user}" * "${password}"
|
||||
'';
|
||||
services.pppd = {
|
||||
enable = true;
|
||||
peers = builtins.mapAttrs (ifName: { upstream, ... }: {
|
||||
enable = true;
|
||||
autostart = true;
|
||||
config = ''
|
||||
plugin pppoe.so
|
||||
plugin rp-pppoe.so
|
||||
nic-${upstream.link}
|
||||
ifname ${ifName}
|
||||
# Login settings. (PAP)
|
||||
name "${upstream.user}"
|
||||
name "${user}"
|
||||
noauth
|
||||
hide-password
|
||||
# Connection settings.
|
||||
|
@ -39,16 +38,17 @@ in lib.mkIf (pppoeInterfaces != {}) {
|
|||
maxfail 0
|
||||
# Seconds between reconnection attempts
|
||||
holdoff 1
|
||||
|
||||
|
||||
# LCP settings.
|
||||
lcp-echo-interval 5
|
||||
lcp-echo-failure 6
|
||||
|
||||
|
||||
# PPPoE compliant settings.
|
||||
noaccomp
|
||||
default-asyncmap
|
||||
mtu 1492
|
||||
# IP settings.
|
||||
#noipdefault
|
||||
defaultroute
|
||||
+ipv6
|
||||
defaultroute6
|
||||
|
@ -64,17 +64,14 @@ in lib.mkIf (pppoeInterfaces != {}) {
|
|||
in networks // {
|
||||
"${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 = {
|
||||
DHCP = lib.mkForce "ipv6";
|
||||
DHCP = lib.mkOverride 900 "ipv6";
|
||||
# accept config set by pppd
|
||||
KeepConfiguration = "yes";
|
||||
};
|
||||
dhcpV6Config = {
|
||||
RapidCommit = true;
|
||||
ForceDHCPv6PDOtherInformation = true;
|
||||
PrefixDelegationHint = "::/56";
|
||||
};
|
||||
};
|
||||
|
@ -84,4 +81,11 @@ in lib.mkIf (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
|
||||
'';
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
];
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
# Pulls together NixOS configuration modules according to the
|
||||
# name/role of the host to be built.
|
||||
{ hostName, lib, ... }:
|
||||
{ hostName, config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) optionals;
|
||||
|
||||
hostConfig = lib.config.site.hosts.${hostName};
|
||||
in {
|
||||
inherit (lib.config) site;
|
||||
site = lib.config.site;
|
||||
|
||||
imports = [
|
||||
../lib/config/options.nix
|
||||
|
@ -20,27 +20,23 @@ in {
|
|||
./server/default.nix
|
||||
] ++
|
||||
optionals (hostConfig.role == "container") [
|
||||
./container/lxc-config.nix
|
||||
./container/defaults.nix
|
||||
./container/dhcp-server.nix
|
||||
./container/wireguard.nix
|
||||
./container/anon.nix
|
||||
./container/dns.nix
|
||||
./container/dnscache.nix
|
||||
] ++
|
||||
optionals lib.config.site.hosts.${hostName}.isRouter [
|
||||
./container/bird.nix
|
||||
] ++
|
||||
optionals (
|
||||
builtins.match "upstream.*" hostName != null ||
|
||||
hostName == "flpk-gw"
|
||||
) [
|
||||
optionals (builtins.match "upstream.*" hostName != null) [
|
||||
./container/upstream.nix
|
||||
./container/upstream/pppoe.nix
|
||||
] ++
|
||||
optionals (hostName == "mgmt-gw") [
|
||||
./container/mgmt-gw.nix
|
||||
] ++
|
||||
optionals (hostName == "vpn-gw") [
|
||||
./container/vpn.nix
|
||||
optionals (hostName == "netboot") [
|
||||
./container/netboot.nix
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ hostName, inputs, lib, pkgs, ... }:
|
||||
{ hostName, inputs, pkgs, config, options, lib, ... }:
|
||||
|
||||
{
|
||||
boot.kernelParams = [
|
||||
|
@ -7,9 +7,9 @@
|
|||
# Prevents automatic creation of interface bond0 by the kernel
|
||||
"bonding.max_bonds=0"
|
||||
];
|
||||
boot.tmp.useTmpfs = true;
|
||||
boot.tmpOnTmpfs = true;
|
||||
# Includes wireguard
|
||||
boot.kernelPackages = pkgs.zfsUnstable.latestCompatibleLinuxPackages;
|
||||
boot.kernelPackages = pkgs.linuxPackages_latest;
|
||||
# Keep building
|
||||
boot.zfs.enableUnstable = true;
|
||||
|
||||
|
@ -19,24 +19,44 @@
|
|||
Storage=volatile
|
||||
'';
|
||||
|
||||
# central logging
|
||||
services.journalbeat = {
|
||||
enable = true;
|
||||
tags = [ "zentralwerk" ];
|
||||
extraConfig = ''
|
||||
journalbeat.inputs:
|
||||
# Paths that should be crawled and fetched. Possible values files and directories.
|
||||
# When setting a directory, all journals under it are merged.
|
||||
# When empty starts to read from local journal.
|
||||
- paths: []
|
||||
journalbeat:
|
||||
seek_position: cursor
|
||||
cursor_seek_fallback: tail
|
||||
write_cursor_state: true
|
||||
cursor_flush_period: 5s
|
||||
clean_field_names: true
|
||||
convert_to_numbers: false
|
||||
move_metadata_to_field: journal
|
||||
default_type: journal
|
||||
kernel: true
|
||||
output.logstash:
|
||||
# Boolean flag to enable or disable the output module.
|
||||
enabled: true
|
||||
hosts: ["${config.site.net.serv.hosts4.logging}:5044"]
|
||||
'';
|
||||
};
|
||||
|
||||
nix = {
|
||||
package = pkgs.nixFlakes;
|
||||
extraOptions = "experimental-features = nix-command flakes";
|
||||
registry = {
|
||||
nixpkgs.flake = inputs.nixpkgs;
|
||||
};
|
||||
|
||||
settings = {
|
||||
substituters = lib.mkBefore [ "https://hydra.hq.c3d2.de" ];
|
||||
trusted-public-keys = [
|
||||
"nix-serve.hq.c3d2.de:KZRGGnwOYzys6pxgM8jlur36RmkJQ/y8y62e52fj1ps=%"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
documentation = {
|
||||
enable = lib.mkForce false;
|
||||
nixos.enable = lib.mkForce false;
|
||||
enable = false;
|
||||
nixos.enable = false;
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
|
@ -44,8 +64,6 @@
|
|||
bridge-utils
|
||||
conntrack-tools
|
||||
dhcpcd
|
||||
dhcpdump
|
||||
dig
|
||||
ethtool
|
||||
git
|
||||
iftop
|
||||
|
@ -58,7 +76,6 @@
|
|||
screen
|
||||
speedtest-cli
|
||||
tcpdump
|
||||
tmux
|
||||
traceroute
|
||||
vim
|
||||
wget
|
||||
|
@ -66,25 +83,6 @@
|
|||
|
||||
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 = "";
|
||||
|
||||
system.stateVersion = "20.09";
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
{ hostName, config, lib, ... }:
|
||||
|
||||
let
|
||||
hostConfig = config.site.hosts.${hostName};
|
||||
|
||||
in {
|
||||
networking.firewall = lib.mkIf hostConfig.firewall.enable {
|
||||
lib.mkIf config.site.hosts.${hostName}.firewall.enable {
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
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 -j REJECT
|
||||
ip46tables -A FORWARD -i core -j REJECT --reject-with net-unreach
|
||||
'';
|
||||
extraStopCommands = ''
|
||||
ip46tables -F FORWARD
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ hostName, config, lib, ... }:
|
||||
{ hostName, config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
# pick an address for a net's gateway
|
||||
|
@ -29,7 +29,7 @@ in
|
|||
builtins.mapAttrs (ifName: { gw4, gw6, ... }:
|
||||
let
|
||||
netConfig = config.site.net.${ifName};
|
||||
in lib.mkIf (config.site.net ? ${ifName}) rec {
|
||||
in rec {
|
||||
matchConfig.Name = ifName;
|
||||
|
||||
networkConfig = {
|
||||
|
@ -57,7 +57,7 @@ in
|
|||
optional (gw4 != null) config.site.net.${ifName}.hosts4.${gw4} ++
|
||||
optional (gw6 != null) (findGw6 ifName gw6);
|
||||
|
||||
}) config.site.hosts.${hostName}.interfaces;
|
||||
}) config.site.hosts.${hostName}.physicalInterfaces;
|
||||
};
|
||||
|
||||
# DNS settings
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ pkgs, ... }:
|
||||
{ pkgs, nixpkgs-master, ... }:
|
||||
{
|
||||
boot.kernelModules = [ "kvm-intel" "pppoe" ];
|
||||
boot.kernelParams = [ "nomodeset" ];
|
||||
|
@ -8,20 +8,16 @@
|
|||
time.timeZone = "Europe/Berlin";
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
inetutils # telnet
|
||||
wget vim git screen
|
||||
ipmitool
|
||||
liboping # noping
|
||||
screen
|
||||
vim
|
||||
wget
|
||||
];
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings.PermitRootLogin = "prohibit-password";
|
||||
};
|
||||
services.openssh.enable = true;
|
||||
services.openssh.permitRootLogin = "prohibit-password";
|
||||
|
||||
# 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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{ self, config, lib, pkgs, ... }:
|
||||
{ hostName, self, config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
# Downgrade: lxc-4.0.9 names network interfaces in containers eth0,
|
||||
# and eth1 despite configured differently.
|
||||
lxc = pkgs.lxc.overrideAttrs (_: rec {
|
||||
version = "4.0.6";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://linuxcontainers.org/downloads/lxc/lxc-${version}.tar.gz";
|
||||
sha256 = "0qz4l7mlhq7hx53q606qgvkyzyr01glsw290v8ppzvxn1fydlrci";
|
||||
};
|
||||
});
|
||||
|
||||
# Containers that are run on this host
|
||||
containers =
|
||||
lib.filterAttrs (_: { role, model, ... }:
|
||||
|
@ -10,6 +20,65 @@ let
|
|||
|
||||
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);
|
||||
|
||||
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}) (builtins.attrNames 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
|
||||
build-script = pkgs.writeScriptBin "build-container" ''
|
||||
#! ${pkgs.runtimeShell} -e
|
||||
|
@ -30,7 +99,6 @@ let
|
|||
${ctName})
|
||||
echo Using prebuilt system for container $c
|
||||
SYSTEM=${self.packages.x86_64-linux."${ctName}-rootfs"}
|
||||
CONFIG=${self.packages.x86_64-linux."${ctName}-lxc-config"}
|
||||
;;
|
||||
'') (
|
||||
builtins.attrNames (
|
||||
|
@ -42,8 +110,6 @@ let
|
|||
echo Building $c
|
||||
nix build -o /nix/var/nix/gcroots/lxc/$c zentralwerk-network#$c-rootfs
|
||||
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
|
||||
|
||||
|
@ -56,13 +122,8 @@ let
|
|||
mkdir -p /var/lib/lxc/$c/rootfs/$d
|
||||
done
|
||||
ln -fs $SYSTEM/init /var/lib/lxc/$c/rootfs/init
|
||||
ln -fs $CONFIG /var/lib/lxc/$c/config
|
||||
done
|
||||
|
||||
# Activate all the desired container after all of them are
|
||||
# built
|
||||
set +e
|
||||
for c in $@; do
|
||||
set +e
|
||||
active=$(systemctl is-active lxc@$c)
|
||||
if [[ "$active" = active ]] ; then
|
||||
echo Activating $c
|
||||
|
@ -74,8 +135,8 @@ let
|
|||
echo Starting $c
|
||||
systemctl start lxc@$c
|
||||
fi
|
||||
set -e
|
||||
done
|
||||
set -e
|
||||
'';
|
||||
|
||||
enable-script = pkgs.writeScriptBin "enable-containers" ''
|
||||
|
@ -102,19 +163,64 @@ in
|
|||
|
||||
virtualisation.lxc = lib.mkIf enabled {
|
||||
enable = true;
|
||||
# Container configs live in /etc so that they can be created
|
||||
# through `environment.etc`.
|
||||
systemConfig = ''
|
||||
lxc.lxcpath = /var/lib/lxc
|
||||
lxc.lxcpath = /etc/lxc/containers
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
# `lxc-attach` et al
|
||||
pkgs.lxc build-script
|
||||
lxc build-script
|
||||
# User scripts
|
||||
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 = "${lxc}/share/lxc/config/common.conf";
|
||||
} (builtins.attrNames containers);
|
||||
|
||||
# Systemd service template for LXC containers
|
||||
systemd.services."lxc@" = {
|
||||
|
@ -124,14 +230,14 @@ in
|
|||
"/var/lib/lxc/%i/rootfs/init"
|
||||
"/etc/start-containers"
|
||||
];
|
||||
serviceConfig = with pkgs; {
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${lxc}/bin/lxc-start -F -C -n %i";
|
||||
ExecStop = "${lxc}/bin/lxc-stop -n %i";
|
||||
ExecReload =
|
||||
let
|
||||
script = writeScript "reload-lxc-container.sh" ''
|
||||
#! ${runtimeShell} -e
|
||||
script = pkgs.writeScript "reload-lxc-container.sh" ''
|
||||
#! ${pkgs.runtimeShell} -e
|
||||
|
||||
SYSTEM=$(dirname $(readlink /var/lib/lxc/$1/rootfs/init))
|
||||
exec ${lxc}/bin/lxc-attach -n $1 $SYSTEM/bin/switch-to-configuration switch
|
||||
|
@ -143,8 +249,6 @@ in
|
|||
Restart = "always";
|
||||
RestartSec = "1s";
|
||||
};
|
||||
# Prevent restart on host nixos-rebuild switch
|
||||
restartIfChanged = false;
|
||||
};
|
||||
|
||||
# Starts all the containers after boot
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Server network configuration
|
||||
{ config, lib, ... }:
|
||||
{ hostName, self, config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
# LXC containers on this host
|
||||
|
@ -49,16 +49,9 @@ in
|
|||
} // (
|
||||
builtins.foldl' (result: net: result // {
|
||||
# Bridges are named just like the corresponding net.
|
||||
"${net}" = {
|
||||
netdevConfig = {
|
||||
Kind = "bridge";
|
||||
Name = "${net}";
|
||||
};
|
||||
extraConfig = ''
|
||||
[Bridge]
|
||||
ForwardDelaySec=2
|
||||
STP=true
|
||||
'';
|
||||
"${net}".netdevConfig = {
|
||||
Kind = "bridge";
|
||||
Name = "${net}";
|
||||
};
|
||||
}) {} bridgeNets
|
||||
) // (
|
||||
|
@ -114,7 +107,5 @@ in
|
|||
networkConfig.Bridge = net;
|
||||
};
|
||||
}) {} ctNets;
|
||||
|
||||
wait-online.anyInterface = true;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
{ config, ... }:
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Use the systemd-boot EFI boot loader.
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.version = 2;
|
||||
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.hostId = "01010101";
|
||||
networking.hostId = "12345678";
|
||||
|
||||
boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ata_piix" "hpsa" "usb_storage" "usbhid" "sd_mod" "sr_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
nixpkgs.config.allowBroken = true;
|
||||
boot.zfs.enableUnstable = true;
|
||||
boot.supportedFilesystems = [ "zfs" ];
|
||||
boot.initrd.supportedFilesystems = [ "zfs" ];
|
||||
# Required for Broadcom NICs
|
||||
|
@ -44,8 +45,8 @@
|
|||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-label/ESP";
|
||||
fsType = "vfat";
|
||||
{ device = "/dev/disk/by-uuid/23f17e88-ab7e-4dcc-a119-2ed1b9c2c91d";
|
||||
fsType = "ext2";
|
||||
};
|
||||
|
||||
swapDevices = [ ];
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
{ ... }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ahci" "usbhid" "sd_mod" "sr_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
nixpkgs.config.allowBroken = true;
|
||||
boot.zfs.enableUnstable = true;
|
||||
boot.supportedFilesystems = [ "zfs" ];
|
||||
boot.initrd.supportedFilesystems = [ "zfs" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
fileSystems."/" =
|
||||
{ device = "server2/root";
|
||||
|
@ -39,6 +35,7 @@
|
|||
};
|
||||
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.version = 2;
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
|
||||
networking.hostName = "server2"; # Define your hostname.
|
||||
|
|
|
@ -0,0 +1,479 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
{% macro uci_network_mgmt(ifname) -%}
|
||||
set network.mgmt=interface
|
||||
set network.mgmt.ifname={{ ifname }}
|
||||
set network.mgmt.proto=static
|
||||
set network.mgmt.ipaddr={{ pillar['hosts-inet']['mgmt'][hostname] }}
|
||||
set network.mgmt.netmask=255.255.255.0
|
||||
set network.mgmt.gateway={{ pillar['hosts-inet']['mgmt']['mgmt-gw'] }}
|
||||
set network.mgmt.ip6addr={{ pillar['hosts-inet6']['dn42']['mgmt'][hostname] }}/64
|
||||
set network.mgmt.ip6gw={{ pillar['hosts-inet6']['dn42']['mgmt']['mgmt-gw'] }}
|
||||
delete network.mgmt.dns
|
||||
add_list network.mgmt.dns={{ pillar['hosts-inet']['serv']['dnscache'] }}
|
||||
add_list network.mgmt.dns={{ pillar['hosts-inet6']['dn42']['serv']['dnscache'] }}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- if conf.get('firstboot') %}
|
||||
ssh-keygen -R 192.168.1.1
|
||||
|
||||
ssh root@192.168.1.1 \
|
||||
"ash -e -x" <<__SSH__
|
||||
{%- else %}
|
||||
ssh root@{{ pillar['hosts-inet']['mgmt'][hostname] }} \
|
||||
"ash -e -x" <<__SSH__
|
||||
{%- endif %}
|
||||
|
||||
# Set root password
|
||||
echo -e '{{ conf['password'] }}\n{{ conf['password'] }}' | passwd
|
||||
|
||||
# add ssh pubkey
|
||||
echo "{{ pillar['ssh']['pubkey'] }}" > /etc/dropbear/authorized_keys
|
||||
|
||||
# System configuration
|
||||
uci batch <<__UCI__
|
||||
set system.@system[0].hostname={{ hostname }}
|
||||
set dhcp.@dnsmasq[0].enabled=0
|
||||
set system.@system[0].log_ip={{ pillar['hosts-inet']['mgmt']['logging'] }}
|
||||
set system.@system[0].log_proto=udp
|
||||
|
||||
delete network.globals.ula_prefix
|
||||
delete network.lan
|
||||
delete network.wan
|
||||
delete network.wan6
|
||||
delete wireless.default_radio0
|
||||
delete wireless.default_radio1
|
||||
|
||||
{%- set bridges = {} %}
|
||||
{%- if conf.get('lan-access') %}
|
||||
{%- do bridges.__setitem__(conf['lan-access'], True) %}
|
||||
{%- endif %}
|
||||
{%- for path, radio in conf['radios'].items() %}
|
||||
{%- for ssid, ssidconf in radio['ssids'].items() %}
|
||||
{%- do bridges.__setitem__(ssidconf['net'], True) %}
|
||||
{%- endfor %}
|
||||
{%- endfor %}
|
||||
|
||||
{%- if conf['model'] == 'TL-WDR4300' %}
|
||||
{# These models have a shared Ethernet chip for LAN/WAN and therefore need switching #}
|
||||
set network.@switch[0]=switch
|
||||
set network.@switch[0].reset=1
|
||||
set network.@switch[0].enable=1
|
||||
set network.@switch[0].enable_vlan=1
|
||||
set network.@switch[0].name=switch0
|
||||
set network.@switch_vlan[0]=switch_vlan
|
||||
set network.@switch_vlan[0].device='switch0'
|
||||
set network.@switch_vlan[0].vlan='1'
|
||||
set network.@switch_vlan[0].ports='0t 1t'
|
||||
set network.@switch_vlan[0].comment='mgmt'
|
||||
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
|
||||
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
|
||||
set network.@switch_vlan[{{ switchnum }}].device='switch0'
|
||||
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='0t 1t 2 3 4 5'
|
||||
{%- else %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='0t 1t'
|
||||
{%- endif %}
|
||||
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
|
||||
{%- endfor %}
|
||||
|
||||
{{ uci_network_mgmt('eth0.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
|
||||
{%- endfor %}
|
||||
|
||||
{%- elif conf['model'] == 'TL-WR1043ND' %}
|
||||
{# These models have a shared Ethernet chip with separate CPU ports for LAN/WAN and therefore need switching #}
|
||||
set network.@switch[0]=switch
|
||||
set network.@switch[0].reset=1
|
||||
set network.@switch[0].enable=1
|
||||
set network.@switch[0].enable_vlan=1
|
||||
set network.@switch[0].name=switch0
|
||||
set network.@switch_vlan[0]=switch_vlan
|
||||
set network.@switch_vlan[0].device='switch0'
|
||||
set network.@switch_vlan[0].vlan='1'
|
||||
set network.@switch_vlan[0].ports='5t 6t'
|
||||
set network.@switch_vlan[0].comment='mgmt'
|
||||
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
|
||||
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
|
||||
set network.@switch_vlan[{{ switchnum }}].device='switch0'
|
||||
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
|
||||
# 0: eth1; 1-4: LAN ports in reverse; 5: WAN port; 6: eth0
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='0 1 2 3 4 5t'
|
||||
{%- else %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='5t 6t'
|
||||
{%- endif %}
|
||||
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
|
||||
{%- endfor %}
|
||||
|
||||
{{ uci_network_mgmt('eth0.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
set network.{{ net }}.ifname='eth1'
|
||||
{%- else %}
|
||||
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
|
||||
{%- elif conf['model'] == 'TL-Archer-C7v2' %}
|
||||
{# These models have a shared Ethernet chip with separate CPU ports for LAN/WAN and therefore need switching #}
|
||||
set network.@switch[0]=switch
|
||||
set network.@switch[0].reset=1
|
||||
set network.@switch[0].enable=1
|
||||
set network.@switch[0].enable_vlan=1
|
||||
set network.@switch[0].name=switch0
|
||||
set network.@switch_vlan[0]=switch_vlan
|
||||
set network.@switch_vlan[0].device='switch0'
|
||||
set network.@switch_vlan[0].vlan='1'
|
||||
set network.@switch_vlan[0].ports='1t 6t'
|
||||
set network.@switch_vlan[0].comment='mgmt'
|
||||
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
|
||||
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
|
||||
set network.@switch_vlan[{{ switchnum }}].device='switch0'
|
||||
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
|
||||
# 0: eth1; 1: WAN port; 2-5: LAN ports; 6: eth0
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='0 1t 2 3 4 5'
|
||||
{%- else %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='1t 6t'
|
||||
{%- endif %}
|
||||
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
|
||||
{%- endfor %}
|
||||
|
||||
{{ uci_network_mgmt('eth0.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
set network.{{ net }}.ifname='eth1'
|
||||
{%- else %}
|
||||
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
|
||||
{%- elif conf['model'] == 'TL-Archer-C7v4' or conf['model'] == 'TL-Archer-C7v5' %}
|
||||
set network.@switch[0]=switch
|
||||
set network.@switch[0].reset=1
|
||||
set network.@switch[0].enable=1
|
||||
set network.@switch[0].enable_vlan=1
|
||||
set network.@switch[0].name=switch0
|
||||
set network.@switch_vlan[0]=switch_vlan
|
||||
set network.@switch_vlan[0].device='switch0'
|
||||
set network.@switch_vlan[0].vlan='1'
|
||||
set network.@switch_vlan[0].ports='0t 1t'
|
||||
set network.@switch_vlan[0].comment='mgmt'
|
||||
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
|
||||
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
|
||||
set network.@switch_vlan[{{ switchnum }}].device='switch0'
|
||||
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
|
||||
# 0: eth0; 1: WAN port; 2-5: LAN ports
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='0t 1t 2 3 4 5'
|
||||
{%- else %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='0t 1t'
|
||||
{%- endif %}
|
||||
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
|
||||
{%- endfor %}
|
||||
|
||||
{{ uci_network_mgmt('eth0.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
|
||||
{%- endfor %}
|
||||
|
||||
{%- elif conf['model'] == 'TL-WR1043NDv4' or conf['model'] == 'TL-WR1043NDv5' %}
|
||||
set network.@switch[0]=switch
|
||||
set network.@switch[0].reset=1
|
||||
set network.@switch[0].enable=1
|
||||
set network.@switch[0].enable_vlan=1
|
||||
set network.@switch[0].name=switch0
|
||||
set network.@switch_vlan[0]=switch_vlan
|
||||
set network.@switch_vlan[0].device='switch0'
|
||||
set network.@switch_vlan[0].vlan='1'
|
||||
set network.@switch_vlan[0].ports='0t 5t'
|
||||
set network.@switch_vlan[0].comment='mgmt'
|
||||
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
|
||||
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
|
||||
set network.@switch_vlan[{{ switchnum }}].device='switch0'
|
||||
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
|
||||
# 0: eth0; 1-4: LAN ports; 5: WAN port
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='0t 1 2 3 4 5t'
|
||||
{%- else %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='0t 5t'
|
||||
{%- endif %}
|
||||
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
|
||||
{%- endfor %}
|
||||
|
||||
{{ uci_network_mgmt('eth0.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
|
||||
{%- endfor %}
|
||||
|
||||
{%- elif conf['model'] == 'TL-WR841Nv8' %}
|
||||
{# Like v9 but with eth0/1 switched #}
|
||||
set network.@switch[0].reset=1
|
||||
set network.@switch[0].enable=1
|
||||
set network.@switch[0].enable_vlan=0
|
||||
|
||||
{{ uci_network_mgmt('eth0.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
{# Add WAN VLAN to bridge #}
|
||||
{%- set ports = ['eth0.' ~ pillar['vlans'][net]] %}
|
||||
{# Add LAN ports to bridge #}
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
{%- do ports.append('eth1') %}
|
||||
{%- endif %}
|
||||
|
||||
set network.{{ net }}.ifname='{{ ' '.join(ports) }}'
|
||||
{%- endfor %}
|
||||
|
||||
{%- elif conf['model'] == 'TL-WR740Nv4' %}
|
||||
{# Separate eth0/1 interfaces for LAN/WAN #}
|
||||
{# eth0 - Port 0: eth0, Port 2: LAN1, Port 3: LAN2, Port 4: LAN3, Port 1: LAN4 #}
|
||||
{# eth1 - WAN #}
|
||||
set network.@switch[0].reset=1
|
||||
set network.@switch[0].enable=1
|
||||
set network.@switch[0].enable_vlan=0
|
||||
|
||||
{{ uci_network_mgmt('eth1.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
{# Add WAN VLAN to bridge #}
|
||||
{%- set ports = ['eth1.' ~ pillar['vlans'][net]] %}
|
||||
{# Add LAN ports to bridge #}
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
{%- do ports.append('eth0') %}
|
||||
{%- endif %}
|
||||
|
||||
set network.{{ net }}.ifname='{{ ' '.join(ports) }}'
|
||||
{%- endfor %}
|
||||
|
||||
{%- elif conf['model'] == 'TL-WA901NDv3' or conf['model'] == 'Ubnt-UniFi-AP-AC-LR' %}
|
||||
{# Only eth0 exists, no switch #}
|
||||
|
||||
{{ uci_network_mgmt('eth0.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
{# Add WAN VLAN to bridge #}
|
||||
set network.{{ net }}.ifname='{{ 'eth0.' ~ pillar['vlans'][net] }}'
|
||||
{%- endfor %}
|
||||
|
||||
{%- elif conf['model'] == 'Ubnt-UAP-nanoHD' %}
|
||||
{# no switch, eth0 exists but is not usable, using "lan" instead #}
|
||||
|
||||
{{ uci_network_mgmt('lan.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
{# Add WAN VLAN to bridge #}
|
||||
set network.{{ net }}.ifname='{{ 'lan.' ~ pillar['vlans'][net] }}'
|
||||
{%- endfor %}
|
||||
|
||||
{%- elif conf['model'] == 'DIR-615H1' or conf['model'] == 'DIR-615D4' %}
|
||||
{# All DIR-615 share the same port layout #}
|
||||
delete network.lan_dev
|
||||
delete network.wan_dev
|
||||
{# switch is cpu port 6, wan:cpu port 4, lan port 1 is cpu port 3, lan port 2 is 2 etc #}
|
||||
set network.@switch[0]=switch
|
||||
set network.@switch[0].reset=1
|
||||
set network.@switch[0].enable=1
|
||||
set network.@switch[0].enable_vlan=1
|
||||
set network.@switch[0].name=switch0
|
||||
set network.@switch_vlan[0]=switch_vlan
|
||||
set network.@switch_vlan[0].device='switch0'
|
||||
set network.@switch_vlan[0].vlan='1'
|
||||
set network.@switch_vlan[0].ports='4t 6t'
|
||||
set network.@switch_vlan[0].comment='mgmt'
|
||||
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
|
||||
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
|
||||
set network.@switch_vlan[{{ switchnum }}].device='switch0'
|
||||
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='0 1 2 3 4t 6t'
|
||||
{%- else %}
|
||||
set network.@switch_vlan[{{ switchnum }}].ports='4t 6t'
|
||||
{%- endif %}
|
||||
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
|
||||
{%- endfor %}
|
||||
|
||||
{{ uci_network_mgmt('eth0.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
#TODO: this should consider lan-access
|
||||
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
|
||||
{%- endfor %}
|
||||
|
||||
{%- else %}
|
||||
{# All other models may have separate Ethernet chips for LAN/WAN #}
|
||||
set network.@switch[0].reset=1
|
||||
set network.@switch[0].enable=1
|
||||
set network.@switch[0].enable_vlan=0
|
||||
|
||||
{{ uci_network_mgmt('eth1.1') }}
|
||||
|
||||
{%- for net in bridges.keys() %}
|
||||
|
||||
set network.{{ net }}=interface
|
||||
set network.{{ net }}.type=bridge
|
||||
set network.{{ net }}.proto=static
|
||||
{# Add WAN VLAN to bridge #}
|
||||
{%- set ports = ['eth1.' ~ pillar['vlans'][net]] %}
|
||||
{# Add LAN ports to bridge #}
|
||||
{%- if conf.get('lan-access') == net %}
|
||||
{%- do ports.append('eth0') %}
|
||||
{%- endif %}
|
||||
|
||||
set network.{{ net }}.ifname='{{ ' '.join(ports) }}'
|
||||
{%- endfor %}
|
||||
|
||||
{%- endif %}
|
||||
|
||||
{%- set index = { 'radio': 0, 'iface': 0 } %}
|
||||
{%- for path, radio in conf['radios'].items() %}
|
||||
set wireless.radio{{ index.radio }}=wifi-device
|
||||
set wireless.radio{{ index.radio }}.type=mac80211
|
||||
set wireless.radio{{ index.radio }}.country=DE
|
||||
set wireless.radio{{ index.radio }}.channel={{ radio['channel'] }}
|
||||
set wireless.radio{{ index.radio }}.path={{ path }}
|
||||
set wireless.radio{{ index.radio }}.hwmode={{ radio.get('hwmode') or '11n' }}
|
||||
set wireless.radio{{ index.radio }}.htmode={{ radio.get('htmode') or 'HT20' }}
|
||||
set wireless.radio{{ index.radio }}.noscan=1
|
||||
delete wireless.radio{{ index.radio }}.disabled
|
||||
|
||||
{%- for ssid, ssidconf in radio['ssids'].items() %}
|
||||
set wireless.wifi{{ index.iface }}=wifi-iface
|
||||
{%- if radio['channel'] < 15 %}
|
||||
{%- if conf['version'] == "nightly" %}
|
||||
{%- set ifprefix = 'wlan2_' %}
|
||||
{%- else %}
|
||||
{%- set ifprefix = 'wlan2-' %}
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
{%- if conf['version'] == "nightly" %}
|
||||
{%- set ifprefix = 'wlan5_' %}
|
||||
{%- else %}
|
||||
{%- set ifprefix = 'wlan5-' %}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- if ssidconf.get('wpa-eap') %}
|
||||
{%- if conf['version'] == "nightly" %}
|
||||
{%- set ifsuffix = '_eap' %}
|
||||
{%- else %}
|
||||
{%- set ifsuffix = '-eap' %}
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
{%- set ifsuffix = '' %}
|
||||
{%- endif %}
|
||||
set wireless.wifi{{ index.iface }}.ifname={{ ifprefix }}{{ ssidconf['net'] }}{{ ifsuffix }}
|
||||
set wireless.wifi{{ index.iface }}.device=radio{{ index.radio }}
|
||||
set wireless.wifi{{ index.iface }}.ssid='{{ ssid }}'
|
||||
set wireless.wifi{{ index.iface }}.mode=ap
|
||||
set wireless.wifi{{ index.iface }}.network={{ ssidconf['net'] }}
|
||||
{%- if ssidconf.get('psk') %}
|
||||
set wireless.wifi{{ index.iface }}.encryption=psk2
|
||||
set wireless.wifi{{ index.iface }}.key='{{ ssidconf['psk'] }}'
|
||||
{%- elif ssidconf.get('wpa-eap') %}
|
||||
set wireless.wifi{{ index.iface }}.encryption=wpa2
|
||||
set wireless.wifi{{ index.iface }}.server='{{ ssidconf['wpa-eap']['server'] }}'
|
||||
set wireless.wifi{{ index.iface }}.port='{{ ssidconf['wpa-eap']['port'] }}'
|
||||
set wireless.wifi{{ index.iface }}.auth_secret='{{ ssidconf['wpa-eap']['secret'] }}'
|
||||
{%- else %}
|
||||
set wireless.wifi{{ index.iface }}.encryption=none
|
||||
delete wireless.wifi{{ index.iface }}.key
|
||||
{%- endif %}
|
||||
set wireless.wifi{{ index.iface }}.mcast_rate=18000
|
||||
|
||||
{%- set x = index.update({ 'iface': index.iface + 1 }) %}
|
||||
{%- endfor %}
|
||||
{%- set x = index.update({ 'radio': index.radio + 1 }) %}
|
||||
{%- endfor %}
|
||||
|
||||
commit
|
||||
__UCI__
|
||||
|
||||
# Cronjob that makes sure WiFi is only visible when server with all
|
||||
# the gateways is reachable
|
||||
cat >/etc/crontabs/root <<__CRON__
|
||||
* * * * * /usr/sbin/wifi-on-link.sh
|
||||
__CRON__
|
||||
cat >/usr/sbin/wifi-on-link.sh <<__SH__
|
||||
#!/bin/sh
|
||||
|
||||
if (ping -c 1 -W 3 {{ pillar['hosts-inet']['mgmt']['mgmt-gw'] }}) ; then
|
||||
REACHABLE=y
|
||||
else
|
||||
REACHABLE=n
|
||||
fi
|
||||
|
||||
if [ "\\\$(cat /sys/class/net/wlan2-pub/operstate)" == "up" ] ; then
|
||||
UP=y
|
||||
else
|
||||
UP=n
|
||||
fi
|
||||
|
||||
{%- if conf.get("error-led") %}
|
||||
ERROR_LED=/sys/class/leds/{{ conf["error-led"] }}/brightness
|
||||
[ \\\$REACHABLE = y ] && echo 0 > \\\$ERROR_LED
|
||||
[ \\\$REACHABLE = n ] && echo 1 > \\\$ERROR_LED
|
||||
{%- endif %}
|
||||
|
||||
[ \\\$REACHABLE = y ] && [ \\\$UP = n ] && wifi up
|
||||
[ \\\$REACHABLE = n ] && [ \\\$UP = y ] && wifi down
|
||||
|
||||
exit 0
|
||||
__SH__
|
||||
chmod a+rx /usr/sbin/wifi-on-link.sh
|
||||
/etc/init.d/cron restart
|
||||
|
||||
for svc in dnsmasq uhttpd ; do
|
||||
rm /etc/rc.d/*\$svc
|
||||
/etc/init.d/\$svc stop
|
||||
done
|
||||
|
||||
{%- if conf.get('firstboot') %}
|
||||
reboot
|
||||
{%- endif %}
|
||||
|
||||
__SSH__
|
||||
|
||||
echo "Base configuration done \\o/"
|
||||
echo "Later run: `dirname $0`/ap_install_collectd.sh {{ pillar['hosts-inet']['mgmt'][hostname] }}"
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
for HOST in $@ ; do
|
||||
ssh root@$HOST \
|
||||
|
|
|
@ -1,51 +1,29 @@
|
|||
{ self, nixpkgs, system, openwrt-imagebuilder }:
|
||||
{ self, nixpkgs, system }:
|
||||
|
||||
let
|
||||
inherit (self.lib) config;
|
||||
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
inherit (pkgs) lib;
|
||||
|
||||
export-openwrt-models = pkgs.writeText "openwrt-models.nix" (
|
||||
lib.generators.toPretty {} self.lib.openwrtModels
|
||||
export-config-file = builtins.toFile "config.nix" (
|
||||
nixpkgs.lib.generators.toPretty {} config
|
||||
);
|
||||
export-config = pkgs.writeText "config.nix" (
|
||||
lib.generators.toPretty {} (
|
||||
lib.recursiveUpdate
|
||||
config
|
||||
{ site.dns.localZones = self.lib.dns.localZones; }
|
||||
));
|
||||
|
||||
encrypt-secrets = pkgs.writeScriptBin "encrypt-secrets" ''
|
||||
#! ${pkgs.runtimeShell} -e
|
||||
|
||||
cd config
|
||||
exec ${pkgs.gnupg}/bin/gpg --armor --batch --trust-model always \
|
||||
--encrypt -r 1F0F221A7483B5EF5D103D8B32EBADE870BAF886 \
|
||||
< secrets-production.nix \
|
||||
> secrets-production.nix.gpg
|
||||
'';
|
||||
decrypt-secrets = pkgs.writeScriptBin "decrypt-secrets" ''
|
||||
#! ${pkgs.runtimeShell} -e
|
||||
|
||||
cd config
|
||||
[ -e secrets-production.nix ] && \
|
||||
mv secrets-production.nix secrets-production.nix.old
|
||||
exec ${pkgs.gnupg}/bin/gpg -d \
|
||||
> secrets-production.nix \
|
||||
< secrets-production.nix.gpg
|
||||
'';
|
||||
switch-to-production = pkgs.writeScriptBin "decrypt-secrets" ''
|
||||
#! ${pkgs.runtimeShell} -e
|
||||
|
||||
${decrypt-secrets}/bin/decrypt-secrets
|
||||
|
||||
cd config
|
||||
cp secrets-production.nix secrets.nix
|
||||
export-config = pkgs.runCommandLocal "config.nix" {} ''
|
||||
cp ${export-config-file} $out
|
||||
'';
|
||||
|
||||
network-cypher-graphs = import ./network-cypher-graphs.nix { inherit config pkgs; };
|
||||
network-graphs = import ./network-graphs.nix { inherit config lib pkgs; };
|
||||
salt-pillar-file = hostName: builtins.toFile "${hostName}.yaml" (
|
||||
nixpkgs.lib.generators.toPretty {} (self.lib.saltPillarFor hostName)
|
||||
);
|
||||
salt-pillars = builtins.foldl' (result: hostName: result // {
|
||||
"${hostName}-pillar" = pkgs.runCommandLocal "${hostName}-pillar.nix" {} ''
|
||||
cp ${salt-pillar-file hostName} $out
|
||||
'';
|
||||
}) {} (
|
||||
builtins.filter (hostName:
|
||||
builtins.elem config.site.hosts.${hostName}.role [ "server" "container" ]
|
||||
) (builtins.attrNames config.site.hosts)
|
||||
);
|
||||
|
||||
mkRootfs = hostName:
|
||||
self.nixosConfigurations.${hostName}.config.system.build.toplevel;
|
||||
|
@ -55,20 +33,7 @@ let
|
|||
"${hostName}-rootfs" = mkRootfs hostName;
|
||||
}) {} (
|
||||
builtins.attrNames (
|
||||
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")
|
||||
nixpkgs.lib.filterAttrs (_: { role, ... }: builtins.elem role ["server" "container"])
|
||||
config.site.hosts
|
||||
)
|
||||
);
|
||||
|
@ -76,33 +41,18 @@ let
|
|||
vm-packages =
|
||||
builtins.foldl' (rootfs: hostName: rootfs // {
|
||||
"${hostName}-vm" = self.nixosConfigurations.${hostName}.config.system.build.vm
|
||||
.overrideAttrs (_oa: {
|
||||
.overrideAttrs (oa: {
|
||||
meta.mainProgram = "run-${hostName}-vm";
|
||||
});
|
||||
}) {} (
|
||||
builtins.attrNames (
|
||||
lib.filterAttrs (_: { role, ... }: role == "server")
|
||||
nixpkgs.lib.filterAttrs (_: { role, ... }: role == "server")
|
||||
config.site.hosts
|
||||
)
|
||||
);
|
||||
|
||||
openwrt = import ./openwrt { inherit self nixpkgs system openwrt-imagebuilder; };
|
||||
|
||||
openwrt-packages = builtins.foldl' (images: hostName: images // {
|
||||
${hostName} = pkgs.writeScriptBin "${hostName}.sh" (
|
||||
openwrt.sshScript hostName
|
||||
);
|
||||
"${hostName}-image" = openwrt.buildImage hostName;
|
||||
}) {} (
|
||||
builtins.attrNames (
|
||||
lib.filterAttrs (_: { role, ... }:
|
||||
role == "ap"
|
||||
) config.site.hosts
|
||||
)
|
||||
);
|
||||
|
||||
device-templates = import ./device-templates.nix {
|
||||
inherit self nixpkgs system openwrt;
|
||||
inherit self nixpkgs system;
|
||||
};
|
||||
|
||||
dns-slaves = import ./dns-slaves.nix {
|
||||
|
@ -112,30 +62,7 @@ let
|
|||
starlink = import ./starlink {
|
||||
inherit pkgs;
|
||||
};
|
||||
|
||||
subnetplans = import ./subnetplans.nix {
|
||||
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 {
|
||||
inherit self nixpkgs system;
|
||||
};
|
||||
|
||||
homepage = pkgs.callPackage ./homepage {
|
||||
inherit self;
|
||||
};
|
||||
in
|
||||
rootfs-packages // lxc-configs // vm-packages // device-templates // openwrt-packages // network-graphs // network-cypher-graphs // starlink // subnetplans // {
|
||||
inherit export-openwrt-models export-config dns-slaves
|
||||
encrypt-secrets decrypt-secrets switch-to-production
|
||||
homepage gateway-report switch-report vlan-report
|
||||
;
|
||||
salt-pillars // rootfs-packages // vm-packages // device-templates // starlink // {
|
||||
inherit export-config dns-slaves;
|
||||
}
|
||||
|
|
|
@ -1,23 +1,50 @@
|
|||
{ self, nixpkgs, system, openwrt }:
|
||||
{ self, nixpkgs, system }:
|
||||
with nixpkgs.lib;
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
config = self.lib.config;
|
||||
|
||||
templates = role: {
|
||||
ap = _: ./ap.sh;
|
||||
switch = model: ../../salt/switches + "/${model}.expect";
|
||||
}.${role};
|
||||
replaceNetmasks = template:
|
||||
builtins.toFile (builtins.baseNameOf template) (
|
||||
builtins.replaceStrings [''{%- import_yaml "netmasks.yaml" as netmasks -%}''] [""] (
|
||||
builtins.readFile template
|
||||
)
|
||||
);
|
||||
expandTemplate = name: template: data:
|
||||
self.lib.expandSaltTemplate name (replaceNetmasks template) data;
|
||||
wrapNixShell = script:
|
||||
pkgs.runCommand (builtins.baseNameOf script) {
|
||||
src = script;
|
||||
} ''
|
||||
(
|
||||
echo '#! /usr/bin/env nix-shell'
|
||||
echo '#! nix-shell -i "expect -f" -p expect telnet'
|
||||
cat $src
|
||||
) > $out
|
||||
chmod a+x $out
|
||||
'';
|
||||
|
||||
device-scripts =
|
||||
builtins.mapAttrs (hostName: hostConfig@{ role, model, ... }:
|
||||
pkgs.writeScriptBin "${hostName}.sh" (
|
||||
let
|
||||
args = {
|
||||
inherit self hostName config hostConfig pkgs;
|
||||
};
|
||||
in import (./switches + "/${model}.nix") (
|
||||
args // import ./switches/shared.nix args
|
||||
)
|
||||
builtins.mapAttrs (hostname: { role, model, ... }:
|
||||
wrapNixShell (
|
||||
expandTemplate "${hostname}.sh" (templates role model) ({
|
||||
inherit hostname;
|
||||
pillar = config.salt-pillar;
|
||||
netmasks = self.lib.netmasks;
|
||||
logging = config.salt-pillar.hosts-inet.mgmt.logging;
|
||||
} // optionalAttrs (config.salt-pillar.switches ? ${hostname}) {
|
||||
switch = config.salt-pillar.switches.${hostname};
|
||||
} // optionalAttrs (config.salt-pillar.cpe ? ${hostname}) {
|
||||
conf = config.salt-pillar.cpe.${hostname};
|
||||
})
|
||||
)
|
||||
) (
|
||||
filterAttrs (_: { role, model, ... }:
|
||||
role == "switch" && model != "dumb"
|
||||
filterAttrs (_: { role, ... }:
|
||||
role == "ap" || role == "switch"
|
||||
) config.site.hosts
|
||||
);
|
||||
|
||||
|
@ -31,8 +58,8 @@ let
|
|||
chmod a+x $out/bin/ap_install_collectd.sh
|
||||
'' +
|
||||
builtins.concatStringsSep "\n" (
|
||||
map (hostName:
|
||||
"ln -s ${device-scripts.${hostName}}/bin/${hostName}.sh $out/bin/${hostName}.sh"
|
||||
map (hostname:
|
||||
"ln -s ${device-scripts.${hostname}} $out/bin/${hostname}.sh"
|
||||
) (builtins.attrNames device-scripts)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -15,13 +15,13 @@ let
|
|||
in
|
||||
|
||||
writeText "named.slave.conf" (
|
||||
lib.concatMapStringsSep "\n" ({ name, ... }: ''
|
||||
lib.concatMapStringsSep "\n" ({ name, ns, ... }: ''
|
||||
zone "${name}" IN {
|
||||
type slave;
|
||||
masters {${mastersStr} };
|
||||
file "/var/lib/bind/slave/${name}.zone";
|
||||
allow-notify { ${mastersStr} };
|
||||
allow-query { any; };
|
||||
allow-notify {${mastersStr} };
|
||||
allow-query { all; };
|
||||
};
|
||||
'') (
|
||||
# public zones only
|
||||
|
|
|
@ -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))}
|
||||
''
|
|
@ -1,74 +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
|
||||
cp *.{html,css,png,svg} $DIR/
|
||||
|
||||
mkdir -p $out/nix-support
|
||||
echo doc homepage $DIR index.html >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
<figure>
|
||||
<img src="@img@" alt="@caption@">
|
||||
<figcaption>@caption@</figcaption>
|
||||
</figure>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -1,3 +0,0 @@
|
|||
Contact: mailto:astro@spaceboyz.net
|
||||
Preferred-Languages: en, de
|
||||
Hiring: https://www.c3d2.de/space.html
|
|
@ -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 |
|
@ -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 |
|
@ -1,172 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
let
|
||||
inherit (pkgs) lib runCommand curl;
|
||||
|
||||
netColor = net:
|
||||
if net == "core"
|
||||
then "grey"
|
||||
else if net == "mgmt"
|
||||
then "brown"
|
||||
else if builtins.elem net [ "c3d2" "serv" "cluster" ]
|
||||
then "green"
|
||||
else if builtins.match "up.+" net != null ||
|
||||
builtins.match "anon.+" net != null
|
||||
then "red"
|
||||
else if builtins.match "priv.+" net != null
|
||||
then "blue"
|
||||
else "black";
|
||||
|
||||
dedupLinks = links:
|
||||
builtins.attrValues (
|
||||
builtins.foldl' (result: { pair, attrs ? {}, startLabel ? "" }:
|
||||
let
|
||||
peer1 = builtins.elemAt pair 0;
|
||||
peer2 = builtins.elemAt pair 1;
|
||||
sorted =
|
||||
if peer1 < peer2
|
||||
then { from = peer1; to = peer2; }
|
||||
else { from = peer2; to = peer1; };
|
||||
key = with sorted; "${from} ${to}";
|
||||
prevAttrs =
|
||||
if result ? ${key}
|
||||
then result.${key}.attrs
|
||||
else {};
|
||||
newAttrs = attrs // (
|
||||
if peer1 < peer2
|
||||
then { taillabel = startLabel; }
|
||||
else { headlabel = startLabel; }
|
||||
);
|
||||
in result // {
|
||||
"${key}" = {
|
||||
inherit (sorted) from to;
|
||||
attrs = prevAttrs // newAttrs;
|
||||
};
|
||||
}
|
||||
) {} links
|
||||
);
|
||||
|
||||
toCypher = { nodes, links, ... }: ''
|
||||
${lib.concatMapStringsSep " " (name:
|
||||
let
|
||||
nodeAttrs = nodes.${name};
|
||||
id = builtins.replaceStrings ["-"] ["_"] name;
|
||||
nodeType = nodeAttrs.type;
|
||||
in ''
|
||||
CREATE (${id}:`${nodeType}`
|
||||
{label:"${name}",
|
||||
${lib.concatMapStringsSep ", " (attr:
|
||||
let
|
||||
value = nodeAttrs.${attr};
|
||||
in
|
||||
if builtins.isString value
|
||||
then "${attr}:\"${value}\""
|
||||
else "${attr}:${toString value}"
|
||||
) (builtins.attrNames nodeAttrs)}
|
||||
}
|
||||
)
|
||||
'') (builtins.attrNames nodes)}
|
||||
|
||||
${lib.concatMapStringsSep " " ({ from, to, attrs }:
|
||||
let
|
||||
idFrom = builtins.replaceStrings ["-"] ["_"] from;
|
||||
idTo = builtins.replaceStrings ["-"] ["_"] to;
|
||||
in ''
|
||||
CREATE (${idFrom})-[:CONNECTED_TO
|
||||
{${lib.concatMapStringsSep ", " (attr:
|
||||
let
|
||||
value = attrs.${attr};
|
||||
in
|
||||
if builtins.isString value
|
||||
then "${attr}:\"${value}\""
|
||||
else "${attr}:${toString value}"
|
||||
) (builtins.attrNames attrs)}
|
||||
}]->(${idTo})
|
||||
'') (dedupLinks links)}
|
||||
'';
|
||||
|
||||
cypherGraph = args@{ name, ... }:
|
||||
runCommand "${name}.cypher" {
|
||||
src = builtins.toFile "${name}.cypher" (
|
||||
toCypher args
|
||||
);
|
||||
} ''
|
||||
sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' $src | tr -d '\n' > $out
|
||||
'';
|
||||
|
||||
in rec {
|
||||
# Layer 2
|
||||
physical-cypher-graph = cypherGraph {
|
||||
name = "physical";
|
||||
nodes =
|
||||
builtins.mapAttrs (_: { role, ... }: {
|
||||
type = {
|
||||
switch = "Switch";
|
||||
server = "Server";
|
||||
container = "Container";
|
||||
ap = "AccessPoint";
|
||||
client = "Client";
|
||||
}.${role};
|
||||
}) (
|
||||
lib.filterAttrs (_: { links, ... }:
|
||||
links != {}
|
||||
) config.site.hosts
|
||||
) // builtins.mapAttrs (_: _: {
|
||||
type = "Other";
|
||||
}) (
|
||||
lib.filterAttrs (net: _:
|
||||
builtins.match "up.*" net != null
|
||||
) config.site.net
|
||||
);
|
||||
links =
|
||||
builtins.concatMap (hostName:
|
||||
map (link: {
|
||||
pair = [ hostName link ];
|
||||
startLabel = ( #lib.optionalString (config.site.hosts.${hostName}.links ? ${link}) (
|
||||
lib.concatStringsSep ","
|
||||
config.site.hosts.${hostName}.links.${link}.ports
|
||||
);
|
||||
}) (
|
||||
builtins.filter (link:
|
||||
config.site.hosts ? ${link}
|
||||
||
|
||||
builtins.match "up.*" link != null
|
||||
) (builtins.attrNames config.site.hosts.${hostName}.links)
|
||||
)
|
||||
) (builtins.attrNames config.site.hosts);
|
||||
};
|
||||
# Layer 3
|
||||
logical-cypher-graph =
|
||||
let
|
||||
containers =
|
||||
lib.filterAttrs (_: { role, ... }:
|
||||
role == "container"
|
||||
) config.site.hosts;
|
||||
in
|
||||
cypherGraph {
|
||||
name = "logical";
|
||||
nodes =
|
||||
builtins.foldl' (result: hostName:
|
||||
result // {
|
||||
"${hostName}".type = "Container";
|
||||
} // builtins.mapAttrs (_: _: {
|
||||
type = "Container";
|
||||
}) containers.${hostName}.interfaces
|
||||
) {} (builtins.attrNames containers);
|
||||
links =
|
||||
builtins.concatMap (hostName:
|
||||
map (net: {
|
||||
pair = [ hostName net ];
|
||||
attrs.color = netColor net;
|
||||
}) (builtins.attrNames containers.${hostName}.interfaces)
|
||||
) (builtins.attrNames containers);
|
||||
};
|
||||
|
||||
|
||||
import-network-graphs = with pkgs; writeScriptBin "import-network-graphs" ''
|
||||
#! ${runtimeShell} -e
|
||||
|
||||
${curl}/bin/curl -X POST -H 'Content-type: application/json' http://localhost:7474/db/data/transaction/commit -d "{\"statements\": [{\"statement\": \"$(cat ${physical-cypher-graph})\"}]}"
|
||||
${curl}/bin/curl -X POST -H 'Content-type: application/json' http://localhost:7474/db/data/transaction/commit -d "{\"statements\": [{\"statement\": \"$(cat ${logical-cypher-graph})\"}]}"
|
||||
'';
|
||||
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
netColor = net:
|
||||
if net == "core"
|
||||
then "grey"
|
||||
else if net == "mgmt"
|
||||
then "brown"
|
||||
else if net == "roof"
|
||||
then "orange"
|
||||
else if net == "flpk"
|
||||
then "yellow"
|
||||
else if builtins.elem net [ "c3d2" "serv" "cluster" ]
|
||||
then "green"
|
||||
else if builtins.match "up.+" net != null ||
|
||||
builtins.match "anon.+" net != null
|
||||
then "red"
|
||||
else if builtins.match "priv.+" net != null
|
||||
then "blue"
|
||||
else "black";
|
||||
|
||||
dedupLinks = links:
|
||||
builtins.attrValues (
|
||||
builtins.foldl' (result: { pair, attrs ? {}, startLabel ? "" }:
|
||||
let
|
||||
peer1 = builtins.elemAt pair 0;
|
||||
peer2 = builtins.elemAt pair 1;
|
||||
sorted =
|
||||
if peer1 < peer2
|
||||
then { from = peer1; to = peer2; }
|
||||
else { from = peer2; to = peer1; };
|
||||
key = with sorted; "${from} ${to}";
|
||||
prevAttrs =
|
||||
if result ? ${key}
|
||||
then result.${key}.attrs
|
||||
else {};
|
||||
newAttrs = attrs // (
|
||||
if peer1 < peer2
|
||||
then { taillabel = startLabel; }
|
||||
else { headlabel = startLabel; }
|
||||
);
|
||||
in result // {
|
||||
"${key}" = {
|
||||
inherit (sorted) from to;
|
||||
attrs = prevAttrs // newAttrs;
|
||||
};
|
||||
}
|
||||
) {} links
|
||||
);
|
||||
|
||||
toDot = { nodes, links, ... }: ''
|
||||
digraph {
|
||||
graph [splines=ortho, nodesep=64]
|
||||
node []
|
||||
edge [arrowhead=none, labelfontsize=8]
|
||||
|
||||
${lib.concatMapStrings (name:
|
||||
let
|
||||
nodeAttrs = nodes.${name};
|
||||
in ''
|
||||
"${name}" [${lib.concatMapStringsSep ", " (attr:
|
||||
let
|
||||
value = nodeAttrs.${attr};
|
||||
in
|
||||
if builtins.isString value
|
||||
then "${attr}=\"${value}\""
|
||||
else "${attr}=${toString value}"
|
||||
) (builtins.attrNames nodeAttrs)}]
|
||||
'') (builtins.attrNames nodes)}
|
||||
|
||||
${lib.concatMapStrings ({ from, to, attrs }: ''
|
||||
"${from}" -> "${to}" [${lib.concatMapStringsSep ", " (attr:
|
||||
let
|
||||
value = attrs.${attr};
|
||||
in
|
||||
if builtins.isString value
|
||||
then "${attr}=\"${value}\""
|
||||
else "${attr}=${toString value}"
|
||||
) (builtins.attrNames attrs)}]
|
||||
'') (dedupLinks links)}
|
||||
}
|
||||
'';
|
||||
renderGraph = args@{ name, engine, ... }:
|
||||
pkgs.runCommand "${name}.png" {
|
||||
src = builtins.toFile "${name}.dot" (
|
||||
toDot args
|
||||
);
|
||||
} ''
|
||||
echo $src
|
||||
${pkgs.graphviz-nox}/bin/${engine} -Tpng $src > $out
|
||||
'';
|
||||
|
||||
in rec {
|
||||
# Layer 2
|
||||
physical-graph = renderGraph {
|
||||
name = "physical";
|
||||
engine = "fdp";
|
||||
nodes =
|
||||
builtins.mapAttrs (_: { role, ... }: {
|
||||
shape = {
|
||||
switch = "box";
|
||||
server = "house";
|
||||
container = "oval";
|
||||
ap = "doubleoctagon";
|
||||
client = "doublecircle";
|
||||
}.${role};
|
||||
}) (
|
||||
lib.filterAttrs (_: { links, ... }:
|
||||
links != {}
|
||||
) config.site.hosts
|
||||
) // builtins.mapAttrs (_: _: {
|
||||
shape = "circle";
|
||||
}) (
|
||||
lib.filterAttrs (net: _:
|
||||
builtins.match "up.*" net != null
|
||||
) config.site.net
|
||||
);
|
||||
links =
|
||||
builtins.concatMap (hostName:
|
||||
map (link: {
|
||||
pair = [ hostName link ];
|
||||
startLabel = ( #lib.optionalString (config.site.hosts.${hostName}.links ? ${link}) (
|
||||
lib.concatStringsSep ","
|
||||
config.site.hosts.${hostName}.links.${link}.ports
|
||||
);
|
||||
}) (
|
||||
builtins.filter (link:
|
||||
config.site.hosts ? ${link}
|
||||
||
|
||||
builtins.match "up.*" link != null
|
||||
) (builtins.attrNames config.site.hosts.${hostName}.links)
|
||||
)
|
||||
) (builtins.attrNames config.site.hosts);
|
||||
};
|
||||
|
||||
# Layer 3
|
||||
logical-graph =
|
||||
let
|
||||
containers =
|
||||
lib.filterAttrs (_: { role, ... }:
|
||||
role == "container"
|
||||
) config.site.hosts;
|
||||
in
|
||||
renderGraph {
|
||||
name = "logical";
|
||||
engine = "sfdp";
|
||||
nodes =
|
||||
builtins.foldl' (result: hostName:
|
||||
result // {
|
||||
"${hostName}".shape = "box";
|
||||
} // builtins.mapAttrs (_: _: {
|
||||
shape = "circle";
|
||||
}) containers.${hostName}.interfaces
|
||||
) {} (builtins.attrNames containers);
|
||||
links =
|
||||
builtins.concatMap (hostName:
|
||||
map (net: {
|
||||
pair = [ hostName net ];
|
||||
attrs.color = netColor net;
|
||||
}) (builtins.attrNames containers.${hostName}.interfaces)
|
||||
) (builtins.attrNames containers);
|
||||
};
|
||||
|
||||
network-graphs = pkgs.runCommand "network-graphs" {} ''
|
||||
DIR=$out/share/doc/zentralwerk
|
||||
mkdir -p $DIR
|
||||
ln -s ${physical-graph} $DIR/physical.png
|
||||
ln -s ${logical-graph} $DIR/logical.png
|
||||
|
||||
mkdir -p $out/nix-support
|
||||
echo doc image $DIR/physical.png >> $out/nix-support/hydra-build-products
|
||||
echo doc image $DIR/logical.png >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
}
|
|
@ -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)
|
||||
);
|
||||
|
||||
}
|
|
@ -1,528 +0,0 @@
|
|||
{ self, pkgs, hostName }:
|
||||
with pkgs;
|
||||
with lib;
|
||||
let
|
||||
inherit (self.lib) config;
|
||||
hostConfig = config.site.hosts.${hostName};
|
||||
|
||||
ports = self.lib.getOpenwrtPorts hostConfig.model;
|
||||
|
||||
uciDeleteAll = key: ''
|
||||
while uci -q delete ${key}[-1]; do :; done
|
||||
'';
|
||||
|
||||
openwrtModel = self.lib.getOpenwrtModel hostConfig.model;
|
||||
|
||||
hasSwitch =
|
||||
if hostConfig.model == "ubnt_unifiac-mesh"
|
||||
# ours don't come with a switch.
|
||||
then false
|
||||
else
|
||||
openwrtModel ? ports
|
||||
&&
|
||||
any ({ switch ? null, ... }: switch != null)
|
||||
(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 =
|
||||
let
|
||||
portByIndex = builtins.foldl' (result: port:
|
||||
let
|
||||
key = if port ? index
|
||||
then port.index
|
||||
else if port ? interface
|
||||
then port.interface
|
||||
else "How to identify port ${generators.toPretty {} port}?";
|
||||
in result // {
|
||||
"${key}" = port;
|
||||
}
|
||||
) {} (builtins.attrValues openwrtModel.ports);
|
||||
in
|
||||
concatMapStringsSep ", " (index:
|
||||
"${index}:${
|
||||
if portByIndex.${index} ? port
|
||||
then portByIndex.${index}.port
|
||||
else if portByIndex.${index} ? interface
|
||||
then portByIndex.${index}.interface
|
||||
else throw "${hostName}: What is port ${generators.toPretty {} portByIndex.${index}.port}?"
|
||||
}"
|
||||
) (
|
||||
builtins.sort builtins.lessThan (
|
||||
builtins.attrNames portByIndex
|
||||
)
|
||||
);
|
||||
|
||||
switchHostInterface =
|
||||
let
|
||||
hostPorts = sort builtins.lessThan (
|
||||
map ({ interface, ... }: interface) (
|
||||
builtins.attrValues (
|
||||
filterAttrs (_: { type, ... }: type == "host")
|
||||
openwrtModel.ports
|
||||
)
|
||||
)
|
||||
);
|
||||
in if hostPorts == []
|
||||
then throw "${hostName}: No host ports found for OpenWRT model ${hostConfig.model}"
|
||||
else builtins.head hostPorts;
|
||||
|
||||
switchPortIndices = f:
|
||||
map ({ index, ... }: index) (
|
||||
builtins.attrValues (
|
||||
filterAttrs (_: port: port ? index && f port)
|
||||
openwrtModel.ports
|
||||
)
|
||||
);
|
||||
|
||||
trunked = map (index: "${index}t");
|
||||
|
||||
# OpenWRT switch ports string ("0t 1t 2 3 4") for a network (VLAN)
|
||||
switchPortsConfig = net:
|
||||
concatStringsSep " " (
|
||||
# Host interface
|
||||
trunked (switchPortIndices ({ interface ? null, ... }: interface == switchHostInterface))
|
||||
++
|
||||
# Access networks
|
||||
optionals (hostConfig.links ? ${net}) (
|
||||
builtins.concatMap (port':
|
||||
switchPortIndices ({ port ? null, ... }: port == port')
|
||||
) hostConfig.links.${net}.ports
|
||||
)
|
||||
++
|
||||
# Trunk ports
|
||||
builtins.concatMap (port':
|
||||
trunked (switchPortIndices ({ port ? null, ... }: port == port'))
|
||||
) (
|
||||
builtins.concatMap ({ ports, ... }: ports) (
|
||||
builtins.attrValues (
|
||||
filterAttrs (_: { trunk, ... }:
|
||||
trunk
|
||||
) hostConfig.links
|
||||
))
|
||||
)
|
||||
);
|
||||
|
||||
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:
|
||||
let
|
||||
inherit (config.site.net.${net}) vlan;
|
||||
in unique (
|
||||
builtins.concatMap ({ trunk, ports, switch ? null, ... }:
|
||||
builtins.concatMap (port:
|
||||
builtins.concatMap (portData:
|
||||
if portData ? port && port == portData.port
|
||||
then [ ((
|
||||
if portData ? switch
|
||||
then switchHostInterface
|
||||
else if portData ? interface
|
||||
then portData.interface
|
||||
else throw "${hostName}: Cannot find interface for ${port} on OpenWRT model ${hostConfig.model}"
|
||||
) + (
|
||||
if trunk || switch != null
|
||||
then ".${toString vlan}"
|
||||
else ""
|
||||
)) ]
|
||||
else []
|
||||
) (builtins.attrValues openwrtModel.ports)
|
||||
++
|
||||
optionals (hostConfig.interfaces ? ${port} && vlan != null) [ "${port}.${toString vlan}" ]
|
||||
) ports
|
||||
) (
|
||||
builtins.attrValues (
|
||||
filterAttrs (link: { nets, ... }:
|
||||
link == net || builtins.elem net nets
|
||||
) hostConfig.links
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
mgmtInterface =
|
||||
if hasDSA
|
||||
then "br0.${toString config.site.net.mgmt.vlan}"
|
||||
else
|
||||
let
|
||||
mgmtInterfaces = networkInterfaces "mgmt";
|
||||
in if builtins.length mgmtInterfaces == 1
|
||||
then builtins.head mgmtInterfaces
|
||||
else "br-mgmt";
|
||||
|
||||
in
|
||||
''
|
||||
# Set root password
|
||||
echo -e '${hostConfig.password}\n${hostConfig.password}' | passwd
|
||||
|
||||
# add ssh pubkeys
|
||||
${concatMapStrings (sshPubKey: ''
|
||||
echo "${sshPubKey}" > /etc/dropbear/authorized_keys
|
||||
'') config.site.sshPubKeys}
|
||||
|
||||
# System configuration
|
||||
${uciDeleteAll "network.@switch_vlan"}
|
||||
${uciDeleteAll "wireless.@wifi-iface"}
|
||||
|
||||
uci set system.@system[0].hostname=${hostName}
|
||||
uci set dhcp.@dnsmasq[0].enabled=0
|
||||
uci set system.@system[0].log_ip=${config.site.net.mgmt.hosts4.logging}
|
||||
uci set system.@system[0].log_proto=udp
|
||||
|
||||
${optionalString hasSwitch ''
|
||||
# Switch config
|
||||
# Ports ${portsDoc}
|
||||
${concatMapStrings (net: ''
|
||||
uci add network switch_vlan
|
||||
uci set network.@switch_vlan[-1]=switch_vlan
|
||||
uci set network.@switch_vlan[-1].device='switch0'
|
||||
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].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:
|
||||
config.site.net.${net1}.vlan < config.site.net.${net2}.vlan
|
||||
) (
|
||||
unique (
|
||||
builtins.concatMap ({ nets, ... }: nets)
|
||||
(builtins.attrValues hostConfig.links)
|
||||
)
|
||||
)
|
||||
)}
|
||||
''}
|
||||
|
||||
# mgmt network
|
||||
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='${
|
||||
if builtins.length (networkInterfaces "mgmt") > 0
|
||||
then concatStringsSep " " (networkInterfaces "mgmt")
|
||||
else throw "${hostName}: No interface for mgmt"
|
||||
}'
|
||||
''}
|
||||
uci set network.mgmt.proto=static
|
||||
${optionalString (hostConfig.interfaces.mgmt.type == "bridge") ''
|
||||
uci set network.mgmt.type=bridge
|
||||
''}
|
||||
uci set network.mgmt.ipaddr=${config.site.net.mgmt.hosts4.${hostName}}
|
||||
uci set network.mgmt.netmask=${self.lib.netmasks.${toString config.site.net.mgmt.subnet4Len}}
|
||||
uci set network.mgmt.gateway=${config.site.net.mgmt.hosts4.mgmt-gw}
|
||||
uci set network.mgmt.ip6addr=${config.site.net.mgmt.hosts6.dn42.${hostName}}/64
|
||||
uci set network.mgmt.ip6gw=${config.site.net.mgmt.hosts6.dn42.mgmt-gw}
|
||||
uci -q delete network.mgmt.dns || true
|
||||
uci add_list network.mgmt.dns=${config.site.net.serv.hosts4.dnscache}
|
||||
uci add_list network.mgmt.dns=${config.site.net.serv.hosts6.dn42.dnscache}
|
||||
|
||||
uci -q delete network.globals.ula_prefix || true
|
||||
# delete unused networks
|
||||
${concatMapStrings (net:
|
||||
optionalString (! hostConfig.interfaces ? ${net}) ''
|
||||
uci -q delete network.${net} || true
|
||||
''
|
||||
) ([ "lan" "wan" "wan6" ] ++ builtins.attrNames config.site.net)}
|
||||
|
||||
# bridged and static networks
|
||||
${concatMapStrings (net:
|
||||
let
|
||||
iface = hostConfig.interfaces.${net};
|
||||
in optionalString (net != "mgmt" && builtins.elem iface.type ["bridge" "phys"]) ''
|
||||
uci set network.${net}=interface
|
||||
${optionalString (iface.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
|
||||
${if hasDSA
|
||||
then ''
|
||||
uci set network.${net}.device='br0.${toString config.site.net.${net}.vlan}'
|
||||
'' else ''
|
||||
uci set network.${net}.ifname='${concatStringsSep " " (networkInterfaces net)}'
|
||||
''}
|
||||
${optionalString (config.site.net.${net}.mtu != null) ''
|
||||
uci set network.${net}.mtu=${toString config.site.net.${net}.mtu}
|
||||
''}
|
||||
|
||||
|
||||
${optionalString (config.site.net.${net}.hosts4 ? ${hostName}) ''
|
||||
# address in net
|
||||
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}}
|
||||
''}
|
||||
${concatMapStrings (hosts6: optionalString (hosts6 ? ${hostName}) ''
|
||||
uci set network.${net}.ip6addr=${hosts6.${hostName}}/64
|
||||
'') (builtins.attrValues config.site.net.${net}.hosts6)}
|
||||
'') (builtins.attrNames hostConfig.interfaces)
|
||||
}
|
||||
|
||||
# vxlan trunks
|
||||
${concatMapStrings (name:
|
||||
let
|
||||
iface = hostConfig.interfaces.${name};
|
||||
in optionalString (iface.type == "vxlan") ''
|
||||
uci set network.${name}=interface
|
||||
uci set network.${name}.proto=vxlan6
|
||||
uci set network.${name}.peer6addr='${iface.vxlan.peer}'
|
||||
uci set network.${name}.port=4789
|
||||
uci set network.${name}.rxcsum=0
|
||||
uci set network.${name}.txcsum=0
|
||||
uci set network.${name}.delegate=0
|
||||
'') (builtins.attrNames hostConfig.interfaces)
|
||||
}
|
||||
|
||||
${uciDeleteAll "wireless.radio"}
|
||||
uci -q delete wireless.default_radio0 || true
|
||||
uci -q delete wireless.default_radio1 || true
|
||||
${concatStrings (imap0 (index: path:
|
||||
let
|
||||
radioConfig = hostConfig.wifi.${path};
|
||||
ifPrefix = if radioConfig.channel < 15
|
||||
then "wlan2"
|
||||
else "wlan5";
|
||||
in ''
|
||||
uci set wireless.radio${toString index}=wifi-device
|
||||
uci set wireless.radio${toString index}.type=mac80211
|
||||
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}.path=${path}
|
||||
uci set wireless.radio${toString index}.htmode=${radioConfig.htmode}
|
||||
uci set wireless.radio${toString index}.noscan=1
|
||||
uci -q delete wireless.radio${toString index}.disabled || true
|
||||
|
||||
${concatMapStrings (ssid:
|
||||
let
|
||||
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 ''
|
||||
uci add wireless wifi-iface
|
||||
uci set wireless.@wifi-iface[-1].ifname=${ifname}
|
||||
uci set wireless.@wifi-iface[-1].device=radio${toString index}
|
||||
uci set wireless.@wifi-iface[-1].ssid='${ssid}'
|
||||
uci set wireless.@wifi-iface[-1].mode=${ssidConfig.mode}
|
||||
uci set wireless.@wifi-iface[-1].network=${ssidConfig.net}
|
||||
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)
|
||||
then ''
|
||||
uci set wireless.@wifi-iface[-1].key='${ssidConfig.psk}'
|
||||
''
|
||||
else ''
|
||||
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 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
|
||||
|
||||
# Add hotfixes for MTU settings
|
||||
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
|
||||
# the gateways is reachable
|
||||
cat >/etc/crontabs/root <<__CRON__
|
||||
* * * * * /usr/sbin/wifi-on-link.sh
|
||||
* * * * * /usr/sbin/usteer-info.sh
|
||||
__CRON__
|
||||
cat >/usr/sbin/wifi-on-link.sh <<__SH__
|
||||
#!/bin/sh
|
||||
|
||||
if (ping -c 1 -W 3 ${config.site.net.mgmt.hosts4.mgmt-gw}) ; then
|
||||
REACHABLE=y
|
||||
else
|
||||
REACHABLE=n
|
||||
fi
|
||||
|
||||
if [ "\\\$(cat /sys/class/net/wlan2-pub/operstate)" == "up" ] ; then
|
||||
UP=y
|
||||
else
|
||||
UP=n
|
||||
fi
|
||||
|
||||
if [ -e /sys/class/leds/blue:dome ] ; then
|
||||
ERROR_LED=/sys/class/leds/blue:dome/brightness
|
||||
[ \\\$REACHABLE = y ] && echo 0 > \\\$ERROR_LED
|
||||
[ \\\$REACHABLE = n ] && echo 1 > \\\$ERROR_LED
|
||||
fi
|
||||
|
||||
[ \\\$REACHABLE = y ] && [ \\\$UP = n ] && wifi up
|
||||
[ \\\$REACHABLE = n ] && [ \\\$UP = y ] && wifi down
|
||||
|
||||
exit 0
|
||||
__SH__
|
||||
chmod a+rx /usr/sbin/wifi-on-link.sh
|
||||
/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
|
||||
rm -f /etc/rc.d/*\$svc
|
||||
/etc/init.d/\$svc stop || true
|
||||
done
|
||||
''
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/sh
|
||||
[ -p /tmp/usteer-info ] || exit 0
|
||||
exec /bin/ubus call usteer local_info > /tmp/usteer-info
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
gem "ipaddress_2", "~> 0.14"
|
|
@ -1,13 +0,0 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
ipaddress_2 (0.14.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
ipaddress_2 (~> 0.14)
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.4
|
|
@ -1,15 +0,0 @@
|
|||
{ pkgs ? import <nixpkgs> {} }:
|
||||
with pkgs;
|
||||
let
|
||||
gems = bundlerEnv {
|
||||
name = "gems-for-subnetplan";
|
||||
gemdir = ./.;
|
||||
};
|
||||
in stdenv.mkDerivation rec {
|
||||
name = "subnetplan";
|
||||
buildInputs = [ gems.wrappedRuby ];
|
||||
buildCommand = ''
|
||||
install -D -m755 ${./render.rb} $out/bin/${name}
|
||||
patchShebangs $out/bin/${name}
|
||||
'';
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
ipaddress_2 = {
|
||||
groups = ["default"];
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1wdy1ka0i9mncjqid2kv3ng6gi95y5xb9ykl0ar8lnrriia42v1c";
|
||||
type = "gem";
|
||||
};
|
||||
version = "0.14.0";
|
||||
};
|
||||
}
|
|
@ -1,151 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'ipaddress_2'
|
||||
require 'erb'
|
||||
|
||||
TABLE_WIDTH = 8
|
||||
|
||||
class Subnet
|
||||
attr_reader :addr, :desc
|
||||
attr_accessor :addr_visible
|
||||
|
||||
def initialize addr, desc
|
||||
@addr = addr
|
||||
@desc = desc
|
||||
@addr_visible = false
|
||||
end
|
||||
end
|
||||
|
||||
class Group
|
||||
attr_accessor :net, :blocks
|
||||
|
||||
def initialize net, blocks
|
||||
@net = net
|
||||
@blocks = blocks
|
||||
end
|
||||
end
|
||||
|
||||
class Block
|
||||
attr_accessor :label, :name, :span
|
||||
|
||||
def initialize label, name
|
||||
@label = label
|
||||
@name = name
|
||||
@span = 1
|
||||
end
|
||||
end
|
||||
|
||||
nets = []
|
||||
while line = gets
|
||||
a, desc = line.split(/ /, 2)
|
||||
addr = IPAddress.parse a
|
||||
desc.chomp!
|
||||
|
||||
nets << Subnet.new(addr, desc)
|
||||
end
|
||||
|
||||
nets.sort_by! { |net| net.addr }
|
||||
|
||||
collisions = 0
|
||||
prev = nil
|
||||
nets.each do |net|
|
||||
if prev and (net.addr.include?(prev.addr) or prev.addr.include?(net.addr))
|
||||
STDERR.puts "#{prev.addr} and #{net.addr} overlap"
|
||||
collisions += 1
|
||||
end
|
||||
prev = net
|
||||
end
|
||||
exit 1 if collisions > 0
|
||||
|
||||
GROUP_PREFIX = 19
|
||||
groups = {}
|
||||
nets.each do |net|
|
||||
if net.addr.prefix > GROUP_PREFIX
|
||||
group = net.addr.supernet(GROUP_PREFIX).to_s
|
||||
else
|
||||
group = net.addr.to_s
|
||||
end
|
||||
(groups[group] ||= []) << net
|
||||
end
|
||||
|
||||
max_prefix = [groups.collect { nets.collect { |net| net.addr.prefix }.max }.max, 64].min
|
||||
groups = groups.collect do |group, nets|
|
||||
allnet = nets[0].addr.clone
|
||||
while allnet.prefix > 0 and not allnet.include?(nets[nets.size - 1].addr)
|
||||
allnet = allnet.supernet(allnet.prefix - 1)
|
||||
end
|
||||
|
||||
blocks = []
|
||||
row = []
|
||||
x = 0
|
||||
allnet.subnet(max_prefix).each do |addr|
|
||||
net = nets.select { |net| net.addr.include? addr }[0]
|
||||
label = net ? "#{addr}/#{net.addr.prefix}" : addr.to_s
|
||||
name = net ? net.desc : ""
|
||||
if row.last and name != "" and row.last.name == name
|
||||
row.last.span += 1
|
||||
else
|
||||
row << Block.new(label, name)
|
||||
end
|
||||
x += 1
|
||||
if x >= TABLE_WIDTH
|
||||
blocks << row
|
||||
row = []
|
||||
x = 0
|
||||
end
|
||||
end
|
||||
blocks << row if row.size > 0
|
||||
|
||||
Group.new(allnet, blocks)
|
||||
end
|
||||
|
||||
def background_color desc
|
||||
case desc
|
||||
when "core"
|
||||
"#9F9F9F"
|
||||
when "mgmt"
|
||||
"#FF3F3F"
|
||||
when "roof"
|
||||
"#FF4F2F"
|
||||
when "c3d2", "flpk"
|
||||
"yellow"
|
||||
when "serv", "cluster"
|
||||
"orange"
|
||||
when "pub"
|
||||
"#7FFF7F"
|
||||
when /priv(\d+)/
|
||||
"hsl(240, 80%, #{60 + 5 * ($1.to_i % 8)}%)"
|
||||
else
|
||||
"white"
|
||||
end
|
||||
end
|
||||
|
||||
html = ERB::new <<~EOF
|
||||
<html>
|
||||
<head>
|
||||
<title>Subnetwork Plan</title>
|
||||
<style>
|
||||
table {
|
||||
margin: 3rem auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table border="1">
|
||||
<% groups.each do |group| %>
|
||||
<tr>
|
||||
<th colspan="<%= TABLE_WIDTH %>"><%= group.net.to_string %></th>
|
||||
</tr>
|
||||
<% group.blocks.each do |row| %>
|
||||
<tr>
|
||||
<% row.each do |block| %>
|
||||
<td colspan="<%= block.span %>" style="background-color: <%= background_color(block.name) %>"><%= block.label %> <%= block.name %></td>
|
||||
<% end %>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
EOF
|
||||
puts html.result
|
|
@ -1,54 +0,0 @@
|
|||
{ self, nixpkgs, system }:
|
||||
|
||||
with nixpkgs.legacyPackages.${system};
|
||||
let
|
||||
config = self.lib.config;
|
||||
in
|
||||
rec {
|
||||
subnetplan4 =
|
||||
stdenv.mkDerivation {
|
||||
name = "subnetplan4.html";
|
||||
src = builtins.toFile "subnets4.txt" (
|
||||
lib.concatMapStringsSep "\n" (net:
|
||||
"${config.site.net.${net}.subnet4} ${net}"
|
||||
) (builtins.attrNames (
|
||||
lib.filterAttrs (_: { subnet4, ... }: subnet4 != null)
|
||||
config.site.net
|
||||
))
|
||||
);
|
||||
buildInputs = [
|
||||
(import ./subnetplan { inherit pkgs; })
|
||||
];
|
||||
buildCommand = ''
|
||||
subnetplan < $src > $out
|
||||
'';
|
||||
};
|
||||
|
||||
subnetplan6 =
|
||||
stdenv.mkDerivation {
|
||||
name = "subnetplan6.html";
|
||||
src = builtins.toFile "subnets6.txt" (
|
||||
lib.concatMapStrings (net:
|
||||
lib.concatMapStrings (ctx: ''
|
||||
${config.site.net.${net}.subnets6.${ctx}} ${net}
|
||||
'') (builtins.attrNames config.site.net.${net}.subnets6)
|
||||
) (builtins.attrNames config.site.net)
|
||||
);
|
||||
buildInputs = [
|
||||
(import ./subnetplan { inherit pkgs; })
|
||||
];
|
||||
buildCommand = ''
|
||||
subnetplan < $src > $out
|
||||
'';
|
||||
};
|
||||
|
||||
subnetplans = runCommand "subnetplans" {} ''
|
||||
DIR=$out/share/doc/zentralwerk
|
||||
mkdir -p $DIR $out/nix-support
|
||||
|
||||
${lib.concatMapStrings (pkg: ''
|
||||
ln -s ${pkg} $DIR/${pkg.name}
|
||||
echo doc report $DIR/${pkg.name} >> $out/nix-support/hydra-build-products
|
||||
'') [ subnetplan4 subnetplan6 ]}
|
||||
'';
|
||||
}
|
|
@ -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} (`${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"}
|
||||
''
|
|
@ -1,167 +0,0 @@
|
|||
# http://h20628.www2.hp.com/km-ext/kmcsdirect/emr_na-c02586144-1.pdf
|
||||
{ self, pkgs, hostName, config, hostConfig
|
||||
, sort, sortBy, sortNetsByVlan
|
||||
, ... }:
|
||||
with pkgs;
|
||||
with lib;
|
||||
''
|
||||
#! ${expect}/bin/expect -f
|
||||
|
||||
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 "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 "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"
|
||||
''
|
|
@ -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"
|
||||
''
|
|
@ -1,154 +0,0 @@
|
|||
# http://ftp.hp.com/pub/networking/software/2600-2800-4100-6108-MgmtConfig-Oct2005-59906023.pdf
|
||||
{ self, pkgs, hostName, config, hostConfig
|
||||
, sort, sortBy, sortNetsByVlan
|
||||
, ... }:
|
||||
with pkgs;
|
||||
with lib;
|
||||
''
|
||||
#! ${expect}/bin/expect -f
|
||||
|
||||
spawn ${inetutils}/bin/telnet ${config.site.net.mgmt.hosts4.${hostName}}
|
||||
expect "Press any key to continue"
|
||||
send "\r"
|
||||
expect "assword: "
|
||||
send "${hostConfig.password}\r"
|
||||
expect "#"
|
||||
send "configure terminal\r"
|
||||
expect "(config)# "
|
||||
|
||||
send "hostname ${hostName}\r"
|
||||
expect "(config)# "
|
||||
send "snmp-server location \"${hostConfig.location}\"\r"
|
||||
expect "(config)# "
|
||||
send "snmp-server contact \"astro@spaceboyz.net\"\r"
|
||||
expect "(config)# "
|
||||
send "password manager\r"
|
||||
expect "New password for Manager: "
|
||||
send "${hostConfig.password}\r"
|
||||
expect "Please retype new password for Manager: "
|
||||
send "${hostConfig.password}\r"
|
||||
expect "(config)# "
|
||||
|
||||
# TODO: ssh, password
|
||||
|
||||
# Enable Logging
|
||||
send "logging ${config.site.net.mgmt.hosts4.logging}\r"
|
||||
expect "(config)# "
|
||||
send "logging facility local6\r"
|
||||
expect "(config)# "
|
||||
|
||||
# TODO ntp
|
||||
# timesync sntp
|
||||
# ip timep manual {#ntp#} interval 10
|
||||
|
||||
${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})#"
|
||||
|
||||
send "jumbo\r"
|
||||
expect "(vlan-${vlan})#"
|
||||
|
||||
${optionalString (hosts4 ? ${hostName}) ''
|
||||
# Actually only used for mgmt_vlan, switches are not routers
|
||||
send "ip address ${hostAddr4} ${netmask}\r"
|
||||
expect "(vlan-${vlan})#"
|
||||
''}
|
||||
|
||||
send "exit\r"
|
||||
expect "(config)# "
|
||||
|
||||
${if net == "mgmt"
|
||||
then ''
|
||||
send "management-vlan ${vlan}\r"
|
||||
expect "(config)# "
|
||||
'' else ''
|
||||
# If not mgmt, reset all VLAN mappings
|
||||
send "no vlan ${vlan} tagged all\r"
|
||||
expect "(config)# "
|
||||
send "no vlan ${vlan} untagged all\r"
|
||||
expect "(config)# "
|
||||
''}
|
||||
''
|
||||
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;
|
||||
port0 = builtins.head linkConfig.ports;
|
||||
isBond =
|
||||
builtins.length linkConfig.ports > 1
|
||||
||
|
||||
hasInfix "-" port0
|
||||
||
|
||||
hasInfix "," port0;
|
||||
ports = concatStringsSep "," linkConfig.ports;
|
||||
in
|
||||
if isTrunk && isBond
|
||||
then ''
|
||||
send "interface ${ports} lacp active\r"
|
||||
expect "(config)# "
|
||||
send "trunk ${ports} trk${linkConfig.group} lacp\r"
|
||||
expect "(config)# "
|
||||
|
||||
${concatMapStrings (vlan: ''
|
||||
send "vlan ${toString vlan} tagged trk${linkConfig.group}\r"
|
||||
expect "(config)# "
|
||||
'') (sort linkConfig.vlans)}
|
||||
''
|
||||
|
||||
else if isTrunk
|
||||
then ''
|
||||
send "no trunk ${ports}\r"
|
||||
expect "(config)# "
|
||||
send "no interface ${ports} lacp\r"
|
||||
expect "(config)# "
|
||||
|
||||
${concatMapStrings (vlan: ''
|
||||
send "vlan ${toString vlan} tagged ${ports}\r"
|
||||
expect "(config)# "
|
||||
'') (sort linkConfig.vlans)}
|
||||
''
|
||||
|
||||
else ''
|
||||
send "no trunk ${ports}\r"
|
||||
expect "(config)# "
|
||||
|
||||
send "vlan ${toString netConfig.vlan} untagged ${ports}\r"
|
||||
expect "(config)# "
|
||||
''
|
||||
) (sortBy (link: hostConfig.links.${link}.ports)
|
||||
(builtins.attrNames hostConfig.links)
|
||||
)}
|
||||
|
||||
send "exit\r"
|
||||
expect "${hostName}# "
|
||||
|
||||
send "write memory\r"
|
||||
expect "${hostName}# "
|
||||
send "exit\r"
|
||||
expect "${hostName}> "
|
||||
send "exit\r"
|
||||
expect "Do you want to log out "
|
||||
expect "y/n]? "
|
||||
send "y"
|
||||
''
|
|
@ -1,145 +0,0 @@
|
|||
# http://static.tp-link.com/res/down/doc/TL-SG3210(UN)_V2.0_CLI_.pdf
|
||||
{ self, pkgs, hostName, config, hostConfig
|
||||
, sort, sortBy, sortNetsByVlan
|
||||
, ... }:
|
||||
with pkgs;
|
||||
with lib;
|
||||
''
|
||||
#! ${pkgs.expect}/bin/expect -f
|
||||
|
||||
spawn ${pkgs.inetutils}/bin/telnet ${config.site.net.mgmt.hosts4.${hostName}}
|
||||
expect "Password:"
|
||||
send "${hostConfig.password}\r"
|
||||
expect ">"
|
||||
send "\r"
|
||||
expect ">"
|
||||
send "enable\r"
|
||||
expect "Password:"
|
||||
send "${hostConfig.password}\r"
|
||||
expect "#"
|
||||
send "configure\r"
|
||||
expect "(config)#"
|
||||
|
||||
send "enable secret 0 ${hostConfig.password}\r"
|
||||
expect "(config)#"
|
||||
#send "enable password 0 ${hostConfig.password}\r"
|
||||
#expect "(config)#"
|
||||
send "service password-encryption\r"
|
||||
expect "(config)#"
|
||||
send "user name admin privilege admin secret 0 ${hostConfig.password}\r"
|
||||
expect "(config)#"
|
||||
|
||||
send "hostname \"${hostName}\"\r"
|
||||
expect "(config)#"
|
||||
send "location \"${hostConfig.location}\"\r"
|
||||
expect "(config)#"
|
||||
|
||||
send "logging host index 1 ${config.site.net.mgmt.hosts4.logging} 6\r"
|
||||
expect "(config)#"
|
||||
|
||||
send "ip management-vlan ${toString config.site.net.mgmt.vlan}\r"
|
||||
expect "(config)#"
|
||||
send "ip ssh server\r"
|
||||
expect "(config)#"
|
||||
send "telnet enable\r"
|
||||
expect "(config)#"
|
||||
send "line vty 0 15\r"
|
||||
expect "(config-line)#"
|
||||
send "password 0 ${hostConfig.password}\r"
|
||||
expect "(config-line)#"
|
||||
send "exit\r"
|
||||
expect "(config)#"
|
||||
|
||||
${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 ''
|
||||
${optionalString (net != "mgmt") ''
|
||||
send "vlan ${vlan}\r"
|
||||
expect "(config-vlan)#"
|
||||
send "name \"${net}\"\r"
|
||||
expect "(config-vlan)#"
|
||||
send "exit\r"
|
||||
expect "(config)#"
|
||||
''}
|
||||
|
||||
send "interface vlan ${vlan}\r"
|
||||
expect "(config-if)#"
|
||||
${optionalString (hosts4 ? ${hostName}) ''
|
||||
# Actually only used for mgmt_vlan, switches are not routers
|
||||
send "ip address ${hostAddr4} ${netmask}\r"
|
||||
expect "(config-if)#"
|
||||
''}
|
||||
send "exit\r"
|
||||
expect "(config)#"
|
||||
''
|
||||
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;
|
||||
port0 = builtins.head linkConfig.ports;
|
||||
isBond =
|
||||
builtins.length linkConfig.ports > 1
|
||||
||
|
||||
hasInfix "-" port0;
|
||||
vlans = concatStringsSep "," (map toString (sort linkConfig.vlans));
|
||||
ports = concatMapStringsSep "," (port:
|
||||
"1/0/${port}"
|
||||
) linkConfig.ports;
|
||||
in
|
||||
if isTrunk
|
||||
then ''
|
||||
send "interface range gigabitEthernet ${ports}\r"
|
||||
expect "(config-if-range)#"
|
||||
send "switchport mode trunk\r"
|
||||
expect "(config-if-range)#"
|
||||
${if isBond
|
||||
then ''
|
||||
send "channel-group ${linkConfig.group} mode active\r"
|
||||
expect "(config-if-range)#"
|
||||
#send "port-channel load-balance src-dst-ip\r"
|
||||
#expect "(config-if-range)#"
|
||||
'' else ''
|
||||
send "no channel-group\r"
|
||||
expect "(config-if-range)#"
|
||||
''}
|
||||
send "switchport trunk allowed vlan ${vlans}\r"
|
||||
expect "(config-if-range)#"
|
||||
send "exit\r"
|
||||
expect "(config)#"
|
||||
'' else ''
|
||||
send "interface range gigabitEthernet ${ports}\r"
|
||||
expect "(config-if-range)#"
|
||||
send "switchport mode access\r"
|
||||
expect "(config-if-range)#"
|
||||
send "switchport access vlan ${toString netConfig.vlan}\r"
|
||||
expect "(config-if-range)#"
|
||||
send "exit\r"
|
||||
expect "(config)#"
|
||||
''
|
||||
) (sortBy (link: hostConfig.links.${link}.ports)
|
||||
(builtins.attrNames hostConfig.links)
|
||||
)}
|
||||
|
||||
send "exit\r"
|
||||
expect "#"
|
||||
send "copy running-config startup-config\r"
|
||||
expect "#"
|
||||
send "exit\r"
|
||||
expect ">"
|
||||
send "exit\r"
|
||||
''
|
|
@ -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
|
||||
''
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue