{ 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; in lib.mapAttrsToList (name: host: { interface = if version == "IPv6" then "wg1" else "wg0"; 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 = host.${version}.public; port = if version == "IPv6" then host.wg.port_v6 else host.wg.port_v4; address = host.${version}.internal; }) wgEnabledHosts; # helper vars to prettify meshnetwork = config.${prefix}.network; currentHost = meshnetwork.hosts.${config.networking.hostName}; in { opt = { enable_upnp_portforward = 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; }; enable_lan_discovery = lib.mkOption { type = lib.types.bool; description = "Try to discover mesh devices on the same local network."; default = true; }; }; config = rec { networking.firewall = { allowedUDPPorts = [ currentHost.wg.port_v4 currentHost.wg.port_v6 ] # UPnP broadcast responses ++ ( if cfg.enable_upnp_portforward then [1900] else [] ); }; networking.wireguard.interfaces.wg0 = { ips = ["${currentHost.IPv4.internal}/24"]; listenPort = currentHost.wg.port_v4; privateKeyFile = "/var/lib/wireguard-keys/private"; mtu = 1280; }; networking.wireguard.interfaces.wg1 = { ips = ["${currentHost.IPv6.internal}/64"]; listenPort = currentHost.wg.port_v6; privateKeyFile = "/var/lib/wireguard-keys/private"; mtu = 1280; }; services.wgautomesh = { enable = true; settings = { interfaces = if cfg.enable_upnp_portforward then [ { name = "wg0"; upnp_forward_external_port = config.networking.wireguard.interfaces.wg0.listenPort; } { name = "wg1"; upnp_forward_external_port = config.networking.wireguard.interfaces.wg1.listenPort; } ] else []; peers = buildPeerlist "IPv6" meshnetwork.hosts ++ buildPeerlist "IPv4" meshnetwork.hosts; lan_discovery = cfg.enable_lan_discovery; }; gossipSecretFile = gossip_secret_path; }; }; }