···
{ config, lib, pkgs, ... }:
4
+
inherit (lib) mkOption types;
cfg = config.security.dhparams;
7
+
bitType = types.addCheck types.int (b: b >= 16) // {
9
+
description = "integer of at least 16 bits";
12
+
paramsSubmodule = { name, config, ... }: {
13
+
options.bits = mkOption {
15
+
default = cfg.defaultBitSize;
17
+
The bit size for the prime that is used during a Diffie-Hellman
22
+
options.path = mkOption {
26
+
The resulting path of the generated Diffie-Hellman parameters
27
+
file for other services to reference. This could be either a
28
+
store path or a file inside the directory specified by
29
+
<option>security.dhparams.path</option>.
34
+
generated = pkgs.runCommand "dhparams-${name}.pem" {
35
+
nativeBuildInputs = [ pkgs.openssl ];
36
+
} "openssl dhparam -out \"$out\" ${toString config.bits}";
37
+
in if cfg.stateful then "${cfg.path}/${name}.pem" else generated;
47
+
Whether to generate new DH params and clean up old DH params.
13
-
Diffie-Hellman parameters to generate.
52
+
type = with types; let
53
+
coerce = bits: { inherit bits; };
54
+
in attrsOf (coercedTo int coerce (submodule paramsSubmodule));
56
+
example = lib.literalExample "{ nginx.bits = 3072; }";
58
+
Diffie-Hellman parameters to generate.
60
+
The value is the size (in bits) of the DH params to generate. The
61
+
generated DH params path can be found in
62
+
<literal>config.security.dhparams.params.<replaceable>name</replaceable>.path</literal>.
15
-
The value is the size (in bits) of the DH params to generate. The
16
-
generated DH params path can be found in
17
-
<filename><replaceable>security.dhparams.path</replaceable>/<replaceable>name</replaceable>.pem</filename>.
64
+
<note><para>The name of the DH params is taken as being the name of
65
+
the service it serves and the params will be generated before the
66
+
said service is started.</para></note>
19
-
Note: The name of the DH params is taken as being the name of the
20
-
service it serves: the params will be generated before the said
68
+
<warning><para>If you are removing all dhparams from this list, you
69
+
have to leave <option>security.dhparams.enable</option> for at
70
+
least one activation in order to have them be cleaned up. This also
71
+
means if you rollback to a version without any dhparams the
72
+
existing ones won't be cleaned up. Of course this only applies if
73
+
<option>security.dhparams.stateful</option> is
74
+
<literal>true</literal>.</para></warning>
76
+
<note><title>For module implementers:</title><para>It's recommended
77
+
to not set a specific bit size here, so that users can easily
78
+
override this by setting
79
+
<option>security.dhparams.defaultBitSize</option>.</para></note>
83
+
stateful = mkOption {
87
+
Whether generation of Diffie-Hellman parameters should be stateful or
88
+
not. If this is enabled, PEM-encoded files for Diffie-Hellman
89
+
parameters are placed in the directory specified by
90
+
<option>security.dhparams.path</option>. Otherwise the files are
91
+
created within the Nix store.
23
-
Warning: If you are removing all dhparams from this list, you have
24
-
to leave security.dhparams.enable for at least one activation in
25
-
order to have them be cleaned up. This also means if you rollback to
26
-
a version without any dhparams the existing ones won't be cleaned
29
-
type = with types; attrsOf int;
31
-
example = { nginx = 3072; };
93
+
<note><para>If this is <literal>false</literal> the resulting store
94
+
path will be non-deterministic and will be rebuilt every time the
95
+
<package>openssl</package> package changes.</para></note>
99
+
defaultBitSize = mkOption {
103
+
This allows to override the default bit size for all of the
104
+
Diffie-Hellman parameters set in
105
+
<option>security.dhparams.params</option>.
37
-
Path to the directory in which Diffie-Hellman parameters will be
default = "/var/lib/dhparams";
47
-
Whether to generate new DH params and clean up old DH params.
113
+
Path to the directory in which Diffie-Hellman parameters will be
114
+
stored. This only is relevant if
115
+
<option>security.dhparams.stateful</option> is
116
+
<literal>true</literal>.
55
-
config = mkIf cfg.enable {
122
+
config = lib.mkIf (cfg.enable && cfg.stateful) {
58
-
description = "Cleanup old Diffie-Hellman parameters";
59
-
wantedBy = [ "multi-user.target" ]; # Clean up even when no DH params is set
125
+
description = "Clean Up Old Diffie-Hellman Parameters";
127
+
# Clean up even when no DH params is set
128
+
wantedBy = [ "multi-user.target" ];
130
+
serviceConfig.RemainAfterExit = true;
serviceConfig.Type = "oneshot";
64
-
if [ ! -d ${cfg.path} ]; then
65
-
mkdir -p ${cfg.path}
134
+
if [ ! -d ${cfg.path} ]; then
135
+
mkdir -p ${cfg.path}
138
+
# Remove old dhparams
139
+
for file in ${cfg.path}/*; do
140
+
if [ ! -f "$file" ]; then
68
-
# Remove old dhparams
70
-
for file in ${cfg.path}/*; do
71
-
if [ ! -f "$file" ]; then
143
+
${lib.concatStrings (lib.mapAttrsToList (name: { bits, path, ... }: ''
144
+
if [ "$file" = ${lib.escapeShellArg path} ] && \
145
+
${pkgs.openssl}/bin/openssl dhparam -in "$file" -text \
146
+
| head -n 1 | grep "(${toString bits} bit)" > /dev/null; then
74
-
'' + concatStrings (mapAttrsToList (name: value:
76
-
if [ "$file" == "${cfg.path}/${name}.pem" ] && \
77
-
${pkgs.openssl}/bin/openssl dhparam -in "$file" -text | head -n 1 | grep "(${toString value} bit)" > /dev/null; then
86
-
# TODO: Ideally this would be removing the *former* cfg.path, though this
87
-
# does not seem really important as changes to it are quite unlikely
88
-
rmdir --ignore-fail-on-non-empty ${cfg.path}
153
+
# TODO: Ideally this would be removing the *former* cfg.path, though
154
+
# this does not seem really important as changes to it are quite
156
+
rmdir --ignore-fail-on-non-empty ${cfg.path}
92
-
mapAttrs' (name: value: nameValuePair "dhparams-gen-${name}" {
93
-
description = "Generate Diffie-Hellman parameters for ${name} if they don't exist yet";
94
-
after = [ "dhparams-init.service" ];
95
-
before = [ "${name}.service" ];
96
-
wantedBy = [ "multi-user.target" ];
97
-
serviceConfig.Type = "oneshot";
100
-
mkdir -p ${cfg.path}
101
-
if [ ! -f ${cfg.path}/${name}.pem ]; then
102
-
${pkgs.openssl}/bin/openssl dhparam -out ${cfg.path}/${name}.pem ${toString value}
159
+
} // lib.mapAttrs' (name: { bits, path, ... }: lib.nameValuePair "dhparams-gen-${name}" {
160
+
description = "Generate Diffie-Hellman Parameters for ${name}";
161
+
after = [ "dhparams-init.service" ];
162
+
before = [ "${name}.service" ];
163
+
wantedBy = [ "multi-user.target" ];
164
+
unitConfig.ConditionPathExists = "!${path}";
165
+
serviceConfig.Type = "oneshot";
167
+
mkdir -p ${lib.escapeShellArg cfg.path}
168
+
${pkgs.openssl}/bin/openssl dhparam -out ${lib.escapeShellArg path} \