See https://github.com/NixOS/nixpkgs/pull/312472. This nixpkgs PR (targeting 24.11) broke merging of attributes in the deprecated attrset. As the deprecated attrset is likely to be removed altogether soon, instead of reporting upstream, and all our >24.05 systems are in randomcat's repo for now, we judged that the course of least resistance was just to patch the config on a separate branch until 24.11 is released.
113 lines
3.9 KiB
Nix
113 lines
3.9 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
let
|
|
cfg = config.birdsong.peering;
|
|
hostName = if null != cfg.hostName then cfg.hostName else config.networking.hostName;
|
|
hosts = config.birdsong.hosts;
|
|
host = hosts.${hostName};
|
|
in
|
|
{
|
|
options.birdsong.peering = {
|
|
enable = mkEnableOption "WireGuard peering with the birdsong network";
|
|
hostName = mkOption {
|
|
default = null;
|
|
description = ''
|
|
The hostname of this peer within the network. Must be listed in
|
|
{option}`birdsong.hosts`. If not set, defaults to
|
|
{option}`networking.hostName`.
|
|
'';
|
|
type = with types; nullOr str;
|
|
};
|
|
interface = mkOption {
|
|
default = "wg-birdsong";
|
|
example = "wg0";
|
|
description = "The name of the network interface to use for WireGuard.";
|
|
type = types.str;
|
|
};
|
|
openPorts = mkOption {
|
|
default = true;
|
|
description = "Whether to automatically open firewall ports.";
|
|
type = types.bool;
|
|
};
|
|
privateKeyFile = mkOption {
|
|
description = ''
|
|
Path to the private key for this peer, as generated by `wg genkey`. Must
|
|
be readable by the user "systemd-network"; systemd.netdev(5) recommends
|
|
it be owned by "root:systemd-network" with a "0640" file mode.
|
|
'';
|
|
type = types.path;
|
|
};
|
|
persistentKeepalive = mkOption {
|
|
default = 0;
|
|
example = 23;
|
|
description = ''
|
|
Constantly ping each peer outside the LAN this often, in seconds, in
|
|
order to keep the WireGuard tunnel open. Set this if you are behind NAT
|
|
to keep the NAT session active, or if you have a dynamic IP to keep the
|
|
other peers aware when your IP changes. To avoid syncing, this should
|
|
ideally be a prime number that is not shared by another peer in the same
|
|
LAN. 0 (the default) disables this.
|
|
'';
|
|
type = types.int;
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
assertions = [
|
|
{
|
|
assertion = config.systemd.network.enable == true;
|
|
message = "birdsong depends on networkd. systemd.network.enable must be true";
|
|
}
|
|
{
|
|
assertion = cfg ? privateKeyFile;
|
|
message = "birdsong.peering.privateKeyFile must be set";
|
|
}
|
|
{
|
|
assertion = hostName != null;
|
|
message = "birdsong.peering.hostName or networking.hostName must be set";
|
|
}
|
|
];
|
|
|
|
boot.kernel.sysctl = mkIf host.isRouter {
|
|
"net.ipv4.conf.${cfg.interface}.forwarding" = true;
|
|
"net.ipv6.conf.${cfg.interface}.forwarding" = true;
|
|
};
|
|
|
|
networking.firewall.allowedUDPPorts = mkIf cfg.openPorts [ host.port ];
|
|
|
|
systemd.network = {
|
|
netdevs."30-birdsong" = {
|
|
netdevConfig = {
|
|
Name = cfg.interface;
|
|
Kind = "wireguard";
|
|
Description = "wireguard tunnel to the birdsong network";
|
|
};
|
|
wireguardConfig = {
|
|
PrivateKeyFile = cfg.privateKeyFile;
|
|
ListenPort = host.port;
|
|
};
|
|
wireguardPeers =
|
|
let
|
|
canDirectPeer = host: peer: peer.subnet == "internet" || (host.subnet != "roaming" && peer.subnet == host.subnet);
|
|
in
|
|
mapAttrsToList
|
|
(name: peer: {
|
|
PublicKey = peer.wireguardKey;
|
|
AllowedIPs = [ peer.ipv4 peer.ipv6 ]
|
|
++ optionals peer.isRouter [ "10.127.0.0/16" "fd70:81ca:0f8f::/48" ];
|
|
Endpoint = mkIf (canDirectPeer host peer) "${peer.endpoint}:${toString peer.port}";
|
|
PersistentKeepalive = mkIf (peer.subnet != host.subnet) cfg.persistentKeepalive;
|
|
})
|
|
(filterAttrs (name: peer: peer != host && (canDirectPeer host peer || canDirectPeer peer host)) hosts);
|
|
};
|
|
|
|
networks."30-birdsong" = {
|
|
matchConfig.Name = cfg.interface;
|
|
networkConfig.Address = [ "${host.ipv4}/16" "${host.ipv6}/48" ]
|
|
++ optionals host.isRouter [ "10.127.0.0/16" "fd70:81ca:0f8f::/48" ];
|
|
};
|
|
};
|
|
};
|
|
}
|