grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / security / step-ca.nix
blob70651e995dda11da22f7c284e6006bd2bb9bd0b4
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.step-ca;
4   settingsFormat = (pkgs.formats.json { });
5 in
7   meta.maintainers = [ ];
9   options = {
10     services.step-ca = {
11       enable = lib.mkEnableOption "the smallstep certificate authority server";
12       openFirewall = lib.mkEnableOption "opening the certificate authority server port";
13       package = lib.mkOption {
14         type = lib.types.package;
15         default = pkgs.step-ca;
16         defaultText = lib.literalExpression "pkgs.step-ca";
17         description = "Which step-ca package to use.";
18       };
19       address = lib.mkOption {
20         type = lib.types.str;
21         example = "127.0.0.1";
22         description = ''
23           The address (without port) the certificate authority should listen at.
24           This combined with {option}`services.step-ca.port` overrides {option}`services.step-ca.settings.address`.
25         '';
26       };
27       port = lib.mkOption {
28         type = lib.types.port;
29         example = 8443;
30         description = ''
31           The port the certificate authority should listen on.
32           This combined with {option}`services.step-ca.address` overrides {option}`services.step-ca.settings.address`.
33         '';
34       };
35       settings = lib.mkOption {
36         type = with lib.types; attrsOf anything;
37         description = ''
38           Settings that go into {file}`ca.json`. See
39           [the step-ca manual](https://smallstep.com/docs/step-ca/configuration)
40           for more information. The easiest way to
41           configure this module would be to run `step ca init`
42           to generate {file}`ca.json` and then import it using
43           `builtins.fromJSON`.
44           [This article](https://smallstep.com/docs/step-cli/basic-crypto-operations#run-an-offline-x509-certificate-authority)
45           may also be useful if you want to customize certain aspects of
46           certificate generation for your CA.
47           You need to change the database storage path to {file}`/var/lib/step-ca/db`.
49           ::: {.warning}
50           The {option}`services.step-ca.settings.address` option
51           will be ignored and overwritten by
52           {option}`services.step-ca.address` and
53           {option}`services.step-ca.port`.
54           :::
55         '';
56       };
57       intermediatePasswordFile = lib.mkOption {
58         type = lib.types.path;
59         example = "/run/keys/smallstep-password";
60         description = ''
61           Path to the file containing the password for the intermediate
62           certificate private key.
64           ::: {.warning}
65           Make sure to use a quoted absolute path instead of a path literal
66           to prevent it from being copied to the globally readable Nix
67           store.
68           :::
69         '';
70       };
71     };
72   };
74   config = lib.mkIf config.services.step-ca.enable (
75     let
76       configFile = settingsFormat.generate "ca.json" (cfg.settings // {
77         address = cfg.address + ":" + toString cfg.port;
78       });
79     in
80     {
81       assertions =
82         [
83           {
84             assertion = !lib.isStorePath cfg.intermediatePasswordFile;
85             message = ''
86               <option>services.step-ca.intermediatePasswordFile</option> points to
87               a file in the Nix store. You should use a quoted absolute path to
88               prevent this.
89             '';
90           }
91         ];
93       systemd.packages = [ cfg.package ];
95       # configuration file indirection is needed to support reloading
96       environment.etc."smallstep/ca.json".source = configFile;
98       systemd.services."step-ca" = {
99         wantedBy = [ "multi-user.target" ];
100         restartTriggers = [ configFile ];
101         unitConfig = {
102           ConditionFileNotEmpty = ""; # override upstream
103         };
104         serviceConfig = {
105           User = "step-ca";
106           Group = "step-ca";
107           UMask = "0077";
108           Environment = "HOME=%S/step-ca";
109           WorkingDirectory = ""; # override upstream
110           ReadWritePaths = ""; # override upstream
112           # LocalCredential handles file permission problems arising from the use of DynamicUser.
113           LoadCredential = "intermediate_password:${cfg.intermediatePasswordFile}";
115           ExecStart = [
116             "" # override upstream
117             "${cfg.package}/bin/step-ca /etc/smallstep/ca.json --password-file \${CREDENTIALS_DIRECTORY}/intermediate_password"
118           ];
120           # ProtectProc = "invisible"; # not supported by upstream yet
121           # ProcSubset = "pid"; # not supported by upstream yet
122           # PrivateUsers = true; # doesn't work with privileged ports therefore not supported by upstream
124           DynamicUser = true;
125           StateDirectory = "step-ca";
126         };
127       };
129       users.users.step-ca = {
130         home = "/var/lib/step-ca";
131         group = "step-ca";
132         isSystemUser = true;
133       };
135       users.groups.step-ca = {};
137       networking.firewall = lib.mkIf cfg.openFirewall {
138         allowedTCPPorts = [ cfg.port ];
139       };
140     }
141   );