{ pkgs, lib, config, hostName, private, ... }:
let
  iface = "wg-intra";
  peers = import wg-intra/peers.nix;
  wg = config.networking.wireguard.interfaces.${iface};
in
{
options.networking.wireguard.${iface}.peers =
  lib.genAttrs (lib.attrNames peers) (peerName: {
    enable = lib.mkEnableOption "this peer";
  });
config = {
networking.wireguard.interfaces.${iface} = lib.recursiveUpdate
  (removeAttrs peers.${hostName} ["ipv4" "persistentKeepalive" "peer"])
  {
    peers =
      lib.mapAttrsToList (peerName: peer:
        lib.recursiveUpdate
          {
            persistentKeepalive =
              peer.persistentKeepalive # Useful if this peer is behind a NAT
              or peers.${hostName}.persistentKeepalive # Useful if this host is behind a NAT
              or null;
          }
          peer.peer)
        (removeAttrs
          (lib.filterAttrs (peerName: _: config.networking.wireguard.${iface}.peers.${peerName}.enable) peers)
          [hostName]);
    privateKeyFile = lib.mkDefault "${private}/${hostName}/wireguard/${iface}/privateKey";

    # Set the MTU to a minimum
    # (IPv4 requires at least 68 but it's 1280 for IPv6).
    # This prevents connections to stall on huge packets,
    # or delaying their initializing due to TCP PMTU probing.
    postSetup = ''
      ip link set dev ${iface} mtu 1280
    '';
  };
networking.hosts = lib.mkMerge [
  (lib.mapAttrs' (hostName: host:
    lib.nameValuePair host.ipv4 [ "${hostName}.wg" ]) peers)
  {
    "${peers.losurdo.ipv4}" = [
      "nix-extracache.losurdo.wg"
      "nix-localcache.losurdo.wg"
      "sftp.losurdo.wg"
    ];
  }
];
networking.firewall.extraCommands = lib.optionalString (wg.listenPort != null) ''
  ip46tables -A nixos-fw -i any -p udp -m udp --dport ${toString wg.listenPort} -j ACCEPT
'';
services.fail2ban.ignoreIP = lib.concatMap
  (host: host.peer.allowedIPs)
  (lib.attrValues peers);
};
}