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