From 7c90a8677090bb144cc8db17aaf485def8d54a91 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Sun, 1 Apr 2018 18:22:14 +0300 Subject: wireguard service: use scripts instead of ExecStarts/Stops This is more in line with what other services do; also looks cleaner. It changes configuration entries for pre-and post-hooks type to lines from lists of strings which are more logical for them; coersion is provided for backwards compatibility. Finally, add several steps to improve robustness: 1. Load kernel module on start if not loaded; 2. Don't remove wireguard interface on start; it is removed on service stop. If it's not something is wrong. --- nixos/modules/services/networking/wireguard.nix | 101 ++++++++++++------------ 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix index 24accd41511c..0591917c7423 100644 --- a/nixos/modules/services/networking/wireguard.nix +++ b/nixos/modules/services/networking/wireguard.nix @@ -53,30 +53,30 @@ let }; preSetup = mkOption { - example = literalExample ['' + example = literalExample '' ${pkgs.iproute}/bin/ip netns add foo - '']; - default = []; - type = with types; listOf str; + ''; + default = ""; + type = with types; coercedTo (listOf str) (concatStringsSep "\n") lines; description = '' - A list of commands called at the start of the interface setup. + Commands called at the start of the interface setup. ''; }; postSetup = mkOption { - example = literalExample ['' - ${pkgs.bash} -c 'printf "nameserver 10.200.100.1" | ${pkgs.openresolv}/bin/resolvconf -a wg0 -m 0' - '']; - default = []; - type = with types; listOf str; - description = "A list of commands called at the end of the interface setup."; + example = literalExample '' + printf "nameserver 10.200.100.1" | ${pkgs.openresolv}/bin/resolvconf -a wg0 -m 0 + ''; + default = ""; + type = with types; coercedTo (listOf str) (concatStringsSep "\n") lines; + description = "Commands called at the end of the interface setup."; }; postShutdown = mkOption { - example = literalExample ["${pkgs.openresolv}/bin/resolvconf -d wg0"]; - default = []; - type = with types; listOf str; - description = "A list of commands called after shutting down the interface."; + example = literalExample "${pkgs.openresolv}/bin/resolvconf -d wg0"; + default = ""; + type = with types; coercedTo (listOf str) (concatStringsSep "\n") lines; + description = "Commands called after shutting down the interface."; }; table = mkOption { @@ -182,9 +182,6 @@ let }; - ipCommand = "${pkgs.iproute}/bin/ip"; - wgCommand = "${pkgs.wireguard}/bin/wg"; - generateUnit = name: values: # exactly one way to specify the private key must be set assert (values.privateKey != null) != (values.privateKeyFile != null); @@ -196,49 +193,53 @@ let after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; environment.DEVICE = name; + path = with pkgs; [ kmod iproute wireguard ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; - ExecStart = flatten([ - values.preSetup + }; + + script = '' + modprobe wireguard + + ${values.preSetup} - "-${ipCommand} link del dev ${name}" - "${ipCommand} link add dev ${name} type wireguard" + ip link add dev ${name} type wireguard - (map (ip: - "${ipCommand} address add ${ip} dev ${name}" - ) values.ips) + ${concatMapStringsSep "\n" (ip: + "ip address add ${ip} dev ${name}" + ) values.ips} - ("${wgCommand} set ${name} private-key ${privKey}" + - optionalString (values.listenPort != null) " listen-port ${toString values.listenPort}") + wg set ${name} private-key ${privKey} ${ + optionalString (values.listenPort != null) " listen-port ${toString values.listenPort}"} - (map (peer: + ${concatMapStringsSep "\n" (peer: assert (peer.presharedKeyFile == null) || (peer.presharedKey == null); # at most one of the two must be set let psk = if peer.presharedKey != null then pkgs.writeText "wg-psk" peer.presharedKey else peer.presharedKeyFile; in - "${wgCommand} set ${name} peer ${peer.publicKey}" + - optionalString (psk != null) " preshared-key ${psk}" + - optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" + - optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" + - optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}" - ) values.peers) - - "${ipCommand} link set up dev ${name}" - - (optionals (values.allowedIPsAsRoutes != false) (map (peer: - (map (allowedIP: - "${ipCommand} route replace ${allowedIP} dev ${name} table ${values.table}" - ) peer.allowedIPs) - ) values.peers)) - - values.postSetup - ]); - ExecStop = flatten([ - "${ipCommand} link del dev ${name}" - values.postShutdown - ]); - }; + "wg set ${name} peer ${peer.publicKey}" + + optionalString (psk != null) " preshared-key ${psk}" + + optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" + + optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" + + optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}" + ) values.peers} + + ip link set up dev ${name} + + ${optionalString (values.allowedIPsAsRoutes != false) (concatStringsSep "\n" (concatMap (peer: + (map (allowedIP: + "ip route replace ${allowedIP} dev ${name} table ${values.table}" + ) peer.allowedIPs) + ) values.peers))} + + ${values.postSetup} + ''; + + preStop = '' + ip link del dev ${name} + ${values.postShutdown} + ''; }; in -- cgit 1.4.1