{ pkgs, lib, config, instanceConfigs, instanceConfig, ... }: let cfg = config.xyno.services.wireguard; ula = "fd68:b6a4:36e4"; ulaPrefix = "${ula}:1337"; # /64 for normal vpn monitoringUlaPrefix = "${ula}:2337"; # /64 for monitoring # uses a hash digest as the host identifier genUlaForHost = prefix: hostName: let hostHash = builtins.hashString "sha512" hostName; localParts = map (n: builtins.substring (n * 4) 4 hostHash) hostHash; localPart = lib.concatStringsSep ":" localParts; in "${prefix}:${localPart}"; # peers list for networkd wgPeers = map ( c: ( (lib.optionals (lib.hasAttr c "publicHostname") { # if peer is publicly on the internet AllowedIPs = (lib.optionals (c.wgServer) [ "${ulaPrefix}::/48" # all traffic in the ula shall be sent to the server ]) ++ (lib.optionals (!c.wgServer) [ "${genUlaForHost ulaPrefix c.hostName}/128" # if a host is reachable but shouldn't play server, send only to the hosts ip ]); Endpoint = "${c.publicHostname}:51820"; PersistentKeepalive = 25; PublicKey = c.wgPubKey; }) ++ (lib.optionals (!(lib.hasAttr c "publicHostname") && instanceConfig.wgServer && (lib.hasAttr c "wgPubKey")) { # if this is the server and the peer isn't reachable on the internet AllowedIPs = [ "${genUlaForHost ulaPrefix c.hostName}/128" "${genUlaForHost monitoringUlaPrefix c.hostName}/128" ]; PublicKey = c.wgPubKey; # TODO: preshared keys }) ) ) instanceConfigs; in { options.xyno.services.wireguard.enable = lib.mkEnableOption "enables wireguard"; options.xyno.services.wireguard.hostsDomain = lib.mkOpion { type = lib.types.str; default = "wg.hailsatan.eu"; }; config = lib.mkIf cfg.enable { xyno.services.monitoring.ip = genUlaForHost monitoringUlaPrefix config.networking.hostName; networking.hosts = lib.mapAttrs' ( n: v: { name = "${v.hostName}.${cfg.hostsDomain}"; value = [ (genUlaForHost ulaPrefix v.hostName) ]; } ); networking.firewall.allowedUDPPorts = lib.mkIf instanceConfig.wgServer [ 51820 ]; systemd.network.netdevs."wg0" = { wireguardConfig = { ListenPort = lib.mkIf instanceConfig.wgServer 51820; PrivateKeyFile = config.sops.secrets.wg_privkey.path; # TODO }; wireguardPeers = wgPeers; }; systemd.network.networks."wg0" = { matchConfig.Name = "wg0"; networkConfig = { Description = "xyno wireguard"; }; address = [ "${(genUlaForHost ulaPrefix config.networking.hostName)}/128" "${(genUlaForHost monitoringUlaPrefix config.networking.hostName)}/128" ]; }; sops.secrets.wg_privkey = { reloadUnits = [ "systemd-networkd.service" ]; }; }; }