From 3ec00be4d03d32a489c969ed3dc5d354d0d80aad Mon Sep 17 00:00:00 2001
From: clerie <git@clerie.de>
Date: Thu, 20 Mar 2025 19:06:51 +0100
Subject: [PATCH] profiles/wg-clerie: Migrate wg-clerie to systemd-networkd

---
 profiles/default.nix           |   1 +
 profiles/wg-clerie/default.nix | 163 +++++++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+)
 create mode 100644 profiles/wg-clerie/default.nix

diff --git a/profiles/default.nix b/profiles/default.nix
index 04aecfb..3daf86a 100644
--- a/profiles/default.nix
+++ b/profiles/default.nix
@@ -9,6 +9,7 @@
     ./mercury-vm
     ./netcup
     ./network-fallback-dhcp
+    ./wg-clerie
   ];
 
 }
diff --git a/profiles/wg-clerie/default.nix b/profiles/wg-clerie/default.nix
new file mode 100644
index 0000000..b6a6bf7
--- /dev/null
+++ b/profiles/wg-clerie/default.nix
@@ -0,0 +1,163 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.profiles.clerie.wg-clerie;
+in
+
+{
+  options = {
+    profiles.clerie.wg-clerie = {
+      enable = mkEnableOption "VPN for public static IP";
+      privateKeyFile = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description = "Path to file containing private key for wireguard interface";
+      };
+      ipv6s = mkOption {
+        type = with types; listOf str;
+        default = [];
+        description = "IPv6 interface addresses";
+      };
+      ipv4s = mkOption {
+        type = with types; listOf str;
+        default = [];
+        description = "IPv4 interface addresses";
+      };
+      defaultViaVPN = mkOption {
+        type = types.bool;
+        default = true;
+        description = "Use VPN default route for a protocol, if that protocol is unavailable in the underlay";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.network.config.routeTables = {
+      wg-clerie = 200;
+    };
+    systemd.network.config.addRouteTablesToIPRoute2 = true;
+
+    sops.secrets.wg-clerie = {
+      owner = "systemd-network";
+      group = "systemd-network";
+    };
+
+    systemd.network.netdevs."10-wg-clerie" = {
+      netdevConfig = {
+        Kind = "wireguard";
+        Name = "wg-clerie";
+      };
+      wireguardConfig = {
+        PrivateKeyFile = if cfg.privateKeyFile != null then cfg.privateKeyFile else
+          config.sops.secrets.wg-clerie.path;
+        RouteTable = "wg-clerie";
+      };
+      wireguardPeers = [
+        {
+          PublicKey = "2p1Jqs3bkXbXHFWE6vp1yxHIFoUaZQEARS2nJzbkuBA=";
+          AllowedIPs = [ "0.0.0.0/0" "::/0" "10.20.30.0/24" "2a01:4f8:c0c:15f1::/113" ];
+          Endpoint = "78.47.183.82:51820";
+          PersistentKeepalive = 25;
+        }
+      ];
+    };
+
+    systemd.network.networks."10-wg-clerie" = {
+      matchConfig.Name = "wg-clerie";
+      address = cfg.ipv6s ++ cfg.ipv4s;
+      routingPolicyRules = (builtins.map
+        (ip: {
+          Priority = 19000;
+          Family = "ipv6";
+          From = ip;
+          #Type = "table";
+          Table = "wg-clerie";
+        })
+        cfg.ipv6s
+      ) ++ (builtins.map
+        (ip: {
+          Priority = 19001;
+          Family = "ipv6";
+          From = ip;
+          Type = "unreachable";
+        })
+        cfg.ipv6s
+      ) ++ (builtins.map
+        (ip: {
+          Priority = 19000;
+          Family = "ipv4";
+          From = ip;
+          #Type = "table";
+          Table = "wg-clerie";
+        })
+        cfg.ipv4s
+      ) ++ (builtins.map
+        (ip: {
+          Priority = 19001;
+          Family = "ipv4";
+          From = ip;
+          Type = "unreachable";
+        })
+        cfg.ipv4s
+      ) ++ [
+        {
+          Priority = 20000;
+          Family = "ipv6";
+          To = "2a01:4f8:c0c:15f1::1/128";
+          IPProtocol = "udp";
+          DestinationPort = 51820;
+          #Type = "table";
+          Table = "main";
+        }
+        {
+          Priority = 20001;
+          Family = "ipv6";
+          To = "2a01:4f8:c0c:15f1::1/128";
+          IPProtocol = "udp";
+          DestinationPort = 51820;
+          Type = "unreachable";
+        }
+        {
+          Priority = 20000;
+          Family = "ipv4";
+          To = "78.47.183.82/32";
+          IPProtocol = "udp";
+          DestinationPort = 51820;
+          #Type = "table";
+          Table = "main";
+        }
+        {
+          Priority = 20001;
+          Family = "ipv4";
+          To = "78.47.183.82/32";
+          IPProtocol = "udp";
+          DestinationPort = 51820;
+          Type = "unreachable";
+        }
+        {
+          Priority = 21000;
+          Family = "both";
+          #Type = "table";
+          Table = "main";
+        }
+      ] ++ (if cfg.defaultViaVPN then [
+        {
+          Priority = 21001;
+          Family = "both";
+          #Type = "table";
+          Table = "wg-clerie";
+        }
+      ] else []) ++ [
+        {
+          Priority = 22000;
+          Family = "both";
+          Type = "unreachable";
+        }
+      ];
+    };
+
+  };
+}