summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/security/dhparams.nix39
-rw-r--r--nixos/tests/dhparams.nix21
2 files changed, 52 insertions, 8 deletions
diff --git a/nixos/modules/security/dhparams.nix b/nixos/modules/security/dhparams.nix
index 7c9fe986e57..64b296eea5b 100644
--- a/nixos/modules/security/dhparams.nix
+++ b/nixos/modules/security/dhparams.nix
@@ -29,7 +29,11 @@ let
       '';
     };
 
-    config.path = "${cfg.path}/${name}.pem";
+    config.path = let
+      generated = pkgs.runCommand "dhparams-${name}.pem" {
+        nativeBuildInputs = [ pkgs.openssl ];
+      } "openssl dhparam -out \"$out\" ${toString config.bits}";
+    in if cfg.stateful then "${cfg.path}/${name}.pem" else generated;
   };
 
 in {
@@ -52,7 +56,9 @@ in {
             have to leave <option>security.dhparams.enable</option> for at
             least one activation in order to have them be cleaned up. This also
             means if you rollback to a version without any dhparams the
-            existing ones won't be cleaned up.</para></warning>
+            existing ones won't be cleaned up. Of course this only applies if
+            <option>security.dhparams.stateful</option> is
+            <literal>true</literal>.</para></warning>
           '';
         type = with types; let
           coerce = bits: { inherit bits; };
@@ -61,12 +67,29 @@ in {
         example = literalExample "{ nginx.bits = 3072; }";
       };
 
+      stateful = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether generation of Diffie-Hellman parameters should be stateful or
+          not. If this is enabled, PEM-encoded files for Diffie-Hellman
+          parameters are placed in the directory specified by
+          <option>security.dhparams.path</option>. Otherwise the files are
+          created within the Nix store.
+
+          <note><para>If this is <literal>false</literal> the resulting store
+          path will be non-deterministic and will be rebuilt every time the
+          <package>openssl</package> package changes.</para></note>
+        '';
+      };
+
       path = mkOption {
-        description =
-          ''
-            Path to the directory in which Diffie-Hellman parameters will be
-            stored.
-          '';
+        description = ''
+          Path to the directory in which Diffie-Hellman parameters will be
+          stored. This only is relevant if
+          <option>security.dhparams.stateful</option> is
+          <literal>true</literal>.
+        '';
         type = types.str;
         default = "/var/lib/dhparams";
       };
@@ -82,7 +105,7 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
+  config = mkIf (cfg.enable && cfg.stateful) {
     systemd.services = {
       dhparams-init = {
         description = "Cleanup old Diffie-Hellman parameters";
diff --git a/nixos/tests/dhparams.nix b/nixos/tests/dhparams.nix
index ead5f2efce7..da75391e4ce 100644
--- a/nixos/tests/dhparams.nix
+++ b/nixos/tests/dhparams.nix
@@ -47,6 +47,13 @@ in import ./make-test.nix {
 
   nodes.generation3 = common;
 
+  nodes.generation4 = {
+    imports = [ common ];
+    security.dhparams.stateful = false;
+    security.dhparams.params.foo2.bits = 18;
+    security.dhparams.params.bar2.bits = 19;
+  };
+
   testScript = { nodes, ... }: let
     getParamPath = gen: name: let
       node = "generation${toString gen}";
@@ -105,5 +112,19 @@ in import ./make-test.nix {
         'test -e ${nodes.generation3.config.security.dhparams.path}'
       );
     };
+
+    ${switchToGeneration 4}
+
+    subtest "check bit sizes dhparam files", sub {
+      ${assertParamBits 4 "foo2" 18}
+      ${assertParamBits 4 "bar2" 19}
+    };
+
+    subtest "check whether dhparam files are in the Nix store", sub {
+      $machine->succeed(
+        'expr match ${getParamPath 4 "foo2"} ${builtins.storeDir}',
+        'expr match ${getParamPath 4 "bar2"} ${builtins.storeDir}',
+      );
+    };
   '';
 }