vuls: init at 0.27.0 (#348530)
[NixPkgs.git] / nixos / modules / services / web-apps / zitadel.nix
blobed7fae8d9dda09c90668f90c6823f6a600990660
1 { config, pkgs, lib, ... }:
3 let
4   cfg = config.services.zitadel;
6   settingsFormat = pkgs.formats.yaml { };
7 in
9   options.services.zitadel =
10     let inherit (lib) mkEnableOption mkOption mkPackageOption types;
11     in {
12       enable = mkEnableOption "ZITADEL, a user and identity access management platform";
14       package = mkPackageOption pkgs "ZITADEL" { default = [ "zitadel" ]; };
16       user = mkOption {
17         type = types.str;
18         default = "zitadel";
19         description = "The user to run ZITADEL under.";
20       };
22       group = mkOption {
23         type = types.str;
24         default = "zitadel";
25         description = "The group to run ZITADEL under.";
26       };
28       openFirewall = mkOption {
29         type = types.bool;
30         default = false;
31         description = ''
32           Whether to open the port specified in `listenPort` in the firewall.
33         '';
34       };
36       masterKeyFile = mkOption {
37         type = types.path;
38         description = ''
39           Path to a file containing a master encryption key for ZITADEL. The
40           key must be 32 bytes.
41         '';
42       };
44       tlsMode = mkOption {
45         type = types.enum [ "external" "enabled" "disabled" ];
46         default = "external";
47         example = "enabled";
48         description = ''
49           The TLS mode to use. Options are:
51           - enabled: ZITADEL accepts HTTPS connections directly. You must
52             configure TLS if this option is selected.
53           - external: ZITADEL forces HTTPS connections, with TLS terminated at a
54             reverse proxy.
55           - disabled: ZITADEL accepts HTTP connections only. Should only be used
56             for testing.
57         '';
58       };
60       settings = mkOption {
61         type = lib.types.submodule {
62           freeformType = settingsFormat.type;
64           options = {
65             Port = mkOption {
66               type = types.port;
67               default = 8080;
68               description = "The port that ZITADEL listens on.";
69             };
71             TLS = {
72               KeyPath = mkOption {
73                 type = types.nullOr types.path;
74                 default = null;
75                 description = "Path to the TLS certificate private key.";
76               };
77               Key = mkOption {
78                 type = types.nullOr types.str;
79                 default = null;
80                 description = ''
81                   The TLS certificate private key, as a base64-encoded string.
83                   Note that the contents of this option will be added to the Nix
84                   store as world-readable plain text. Set
85                   [KeyPath](#opt-services.zitadel.settings.TLS.KeyPath) instead
86                   if this is undesired.
87                 '';
88               };
89               CertPath = mkOption {
90                 type = types.nullOr types.path;
91                 default = null;
92                 description = "Path to the TLS certificate.";
93               };
94               Cert = mkOption {
95                 type = types.nullOr types.str;
96                 default = null;
97                 description = ''
98                   The TLS certificate, as a base64-encoded string.
100                   Note that the contents of this option will be added to the Nix
101                   store as world-readable plain text. Set
102                   [CertPath](#opt-services.zitadel.settings.TLS.CertPath) instead
103                   if this is undesired.
104                 '';
105               };
106             };
107           };
108         };
109         default = { };
110         example = lib.literalExpression ''
111           {
112             Port = 8123;
113             ExternalDomain = "example.com";
114             TLS = {
115               CertPath = "/path/to/cert.pem";
116               KeyPath = "/path/to/cert.key";
117             };
118             Database.cockroach.Host = "db.example.com";
119           };
120         '';
121         description = ''
122           Contents of the runtime configuration file. See
123           https://zitadel.com/docs/self-hosting/manage/configure for more
124           details.
125         '';
126       };
128       extraSettingsPaths = mkOption {
129         type = types.listOf types.path;
130         default = [ ];
131         description = ''
132           A list of paths to extra settings files. These will override the
133           values set in [settings](#opt-services.zitadel.settings). Useful if
134           you want to keep sensitive secrets out of the Nix store.
135         '';
136       };
138       steps = mkOption {
139         type = settingsFormat.type;
140         default = { };
141         example = lib.literalExpression ''
142           {
143             FirstInstance = {
144               InstanceName = "Example";
145               Org.Human = {
146                 UserName = "foobar";
147                 FirstName = "Foo";
148                 LastName = "Bar";
149               };
150             };
151           }
152         '';
153         description = ''
154           Contents of the database initialization config file. See
155           https://zitadel.com/docs/self-hosting/manage/configure for more
156           details.
157         '';
158       };
160       extraStepsPaths = mkOption {
161         type = types.listOf types.path;
162         default = [ ];
163         description = ''
164           A list of paths to extra steps files. These will override the values
165           set in [steps](#opt-services.zitadel.steps). Useful if you want to
166           keep sensitive secrets out of the Nix store.
167         '';
168       };
169     };
171   config = lib.mkIf cfg.enable {
172     assertions = [{
173       assertion = cfg.tlsMode == "enabled"
174         -> ((cfg.settings.TLS.Key != null || cfg.settings.TLS.KeyPath != null)
175         && (cfg.settings.TLS.Cert != null || cfg.settings.TLS.CertPath
176         != null));
177       message = ''
178         A TLS certificate and key must be configured in
179         services.zitadel.settings.TLS if services.zitadel.tlsMode is enabled.
180       '';
181     }];
183     networking.firewall.allowedTCPPorts =
184       lib.mkIf cfg.openFirewall [ cfg.settings.Port ];
186     systemd.services.zitadel =
187       let
188         configFile = settingsFormat.generate "config.yaml" cfg.settings;
189         stepsFile = settingsFormat.generate "steps.yaml" cfg.steps;
191         args = lib.cli.toGNUCommandLineShell { } {
192           config = cfg.extraSettingsPaths ++ [ configFile ];
193           steps = cfg.extraStepsPaths ++ [ stepsFile ];
194           masterkeyFile = cfg.masterKeyFile;
195           inherit (cfg) tlsMode;
196         };
197       in
198       {
199         description = "ZITADEL identity access management";
200         path = [ cfg.package ];
201         wantedBy = [ "multi-user.target" ];
203         script = ''
204           zitadel start-from-init ${args}
205         '';
207         serviceConfig = {
208           Type = "simple";
209           User = cfg.user;
210           Group = cfg.group;
211           Restart = "on-failure";
212         };
213       };
215     users.users.zitadel = lib.mkIf (cfg.user == "zitadel") {
216       isSystemUser = true;
217       group = cfg.group;
218     };
219     users.groups.zitadel = lib.mkIf (cfg.group == "zitadel") { };
220   };
222   meta.maintainers = [ ];