{ lib, config, pkgs, ... }: let cfg = config.pub-solar.wireguard.tunnel; in { options.pub-solar.wireguard.tunnel = { ownIPs = lib.mkOption { description = "Internal ips in wireguard used for cluster control-plane communication."; type = lib.types.listOf lib.types.str; default = []; }; privateKeyFile = lib.mkOption { description = "Location of private key file"; type = lib.types.path; }; peer = { publicKey = lib.mkOption { description = "Public key of the peer"; type = lib.types.str; }; endpoint = lib.mkOption { description = "Peer endpoint address"; type = lib.types.str; }; }; useDNS = lib.mkOption { description = "Whether to use the DNS of the interface as default"; default = false; type = lib.types.bool; }; }; config = lib.mkIf (lib.length cfg.ownIPs != 0){ networking.firewall.allowedUDPPorts = [51820]; systemd.network.wait-online.ignoredInterfaces = [ "wg-tunnel" ]; systemd.targets.wireguard-wg-tunnel = { wantedBy = lib.mkForce []; }; systemd.services.wireguard-wg-tunnel = { wants = [ "wireguard-wg-private.service" ]; preStart = '' while true; do if ${pkgs.netcat}/bin/nc -w 5 -z 10.13.12.7 22 2>/dev/null; then exit 0; else sleep 1; fi done; ''; serviceConfig = { Type = lib.mkForce "simple"; Restart = "on-failure"; RestartSec = "30"; }; environment = { WG_ENDPOINT_RESOLUTION_RETRIES = "infinity"; }; }; networking.wireguard.interfaces = let splitEndpoint = (lib.strings.splitString ":" cfg.peer.endpoint); joinIPV6 = p: ip: p + (if (lib.stringLength ip > 0) then ":" else "") + ip; isIPV4 = lib.length splitEndpoint < 3; ipFlag = if isIPV4 then "-4" else "-6"; endpointIP = (if isIPV4 then lib.elemAt splitEndpoint 0 else lib.lists.fold joinIPV6 "" ((lib.lists.take ((lib.length splitEndpoint) - 1)) splitEndpoint) ); endpointIPStripped = lib.strings.removePrefix "[" (lib.strings.removeSuffix "]" endpointIP); in { wg-tunnel = { listenPort = 51820; ips = cfg.ownIPs; privateKeyFile = cfg.privateKeyFile; postSetup = '' defaultRoute=$(${pkgs.iproute2}/bin/ip ${ipFlag} r | ${pkgs.gnugrep}/bin/grep "default via" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $3 " " $4 " " $5 }') ${pkgs.iproute2}/bin/ip ${ipFlag} route add "${endpointIPStripped}${if isIPV4 then "/32" else "/128"}" metric 256 via $defaultRoute ip -4 route delete default dev wg-tunnel || true ip -4 route add default dev wg-tunnel metric 512 ip -6 route delete default dev wg-tunnel || true ip -6 route add default dev wg-tunnel metric 512 '' + (if cfg.useDNS then ''printf "nameserver 10.64.0.1" | resolvconf -a wg-tunnel -m 0 -x'' else ""); postShutdown = '' addedRoute=$(${pkgs.iproute2}/bin/ip ${ipFlag} r | ${pkgs.gnugrep}/bin/grep "${endpointIPStripped}" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $1 " " $2 " " $3 " " $4 " " $5 }') if [ -n "$addedRoute" ]; then ${pkgs.iproute2}/bin/ip ${ipFlag} route delete $addedRoute fi '' + (if cfg.useDNS then ''resolvconf -d wg-tunnel -f'' else ""); peers = [ { publicKey = cfg.peer.publicKey; allowedIPs = [ "0.0.0.0/0" "::/0" ]; endpoint = cfg.peer.endpoint; persistentKeepalive = 30; dynamicEndpointRefreshSeconds = 30; } ]; }; }; }; }