main
 1# Auto-derive WireGuard client config from hostname + globals.
 2# VPN server (carthage) is excluded — it keeps its own server config.
 3{
 4  hostname,
 5  globals,
 6  libx,
 7  lib,
 8  ...
 9}:
10let
11  # The active VPN server hostname.
12  # Change to "carthage" when cutting over from DigitalOcean to Hetzner.
13  vpnServer = "carthage";
14
15  machine = globals.machines.${hostname};
16  isServer = hostname == "carthage";
17  hasVpn = machine ? net && machine.net ? vpn;
18in
19{
20  config = lib.mkIf (hasVpn && !isServer) {
21    services.wireguard = {
22      enable = true;
23      ips = libx.wg-ips machine.net.vpn.ips;
24      endpoint = globals.net.vpn.endpoint;
25      endpointPublicKey = globals.machines.${vpnServer}.net.vpn.pubkey;
26      # Conservative MTU for paths with extra encapsulation (mobile, PPPoE, DS-Lite).
27      # Default 1420 causes silent packet drops on some networks (e.g. Vodafone DE).
28      mtu = 1340;
29    };
30  };
31}