mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-12 20:55:31 +03:00

Enabling networking.wireguard.useNetworkd currently requires users to modify the permissions of their private key files. Since that is a bad upgrade experience, the module should be disabled by default for now. Once systemd credential support is added to the module, it should be safe to once again enable it by default for networkd users.
206 lines
7.2 KiB
Nix
206 lines
7.2 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
let
|
|
inherit (lib) types;
|
|
inherit (lib.attrsets)
|
|
filterAttrs
|
|
mapAttrs
|
|
mapAttrs'
|
|
mapAttrsToList
|
|
nameValuePair
|
|
;
|
|
inherit (lib.lists) concatMap concatLists;
|
|
inherit (lib.modules) mkIf;
|
|
inherit (lib.options) literalExpression mkOption;
|
|
inherit (lib.strings) hasInfix;
|
|
inherit (lib.trivial) flip;
|
|
|
|
removeNulls = filterAttrs (_: v: v != null);
|
|
|
|
generateNetdev =
|
|
name: interface:
|
|
nameValuePair "40-${name}" {
|
|
netdevConfig = removeNulls {
|
|
Kind = "wireguard";
|
|
Name = name;
|
|
MTUBytes = interface.mtu;
|
|
};
|
|
wireguardConfig = removeNulls {
|
|
PrivateKeyFile = interface.privateKeyFile;
|
|
ListenPort = interface.listenPort;
|
|
FirewallMark = interface.fwMark;
|
|
RouteTable = if interface.allowedIPsAsRoutes then interface.table else null;
|
|
RouteMetric = interface.metric;
|
|
};
|
|
wireguardPeers = map generateWireguardPeer interface.peers;
|
|
};
|
|
|
|
generateWireguardPeer =
|
|
peer:
|
|
removeNulls {
|
|
PublicKey = peer.publicKey;
|
|
PresharedKeyFile = peer.presharedKeyFile;
|
|
AllowedIPs = peer.allowedIPs;
|
|
Endpoint = peer.endpoint;
|
|
PersistentKeepalive = peer.persistentKeepalive;
|
|
};
|
|
|
|
generateNetwork = name: interface: {
|
|
matchConfig.Name = name;
|
|
address = interface.ips;
|
|
};
|
|
|
|
cfg = config.networking.wireguard;
|
|
|
|
refreshEnabledInterfaces = filterAttrs (
|
|
name: interface: interface.dynamicEndpointRefreshSeconds != 0
|
|
) cfg.interfaces;
|
|
|
|
generateRefreshTimer =
|
|
name: interface:
|
|
nameValuePair "wireguard-dynamic-refresh-${name}" {
|
|
partOf = [ "wireguard-dynamic-refresh-${name}.service" ];
|
|
wantedBy = [ "timers.target" ];
|
|
description = "Wireguard dynamic endpoint refresh (${name}) timer";
|
|
timerConfig.OnBootSec = interface.dynamicEndpointRefreshSeconds;
|
|
timerConfig.OnUnitInactiveSec = interface.dynamicEndpointRefreshSeconds;
|
|
};
|
|
|
|
generateRefreshService =
|
|
name: interface:
|
|
nameValuePair "wireguard-dynamic-refresh-${name}" {
|
|
description = "Wireguard dynamic endpoint refresh (${name})";
|
|
after = [ "network-online.target" ];
|
|
wants = [ "network-online.target" ];
|
|
path = with pkgs; [
|
|
iproute2
|
|
systemd
|
|
];
|
|
# networkd doesn't provide a mechanism for refreshing endpoints.
|
|
# See: https://github.com/systemd/systemd/issues/9911
|
|
# This hack does the job but takes down the whole interface to do it.
|
|
script = ''
|
|
ip link delete ${name}
|
|
networkctl reload
|
|
'';
|
|
};
|
|
|
|
in
|
|
{
|
|
meta.maintainers = [ lib.maintainers.majiir ];
|
|
|
|
options.networking.wireguard = {
|
|
useNetworkd = mkOption {
|
|
default = false;
|
|
type = types.bool;
|
|
description = ''
|
|
Whether to use networkd as the network configuration backend for
|
|
Wireguard instead of the legacy script-based system.
|
|
|
|
::: {.warning}
|
|
Some options have slightly different behavior with the networkd and
|
|
script-based backends. Check the documentation for each Wireguard
|
|
option you use before enabling this option.
|
|
:::
|
|
'';
|
|
};
|
|
};
|
|
|
|
config = mkIf (cfg.enable && cfg.useNetworkd) {
|
|
|
|
# TODO: Some of these options may be possible to support in networkd.
|
|
#
|
|
# privateKey and presharedKey are trivial to support, but we deliberately
|
|
# don't in order to discourage putting secrets in the /nix store.
|
|
#
|
|
# generatePrivateKeyFile can be supported if we can order a service before
|
|
# networkd configures interfaces. There is also a systemd feature request
|
|
# for key generation: https://github.com/systemd/systemd/issues/14282
|
|
#
|
|
# preSetup, postSetup, preShutdown and postShutdown may be possible, but
|
|
# networkd is not likely to support script hooks like this directly. See:
|
|
# https://github.com/systemd/systemd/issues/11629
|
|
#
|
|
# socketNamespace and interfaceNamespace can be implemented once networkd
|
|
# supports setting a netdev's namespace. See:
|
|
# https://github.com/systemd/systemd/issues/11629
|
|
# https://github.com/systemd/systemd/pull/14915
|
|
|
|
assertions = concatLists (
|
|
flip mapAttrsToList cfg.interfaces (
|
|
name: interface:
|
|
[
|
|
# Interface assertions
|
|
{
|
|
assertion = interface.privateKey == null;
|
|
message = "networking.wireguard.interfaces.${name}.privateKey cannot be used with networkd. Use privateKeyFile instead.";
|
|
}
|
|
{
|
|
assertion = !interface.generatePrivateKeyFile;
|
|
message = "networking.wireguard.interfaces.${name}.generatePrivateKeyFile cannot be used with networkd.";
|
|
}
|
|
{
|
|
assertion = interface.preSetup == "";
|
|
message = "networking.wireguard.interfaces.${name}.preSetup cannot be used with networkd.";
|
|
}
|
|
{
|
|
assertion = interface.postSetup == "";
|
|
message = "networking.wireguard.interfaces.${name}.postSetup cannot be used with networkd.";
|
|
}
|
|
{
|
|
assertion = interface.preShutdown == "";
|
|
message = "networking.wireguard.interfaces.${name}.preShutdown cannot be used with networkd.";
|
|
}
|
|
{
|
|
assertion = interface.postShutdown == "";
|
|
message = "networking.wireguard.interfaces.${name}.postShutdown cannot be used with networkd.";
|
|
}
|
|
{
|
|
assertion = interface.socketNamespace == null;
|
|
message = "networking.wireguard.interfaces.${name}.socketNamespace cannot be used with networkd.";
|
|
}
|
|
{
|
|
assertion = interface.interfaceNamespace == null;
|
|
message = "networking.wireguard.interfaces.${name}.interfaceNamespace cannot be used with networkd.";
|
|
}
|
|
]
|
|
++ flip concatMap interface.ips (ip: [
|
|
# IP assertions
|
|
{
|
|
assertion = hasInfix "/" ip;
|
|
message = "networking.wireguard.interfaces.${name}.ips value \"${ip}\" requires a subnet (e.g. 192.0.2.1/32) with networkd.";
|
|
}
|
|
])
|
|
++ flip concatMap interface.peers (peer: [
|
|
# Peer assertions
|
|
{
|
|
assertion = peer.presharedKey == null;
|
|
message = "networking.wireguard.interfaces.${name}.peers[].presharedKey cannot be used with networkd. Use presharedKeyFile instead.";
|
|
}
|
|
{
|
|
assertion = peer.dynamicEndpointRefreshSeconds == null;
|
|
message = "networking.wireguard.interfaces.${name}.peers[].dynamicEndpointRefreshSeconds cannot be used with networkd. Use networking.wireguard.interfaces.${name}.dynamicEndpointRefreshSeconds instead.";
|
|
}
|
|
{
|
|
assertion = peer.dynamicEndpointRefreshRestartSeconds == null;
|
|
message = "networking.wireguard.interfaces.${name}.peers[].dynamicEndpointRefreshRestartSeconds cannot be used with networkd.";
|
|
}
|
|
])
|
|
)
|
|
);
|
|
|
|
systemd.network = {
|
|
enable = true;
|
|
netdevs = mapAttrs' generateNetdev cfg.interfaces;
|
|
networks = mapAttrs generateNetwork cfg.interfaces;
|
|
};
|
|
|
|
systemd.timers = mapAttrs' generateRefreshTimer refreshEnabledInterfaces;
|
|
systemd.services = mapAttrs' generateRefreshService refreshEnabledInterfaces;
|
|
};
|
|
}
|