flake/modules/services/mkMesh.nix

110 lines
3.3 KiB
Nix
Raw Normal View History

{
config,
pkgs,
lib,
cfg,
...
2024-11-12 03:46:56 +01:00
}: let
buildInputs = [pkgs.wgautomesh];
prefix = "lyn";
2024-11-13 05:15:14 +01:00
# 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: {
2025-01-14 18:56:49 +01:00
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
2025-01-14 18:56:49 +01:00
endpoint = host.${version}.public;
port =
if version == "IPv6"
then host.wg.port_v6
else host.wg.port_v4;
address = host.${version}.internal;
})
2025-01-14 18:56:49 +01:00
wgEnabledHosts;
2024-11-12 03:46:56 +01:00
# helper vars to prettify
2024-11-13 05:15:14 +01:00
meshnetwork = config.${prefix}.network;
currentHost = meshnetwork.hosts.${config.networking.hostName};
2024-11-12 03:46:56 +01:00
in {
opt = {
2025-01-14 21:43:47 +01:00
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;
};
2025-01-14 21:43:47 +01:00
enable_lan_discovery = lib.mkOption {
type = lib.types.bool;
description = "Try to discover mesh devices on the same local network.";
default = true;
};
};
2025-01-14 18:56:49 +01:00
config = rec {
networking.firewall = {
2025-01-15 14:12:48 +01:00
allowedUDPPorts = [
currentHost.wg.port_v4
currentHost.wg.port_v6
];
# UPnP broadcast responses
# credits: https://github.com/NixOS/nixpkgs/issues/161328
extraPackages =
if cfg.enable_upnp_portforward
then [pkgs.ipset]
else [];
extraCommands =
if cfg.enable_upnp_portforward
then ''
if ! ipset --quiet list upnp; then
ipset create upnp hash:ip,port timeout 3
fi
iptables -A OUTPUT -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j SET --add-set upnp src,src --exist
iptables -A nixos-fw -p udp -m set --match-set upnp dst,dst -j nixos-fw-accept
''
else "";
};
2024-11-14 01:48:38 +01:00
2024-11-13 20:30:39 +01:00
networking.wireguard.interfaces.wg0 = {
2025-01-14 18:56:49 +01:00
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;
2024-11-13 20:30:39 +01:00
privateKeyFile = "/var/lib/wireguard-keys/private";
mtu = 1280;
2024-11-13 20:30:39 +01:00
};
2024-11-13 20:30:39 +01:00
services.wgautomesh = {
enable = true;
settings = {
2025-01-14 18:56:49 +01:00
interfaces =
2025-01-14 21:43:47 +01:00
if cfg.enable_upnp_portforward
2025-01-14 18:56:49 +01:00
then [
{
name = "wg0";
upnp_forward_ext_port_v4 = config.networking.wireguard.interfaces.wg0.listenPort;
2025-01-14 18:56:49 +01:00
}
]
2025-01-14 21:43:47 +01:00
else [];
2025-01-14 18:56:49 +01:00
peers = buildPeerlist "IPv6" meshnetwork.hosts ++ buildPeerlist "IPv4" meshnetwork.hosts;
2025-01-14 21:43:47 +01:00
lan_discovery = cfg.enable_lan_discovery;
upnp_open_ports = cfg.enable_upnp_portforward;
2024-11-13 20:30:39 +01:00
};
gossipSecretFile = gossip_secret_path;
};
};
}