91 lines
2.5 KiB
Nix
91 lines
2.5 KiB
Nix
|
{ config, lib, pkgs, ... }:
|
||
|
|
||
|
with lib;
|
||
|
let
|
||
|
hostname = config.instance.hostname;
|
||
|
host = config.fudo.hosts.${hostname};
|
||
|
host-secrets = config.fudo.secrets.host-secrets.${hostname};
|
||
|
|
||
|
cfg = config.fudo.services.wireguard-gateway;
|
||
|
|
||
|
peerOpts = { name, ... }: {
|
||
|
options = with types; {
|
||
|
public-key = mkOption {
|
||
|
type = str;
|
||
|
description = "Peer public key.";
|
||
|
};
|
||
|
|
||
|
assigned-ip = mkOption {
|
||
|
type = str;
|
||
|
description = "IP address assigned to this peer.";
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
in {
|
||
|
options.fudo.services.wireguard-gateway = with types; {
|
||
|
enable = mkEnableOption "Enable WireGuard gateway: let external clients join the local network.";
|
||
|
|
||
|
network = mkOption {
|
||
|
type = str;
|
||
|
description = "IP address range to use for clients.";
|
||
|
default = "172.16.0.0/24";
|
||
|
};
|
||
|
|
||
|
listen-port = mkOption {
|
||
|
type = port;
|
||
|
description = "Port on which to listen for incoming connections.";
|
||
|
default = 51820;
|
||
|
};
|
||
|
|
||
|
peers = mkOption {
|
||
|
type = attrsOf (submodule peerOpts);
|
||
|
description = "Map of peer to peer options.";
|
||
|
default = {};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
config = mkIf cfg.enable {
|
||
|
assertions = [
|
||
|
{
|
||
|
assertion = all (peerOpts:
|
||
|
pkgs.lib.ip.ipv4OnNetwork peerOpts.assigned-ip cfg.network)
|
||
|
(attrValues cfg.peers);
|
||
|
message = "Peer IPs must be on the assigned network.";
|
||
|
}
|
||
|
{
|
||
|
assertion = host.wireguard.private-key-file != null;
|
||
|
message = "WireGuard gateway server private key file must be set.";
|
||
|
}
|
||
|
];
|
||
|
|
||
|
fudo.secrets.host-secrets.${hostname} = {
|
||
|
wireguard-gateway-privkey-file = {
|
||
|
source-file = host.wireguard.private-key-file;
|
||
|
target-file = "/run/wireguard-gateway/key";
|
||
|
};
|
||
|
};
|
||
|
|
||
|
networking = {
|
||
|
firewall.allowedUDPPorts = [ cfg.listen-port ];
|
||
|
wireguard.interfaces.wg-gw0 = {
|
||
|
ips = [ cfg.network ];
|
||
|
listenPort = cfg.listen-port;
|
||
|
postSetup =
|
||
|
"${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s ${cfg.network} -o ${cfg.external-interface} -j MASQUERADE";
|
||
|
postShutdown =
|
||
|
"${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s ${cfg.network} -o ${cfg.external-interface} -j MASQUERADE";
|
||
|
|
||
|
privateKeyFile = host-secrets.wireguard-gateway-privkey-file.target-file;
|
||
|
|
||
|
peers = let
|
||
|
peerList = attrValues cfg.peers;
|
||
|
in map (peerOpts: {
|
||
|
publicKey = peerOpts.public-key;
|
||
|
allowedIPs = [ "${peerOpts.ip}/32" ];
|
||
|
}) cfg.peers;
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
}
|