From 57d30c7a61d8fb3d8964a1f60c37f8f9c0b34a9c Mon Sep 17 00:00:00 2001 From: Felix Uhl Date: Fri, 2 Aug 2024 22:07:27 +0200 Subject: [PATCH] nixos/wg-quick: add generatePrivateKeyFile option (#331253) This option is already present in the wireguard module, but missing from the wg-quick module. This is very annoying, because it means you can't easily get a safe and valid configuration on first boot when using wg-quick. This change adds the same option with the same description text and the same script, but instead of generating an entire systemd unit dedicated to creating the key file, it adds the script as a PreUp script, which is a much simpler solution. I've tested this in my own configuration, and it does indeed work. wg-quick allows multiple PreUp scripts, which are run in order, and all PreUp scripts are run before the private key is read from disk, see `man wg-quick`. --- .../modules/services/networking/wg-quick.nix | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/nixos/modules/services/networking/wg-quick.nix b/nixos/modules/services/networking/wg-quick.nix index 2062f2806d79..369c5a939765 100644 --- a/nixos/modules/services/networking/wg-quick.nix +++ b/nixos/modules/services/networking/wg-quick.nix @@ -57,6 +57,15 @@ let ''; }; + generatePrivateKeyFile = mkOption { + default = false; + type = types.bool; + description = '' + Automatically generate a private key with + {command}`wg genkey`, at the privateKeyFile location. + ''; + }; + privateKeyFile = mkOption { example = "/private/wireguard_key"; type = with types; nullOr str; @@ -218,9 +227,24 @@ let writeScriptFile = name: text: ((pkgs.writeShellScriptBin name text) + "/bin/${name}"); + generatePrivateKeyScript = privateKeyFile: '' + set -e + + # If the parent dir does not already exist, create it. + # Otherwise, does nothing, keeping existing permissions intact. + mkdir -p --mode 0755 "${dirOf privateKeyFile}" + + if [ ! -f "${privateKeyFile}" ]; then + # Write private key file with atomically-correct permissions. + (set -e; umask 077; wg genkey > "${privateKeyFile}") + fi + ''; + generateUnit = name: values: assert assertMsg (values.configFile != null || ((values.privateKey != null) != (values.privateKeyFile != null))) "Only one of privateKey, configFile or privateKeyFile may be set"; + assert assertMsg (values.generatePrivateKeyFile == false || values.privateKeyFile != null) "generatePrivateKeyFile requires privateKeyFile to be set"; let + generateKeyScriptFile = if values.generatePrivateKeyFile then writeScriptFile "generatePrivateKey.sh" (generatePrivateKeyScript values.privateKeyFile) else null; preUpFile = if values.preUp != "" then writeScriptFile "preUp.sh" values.preUp else null; postUp = optional (values.privateKeyFile != null) "wg set ${name} private-key <(cat ${values.privateKeyFile})" ++ @@ -247,6 +271,7 @@ let optionalString (values.mtu != null) "MTU = ${toString values.mtu}\n" + optionalString (values.privateKey != null) "PrivateKey = ${values.privateKey}\n" + optionalString (values.listenPort != null) "ListenPort = ${toString values.listenPort}\n" + + optionalString (generateKeyScriptFile != null) "PreUp = ${generateKeyScriptFile}\n" + optionalString (preUpFile != null) "PreUp = ${preUpFile}\n" + optionalString (postUpFile != null) "PostUp = ${postUpFile}\n" + optionalString (preDownFile != null) "PreDown = ${preDownFile}\n" +