{ config, pkgs, ... }: let wgPort = 51820; # Common port used on all peers firewallMark = 42; inherit (pkgs) lib; inherit (lib.attrsets) mapAttrsToList; # The topology is hub-and-spoke/star # sagittarius is the hub == 2301:db8:acad:a::1 # it hosts authoritative DNS and spokes do keepalive with it. hub = { hostName = "sagittarius"; address = "2301:db8:acad:a::1/128"; publicKey = "GrrN8j9ZlPjTU5sQD4l8RDCGAn2YYszbSIE1zuG4OiI="; endpoint = "95.216.136.85:${toString wgPort}"; }; spokes = { nyaan = { address = "2301:db8:acad:a::2/128"; publicKey = "u5nh+YNV84IbS7g0ncfs/V+cqEudNh500LQ7pmdS7j0="; }; pixel8 = { address = "2301:db8:acad:a::3/128"; publicKey = "awBcQzNBdlYWpoOF1n7ijol2EiaJy5cxrVXfrqCvM0k="; }; underworld = { address = "2301:db8:acad:a::4/128"; publicKey = "GPVOvXqg8rp1a38T6YDHQN6UkG2TJT399A4wNtK4WTM="; }; }; generatePeer = hostname: values: { PublicKey = values.publicKey; AllowedIPs = [ values.address ]; } // lib.optionalAttrs (builtins.hasAttr "endpoint" values) { Endpoint = values.endpoint; PersistentKeepalive = 1; }; hubPeers = mapAttrsToList generatePeer spokes; spokePeers = [ { PublicKey = hub.publicKey; AllowedIPs = [ "2301:db8:acad:a::/64" ]; Endpoint = hub.endpoint; PersistentKeepalive = 10; } ]; hostname = config.networking.hostName; isHub = hostname == hub.hostName; conf = if isHub then hub else spokes."${hostname}"; privateKeyPath = ./secrets/wireguard/${hostname}.txt; in { sops.secrets."wireguard-${hostname}-pk" = { sopsFile = privateKeyPath; owner = "systemd-network"; group = "systemd-network"; mode = "0640"; format = "binary"; }; networking.nameservers = [ "2301:db8:acad:a::1" # see the zonefile in etc/dns ]; systemd.network = { enable = true; networks."50-wg" = { matchConfig.Name = "wg0"; address = [ conf.address ]; networkConfig = lib.mkIf isHub { IPv6Forwarding = true; IPv6AcceptRA = false; # Disable RA acceptance on router interfaces }; }; netdevs."50-wg" = { netdevConfig = { Kind = "wireguard"; Name = "wg0"; }; wireguardConfig = { ListenPort = wgPort; PrivateKeyFile = config.sops.secrets."wireguard-${hostname}-pk".path; # To automatically create routes for everything in AllowedIPs, # add RouteTable=main RouteTable = "main"; # FirewallMark marks all packets send and received by wg0 with the # number, which can be used to define policy rules on these packets. FirewallMark = firewallMark; }; wireguardPeers = if isHub then hubPeers else spokePeers; }; }; boot.kernel.sysctl = lib.mkIf isHub { # I *think* this should be fine since networkd will prevent forwarding # on any interface that doesn't have IPv6Forwarding set to true. "net.ipv6.conf.wg0.forwarding" = true; }; }