summary refs log tree commit diff
path: root/nixos/modules/security/dhparams.nix
blob: 55c75713101d323dca33a1eb5754430d042a64e7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{ config, lib, pkgs, ... }:

with lib;
let
  cfg = config.security.dhparams;
in
{
  options = {
    security.dhparams = {
      params = mkOption {
        description =
          ''
            Diffie-Hellman parameters to generate.

            The value is the size (in bits) of the DH params to generate. The
            generated DH params path can be found in
            <filename><replaceable>security.dhparams.path</replaceable>/<replaceable>name</replaceable>.pem</filename>.

            Note: The name of the DH params is taken as being the name of the
            service it serves: the params will be generated before the said
            service is started.

            Warning: If you are removing all dhparams from this list, you have
            to leave security.dhparams.enable 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.
          '';
        type = with types; attrsOf int;
        default = {};
        example = { nginx = 3072; };
      };

      path = mkOption {
        description =
          ''
            Path to the directory in which Diffie-Hellman parameters will be
            stored.
          '';
        type = types.str;
        default = "/var/lib/dhparams";
      };

      enable = mkOption {
        description =
          ''
            Whether to generate new DH params and clean up old DH params.
          '';
        default = false;
        type = types.bool;
      };
    };
  };

  config = mkIf cfg.enable {
    systemd.services = {
      dhparams-init = {
        description = "Cleanup old Diffie-Hellman parameters";
        wantedBy = [ "multi-user.target" ]; # Clean up even when no DH params is set
        serviceConfig.Type = "oneshot";
        script =
          # Create directory
          ''
            if [ ! -d ${cfg.path} ]; then
              mkdir -p ${cfg.path}
            fi
          '' +
          # Remove old dhparams
          ''
            for file in ${cfg.path}/*; do
              if [ ! -f "$file" ]; then
                continue
              fi
          '' + concatStrings (mapAttrsToList (name: value:
          ''
              if [ "$file" == "${cfg.path}/${name}.pem" ] && \
                  ${pkgs.openssl}/bin/openssl dhparam -in "$file" -text | head -n 1 | grep "(${toString value} bit)" > /dev/null; then
                continue
              fi
          ''
          ) cfg.params) +
          ''
              rm $file
            done

            # TODO: Ideally this would be removing the *former* cfg.path, though this
            # does not seem really important as changes to it are quite unlikely
            rmdir --ignore-fail-on-non-empty ${cfg.path}
          '';
      };
    } //
      mapAttrs' (name: value: nameValuePair "dhparams-gen-${name}" {
        description = "Generate Diffie-Hellman parameters for ${name} if they don't exist yet";
        after = [ "dhparams-init.service" ];
        before = [ "${name}.service" ];
        wantedBy = [ "multi-user.target" ];
        serviceConfig.Type = "oneshot";
        script =
          ''
            mkdir -p ${cfg.path}
            if [ ! -f ${cfg.path}/${name}.pem ]; then
              ${pkgs.openssl}/bin/openssl dhparam -out ${cfg.path}/${name}.pem ${toString value}
            fi
          '';
      }) cfg.params;
  };
}