This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / modules / zitadel / default.nix
6.7 kB 195 lines
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.lass.zitadel; 9 zitadel = config.services.zitadel; 10 appsDir = "/var/lib/zitadel-apps"; 11 # Written by zitadel's setup when it creates the first instance. 12 patFile = "/var/lib/zitadel/reconcile.pat"; 13 14 reconcileConfig = pkgs.writeText "zitadel-reconcile.json" ( 15 builtins.toJSON { 16 url = "http://127.0.0.1:${toString zitadel.settings.Port}"; 17 domain = zitadel.settings.ExternalDomain; 18 stateDir = appsDir; 19 inherit patFile; 20 inherit (cfg) loginPolicy idps; 21 projects = lib.mapAttrs (_: project: { 22 inherit (project) access users; 23 apps = lib.mapAttrs (_: app: { 24 inherit (app) redirectUris envFile; 25 authMethodType = "OIDC_AUTH_METHOD_TYPE_${lib.toUpper app.authMethod}"; 26 }) project.apps; 27 }) cfg.projects; 28 } 29 ); 30in 31{ 32 options.lass.zitadel = { 33 loginPolicy = lib.mkOption { 34 type = lib.types.attrsOf lib.types.anything; 35 default = { }; 36 example = { 37 allowRegister = true; 38 }; 39 description = '' 40 Fields of the instance's default login policy, as in Zitadel's admin 41 API (PUT /admin/v1/policies/login). Unlisted fields keep their value. 42 ''; 43 }; 44 45 idps = lib.mkOption { 46 default = { }; 47 description = '' 48 External identity providers, by display name, added to the login 49 policy. Users may log in, register and link accounts with them. An 50 IdP whose credential files are empty is skipped. 51 ''; 52 type = lib.types.attrsOf ( 53 lib.types.submodule { 54 options = { 55 type = lib.mkOption { 56 type = lib.types.enum [ 57 "github" 58 "google" 59 ]; 60 }; 61 clientIdFile = lib.mkOption { type = lib.types.str; }; 62 clientSecretFile = lib.mkOption { type = lib.types.str; }; 63 scopes = lib.mkOption { type = lib.types.listOf lib.types.str; }; 64 }; 65 } 66 ); 67 }; 68 69 projects = lib.mkOption { 70 default = { }; 71 description = '' 72 Zitadel projects, one per service, in the default organization. 73 Projects and apps removed from here are left in Zitadel. 74 ''; 75 type = lib.types.attrsOf ( 76 lib.types.submodule ( 77 { name, ... }: 78 let 79 project = name; 80 in 81 { 82 options = { 83 access = lib.mkOption { 84 type = lib.types.enum [ 85 "public" 86 "declarative" 87 "managed" 88 ]; 89 description = '' 90 Who may log in to the project's apps: 91 - public: every user of the instance. 92 - declarative: the users listed in `users`. All other user 93 grants of the project are removed. 94 - managed: users with a user grant on the project, given by 95 an admin in the console. 96 ''; 97 }; 98 users = lib.mkOption { 99 type = lib.types.listOf lib.types.str; 100 default = [ ]; 101 description = '' 102 Login names or verified email addresses of the users that 103 get a user grant on the project (access = "declarative"). 104 Users who have not registered yet are skipped until the 105 next run. 106 ''; 107 }; 108 apps = lib.mkOption { 109 default = { }; 110 description = "OIDC web apps of the project."; 111 type = lib.types.attrsOf ( 112 lib.types.submodule ( 113 { name, ... }: 114 { 115 options = { 116 redirectUris = lib.mkOption { type = lib.types.listOf lib.types.str; }; 117 authMethod = lib.mkOption { 118 type = lib.types.enum [ 119 "basic" 120 "post" 121 ]; 122 default = "basic"; 123 description = "How the app sends its client secret to the token endpoint."; 124 }; 125 envFile = { 126 path = lib.mkOption { 127 type = lib.types.str; 128 default = "${appsDir}/${project}-${name}.env"; 129 description = "Env file with the app's client id and secret."; 130 }; 131 owner = lib.mkOption { 132 type = lib.types.str; 133 default = "root"; 134 }; 135 clientIdVariable = lib.mkOption { 136 type = lib.types.str; 137 default = "CLIENT_ID"; 138 }; 139 clientSecretVariable = lib.mkOption { 140 type = lib.types.str; 141 default = "CLIENT_SECRET"; 142 }; 143 }; 144 }; 145 } 146 ) 147 ); 148 }; 149 }; 150 } 151 ) 152 ); 153 }; 154 }; 155 156 config = lib.mkIf zitadel.enable { 157 assertions = lib.mapAttrsToList (name: project: { 158 assertion = project.users == [ ] || project.access == "declarative"; 159 message = "lass.zitadel.projects.${name}.users needs access = \"declarative\""; 160 }) cfg.projects; 161 162 services.zitadel.steps.FirstInstance = { 163 PatPath = patFile; 164 Org.Machine.Machine = { 165 Username = "reconcile"; 166 Name = "zitadel-reconcile"; 167 }; 168 # Zitadel's default for tokens without expiry; an empty Pat section 169 # creates no token. 170 Org.Machine.Pat.ExpirationDate = "9999-01-01T00:00:00Z"; 171 }; 172 systemd.services.zitadel.serviceConfig = { 173 StateDirectory = "zitadel"; 174 StateDirectoryMode = "0700"; 175 }; 176 177 systemd.services.zitadel-reconcile = { 178 description = "Apply lass.zitadel to Zitadel"; 179 wantedBy = [ "multi-user.target" ]; 180 wants = [ "zitadel.service" ]; 181 after = [ "zitadel.service" ]; 182 environment.PYTHONUNBUFFERED = "1"; 183 serviceConfig = { 184 Type = "oneshot"; 185 RemainAfterExit = true; 186 ExecStart = "${ 187 pkgs.writers.writePython3 "zitadel-reconcile" { } ./reconcile.py 188 } ${reconcileConfig}"; 189 StateDirectory = "zitadel-apps"; 190 StateDirectoryMode = "0711"; 191 UMask = "0077"; 192 }; 193 }; 194 }; 195}