{ lib, config, machines, pkgs, ... }: let serverHostName = "vueko"; serverPort = 51820; peers = { hitagi = { address = "10.80.0.5"; publicKey = "t7hpd2yZupAKHxYerHtXnlPRUjV1aGbrrzjYakKdOwE="; }; vueko = { address = "10.80.0.6"; publicKey = "JbOfL4FxPCzJOjI8AGklPHY2FniCXq0QwOa08gjSyns="; }; fuuko = { address = "10.80.0.7"; publicKey = "VXic8mhaJBSl6yFkx0Cu6JI8tqqjjM3UbW7x+05pV0M="; }; mayushii = { address = "10.80.0.9"; publicKey = "nnLdgywXmDg8HWH6I0G28Z2zb4OmmyFDpnvvEBzKJTg="; }; renge = { address = "10.80.0.11"; publicKey = "RlLs/uiWb9qaBU2iDgRag7Q+FFaR7oHI3yOPLZPKgmA="; }; nunotaba = { address = "10.80.0.4"; publicKey = "LscDAJR0IjOzNuwX3geYgcvxyvaNhAOc/ojgvGyunT8="; }; }; cfg = config.sbruder.wireguard.home; enableServer = config.networking.hostName == serverHostName; in { options = { sbruder.wireguard.home = { enable = lib.mkEnableOption "WireGuard tunnel wg-home"; address = lib.mkOption { type = lib.types.str; visible = false; readOnly = true; }; }; }; config = lib.mkIf cfg.enable { sops.secrets.wg-home-private-key = { owner = config.users.users.systemd-network.name; sopsFile = ./../../machines + "/${config.networking.hostName}/secrets.yaml"; }; sbruder.wireguard.home.address = peers."${config.networking.hostName}".address; systemd.network = { enable = true; netdevs = { wg-home = { netdevConfig = { Kind = "wireguard"; Name = "wg-home"; }; wireguardConfig = { PrivateKeyFile = config.sops.secrets.wg-home-private-key.path; } // (lib.optionalAttrs enableServer { ListenPort = serverPort; }); wireguardPeers = if enableServer then map (peerConfig: with peerConfig; { wireguardPeerConfig = { PublicKey = publicKey; AllowedIPs = [ "${address}/32" ]; }; }) (lib.attrValues (lib.filterAttrs (n: v: n != config.networking.hostName) peers)) else [ { wireguardPeerConfig = { PublicKey = peers."${serverHostName}".publicKey; AllowedIPs = [ "10.80.0.0/24" ]; #Endpoint = "${serverHostName}.sbruder.de:${toString serverPort}"; # not possible because sadly not all devices have IPv6 connectivity Endpoint = "195.201.139.15:${toString serverPort}"; PersistentKeepalive = 25; }; } ]; }; }; networks = { wg-home = { name = "wg-home"; address = lib.singleton "${config.sbruder.wireguard.home.address}/24"; networkConfig = lib.optionalAttrs enableServer { IPForward = "ipv4"; }; }; }; }; networking.firewall = { trustedInterfaces = [ "wg-home" ]; allowedUDPPorts = lib.optionals enableServer [ serverPort 53 ]; }; services.bind = lib.mkIf enableServer { enable = true; zones = lib.singleton { name = "vpn.sbruder.de"; master = true; file = let # !!! very hacky hexStringToInt = hex: (builtins.fromTOML "int = 0x${hex}").int; peerRecords = lib.concatStrings (lib.mapAttrsToList (peer: peerConfig: '' ${peer} IN A ${peerConfig.address} '') peers); peerRecordsHash = builtins.hashString "sha256" peerRecords; serial = hexStringToInt (lib.substring 0 8 peerRecordsHash); in pkgs.writeText "vpn.sbruder.de.zone" ('' $TTL 3600 @ IN SOA ${serverHostName}.sbruder.de. hostmaster.sbruder.de. ${toString serial} 28800 3600 604800 3600 @ IN NS ${serverHostName}.sbruder.de. @ IN A ${peers.${serverHostName}.address} '' + peerRecords); }; }; services.nginx = lib.mkIf enableServer { virtualHosts."vpn.sbruder.de" = { root = let templateData = { machines = lib.mapAttrs (machine: { config, ... }: { syncthing = if config.services.syncthing.enable then 8384 else null; }) machines; }; in pkgs.stdenv.mkDerivation { name = "vpn-home"; src = ./home; nativeBuildInputs = with pkgs; [ j2cli ]; buildPhase = '' runHook preBuild j2 -f json -o index.html index.html.j2 - << EOF ${builtins.toJSON templateData} EOF runHook postBuild ''; installPhase = '' runHook preInstall install -D index.html $out/index.html install -D style.css $out/style.css runHook postInstall ''; }; }; }; }; }