feat[server]: support multiple wireguard tunnels

This commit is contained in:
Leon Schwarzäugl 2025-12-22 14:14:45 +01:00 committed by Leon Schwarzäugl
parent 1ffb154031
commit 91157e2cca
16 changed files with 546 additions and 357 deletions

View file

@ -2801,11 +2801,10 @@ This is my main server that I run at home. It handles most tasks that require bi
loader.efi.canTouchEfiVariables = true; loader.efi.canTouchEfiVariables = true;
}; };
# globals.hosts.${config.node.name}.ipv4 = config.repo.secrets.local.ipv4; networking.hosts = {
# globals.networks.home.hosts.${config.node.name} = { ${globals.networks.home-lan.hosts.hintbooth.ipv4} = [ "server.hintbooth.${globals.domains.main}" ];
# ipv4 = config.repo.secrets.local.home-ipv4; ${globals.networks.home-lan.hosts.hintbooth.ipv6} = [ "server.hintbooth.${globals.domains.main}" ];
# mac = config.repo.secrets.local.home-mac; };
# };
swarselsystems = { swarselsystems = {
info = "ASRock J4105-ITX, 32GB RAM"; info = "ASRock J4105-ITX, 32GB RAM";
@ -2818,10 +2817,16 @@ This is my main server that I run at home. It handles most tasks that require bi
isNixos = true; isNixos = true;
proxyHost = "twothreetunnel"; proxyHost = "twothreetunnel";
server = { server = {
wireguard = { wireguard.interfaces = {
wgProxy = {
isClient = true; isClient = true;
serverName = "twothreetunnel"; serverName = "twothreetunnel";
}; };
wgHome = {
isClient = true;
serverName = "hintbooth";
};
};
restic = { restic = {
bucketName = "SwarselWinters"; bucketName = "SwarselWinters";
paths = [ paths = [
@ -3270,6 +3275,16 @@ This is my main server that I run at home. It handles most tasks that require bi
rootDisk = "/dev/sda"; rootDisk = "/dev/sda";
swapSize = "8G"; swapSize = "8G";
networkKernelModules = [ "igb" ]; networkKernelModules = [ "igb" ];
server = {
wireguard.interfaces = {
wgHome = {
isServer = true;
peers = [
"winters"
];
};
};
};
}; };
} // lib.optionalAttrs (!minimal) { } // lib.optionalAttrs (!minimal) {
@ -3282,6 +3297,7 @@ This is my main server that I run at home. It handles most tasks that require bi
swarselmodules = { swarselmodules = {
server = { server = {
nginx = lib.mkForce false; # we get this from the server profile nginx = lib.mkForce false; # we get this from the server profile
wireguard = true;
}; };
}; };
@ -3681,10 +3697,12 @@ This machine mainly acts as my proxy server to stand before my local machines.
isCloud = true; isCloud = true;
proxyHost = "twothreetunnel"; proxyHost = "twothreetunnel";
server = { server = {
wireguard = { wireguard.interfaces = {
wgProxy = {
isClient = true; isClient = true;
serverName = "twothreetunnel"; serverName = "twothreetunnel";
}; };
};
restic = { restic = {
bucketName = "SwarselMoonside"; bucketName = "SwarselMoonside";
paths = [ paths = [
@ -3912,10 +3930,12 @@ This machine mainly acts as my proxy server to stand before my local machines.
isCloud = true; isCloud = true;
proxyHost = "twothreetunnel"; proxyHost = "twothreetunnel";
server = { server = {
wireguard = { wireguard.interfaces = {
wgProxy = {
isClient = true; isClient = true;
serverName = "twothreetunnel"; serverName = "twothreetunnel";
}; };
};
garage = { garage = {
data_dir = { data_dir = {
capacity = "150G"; capacity = "150G";
@ -4550,18 +4570,20 @@ This machine mainly acts as my proxy server to stand before my local machines.
isLinux = true; isLinux = true;
isCloud = true; isCloud = true;
server = { server = {
wireguard = { wireguard.interfaces = {
ifName = "wg"; wgProxy = {
# ifName = "wg";
isServer = true; isServer = true;
peers = [ peers = [
"moonside" "moonside"
"winters" "winters"
"belchsfactory" "belchsfactory"
"eagleland" # "eagleland"
]; ];
}; };
}; };
}; };
};
} // lib.optionalAttrs (!minimal) { } // lib.optionalAttrs (!minimal) {
swarselprofiles = { swarselprofiles = {
server = true; server = true;
@ -5993,7 +6015,13 @@ in
description = "List of external dns nameservers"; description = "List of external dns nameservers";
}; };
}; };
}; };
}; };
}; };
@ -9079,177 +9107,219 @@ lspci -k -d 14c3:0616
#+begin_src nix-ts :tangle modules/nixos/server/wireguard.nix #+begin_src nix-ts :tangle modules/nixos/server/wireguard.nix
{ self, lib, pkgs, config, confLib, nodes, globals, ... }: { self, lib, pkgs, config, confLib, nodes, globals, ... }:
let let
wgInterface = "wg0"; inherit (confLib.gen {
inherit (confLib.gen { name = "wireguard"; port = 52829; user = "systemd-network"; group = "systemd-network"; }) servicePort serviceName serviceUser serviceGroup; name = "wireguard";
port = 52829;
user = "systemd-network";
group = "systemd-network";
}) servicePort serviceName serviceUser serviceGroup;
inherit (config.swarselsystems) sopsFile; inherit (config.swarselsystems) sopsFile;
wgSopsFile = self + "/secrets/repo/wg.yaml"; wgSopsFile = self + "/secrets/repo/wg.yaml";
inherit (config.swarselsystems.server.wireguard) peers isClient isServer serverName serverNetConfigPrefix ifName;
cfg = config.swarselsystems.server.wireguard;
inherit (cfg) interfaces;
ifaceList = builtins.attrValues interfaces;
in in
{ {
options = { options = {
swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} settings"; swarselmodules.server.${serviceName} =
lib.mkEnableOption "enable ${serviceName} settings";
swarselsystems.server.wireguard = { swarselsystems.server.wireguard = {
isServer = lib.mkEnableOption "set this as a wireguard server"; interfaces = lib.mkOption {
isClient = lib.mkEnableOption "set this as a wireguard client"; type = lib.types.attrsOf (lib.types.submodule ({ name, config, ... }: {
options = {
isServer = lib.mkEnableOption "set this interface as a wireguard server";
isClient = lib.mkEnableOption "set this interface as a wireguard client";
serverName = lib.mkOption { serverName = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = ""; default = "";
description = "Hostname of the WireGuard server this interface connects to (when isClient = true).";
}; };
serverNetConfigPrefix = lib.mkOption { serverNetConfigPrefix = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "${if nodes.${serverName}.config.swarselsystems.isCloud then nodes.${serverName}.config.node.name else "home"}"; default =
let
serverCfg = nodes.${config.serverName}.config;
in
if serverCfg.swarselsystems.isCloud
then serverCfg.node.name
else "home";
readOnly = true; readOnly = true;
description = "Prefix used to look up the server network in globals.networks.\"<prefix>-wg\".";
}; };
ifName = lib.mkOption { ifName = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = wgInterface; default = name;
description = "Name of the WireGuard interface.";
}; };
peers = lib.mkOption { peers = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
description = "Wireguard peer config names"; description = "WireGuard peer config names (clients when this host is server, or additional peers).";
};
};
}));
default = { };
description = "WireGuard interfaces defined on this host.";
};
}; };
}; };
};
config = lib.mkIf config.swarselmodules.server.${serviceName} { config = lib.mkIf config.swarselmodules.server.${serviceName} {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
wireguard-tools wireguard-tools
]; ];
sops = { sops.secrets =
secrets = { lib.mkMerge (
wireguard-private-key = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0600"; }; [
# create this secret only if this is a simple client with only one peer (the server) {
"wireguard-${serverName}-${config.node.name}-presharedKey" = lib.mkIf (isClient && peers == [ ]) { sopsFile = wgSopsFile; owner = serviceUser; group = serviceGroup; mode = "0600"; }; # shared host private key
wireguard-private-key = {
inherit sopsFile;
owner = serviceUser;
group = serviceGroup;
mode = "0600";
};
} }
# create these secrets only if this host has multiple peers ] ++ (map
// lib.optionalAttrs (peers != [ ]) (builtins.listToAttrs (map (i:
(clientName: { let
name = "wireguard-${config.node.name}-${clientName}-presharedKey"; simpleClientSecrets =
value = { sopsFile = wgSopsFile; owner = serviceUser; group = serviceGroup; mode = "0600"; }; lib.optionalAttrs (i.isClient && i.peers == [ ]) {
}) "wireguard-${i.serverName}-${config.node.name}-${i.ifName}-presharedKey" = {
peers)); sopsFile = wgSopsFile;
owner = serviceUser;
group = serviceGroup;
mode = "0600";
};
}; };
multiPeerSecrets =
lib.optionalAttrs (i.peers != [ ]) (builtins.listToAttrs (map
(clientName: {
name = "wireguard-${config.node.name}-${clientName}-${i.ifName}-presharedKey";
value = {
sopsFile = wgSopsFile;
owner = serviceUser;
group = serviceGroup;
mode = "0600";
};
})
i.peers));
in
simpleClientSecrets // multiPeerSecrets
)
ifaceList)
);
networking = { networking = {
firewall.checkReversePath = lib.mkIf isClient "loose"; firewall.checkReversePath =
firewall.allowedUDPPorts = [ servicePort ]; lib.mkIf (lib.any (i: i.isClient) ifaceList) "loose";
# nat = lib.mkIf (config.swarselsystems.isCloud && isServer) {
# enable = true; firewall.allowedUDPPorts =
# enableIPv6 = true; lib.mkIf (lib.any (i: i.isServer) ifaceList) [ servicePort ];
# externalInterface = "enp0s6";
# internalInterfaces = [ ifName ];
# };
# interfaces.${ifName}.mtu = 1280; # the default (1420) is not enough!
}; };
systemd.network = { systemd.network = {
enable = true; enable = true;
networks."50-${ifName}" = { networks = lib.mkMerge (map
(i:
let
inherit (i) ifName;
in
{
"50-${ifName}" = {
matchConfig.Name = ifName; matchConfig.Name = ifName;
linkConfig = { linkConfig = {
MTUBytes = 1408; # TODO: figure out where we lose those 12 bits (8 from pppoe maybe + ???) MTUBytes = 1408; # TODO: figure out where we lose those 12 bits (8 from pppoe maybe + ???)
}; };
# networkConfig = lib.mkIf (config.swarselsystems.isCloud && isServer) { address =
# IPv4Forwarding = true; if i.isServer then [
# IPv6Forwarding = true; globals.networks."${config.swarselsystems.server.netConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv4
# }; globals.networks."${config.swarselsystems.server.netConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv6
address = if isServer then [
globals.networks."${config.swarselsystems.server.netConfigPrefix}-wg".hosts.${config.node.name}.cidrv4
globals.networks."${config.swarselsystems.server.netConfigPrefix}-wg".hosts.${config.node.name}.cidrv6
] else [ ] else [
globals.networks."${serverNetConfigPrefix}-wg".hosts.${config.node.name}.cidrv4 globals.networks."${i.serverNetConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv4
globals.networks."${serverNetConfigPrefix}-wg".hosts.${config.node.name}.cidrv6 globals.networks."${i.serverNetConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv6
]; ];
}; };
})
ifaceList);
netdevs."50-${ifName}" = { netdevs = lib.mkMerge (map
(i:
let
inherit (i) ifName;
in
{
"50-${ifName}" = {
netdevConfig = { netdevConfig = {
Kind = "wireguard"; Kind = "wireguard";
Name = ifName; Name = ifName;
}; };
wireguardConfig = { wireguardConfig = {
ListenPort = lib.mkIf isServer servicePort; ListenPort = lib.mkIf i.isServer servicePort;
# ensure file is readable by `systemd-network` user
PrivateKeyFile = config.sops.secrets.wireguard-private-key.path; PrivateKeyFile = config.sops.secrets.wireguard-private-key.path;
# To automatically create routes for everything in AllowedIPs, RouteTable = lib.mkIf i.isClient "main";
# add RouteTable=main
RouteTable = lib.mkIf isClient "main";
# FirewallMark marks all packets send and received by wg0
# with the number 42, which can be used to define policy rules on these packets.
# FirewallMark = 42;
}; };
wireguardPeers = lib.optionals isClient [
wireguardPeers =
lib.optionals i.isClient [
{ {
PublicKey = builtins.readFile "${self}/secrets/public/wg/${serverName}.pub"; PublicKey =
PresharedKeyFile = config.sops.secrets."wireguard-${serverName}-${config.node.name}-presharedKey".path; builtins.readFile "${self}/secrets/public/wg/${i.serverName}.pub";
Endpoint = "server.${serverName}.${globals.domains.main}:${toString servicePort}";
# Access to the whole network is routed through our entry node. PresharedKeyFile =
config.sops.secrets."wireguard-${i.serverName}-${config.node.name}-${i.ifName}-presharedKey".path;
Endpoint =
"server.${i.serverName}.${globals.domains.main}:${toString servicePort}";
PersistentKeepalive = 25; PersistentKeepalive = 25;
AllowedIPs = AllowedIPs =
let let
wgNetwork = globals.networks."${serverNetConfigPrefix}-wg"; wgNetwork = globals.networks."${i.serverNetConfigPrefix}-${i.ifName}";
in in
(lib.optional (wgNetwork.cidrv4 != null) wgNetwork.cidrv4) (lib.optional (wgNetwork.cidrv4 != null) wgNetwork.cidrv4)
++ (lib.optional (wgNetwork.cidrv6 != null) wgNetwork.cidrv6); ++ (lib.optional (wgNetwork.cidrv6 != null) wgNetwork.cidrv6);
} }
] ++ lib.optionals isServer (map ]
++ lib.optionals i.isServer (map
(clientName: { (clientName: {
PublicKey = builtins.readFile "${self}/secrets/public/wg/${clientName}.pub"; PublicKey =
PresharedKeyFile = config.sops.secrets."wireguard-${config.node.name}-${clientName}-presharedKey".path; builtins.readFile "${self}/secrets/public/wg/${clientName}.pub";
# PersistentKeepalive = 25;
PresharedKeyFile =
config.sops.secrets."wireguard-${config.node.name}-${clientName}-${i.ifName}-presharedKey".path;
AllowedIPs = AllowedIPs =
let let
clientInWgNetwork = globals.networks."${config.swarselsystems.server.netConfigPrefix}-wg".hosts.${clientName}; clientInWgNetwork =
globals.networks."${config.swarselsystems.server.netConfigPrefix}-${i.ifName}".hosts.${clientName};
in in
(lib.optional (clientInWgNetwork.ipv4 != null) (lib.net.cidr.make 32 clientInWgNetwork.ipv4)) (lib.optional (clientInWgNetwork.ipv4 != null)
++ (lib.optional (clientInWgNetwork.ipv6 != null) (lib.net.cidr.make 128 clientInWgNetwork.ipv6)); (lib.net.cidr.make 32 clientInWgNetwork.ipv4))
++ (lib.optional (clientInWgNetwork.ipv6 != null)
(lib.net.cidr.make 128 clientInWgNetwork.ipv6));
}) })
peers); i.peers);
}; };
})
ifaceList);
}; };
# networking = {
# wireguard = {
# enable = true;
# interfaces = {
# wg1 = {
# privateKeyFile = config.sops.secrets.wireguard-private-key.path;
# ips = [ "192.168.178.201/24" ];
# peers = [
# {
# publicKey = "PmeFInoEJcKx+7Kva4dNnjOEnJ8lbudSf1cbdo/tzgw=";
# presharedKeyFile = config.sops.secrets.wireguard-home-preshared-key.path;
# name = "moonside";
# persistentKeepalive = 25;
# # endpoint = "${config.repo.secrets.common.ipv4}:51820";
# endpoint = "${config.repo.secrets.common.wireguardEndpoint}";
# # allowedIPs = [
# # "192.168.3.0/24"
# # "192.168.1.0/24"
# # ];
# allowedIPs = [
# "192.168.178.0/24"
# ];
# }
# ];
# };
# };
# };
# };
}; };
} }
#+end_src #+end_src
@ -15332,7 +15402,7 @@ Some standard options that should be set vor every microvm guest. We set the def
Hold standard options for nix-topology per config Hold standard options for nix-topology per config
#+begin_src nix-ts :tangle modules/nixos/optional/nix-topology-self.nix #+begin_src nix-ts :tangle modules/nixos/optional/nix-topology-self.nix
{ config, globals, ... }: { lib, config, globals, ... }:
{ {
topology.self = { topology.self = {
icon = lib.mkIf config.swarselsystems.isCloud "devices.cloud-server"; icon = lib.mkIf config.swarselsystems.isCloud "devices.cloud-server";
@ -22436,9 +22506,9 @@ In short, the options defined here are passed to the modules systems using =_mod
config.swarselsystems.proxyHost != config.node.name config.swarselsystems.proxyHost != config.node.name
then then
if if
config.swarselsystems.server.wireguard.isClient config.swarselsystems.server.wireguard.interfaces.wgProxy.isClient
then then
globals.networks."${config.swarselsystems.server.wireguard.serverNetConfigPrefix}-wg".hosts.${config.node.name}.ipv4 globals.networks."${config.swarselsystems.server.wireguard.interfaces.wgProxy.serverNetConfigPrefix}-wgProxy".hosts.${config.node.name}.ipv4
else else
globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4 globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4
else else

View file

@ -29,10 +29,12 @@
isCloud = true; isCloud = true;
proxyHost = "twothreetunnel"; proxyHost = "twothreetunnel";
server = { server = {
wireguard = { wireguard.interfaces = {
wgProxy = {
isClient = true; isClient = true;
serverName = "twothreetunnel"; serverName = "twothreetunnel";
}; };
};
garage = { garage = {
data_dir = { data_dir = {
capacity = "150G"; capacity = "150G";

View file

@ -76,10 +76,12 @@ in
isCloud = true; isCloud = true;
proxyHost = "twothreetunnel"; proxyHost = "twothreetunnel";
server = { server = {
wireguard = { wireguard.interfaces = {
wgProxy = {
isClient = true; isClient = true;
serverName = "twothreetunnel"; serverName = "twothreetunnel";
}; };
};
restic = { restic = {
bucketName = "SwarselMoonside"; bucketName = "SwarselMoonside";
paths = [ paths = [

View file

@ -25,18 +25,20 @@
isLinux = true; isLinux = true;
isCloud = true; isCloud = true;
server = { server = {
wireguard = { wireguard.interfaces = {
ifName = "wg"; wgProxy = {
# ifName = "wg";
isServer = true; isServer = true;
peers = [ peers = [
"moonside" "moonside"
"winters" "winters"
"belchsfactory" "belchsfactory"
"eagleland" # "eagleland"
]; ];
}; };
}; };
}; };
};
} // lib.optionalAttrs (!minimal) { } // lib.optionalAttrs (!minimal) {
swarselprofiles = { swarselprofiles = {
server = true; server = true;

View file

@ -1,5 +1,5 @@
{ {
"data": "ENC[AES256_GCM,data:8MWVw/6bXo/1lp3IKzN/9rt3RKoU+2bv8voov+CLQzYWZ8yzOCp3ZxtK1qT8ol4oalTdf5KLnVcHjBCrI2vECO10otXQMmr7oyDpe6ORvIFSSjc3wCfA5Ddaot4qd7Eqwg261mjk2xtk+rNG1mkIfshMDXwX0GKXEocp7kGFncagMNB5armJjMC/HeukQMi7yxe5ahpz4K10/mkQiluZKVYxzzFkBMAyAUgzNYJxRbxnalq0nNmtb7pSHaVJk0JnapFEy2Jnswl8NmbmmC7O91EdDxEWUX6MRI9DMoLehFcU/Ij/Nn994jC3RNywgkPDv29uEvz5BPw3y9KNYrqzuCj0GFTODgNBykjw/fmmYPfSfgXrpS4QRE3ZklLsFvADPMIwnW7F65XCx7VVy5j9OGT3NObdwweFpsqh1+gyIq/Ity/RpkQ6uqqseRclO1vQYAqDzuh1SOi3SBP3C7J2HNMfJy5TkhzyzRTBItaYbKqVPWm1nsBf8ZldCQ==,iv:wYfg9ZesEPMsF9GbM2r4vZoiOABPRyWOHUrZJMetPVQ=,tag:pJJ7yGSme2EXmk4duQ+0RA==,type:str]", "data": "ENC[AES256_GCM,data:UKXEKxP1SDqQWktd3eQzkoqsk6k3m9Rj+JNk3xmdZmp5p+pXnY+uDltSIL2PTsOy7wtf4gp16jze1PhHvYojuN2nnou/D1KJALPHBgGiR8CgBlbX5nrCbtHrs4SZq+M7QihRV8lsG8gU0aIm0lDO83cJ0boUfnZdexDPjcuhYJj5nmgOG1bV60LOJNg7yn//hlVhovrf7ygXOk9HirDMmK9MVkKw5utD7iE4Cm7txrK1z9rQLJYM3kzwsWJAGkIc/IbI4Css10ScNK9VMKU4B596Dv2eCHvSIUJ8Y8AJrE/1+jp8XQW4aUMcFsbKpwjL2mOm0DSFupr/D60vJ1j5ovEIT4Vt51H4cpcBduBUCHoRZ1S/fZePxYaPunEI9lJVSQeANGevqXmvd8SSpO8YFN2S06CsFcx8hadQpq79uD7hm4tZzNUFOm2fytY9WMl0YWlSM4g3U30tKVVo+RMmm43oMaStOiyXUyohXjKY5QJqI+rJRRifKUhfze4Z4aGn,iv:nOU57gwkc3hld/+IqqHYtEiJYXzOFwTaG6cNEl7ZNHk=,tag:kRp580c9haQSQmOw2hBvrw==,type:str]",
"sops": { "sops": {
"age": [ "age": [
{ {
@ -7,8 +7,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqdEhDamZTRUhQZFNDTTl4\nVVVNNGZXa2h2THVzY0JWMjE2WjNJT0ZoblV3ClYzeEt4c0dWRzlISnN3NGthR21M\nTEtDQ011dFdhRVdPWlpweS9ma0N3dmsKLS0tIHFPQzQ5VzkyODZyY1JpcE4xR2Nl\nY2MrSERXTWkvNVZCR2xHUGh4ZXMvYTgK7pxPjnh3idl4QzBkR6LHyRskgqA3apS2\nkbg7As6wlEs34TAO8reyZknKTUd3Xif1v9RXiTcu1sEKHqkcqEoDog==\n-----END AGE ENCRYPTED FILE-----\n" "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqdEhDamZTRUhQZFNDTTl4\nVVVNNGZXa2h2THVzY0JWMjE2WjNJT0ZoblV3ClYzeEt4c0dWRzlISnN3NGthR21M\nTEtDQ011dFdhRVdPWlpweS9ma0N3dmsKLS0tIHFPQzQ5VzkyODZyY1JpcE4xR2Nl\nY2MrSERXTWkvNVZCR2xHUGh4ZXMvYTgK7pxPjnh3idl4QzBkR6LHyRskgqA3apS2\nkbg7As6wlEs34TAO8reyZknKTUd3Xif1v9RXiTcu1sEKHqkcqEoDog==\n-----END AGE ENCRYPTED FILE-----\n"
} }
], ],
"lastmodified": "2025-12-03T16:34:02Z", "lastmodified": "2025-12-22T01:24:25Z",
"mac": "ENC[AES256_GCM,data:OBETnq727ZC90fB5eZsgGGpLz8tImqaRH4LEQsxzDWbLBeGz/eFTBAHiB5MRHV1X87M2RLgtLsylu58AKmctPxQtAwuDl/oy6AIyGhEbK0bohzryHX7hv4JlWasTWoBg64nCu63YlvuWLiLPNOuqDe6ODa7kLfk+SW8rOoVzJSc=,iv:+5SgpVThJnJUeqZUc2Sn1nkYjnaDGMjjRaSgn0gDCo8=,tag:lIsAjeaO9R6zluwdibD2BQ==,type:str]", "mac": "ENC[AES256_GCM,data:NtGHAadNGMfyCOqiaE/XRZqu4CnQ1IujgI3/IraY6E3luqzFVxJk/CgWD2rjbhLmaL7hd3Tay2LjL5uFxzM7kAE9QaaZtcxYKbudhznUdi/UEZ2ZtqyXqafXfCjEVbETaTAP3YGmQwJ/kAMj+FZp9yx7d6B8SVqWu1PatJGsOIA=,iv:OW6Xsr2MmEJq70TnEIJFgwLi3iMmKFV2Fy05a5G6Ibw=,tag:8KtNH6tEj/rQoht7FRDN3Q==,type:str]",
"pgp": [ "pgp": [
{ {
"created_at": "2025-12-01T23:06:36Z", "created_at": "2025-12-01T23:06:36Z",

View file

@ -31,6 +31,16 @@
rootDisk = "/dev/sda"; rootDisk = "/dev/sda";
swapSize = "8G"; swapSize = "8G";
networkKernelModules = [ "igb" ]; networkKernelModules = [ "igb" ];
server = {
wireguard.interfaces = {
wgHome = {
isServer = true;
peers = [
"winters"
];
};
};
};
}; };
} // lib.optionalAttrs (!minimal) { } // lib.optionalAttrs (!minimal) {
@ -43,6 +53,7 @@
swarselmodules = { swarselmodules = {
server = { server = {
nginx = lib.mkForce false; # we get this from the server profile nginx = lib.mkForce false; # we get this from the server profile
wireguard = true;
}; };
}; };

View file

@ -1,5 +1,5 @@
{ {
"data": "ENC[AES256_GCM,data:0KCJFnho4v+hEcPsJkK3bSUaSZnaOcXDKIQ5loWxmRkvEYxoDgOEgcgnm9zzuZWGwxPLeN2HxeRIWsG7rDk5xxTiRF4rIVUvIObeDChMDsgL2G26VVzYc4+Vm7kT6GHINDiKMGspktNQRhqCh/0HaGkle62z9lBPn3IO+c/1dumWI6UwC9zqa9PTcsH8nWy8lpovdhD7B4+A/aPZhnC2qpBZGmveh3dJe+zR/iiRRqjFgQ1rdQr5USjQjA2wJvKzx1HdkRbw9OXnINdMeVGi05SItsRz0KekzpCwq2wwhyOon8Qlour4CugV20w+csbsqmbXdGaaB2BK4oMWJh74lb77HBk0zbWCXw==,iv:P9lXQtmHkq5q6BkKuF8N/Yvm3gul4SQ7bYqS7nzNIyU=,tag:lixSTKRQ5WJOozWfTj6V+A==,type:str]", "data": "ENC[AES256_GCM,data:mi/EbLHjvOmJyK30E719clNAN/hq6FCS1ld0pLG4ahuuDkOfgbUr0vPEmhlxoIrkmD3HNkDufTlFsWezZ9s6OiZKS1ASRSPI96Js43BwVLotub1/YJaV0JMFNVoKTo9ag/5soaAbta0GNq0wExIjBNaVExCmNOs3puXCod4nOI9qmcn/ytx+98+3iZk8p87NTauX5W3jb87QjMqucWaEWxo4DLerkLI54baEMKJUULYRO4/BJ102pFq1twOVNm7v4R8FLbjknNL0A5T2ymmAJqOSpRLApcFJjSda6JkVoMV380a7Wa9cawLF/9xHRJn2K5R5uRx7JTLxL2VuW1olYMSrImO/d08277ZHymxeV07nJCyO/Y/0aR36P5YxJrUwNwKe31oR2RSm3Ns7u/DoC3gymYzbBLlBYMfocl34lL4EkK56W2qiGAfuEf6v/kXqS9X6si+rGDEaXkuS/0UEtsP7AxsUpRYHWngk/DGOUTzKXPkMsNv6IbxHSK4wpA1Xka93r13DrKTzcaoXOqEe+K9GWiJsJl0zAM4UEmYcXF7sh7WzYeeY3D1RT7nt4I0AHaPkt7PKsdo/DR3xQPUluQ553vVUe2rAMokqRVHHzM5OuGwng5iLb3u0fZaD,iv:bmp/x16E/gRXCDqcg5sUt+DRFCRsHIO0/01nr+uFR7Y=,tag:wFw8Efid68B88gTkAbCzuw==,type:str]",
"sops": { "sops": {
"age": [ "age": [
{ {
@ -7,8 +7,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXc3VHa0p2MVdIdHRrbEVi\ndUwxMXA3cFpDODA0Z0MyUC9aemF4U2RXeUhrCmZjSDBLZ0twRk5rZG16blorQVVZ\nRE5SNE51bGlhYTVqcThFUVIvTWxwOW8KLS0tIEVHZ3Z6VVZHK2FUQWZQNVlOTkpL\nYUpNUSsyQllQL0lUa0FaODZiSjBDSk0KSJHdYoiOuma7YFjLpssAgw8BfBo5tl+o\nRvNt9rsXUlXEwMlcmYpkgUlsSAJnus+uE9AdBSvTyFRb9Wo696YFRg==\n-----END AGE ENCRYPTED FILE-----\n" "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXc3VHa0p2MVdIdHRrbEVi\ndUwxMXA3cFpDODA0Z0MyUC9aemF4U2RXeUhrCmZjSDBLZ0twRk5rZG16blorQVVZ\nRE5SNE51bGlhYTVqcThFUVIvTWxwOW8KLS0tIEVHZ3Z6VVZHK2FUQWZQNVlOTkpL\nYUpNUSsyQllQL0lUa0FaODZiSjBDSk0KSJHdYoiOuma7YFjLpssAgw8BfBo5tl+o\nRvNt9rsXUlXEwMlcmYpkgUlsSAJnus+uE9AdBSvTyFRb9Wo696YFRg==\n-----END AGE ENCRYPTED FILE-----\n"
} }
], ],
"lastmodified": "2025-12-15T22:09:17Z", "lastmodified": "2025-12-22T09:31:39Z",
"mac": "ENC[AES256_GCM,data:C2Jwz+4Rz76ZVa/kT1OxtNp0gvdrEDd7QmlIgDv3WeocVb05TaWKap1Z9ytjR1U8ZBpYWiLJ4DGNh3WEL3/kQpTuO3WsaTP/VWQiQdPn9AKpTPjlFblRxcAUiN8yxj+OVScvb8FUBfTCHSXII8oqHmGHRXbsduauGtiFh3RKK4Y=,iv:5YpsTABeP1TNh3CeAsDEG2WloCFXvTR5sESOTpvvRgY=,tag:ezYnBZ34kQZ/sAJLjUrD7g==,type:str]", "mac": "ENC[AES256_GCM,data:rOOL5gRTILzOnIU7LveEAI3HeLkf16wTZL4toxBqDiReWwXllCeUaFJ+n5awehit44LL1HrFVgZ/uUsnJBpF6WciPjXTKeRZsazhEKEuBhvcfJzvDQvj/ls5QsEXr/xuDmVaLNM7s7QCok+iefSS4Cu9IHhrmmdo1GyIw6gvNP0=,iv:pDnLtzMbGWR0PnIshenuNNvHIglvNFD+DJuUOapWGQI=,tag:9azzi8367Nq0Z0yGW8H5sg==,type:str]",
"pgp": [ "pgp": [
{ {
"created_at": "2025-12-15T22:09:23Z", "created_at": "2025-12-15T22:09:23Z",

View file

@ -0,0 +1,48 @@
wireguard-private-key: ENC[AES256_GCM,data:DBCK92h8mGxDshB5OIEbyUENc6a4jmvzKPvljUn50AM1I5vBm/bSTDRStIM=,iv:K/OiPnAlXNt3RqBiBiiZqIY8vqsIw0kmKE+aeeVhr+Q=,tag:eloCJ7yjI2tpHMxwNxZDDw==,type:str]
sops:
age:
- recipient: age1wmx8y2hs83j2u5srdnfxljrzxm8jtxl6fr0mq7xf2ldxyglpzf2qq89rpx
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwTzZxNUdxbWUzbkp5eDE4
a3NGaWwrRXZxaXRvTmJjQUZHZU5wY3FpTTNrCmNxN21hU0dBd2piZUNCNndNaUNo
K252RGYyWVpXanZiVGMveXRnc0ViOFEKLS0tIFQ1T0dXUjlYdUNOcXJYZzA2YmtN
YWlkK0xrclpXYTkxUXFiNGMxU1NnMGcKCZzLfTPjeeGxyD43dOGDYsQVsw24cyHI
jz0B9VV07p33OP448eLyLgwpVFaNG0q+hXPH+0fb3V3foBT2QSeuPA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-12-22T08:58:44Z"
mac: ENC[AES256_GCM,data:GnnNiw5DwXDCXEWqMa6eGYVNK4GyNvoNf9WK5wYE+uT8nolKD/pFEjqt++vHHlmEbPePhErAAu2vr7QGH/p8c+oEOEjiLJicMxJ72Bx8+5RLe4WuKO3GLTizgCy2f9Fr3gDWaKG8W9XF6xVzwPzzguRpfo1F0fmrPW6/EiGJDJ0=,iv:DWclKhUVp9UYc0F1J1k5+Y80dPK/RXoPDmylYlbmtiE=,tag:VgBHoVWPhOIwn7vuDwxKSw==,type:str]
pgp:
- created_at: "2025-12-22T08:56:58Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAwDh3VI7VctTAQ/9E8KBoKOUyeIflZzmSriaoQ2/I0EnqKd9cLLFyqFFd4Gp
ZyOfaTqQE9/NWOG3KkG3iuHyCEdHjP14QolJDPPfuqjVnIkc0hKJ/TqwWb5OXurZ
hbkFZEYtuGWXGNugL0T/BnSUqXhd5sFBJueZD0LU7xBsmaDqMFlY//iheNEgq0RA
a3HeQL9gH4d1eUPje9XfcJ+onj9yYgejQ905ZIOAyrYTLVjnSc9HKJ3kz+rpin1J
2JHULBZEzigNiFXE2XmAatIM6PNBVJ21VL7CEPTt/qauRVHLsrz4PKcR/VMTzwJ/
A0hdMrYbYRKOL0rHDYyjpoeuKsUDNV0Gi//WQDXN9DGMREG5P4PH7+yPBcc+vgLK
E7B6RJcUFyuRh/n/KPGzKk1KX3KOQMjIKUaUGy7Ru91K8rG+/EH1ker6csDpe2aY
bYjtPnjiIvd/dR++JLALQJfCuFC6pUhGAC71Bchr4U2Rg+s9pRZBOYco7pJMJubd
rkt61MYFNpcZkyQ9mYAVCd13JcmoTsAtwmUkdU098tfCVA8sMRgFF1f2DK8iyRrq
jfh6pX1/UqFtOug8hElBJHMQkl9eAKla6COQeGtZC3LkxkKhkNLTcMLf4I5Tzf8o
ftxFw1eW4174Psg9vo+/T1zcOYQTVIUfnlPuK/oiCJIAWZ2U92HnCa9pwQe8nkSF
AgwDC9FRLmchgYQBD/4lFaFk9tlyBnTWY5yWJmpcV1gPSwLyeMnax/89/Nnixu1/
205CvMGEReFEQ4CDTp+WXwp7DA3PKqhg/hEq/x9cmH0kAkQg1n9QoJcd2UzDadfp
89ABsW5fBZJSLdHn3P06VIihe516GnsDA/KL88PdkYXpElgfqWXC8g2URKW6QeO5
j/XzOXDiMdO2+K37NcbwSQsMd0pc2BAJ4mmjvjm0aZe6ddF1917WYFkOZi09clNh
iYW8Vk4hmOkGqEO3zNjQkzZ6Ra9Cm4qr1BG7k+n4sxuwoae2T14/DlCSYh/llSTw
N25tWEeXeaAtQgVwoWYLrmSdCKYtxyACPrt6uEYaGE7wbXgBgCX91HuznlHiUvnG
uagiFMxr0x4G2Q+C8OuptKBneBcR6a21q3HaGdl/99F3fM7C2bvzv2y+ZScBP6fH
LvZjF/r3qrLONCqtaQ4Kw9LPzow8wMkCkshC7K0KNRq10ww7s9kbY8io4+QVLv3p
ZHbN+U+9BheVOAF8uX8V+OQfeFdp0VTbPZa7v1mLdbjshPNi7SEhlCjrtB8yqRtd
cl2tinqfWAosYt0xdUmH9uoY7bz9+BKIZ6FVl1huP2DEa5JAjnVItyLG+n2GpIqN
1SBaC/OCbJFawPmZgaWou+kxpLr7hu6kmPdCcdtHa4TYuanLkOTk0r0mztzhjNJe
Af5UVQLJJ7tduvLAB+vh/z91qgv0ftVDq4Kkr7Ma37OYAx4VzuHwEXNLKu2C6CwE
M7sp4ZglesyABMbOEhwxqg/kCYGS76kThwkrJfrgf82FgnMdUyYCMhhgy6iFow==
=izPI
-----END PGP MESSAGE-----
fp: 4BE7925262289B476DBBC17B76FD3810215AE097
unencrypted_suffix: _unencrypted
version: 3.11.0

View file

@ -1,4 +1,4 @@
{ self, lib, minimal, ... }: { self, lib, minimal, globals, ... }:
{ {
imports = [ imports = [
@ -15,11 +15,10 @@
loader.efi.canTouchEfiVariables = true; loader.efi.canTouchEfiVariables = true;
}; };
# globals.hosts.${config.node.name}.ipv4 = config.repo.secrets.local.ipv4; networking.hosts = {
# globals.networks.home.hosts.${config.node.name} = { ${globals.networks.home-lan.hosts.hintbooth.ipv4} = [ "server.hintbooth.${globals.domains.main}" ];
# ipv4 = config.repo.secrets.local.home-ipv4; ${globals.networks.home-lan.hosts.hintbooth.ipv6} = [ "server.hintbooth.${globals.domains.main}" ];
# mac = config.repo.secrets.local.home-mac; };
# };
swarselsystems = { swarselsystems = {
info = "ASRock J4105-ITX, 32GB RAM"; info = "ASRock J4105-ITX, 32GB RAM";
@ -32,10 +31,16 @@
isNixos = true; isNixos = true;
proxyHost = "twothreetunnel"; proxyHost = "twothreetunnel";
server = { server = {
wireguard = { wireguard.interfaces = {
wgProxy = {
isClient = true; isClient = true;
serverName = "twothreetunnel"; serverName = "twothreetunnel";
}; };
wgHome = {
isClient = true;
serverName = "hintbooth";
};
};
restic = { restic = {
bucketName = "SwarselWinters"; bucketName = "SwarselWinters";
paths = [ paths = [

View file

@ -202,7 +202,13 @@ in
description = "List of external dns nameservers"; description = "List of external dns nameservers";
}; };
}; };
}; };
}; };
}; };

View file

@ -1,4 +1,4 @@
{ config, globals, ... }: { lib, config, globals, ... }:
{ {
topology.self = { topology.self = {
icon = lib.mkIf config.swarselsystems.isCloud "devices.cloud-server"; icon = lib.mkIf config.swarselsystems.isCloud "devices.cloud-server";

View file

@ -1,176 +1,217 @@
{ self, lib, pkgs, config, confLib, nodes, globals, ... }: { self, lib, pkgs, config, confLib, nodes, globals, ... }:
let let
wgInterface = "wg0"; inherit (confLib.gen {
inherit (confLib.gen { name = "wireguard"; port = 52829; user = "systemd-network"; group = "systemd-network"; }) servicePort serviceName serviceUser serviceGroup; name = "wireguard";
port = 52829;
user = "systemd-network";
group = "systemd-network";
}) servicePort serviceName serviceUser serviceGroup;
inherit (config.swarselsystems) sopsFile; inherit (config.swarselsystems) sopsFile;
wgSopsFile = self + "/secrets/repo/wg.yaml"; wgSopsFile = self + "/secrets/repo/wg.yaml";
inherit (config.swarselsystems.server.wireguard) peers isClient isServer serverName serverNetConfigPrefix ifName;
cfg = config.swarselsystems.server.wireguard;
inherit (cfg) interfaces;
ifaceList = builtins.attrValues interfaces;
in in
{ {
options = { options = {
swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} settings"; swarselmodules.server.${serviceName} =
lib.mkEnableOption "enable ${serviceName} settings";
swarselsystems.server.wireguard = { swarselsystems.server.wireguard = {
isServer = lib.mkEnableOption "set this as a wireguard server"; interfaces = lib.mkOption {
isClient = lib.mkEnableOption "set this as a wireguard client"; type = lib.types.attrsOf (lib.types.submodule ({ name, config, ... }: {
options = {
isServer = lib.mkEnableOption "set this interface as a wireguard server";
isClient = lib.mkEnableOption "set this interface as a wireguard client";
serverName = lib.mkOption { serverName = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = ""; default = "";
description = "Hostname of the WireGuard server this interface connects to (when isClient = true).";
}; };
serverNetConfigPrefix = lib.mkOption { serverNetConfigPrefix = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "${if nodes.${serverName}.config.swarselsystems.isCloud then nodes.${serverName}.config.node.name else "home"}"; default =
let
serverCfg = nodes.${config.serverName}.config;
in
if serverCfg.swarselsystems.isCloud
then serverCfg.node.name
else "home";
readOnly = true; readOnly = true;
description = "Prefix used to look up the server network in globals.networks.\"<prefix>-wg\".";
}; };
ifName = lib.mkOption { ifName = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = wgInterface; default = name;
description = "Name of the WireGuard interface.";
}; };
peers = lib.mkOption { peers = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
description = "Wireguard peer config names"; description = "WireGuard peer config names (clients when this host is server, or additional peers).";
};
};
}));
default = { };
description = "WireGuard interfaces defined on this host.";
};
}; };
}; };
};
config = lib.mkIf config.swarselmodules.server.${serviceName} { config = lib.mkIf config.swarselmodules.server.${serviceName} {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
wireguard-tools wireguard-tools
]; ];
sops = { sops.secrets =
secrets = { lib.mkMerge (
wireguard-private-key = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0600"; }; [
# create this secret only if this is a simple client with only one peer (the server) {
"wireguard-${serverName}-${config.node.name}-presharedKey" = lib.mkIf (isClient && peers == [ ]) { sopsFile = wgSopsFile; owner = serviceUser; group = serviceGroup; mode = "0600"; }; # shared host private key
wireguard-private-key = {
inherit sopsFile;
owner = serviceUser;
group = serviceGroup;
mode = "0600";
};
} }
# create these secrets only if this host has multiple peers ] ++ (map
// lib.optionalAttrs (peers != [ ]) (builtins.listToAttrs (map (i:
(clientName: { let
name = "wireguard-${config.node.name}-${clientName}-presharedKey"; simpleClientSecrets =
value = { sopsFile = wgSopsFile; owner = serviceUser; group = serviceGroup; mode = "0600"; }; lib.optionalAttrs (i.isClient && i.peers == [ ]) {
}) "wireguard-${i.serverName}-${config.node.name}-${i.ifName}-presharedKey" = {
peers)); sopsFile = wgSopsFile;
owner = serviceUser;
group = serviceGroup;
mode = "0600";
};
}; };
multiPeerSecrets =
lib.optionalAttrs (i.peers != [ ]) (builtins.listToAttrs (map
(clientName: {
name = "wireguard-${config.node.name}-${clientName}-${i.ifName}-presharedKey";
value = {
sopsFile = wgSopsFile;
owner = serviceUser;
group = serviceGroup;
mode = "0600";
};
})
i.peers));
in
simpleClientSecrets // multiPeerSecrets
)
ifaceList)
);
networking = { networking = {
firewall.checkReversePath = lib.mkIf isClient "loose"; firewall.checkReversePath =
firewall.allowedUDPPorts = [ servicePort ]; lib.mkIf (lib.any (i: i.isClient) ifaceList) "loose";
# nat = lib.mkIf (config.swarselsystems.isCloud && isServer) {
# enable = true; firewall.allowedUDPPorts =
# enableIPv6 = true; lib.mkIf (lib.any (i: i.isServer) ifaceList) [ servicePort ];
# externalInterface = "enp0s6";
# internalInterfaces = [ ifName ];
# };
# interfaces.${ifName}.mtu = 1280; # the default (1420) is not enough!
}; };
systemd.network = { systemd.network = {
enable = true; enable = true;
networks."50-${ifName}" = { networks = lib.mkMerge (map
(i:
let
inherit (i) ifName;
in
{
"50-${ifName}" = {
matchConfig.Name = ifName; matchConfig.Name = ifName;
linkConfig = { linkConfig = {
MTUBytes = 1408; # TODO: figure out where we lose those 12 bits (8 from pppoe maybe + ???) MTUBytes = 1408; # TODO: figure out where we lose those 12 bits (8 from pppoe maybe + ???)
}; };
# networkConfig = lib.mkIf (config.swarselsystems.isCloud && isServer) {
# IPv4Forwarding = true;
# IPv6Forwarding = true;
# };
address = address =
if isServer then [ if i.isServer then [
globals.networks."${config.swarselsystems.server.netConfigPrefix}-wg".hosts.${config.node.name}.cidrv4 globals.networks."${config.swarselsystems.server.netConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv4
globals.networks."${config.swarselsystems.server.netConfigPrefix}-wg".hosts.${config.node.name}.cidrv6 globals.networks."${config.swarselsystems.server.netConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv6
] else [ ] else [
globals.networks."${serverNetConfigPrefix}-wg".hosts.${config.node.name}.cidrv4 globals.networks."${i.serverNetConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv4
globals.networks."${serverNetConfigPrefix}-wg".hosts.${config.node.name}.cidrv6 globals.networks."${i.serverNetConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv6
]; ];
}; };
})
ifaceList);
netdevs."50-${ifName}" = { netdevs = lib.mkMerge (map
(i:
let
inherit (i) ifName;
in
{
"50-${ifName}" = {
netdevConfig = { netdevConfig = {
Kind = "wireguard"; Kind = "wireguard";
Name = ifName; Name = ifName;
}; };
wireguardConfig = { wireguardConfig = {
ListenPort = lib.mkIf isServer servicePort; ListenPort = lib.mkIf i.isServer servicePort;
# ensure file is readable by `systemd-network` user
PrivateKeyFile = config.sops.secrets.wireguard-private-key.path; PrivateKeyFile = config.sops.secrets.wireguard-private-key.path;
# To automatically create routes for everything in AllowedIPs, RouteTable = lib.mkIf i.isClient "main";
# add RouteTable=main
RouteTable = lib.mkIf isClient "main";
# FirewallMark marks all packets send and received by wg0
# with the number 42, which can be used to define policy rules on these packets.
# FirewallMark = 42;
}; };
wireguardPeers = lib.optionals isClient [
wireguardPeers =
lib.optionals i.isClient [
{ {
PublicKey = builtins.readFile "${self}/secrets/public/wg/${serverName}.pub"; PublicKey =
PresharedKeyFile = config.sops.secrets."wireguard-${serverName}-${config.node.name}-presharedKey".path; builtins.readFile "${self}/secrets/public/wg/${i.serverName}.pub";
Endpoint = "server.${serverName}.${globals.domains.main}:${toString servicePort}";
# Access to the whole network is routed through our entry node. PresharedKeyFile =
config.sops.secrets."wireguard-${i.serverName}-${config.node.name}-${i.ifName}-presharedKey".path;
Endpoint =
"server.${i.serverName}.${globals.domains.main}:${toString servicePort}";
PersistentKeepalive = 25; PersistentKeepalive = 25;
AllowedIPs = AllowedIPs =
let let
wgNetwork = globals.networks."${serverNetConfigPrefix}-wg"; wgNetwork = globals.networks."${i.serverNetConfigPrefix}-${i.ifName}";
in in
(lib.optional (wgNetwork.cidrv4 != null) wgNetwork.cidrv4) (lib.optional (wgNetwork.cidrv4 != null) wgNetwork.cidrv4)
++ (lib.optional (wgNetwork.cidrv6 != null) wgNetwork.cidrv6); ++ (lib.optional (wgNetwork.cidrv6 != null) wgNetwork.cidrv6);
} }
] ++ lib.optionals isServer (map ]
++ lib.optionals i.isServer (map
(clientName: { (clientName: {
PublicKey = builtins.readFile "${self}/secrets/public/wg/${clientName}.pub"; PublicKey =
PresharedKeyFile = config.sops.secrets."wireguard-${config.node.name}-${clientName}-presharedKey".path; builtins.readFile "${self}/secrets/public/wg/${clientName}.pub";
# PersistentKeepalive = 25;
PresharedKeyFile =
config.sops.secrets."wireguard-${config.node.name}-${clientName}-${i.ifName}-presharedKey".path;
AllowedIPs = AllowedIPs =
let let
clientInWgNetwork = globals.networks."${config.swarselsystems.server.netConfigPrefix}-wg".hosts.${clientName}; clientInWgNetwork =
globals.networks."${config.swarselsystems.server.netConfigPrefix}-${i.ifName}".hosts.${clientName};
in in
(lib.optional (clientInWgNetwork.ipv4 != null) (lib.net.cidr.make 32 clientInWgNetwork.ipv4)) (lib.optional (clientInWgNetwork.ipv4 != null)
++ (lib.optional (clientInWgNetwork.ipv6 != null) (lib.net.cidr.make 128 clientInWgNetwork.ipv6)); (lib.net.cidr.make 32 clientInWgNetwork.ipv4))
++ (lib.optional (clientInWgNetwork.ipv6 != null)
(lib.net.cidr.make 128 clientInWgNetwork.ipv6));
}) })
peers); i.peers);
}; };
})
ifaceList);
}; };
# networking = {
# wireguard = {
# enable = true;
# interfaces = {
# wg1 = {
# privateKeyFile = config.sops.secrets.wireguard-private-key.path;
# ips = [ "192.168.178.201/24" ];
# peers = [
# {
# publicKey = "PmeFInoEJcKx+7Kva4dNnjOEnJ8lbudSf1cbdo/tzgw=";
# presharedKeyFile = config.sops.secrets.wireguard-home-preshared-key.path;
# name = "moonside";
# persistentKeepalive = 25;
# # endpoint = "${config.repo.secrets.common.ipv4}:51820";
# endpoint = "${config.repo.secrets.common.wireguardEndpoint}";
# # allowedIPs = [
# # "192.168.3.0/24"
# # "192.168.1.0/24"
# # ];
# allowedIPs = [
# "192.168.178.0/24"
# ];
# }
# ];
# };
# };
# };
# };
}; };
} }

View file

@ -8,9 +8,9 @@
config.swarselsystems.proxyHost != config.node.name config.swarselsystems.proxyHost != config.node.name
then then
if if
config.swarselsystems.server.wireguard.isClient config.swarselsystems.server.wireguard.interfaces.wgProxy.isClient
then then
globals.networks."${config.swarselsystems.server.wireguard.serverNetConfigPrefix}-wg".hosts.${config.node.name}.ipv4 globals.networks."${config.swarselsystems.server.wireguard.interfaces.wgProxy.serverNetConfigPrefix}-wgProxy".hosts.${config.node.name}.ipv4
else else
globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4 globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4
else else

View file

@ -0,0 +1 @@
M5vKsS+gw13pS7TTMktxBXJRooIMKiTXjZ6NJgQDAEY=

View file

@ -1,5 +1,5 @@
{ {
"data": "ENC[AES256_GCM,data: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,iv:/e9U+fXMYBOjubsIOKa3dZV6bs6F+OqTyBryUrwPySM=,tag:ThVhvz+Hg6Wq8MMkR4eQOw==,type:str]", "data": "ENC[AES256_GCM,data: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,iv:5B9BO9Pf254uA5ovKKhU6qcKCvsxgU/z2SXSuvvrXRM=,tag:63d6vx0R+pth+2pjFY3XoA==,type:str]",
"sops": { "sops": {
"age": [ "age": [
{ {
@ -51,8 +51,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvbTFqR3RScWxnTFR3dlhv\nNUNEVGRkUDB4L3J6ckJIMWZCWk44RjdpVmxRCkhzZTBuSGduanBmQWsvNW5XMWQv\nYVZmNS9FVzN3a05kUVBheDljYUUrcHcKLS0tIGxPN1dWVkg4NUpnZGJ6VWFJWFVZ\nYnNvRG94MmFxYnlDQ0JyeDNFQldzdlkKsp+nYSR6Lxq8b3/dpMO7uTbNnO0Bva7w\nb9s908PLaZEN1jywEoba3yq743vuEHCKQWFIfDtsRcbNR6Yr4d2eGw==\n-----END AGE ENCRYPTED FILE-----\n" "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvbTFqR3RScWxnTFR3dlhv\nNUNEVGRkUDB4L3J6ckJIMWZCWk44RjdpVmxRCkhzZTBuSGduanBmQWsvNW5XMWQv\nYVZmNS9FVzN3a05kUVBheDljYUUrcHcKLS0tIGxPN1dWVkg4NUpnZGJ6VWFJWFVZ\nYnNvRG94MmFxYnlDQ0JyeDNFQldzdlkKsp+nYSR6Lxq8b3/dpMO7uTbNnO0Bva7w\nb9s908PLaZEN1jywEoba3yq743vuEHCKQWFIfDtsRcbNR6Yr4d2eGw==\n-----END AGE ENCRYPTED FILE-----\n"
} }
], ],
"lastmodified": "2025-12-19T16:02:26Z", "lastmodified": "2025-12-19T16:42:32Z",
"mac": "ENC[AES256_GCM,data:jP8kwTNwYRteIxbk5Zu8VHzapyVvUUTCmq67agl+uRYNaPmtkZiBjmrG8oN0hWgEpbytrvKPZzWJ92NTxzyGdvW7sIHX2z6PTU0O1u/x4jmWKvv/zDZhy9+7kVlWYrc7AO7gIRdzWtHmOzYkm2+soNmq/cd5sj2/DeiksmUK/10=,iv:qKayuVRwMg+qfEuYhIGqG1fx46SpKA9UFlt7aBSDhLM=,tag:fl0j4VBMaQzmA0clFEcEwg==,type:str]", "mac": "ENC[AES256_GCM,data:+x9MU+PNHfd7FgWTvx/Dt68IonCM99J54bOSgZzhN1uDepGCCbw9VvkqHLOy3+w+9i7R4o+xLggeV29WrGPqrx8aT5LNVo3jIjGXGTkOxwQ2X1GUkzZb4VrIMJlA/1P7Zt2XhnfoiFg/DZtjyhi4WB4WY2lC5QY1ZSH7ixBstU4=,iv:Wz1ndrqvP2666viHYdcCdYEiLvz2K0y54Uvv2Uzz1Wk=,tag:C5d8dxTtjTEGnhoy9nfUnw==,type:str]",
"pgp": [ "pgp": [
{ {
"created_at": "2025-12-15T21:53:38Z", "created_at": "2025-12-15T21:53:38Z",

View file

@ -1,7 +1,8 @@
wireguard-twothreetunnel-winters-presharedKey: ENC[AES256_GCM,data:v+RyEcJh7dSBuOUgJFG6f3C8CYchEDy1mk2vUXlJbeeqAFcU3d9/M7QbHz0=,iv:GGJ61LsTq1lKcg0xjO3Co1PVqGW56Tgb0dWtT+7suz8=,tag:WCAsVbBsOeo7xmqRwdCinA==,type:str] wireguard-twothreetunnel-winters-wgProxy-presharedKey: ENC[AES256_GCM,data:FZWARdSb8o3KpgJikYIC7hYLZ+WUaulZoisE4Ifdpsr8tBazY9bVlf6D9p4=,iv:QSUUWFR6uUoX62l0kMiVKkmlI0lEXuDEV7PSfBLJymM=,tag:eupex55cEm7lDKHFbJOkmg==,type:str]
wireguard-twothreetunnel-moonside-presharedKey: ENC[AES256_GCM,data:vkUcgip1lrYEYwcbLF5WSPUK8m7ouuyDtVykcl4Lah21asBhCmDtqqNzvvw=,iv:1zVhRsxLQvBpHcSjcswwSCotelZk7SWI9NkXdrAS21Y=,tag:0DvNJMaiYl93flbjNQBVwg==,type:str] wireguard-twothreetunnel-moonside-wgProxy-presharedKey: ENC[AES256_GCM,data:Y/EwbaVbGljiz9XZmr7+/udBfeaY+CLMfnKzekXP50Hu8ek8aA1/SKs2qd0=,iv:BijEDkfpRWox8CPwCoZLA42WihYIqHJJgSgOfsOGcG4=,tag:8+qEnqTsqyNdD4oVPiuQuQ==,type:str]
wireguard-twothreetunnel-eagleland-presharedKey: ENC[AES256_GCM,data:5JMTgXPcRzcr3GfGinAeLvldweArGyB8gyqRNtxlKa1RPY9pPa7s8Pxhdng=,iv:Mk6fLKpf8XbSGEU8b/j+ZZcQxcxhKGHRPSmk5Q9lrXQ=,tag:GACQf8x46LVQMwrlp6+NSA==,type:str] wireguard-twothreetunnel-eagleland-wgProxy-presharedKey: ENC[AES256_GCM,data:dF8VPApd6iYKIZjBXB2rjIXIxyy2+U76TdyFuyUW0zSbtjzqn1ZKrhX4w/M=,iv:GqOHsS97di9sHqjndlq0EdWLcJ1EMLmDOnFJlBgTvYU=,tag:PdxEYlg3lPShUJYlANLjhg==,type:str]
wireguard-twothreetunnel-belchsfactory-presharedKey: ENC[AES256_GCM,data:MKla1VJiFzpWxrxXA+FUU10KQmrO926wKdBCM0tQDvkQWrR1FpvbbeBfdzM=,iv:5aIhbhiAsfIXUojuLwRsuhZAPvGkORZTOo+0Rc5/bpY=,tag:nG++1kDULmAMfCx0a8P40Q==,type:str] wireguard-twothreetunnel-belchsfactory-wgProxy-presharedKey: ENC[AES256_GCM,data:NAbVE7ysGDD6TT0RxdL6bTNloac4RBU1JWeTFqYo9PO6ZU2f/yq6aboi2AA=,iv:Ky4UvgRDEG1UgDmi+m5mHWHO+yUGzphQPYIuyAXDkhw=,tag:WP+/8q8jfitNC/rXN5Mp2A==,type:str]
wireguard-hintbooth-winters-wgHome-presharedKey: ENC[AES256_GCM,data:57KGUxn1BibZ+9H9mXg9EYmcy1JBX+M79ACL3Qt0XEMl0dFlk9Wq6cr3JTg=,iv:9QHdykNlUU1H0uco21zA8leQH73PAeL+xTVi6V9zx7U=,tag:6mfSCddnVGMBEAqCHDIIrw==,type:str]
sops: sops:
age: age:
- recipient: age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza - recipient: age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza
@ -112,8 +113,8 @@ sops:
THZaSXhMNldUbHpBMVZQWXYwaVVQYWsKpUbG+lC37W6bzOuu9MaUmEZ5T1b5EC9k THZaSXhMNldUbHpBMVZQWXYwaVVQYWsKpUbG+lC37W6bzOuu9MaUmEZ5T1b5EC9k
VIY9XUoA7h0Z6G5Jrx/lrf6qsghMqd59gPA1qh8KlCJBAUJPHzQKVg== VIY9XUoA7h0Z6G5Jrx/lrf6qsghMqd59gPA1qh8KlCJBAUJPHzQKVg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-12-03T15:54:14Z" lastmodified: "2025-12-22T09:11:50Z"
mac: ENC[AES256_GCM,data:yPPp6WQvcMB6mV/V62Y0Ki8Fq2trV3HKTykP5HD7J7ZgUiFNmLPbAApMeefe7Bb8pF7ETrkjRhET7/pXJX7anaOd6Y6pCyF75/xQDzwJ0Ac3FSPgeoOwlA/W+OrRMm9Hla9Q5gNPzgYirIHXoO+aScLcTQp46tiQv8B0Ol0ZSoI=,iv:eIT/EcVpWk79eerrxqy7AqtqNtpJi5sOIe0wmHRjYfI=,tag:4KPyZE9s62fCisjgihH4Jg==,type:str] mac: ENC[AES256_GCM,data:D6qKXhSuYGPm9K7Al/la3O++DmOTQN5++96k44IIvgSR5Q3kTkMYxPsf3PWNyjMm09+9aRauuHPHj098+W1rXaq43Iqr24JAuaZNwLyxtqkaibv/Zhx1RgEWGXyOHDtlfIPoULNKVZ0ls2mtk40oQHsfhnRyS42m+HMQnL+tCF4=,iv:uzKbpZu9P05KbaXnBUxN4rA9nYOXpeK+E/scWoFxpcs=,tag:PuMdBx3JOT1EfFkOPV0G2g==,type:str]
pgp: pgp:
- created_at: "2025-12-15T21:53:40Z" - created_at: "2025-12-15T21:53:40Z"
enc: |- enc: |-