nixos-config/modules/wireguard/home.nix

118 lines
3.6 KiB
Nix

{ lib, config, pkgs, ... }:
let
serverHostName = "vueko";
peers = {
nunotaba = {
address = "10.80.0.4";
publicKey = "DvR8mUkll4uyYhNcX82caMkbcw0Lykg8zDzm/3PD5jw=";
public = false;
};
sayuri = {
address = "10.80.0.5";
publicKey = "t7hpd2yZupAKHxYerHtXnlPRUjV1aGbrrzjYakKdOwE=";
public = false;
};
vueko = {
address = "10.80.0.6";
publicKey = "JbOfL4FxPCzJOjI8AGklPHY2FniCXq0QwOa08gjSyns=";
public = false;
};
fuuko = {
address = "10.80.0.7";
publicKey = "VXic8mhaJBSl6yFkx0Cu6JI8tqqjjM3UbW7x+05pV0M=";
public = true;
};
mayushii = {
address = "10.80.0.9";
publicKey = "nnLdgywXmDg8HWH6I0G28Z2zb4OmmyFDpnvvEBzKJTg=";
public = false;
};
};
cfg = config.sbruder.wireguard.home;
enableServer = config.networking.hostName == serverHostName;
isPublic = peers.${config.networking.hostName}.public; # publicly reachable
in
{
options = {
sbruder.wireguard.home = {
enable = lib.mkEnableOption "WireGuard tunnel wg-home";
address = lib.mkOption {
type = lib.types.str;
visible = false;
readOnly = true;
};
};
};
config = lib.mkIf cfg.enable {
sops.secrets.wg-home-private-key = {
sopsFile = ./../../machines + "/${config.networking.hostName}/secrets.yaml";
};
sbruder.wireguard.home.address = peers."${config.networking.hostName}".address;
networking.wireguard.interfaces.wg-home = {
privateKeyFile = config.sops.secrets.wg-home-private-key.path;
ips = [ "${cfg.address}/24" ];
listenPort = if enableServer || isPublic then 51820 else null;
peers =
# fallback/central server for clients that are not publicly reachable
lib.optional (!enableServer)
{
allowedIPs = [ "10.80.0.0/24" ];
publicKey = peers."${serverHostName}".publicKey;
endpoint = "${serverHostName}.sbruder.de:51820";
persistentKeepalive = 25;
} ++ (lib.mapAttrsToList
(hostname: peerConfig: with peerConfig; {
allowedIPs = [ "${address}/32" ];
inherit publicKey;
} // (lib.optionalAttrs (public && !enableServer) {
endpoint = "${hostname}.sbruder.de:51820";
}))
(lib.filterAttrs
(n: v: n != config.networking.hostName && (enableServer || v.public || isPublic))
peers));
};
networking.firewall = {
trustedInterfaces = [ "wg-home" ];
allowedUDPPorts = lib.optional (isPublic || enableServer) 51820
++ lib.optional enableServer 53;
};
boot.kernel.sysctl = lib.optionalAttrs enableServer {
"net.ipv4.ip_forward" = 1;
};
services.bind = lib.mkIf enableServer {
enable = true;
zones = lib.singleton {
name = "vpn.sbruder.de";
master = true;
file =
let
# !!! very hacky
hexStringToInt = hex: (builtins.fromTOML "int = 0x${hex}").int;
peerRecords = lib.concatStrings
(lib.mapAttrsToList
(peer: peerConfig: ''
${peer} IN A ${peerConfig.address}
'')
peers);
peerRecordsHash = builtins.hashString "sha256" peerRecords;
serial = hexStringToInt (lib.substring 0 8 peerRecordsHash);
in
pkgs.writeText "vpn.sbruder.de.zone" (''
$TTL 3600
@ IN SOA ${serverHostName}.sbruder.de. hostmaster.sbruder.de. ${toString serial} 28800 3600 604800 3600
@ IN NS ${serverHostName}.sbruder.de.
'' + peerRecords);
};
};
};
}