{ config, pkgs, lib, ... }: let address4 = "172.22.99.253"; address6 = "fe80::deca:fbad"; inherit (pkgs) neighbors; in { networking = { hostName = "dn42"; useNetworkd = true; # No Firewalling! firewall.enable = false; }; services.resolved.enable = false; c3d2 = { isInHq = true; hq = { interface = "c3d2"; statistics.enable = true; }; deployment = { server = "server10"; mounts = [ "etc" "home" "var"]; }; }; services.collectd.plugins.exec = let routecount = pkgs.writeScript "run-routecount" '' #!${pkgs.bash}/bin/bash export PATH=${lib.makeBinPath (with pkgs; [ ruby iproute ] )} ruby ${./routecount.rb} ''; in '' Exec "collectd" "${routecount}" ''; # SSH for deployment services.openssh.enable = true; sops = { age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; defaultSopsFile = ./secrets.yaml; secrets = builtins.foldl' (result: name: let conf = neighbors.${name}; in result // ( if conf ? openvpn then { "neighbors/${name}/openvpn/key" = {}; } else if conf ? wireguard then { "neighbors/${name}/wireguard/privateKey" = {}; } else {} ) ) {} (builtins.attrNames neighbors); }; boot.kernel.sysctl = { "net.ipv4.conf.all.forwarding" = true; "net.ipv4.conf.default.forwarding" = true; "net.ipv6.conf.all.forwarding" = true; "net.ipv6.conf.default.forwarding" = true; }; boot.postBootCommands = '' if [ ! -c /dev/net/tun ]; then mkdir -p /dev/net mknod -m 666 /dev/net/tun c 10 200 fi ''; services.openvpn = let openvpnNeighbors = lib.filterAttrs (_: conf: conf ? openvpn) neighbors; mkServer = name: conf: { config = '' dev ${name} dev-type tun ifconfig ${address4} ${conf.address4} user nobody group nogroup persist-tun persist-key ping 30 ping-restart 45 verb 1 ${conf.openvpn} secret ${config.sops.secrets."neighbors/${name}/openvpn/key".path} ''; up = '' ${pkgs.iproute}/bin/ip addr flush dev $1 ${pkgs.iproute}/bin/ip addr add ${address4} dev ${name} peer ${conf.address4}/32 ${pkgs.iproute}/bin/ip addr add ${address6}/64 dev $1 ''; }; in { servers = builtins.mapAttrs mkServer openvpnNeighbors; }; networking.wireguard = { enable = true; interfaces = let wireguardNeighbors = lib.filterAttrs (_: conf: conf ? wireguard) neighbors; in builtins.mapAttrs (name: conf: { inherit (conf.wireguard) listenPort; privateKeyFile = config.sops.secrets."neighbors/${name}/wireguard/privateKey".path; ips = [ "${address4}/32" "${address6}/64" ]; allowedIPsAsRoutes = false; postSetup = '' ${pkgs.iproute}/bin/ip addr del ${address4}/32 dev ${name} ${pkgs.iproute}/bin/ip addr add ${address4} dev ${name}${if conf ? address4 then " peer ${conf.address4}/32" else ""} ''; peers = [ ({ inherit (conf.wireguard) publicKey; allowedIPs = [ "0.0.0.0/0" "::0/0" ]; persistentKeepalive = 30; } // (lib.optionalAttrs (conf.wireguard ? endpoint) { inherit (conf.wireguard) endpoint; })) ]; }) wireguardNeighbors; }; services.bird2 = { enable = true; config = let bgpNeighbors = builtins.concatStringsSep "\n" (builtins.attrValues (builtins.mapAttrs (name: conf@{ multiprotocol ? false, ... }: let neighbor4 = if conf ? address4 && multiprotocol != "ipv6" then '' protocol bgp ${name}_4 from dnpeers { neighbor ${conf.address4} as ${builtins.toString conf.asn}; } '' else ""; neighbor6 = if conf ? address6 && multiprotocol != "ipv4" then '' protocol bgp ${name}_6 from dnpeers { neighbor ${conf.address6}%${interface} as ${ builtins.toString conf.asn }; } '' else ""; interface = conf.interface or name; in "${neighbor4}${neighbor6}") neighbors)); in '' protocol kernel { ipv4 { export all; }; } protocol kernel { ipv6 { export all; }; } protocol device { scan time 10; } protocol static { ipv4; route 10.0.0.0/8 unreachable; route 172.16.0.0/12 unreachable; route 192.168.0.0/16 unreachable; } protocol static { ipv6; route 2000::/3 via 2a00:8180:2c00:281::c3d2:3; route fd00::/8 unreachable; } protocol static hq4 { ipv4; route 172.22.99.0/24 via "c3d2"; } protocol static hq6 { ipv6; route fd23:42:c3d2:500::/56 unreachable; } template bgp dnpeers { local as 64699; ipv4 { import filter { if proto = "hq4" then reject; accept; }; export filter { if source = RTS_BGP then accept; if proto = "hq4" then accept; reject; }; }; ipv6 { import filter { if proto = "hq6" then reject; accept; }; export filter { if source = RTS_BGP then accept; if proto = "hq6" then accept; reject; }; }; } ${bgpNeighbors} router id ${address4}; ''; }; # 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 = "19.09"; # Did you read the comment? }