diff --git a/hosts/containers/freifunk/configuration.nix b/hosts/containers/freifunk/configuration.nix new file mode 100644 index 00000000..a9c8b65f --- /dev/null +++ b/hosts/containers/freifunk/configuration.nix @@ -0,0 +1,268 @@ +{ config, pkgs, lib, ... }: + +let + coreAddress = "172.20.72.40"; + corePrefixlen = 26; + meshInterface = "bmx"; + meshLoopback = "bmx_prime"; + ddmeshRegisterUrl = "https://register.freifunk-dresden.de/bot.php"; + secrets = import ; + ddmeshRegisterKey = secrets.ddmeshRegisterKey; + ddmeshNode = 51073; + ddmeshAddrPart = "200.74"; + rt_table = 7; + bmxd = import (toString ) { inherit pkgs; }; + sysinfo-json = import { + inherit pkgs bmxd ddmeshNode; + }; +in { + imports = [ + + + + + ]; + + boot.tmpOnTmpfs = true; + c3d2 = { + isInHq = false; + enableHail = false; + hq.statistics.enable = true; + }; + services.collectd.plugins.protocols = ""; + + networking.hostName = "freifunk"; + networking.useNetworkd = true; + networking.nameservers = [ "172.20.73.8" "9.9.9.9" ]; + networking.firewall.enable = false; + networking.nat = { + enable = true; + # This doesn't really work, hence the `extraCommands` + externalInterface = meshInterface; + #internalInterfaces = [ "core" ]; + + # Setup routing into Freifunk, + # masquerading anything that isn't already their IP range + extraCommands = '' + ${pkgs.iproute}/bin/ip rule del priority 300 || true + ${pkgs.iproute}/bin/ip rule add to 10.200.0.0/16 table bmx priority 300 + ${pkgs.iptables}/bin/iptables -t nat -F POSTROUTING + ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING \ + \! --source 10.200.0.0/15 -o ${meshInterface} -j SNAT --to 10.200.${ddmeshAddrPart} + set -e + ''; + }; + # Configure rt_table name + networking.iproute2 = { + enable = true; + rttablesExtraConfig = "${toString rt_table} bmx"; + }; + + # Required for krops: ssh git + services.openssh.enable = true; + environment.systemPackages = with pkgs; [ git tcpdump ]; + + systemd.network = { + netdevs = { + # Dummy interface for primary (10.200) address + bmx_prime = { + enable = true; + netdevConfig = { + Kind = "bridge"; + Name = meshLoopback; + }; + }; + }; + networks = { + # Wired mesh interface + "10-bmx" = { + enable = true; + matchConfig = { Name = meshInterface; }; + addresses = [ { + addressConfig = { + Address = "10.201.${ddmeshAddrPart}/16"; + Broadcast = "10.255.255.255"; + }; + } ]; + }; + # Dummy interface for primary (10.200) address + "11-bmx-loopback" = { + enable = true; + matchConfig = { Name = meshLoopback; }; + addresses = [ { + addressConfig = { + Address = "10.200.${ddmeshAddrPart}/32"; + Broadcast = "10.255.255.255"; + }; + } ]; + }; + # ZW + "20-core" = { + enable = true; + matchConfig = { Name = "core"; }; + addresses = map (Address: { addressConfig = { inherit Address; }; }) [ + "${coreAddress}/${toString corePrefixlen}" + "2a02:8106:208:5281:8000::1/64" + "fd23:42:c3d2:581:8000::1/64" + ]; + routes = map (Gateway: { routeConfig = { inherit Gateway; }; }) [ + # upstream1 + "2a02:8106:208:5281::b:0" + # anon1 + "172.20.72.7" + ]; + }; + }; + }; + # Freifunk Dresden routing daemon + systemd.services.bmxd = { + after = [ "systemd-networkd.service" ]; + wantedBy = [ "network.target" ]; + serviceConfig = { + ExecStart = '' + ${bmxd}/sbin/bmxd \ + --rt_table_offset=${toString rt_table} \ + --no_fork 1 \ + --throw-rules 0 \ + --prio-rules 0 \ + --gateway_tunnel_network 10.200.0.0/16 \ + --purge_timeout 20 \ + --one_way_tunnel 1 \ + -g 500000/50000 \ + dev=bmx_prime /linklayer 0 \ + dev=${meshInterface} /linklayer 1 + ''; + Restart = "always"; + }; + }; + + # Re-register periodically + systemd.services.ddmesh-register-node = { + script = '' + ${pkgs.curl}/bin/curl \ + -o /tmp/ddmesh-registration.json \ + '${ddmeshRegisterUrl}?registerkey=${ddmeshRegisterKey}&node=${toString ddmeshNode}' + ''; + serviceConfig = { + User = "nobody"; + Group = "nogroup"; + }; + }; + systemd.timers.ddmesh-register-node = { + partOf = [ "ddmesh-register-node.service" ]; + wantedBy = [ "timers.target" ]; + timerConfig.OnCalendar = "daily"; + }; + + # Refresh sysinfo.json + systemd.services.sysinfo-json = { + script = '' + ${sysinfo-json}/bin/bmxddump.sh + ${sysinfo-json}/bin/sysinfo-json.cgi > /tmp/sysinfo.json + ''; + }; + systemd.timers.sysinfo-json = { + partOf = [ "sysinfo-json.service" ]; + wantedBy = [ "timers.target" ]; + timerConfig.OnCalendar = "minutely"; + }; + + # Advertise Freifunk routes to ZW core + services.bird2 = { + enable = true; + config = '' + protocol kernel K4 { + ipv4 { + export all; + }; + } + protocol kernel K6 { + ipv6 { + export all; + }; + } + protocol device { + scan time 10; + } + + protocol ospf v2 ZW4 { + area 0 { + networks { + 172.20.72.0/21; + }; + stubnet 10.200.0.0/15; + interface "core" { + authentication cryptographic; + password "${import }"; + }; + }; + } + + protocol ospf v3 ZW6 { + area 0 { + networks { + fd23:42:c3d2:500::/56; + 2a02:8106:208:5200::/56; + 2a02:8106:211:e900::/56; + }; + interface "core" { + #authentication cryptographic; + #password "${import }"; + }; + }; + } + + router id ${coreAddress}; + ''; + }; + + # HTTP Reverse Proxy to provide services into Freifunk + services.nginx = { + enable = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + appendHttpConfig = '' + proxy_buffering off; + ''; + + virtualHosts = { + "c3d2.ffdd" = { + default = true; + root = ; + locations = + let + sysinfo-json = { + alias = "/tmp/sysinfo.json"; + extraConfig = '' + add_header Content-Type "application/json;charset=UTF-8"; + ''; + }; + in { + "/" = { + index = "index.html"; + extraConfig = '' + etag off; + add_header etag "\"${builtins.substring 11 32 ( + "/assets")}\""; + ''; + }; + "=/sysinfo-json.cgi" = sysinfo-json; + "=/sysinfo.json" = sysinfo-json; + }; + }; + "storage.hq.c3d2.ffdd".locations."/".proxyPass = "http://storage.hq.c3d2.de/"; + "grafana.hq.c3d2.ffdd".locations."/" = { + proxyPass = "https://grafana.hq.c3d2.de/"; + extraConfig = '' + proxy_ssl_server_name on; + ''; + }; + "influxdb.hq.c3d2.ffdd".locations."/".proxyPass = "http://grafana.hq.c3d2.de:8086/"; + }; + }; + + # This value determines the NixOS release with which your system is to be + # compatible, in order to avoid breaking some software such as database + # servers. You should change this only after NixOS release notes say you + # should. + system.stateVersion = "20.03"; # Did you read the comment? +} diff --git a/hosts/containers/freifunk/freifunk.qcow2 b/hosts/containers/freifunk/freifunk.qcow2 deleted file mode 100644 index f760381f..00000000 Binary files a/hosts/containers/freifunk/freifunk.qcow2 and /dev/null differ