{ config, pkgs, lib, cfg, ... }: let buildInputs = [pkgs.wgautomesh]; prefix = "lyn"; # decrypt gossip secret # change this to comply with you secret management gossip_secret_path = config.sops.secrets."all/meshnetwork/gossip_secret".path; # function to make a peerlist suitable for wgautomesh buildPeerlist = version: hosts: let #filter out hosts that have wg.enabled set to false wgEnabledHosts = lib.filterAttrs (_: host: host.wg.enabled or false) hosts; #filter out hosts that don't support IP{$version} filteredHosts = lib.filterAttrs (_: host: host.${version} != null) wgEnabledHosts; in lib.mapAttrsToList (name: host: { pubkey = host.wg.pubkey; #if there is no public IP, make endpoint null so wgautomesh knows it unknown. Else format it to a SocketAddr endpoint = if host.${version}.public == "" then null else "${ if version == "IPv6" then "[${host.${version}.public}]" else host.${version}.public }:${toString host.wg.port}"; address = host.${version}.internal; }) filteredHosts; # helper vars to prettify meshnetwork = config.${prefix}.network; currentHost = meshnetwork.hosts.${config.networking.hostName}; wireguardPort = currentHost.wg.port; in { opt = { useIPv6 = lib.mkOption { type = lib.types.bool; description = "Whether to use IPv6. Defaults to true"; default = true; }; enable_upnp = lib.mkOption { type = lib.types.bool; description = "Whether to allow the wireguard port in the gateway using UPnP IGD. Necessary on some firewalls, might spam unnecessary debug messages on environments without IGD gateways."; default = false; }; }; config = { networking.firewall = { allowedUDPPorts = [ wireguardPort ] # UPnP broadcast responses ++ ( if cfg.enable_upnp then [1900] else [] ); }; networking.wireguard.interfaces.wg0 = { ips = if cfg.useIPv6 then ["${currentHost.IPv6.internal}/64"] else ["${currentHost.IPv4.internal}/24"]; listenPort = wireguardPort; privateKeyFile = "/var/lib/wireguard-keys/private"; mtu = 1280; }; services.wgautomesh = { enable = true; settings = { interface = "wg0"; peers = if cfg.useIPv6 then buildPeerlist "IPv6" meshnetwork.hosts else buildPeerlist "IPv4" meshnetwork.hosts; upnp_forward_external_port = wireguardPort; }; gossipSecretFile = gossip_secret_path; #DEBUG logLevel = "trace"; }; }; }