diff --git a/flake.lock b/flake.lock
index 372528d..e8dd9f5 100644
--- a/flake.lock
+++ b/flake.lock
@@ -533,11 +533,11 @@
     },
     "nixpkgs_3": {
       "locked": {
-        "lastModified": 1742288794,
-        "narHash": "sha256-Txwa5uO+qpQXrNG4eumPSD+hHzzYi/CdaM80M9XRLCo=",
+        "lastModified": 1742422364,
+        "narHash": "sha256-mNqIplmEohk5jRkqYqG19GA8MbQ/D4gQSK0Mu4LvfRQ=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "b6eaf97c6960d97350c584de1b6dcff03c9daf42",
+        "rev": "a84ebe20c6bc2ecbcfb000a50776219f48d134cc",
         "type": "github"
       },
       "original": {
diff --git a/hosts/_iso/configuration.nix b/hosts/_iso/configuration.nix
index d971c32..b4af756 100644
--- a/hosts/_iso/configuration.nix
+++ b/hosts/_iso/configuration.nix
@@ -6,11 +6,16 @@
     ../../configuration/gpg-ssh
   ];
 
+  profiles.clerie.network-fallback-dhcp.enable = true;
+
   # systemd in initrd is broken with ISOs
   # Failed to mount /sysroot/iso
   # https://github.com/NixOS/nixpkgs/issues/327187
   boot.initrd.systemd.enable = false;
 
+  networking.useDHCP = false;
+  systemd.network.enable = true;
+
   networking.hostName = "isowo";
   isoImage.isoBaseName = lib.mkForce "nixos-isowo";
 
diff --git a/hosts/aluminium/configuration.nix b/hosts/aluminium/configuration.nix
index 6651cfd..87d0aa0 100644
--- a/hosts/aluminium/configuration.nix
+++ b/hosts/aluminium/configuration.nix
@@ -18,7 +18,10 @@
     terminal_output serial
   ";
 
-  services.wg-clerie = {
+  networking.useDHCP = false;
+  systemd.network.enable = true;
+
+  profiles.clerie.wg-clerie = {
     enable = true;
     ipv6s = [ "2a01:4f8:c0c:15f1::8106/128" ];
     ipv4s = [ "10.20.30.106/32" ];
diff --git a/hosts/astatine/configuration.nix b/hosts/astatine/configuration.nix
index ea8cac3..72ad6bd 100644
--- a/hosts/astatine/configuration.nix
+++ b/hosts/astatine/configuration.nix
@@ -19,14 +19,13 @@
   ";
 
   networking.useDHCP = false;
-
   systemd.network.enable = true;
 
-  #services.wg-clerie = {
-  #  enable = true;
-  #  ipv6s = [ "2a01:4f8:c0c:15f1::8108/128" ];
-  #  ipv4s = [ "10.20.30.108/32" ];
-  #};
+  profiles.clerie.wg-clerie = {
+    enable = true;
+    ipv6s = [ "2a01:4f8:c0c:15f1::8108/128" ];
+    ipv4s = [ "10.20.30.108/32" ];
+  };
 
   clerie.monitoring = {
     enable = true;
diff --git a/hosts/beryllium/configuration.nix b/hosts/beryllium/configuration.nix
index 15235da..274d44c 100644
--- a/hosts/beryllium/configuration.nix
+++ b/hosts/beryllium/configuration.nix
@@ -25,40 +25,12 @@
 
   networking.firewall.enable = false;
 
-  #networking.iproute2.enable = true;
-  #networking.iproute2.rttablesExtraConfig = ''
-  #  200 wg-clerie
-  #'';
-
-  #petabyte.policyrouting = {
-  #  enable = true;
-  #  rules6 = [
-  #    { rule = "from 2a01:4f8:c0c:15f1::8107/128 lookup wg-clerie"; prio = 20000; }
-  #    { rule = "from 2a01:4f8:c0c:15f1::8107/128 unreachable"; prio = 20001; }
-  #  ];
-  #  rules4 = [
-  #    { rule = "from 10.20.30.107/32 lookup wg-clerie"; prio = 20000; }
-  #    { rule = "from 10.20.30.107/32 unreachable"; prio = 20001; }
-  #  ];
-  #};
-
-
-  #networking.wireguard.enable = true;
-  #networking.wireguard.interfaces = {
-  #  wg-clerie = {
-  #    ips = [ "2a01:4f8:c0c:15f1::8107/128" "10.20.30.107/32" ];
-  #    table = "wg-clerie";
-  #    peers = [
-  #      {
-  #        endpoint = "vpn.clerie.de:51820";
-  #        persistentKeepalive = 25;
-  #        allowedIPs = [ "0.0.0.0/0" "::/0" "10.20.30.0/24" "2a01:4f8:c0c:15f1::/113" ];
-  #        publicKey = "2p1Jqs3bkXbXHFWE6vp1yxHIFoUaZQEARS2nJzbkuBA=";
-  #      }
-  #    ];
-  #    privateKeyFile = "/var/src/secrets/wireguard/wg-clerie";
-  #  };
-  #};
+  profiles.clerie.wg-clerie = {
+    enable = true;
+    ipv6s = [ "2a01:4f8:c0c:15f1::8107/128" ];
+    ipv4s = [ "10.20.30.107/32" ];
+    privateKeyFile = "/var/src/secrets/wireguard/wg-clerie";
+  };
 
   clerie.monitoring = {
     enable = true;
diff --git a/hosts/krypton/network.nix b/hosts/krypton/network.nix
index 4197c76..fb71faf 100644
--- a/hosts/krypton/network.nix
+++ b/hosts/krypton/network.nix
@@ -1,7 +1,9 @@
 { ... }:
 
 {
-  services.wg-clerie = {
+  profiles.clerie.common-networking.enable = true;
+
+  profiles.clerie.wg-clerie = {
     enable = true;
     ipv6s = [ "2a01:4f8:c0c:15f1::8011/128" ];
     ipv4s = [ "10.20.30.11/32" ];
diff --git a/hosts/tungsten/configuration.nix b/hosts/tungsten/configuration.nix
index f1028db..2751f57 100644
--- a/hosts/tungsten/configuration.nix
+++ b/hosts/tungsten/configuration.nix
@@ -23,11 +23,11 @@
 
   networking.hostName = "tungsten";
 
-  #services.wg-clerie = {
-  #  enable = true;
-  #  ipv6s = [ "2a01:4f8:c0c:15f1::8112/128" ];
-  #  ipv4s = [ "10.20.30.112/32" ];
-  #};
+  profiles.clerie.wg-clerie = {
+    enable = true;
+    ipv6s = [ "2a01:4f8:c0c:15f1::8112/128" ];
+    ipv4s = [ "10.20.30.112/32" ];
+  };
 
   clerie.monitoring = {
     enable = true;
diff --git a/hosts/zinc/configuration.nix b/hosts/zinc/configuration.nix
index 13a428a..07c0747 100644
--- a/hosts/zinc/configuration.nix
+++ b/hosts/zinc/configuration.nix
@@ -11,6 +11,8 @@
       ./programs.nix
     ];
 
+  profiles.clerie.common-networking.enable = true;
+
   # Use the systemd-boot EFI boot loader.
   boot.loader.systemd-boot.enable = true;
   boot.loader.efi.canTouchEfiVariables = true;
@@ -25,7 +27,7 @@
 
   boot.initrd.systemd.enable = false;
 
-  services.wg-clerie = {
+  profiles.clerie.wg-clerie = {
     enable = true;
     ipv6s = [ "2a01:4f8:c0c:15f1::8109/128" ];
     ipv4s = [ "10.20.30.109/32" ];
diff --git a/profiles/common-networking/default.nix b/profiles/common-networking/default.nix
new file mode 100644
index 0000000..4a3b3b5
--- /dev/null
+++ b/profiles/common-networking/default.nix
@@ -0,0 +1,24 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+
+  options.profiles.clerie.common-networking = {
+    enable = mkEnableOption "Common networking config";
+  };
+
+  config = mkIf config.profiles.clerie.common-networking.enable {
+
+    # Disable scripted network
+    networking.useDHCP = false;
+    # Enable systemd-networkd
+    systemd.network.enable = true;
+
+    # Don't wait for online, if NetworkManger is running too
+    systemd.network.wait-online = mkIf (config.networking.networkmanager.enable == true) {
+      enable = false;
+    };
+
+  };
+}
diff --git a/profiles/default.nix b/profiles/default.nix
index 04aecfb..56cb944 100644
--- a/profiles/default.nix
+++ b/profiles/default.nix
@@ -3,12 +3,14 @@
 {
 
   imports = [
+    ./common-networking
     ./cybercluster-vm
     ./fem-net
     ./hetzner-cloud
     ./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..9ae527e
--- /dev/null
+++ b/profiles/wg-clerie/default.nix
@@ -0,0 +1,170 @@
+{ 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 = (mkIf (cfg.privateKeyFile == null) {
+      secrets.wg-clerie = {
+        owner = "systemd-network";
+        group = "systemd-network";
+      };
+    });
+
+    networking.networkmanager.unmanaged = [
+      "interface-name:wg-clerie"
+    ];
+
+    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;
+      linkConfig.RequiredForOnline = "no";
+      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";
+        }
+      ];
+    };
+
+  };
+}