diff --git a/.just/machine.just b/.just/machine.just index 6dabbc0..65d1a7b 100644 --- a/.just/machine.just +++ b/.just/machine.just @@ -6,4 +6,4 @@ [doc('Update the target machine')] update machine: - nixos-rebuild switch --use-remote-sudo --target-host {{ machine }} --flake ..#{{ machine }} \ No newline at end of file + nixos-rebuild switch --use-remote-sudo --target-host {{ machine }} --flake .#{{ machine }} \ No newline at end of file diff --git a/.just/vars.just b/.just/vars.just index 167144a..46bb5fd 100644 --- a/.just/vars.just +++ b/.just/vars.just @@ -1,6 +1,5 @@ base_path := invocation_directory() / "systems/x86_64-linux" sops := "nix shell nixpkgs#sops --command sops" -yq := "nix shell nixpkgs#yq --command yq" @_default: just --list @@ -20,9 +19,6 @@ list machine: echo "Done" -@get machine key: - {{ sops }} decrypt {{ base_path }}/{{ machine }}/secrets.yml | {{ yq }} ".$(echo "{{ key }}" | sed -E 's/\//./g')" - @remove machine key: {{ sops }} unset {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')" diff --git a/.justfile b/.justfile index 2788376..1c9fc03 100644 --- a/.justfile +++ b/.justfile @@ -15,8 +15,4 @@ mod machine '.just/machine.just' @update: nix flake update git commit -m 'chore: update dependencies' -- ./flake.lock > /dev/null - echo "Done" - -[doc('Introspection on flake output')] -@select key: - nix eval --json .#{{ key }} | jq . \ No newline at end of file + echo "Done" \ No newline at end of file diff --git a/modules/nixos/services/authentication/zitadel/default.nix b/modules/nixos/services/authentication/zitadel/default.nix index eaa3c60..59abcf3 100644 --- a/modules/nixos/services/authentication/zitadel/default.nix +++ b/modules/nixos/services/authentication/zitadel/default.nix @@ -12,12 +12,8 @@ in enable = mkEnableOption "Zitadel"; organization = mkOption { - type = types.attrsOf (types.submodule ({ name, ... }: { - options = - let - org = name; - in - { + type = types.attrsOf (types.submodule { + options = { isDefault = mkOption { type = types.bool; default = false; @@ -112,82 +108,13 @@ in }; }); }; - - user = mkOption { - default = {}; - type = types.attrsOf (types.submodule ({ name, ... }: { - options = - let - username = name; - in - { - email = mkOption { - type = types.str; - example = "someone@some.domain"; - description = '' - Username. - ''; - }; - - userName = mkOption { - type = types.nullOr types.str; - default = cfg.organization.${org}.user.${username}.email; - example = "someone@some.domain"; - description = '' - Username. Default value is the user's email, you can overwrite that by setting this option - ''; - }; - - firstName = mkOption { - type = types.str; - example = "John"; - description = '' - First name of the user. - ''; - }; - - lastName = mkOption { - type = types.str; - example = "Doe"; - description = '' - Last name of the user. - ''; - }; - - roles = mkOption { - type = types.listOf types.str; - default = []; - example = "[ \"ORG_OWNER\" ]"; - description = '' - List of roles granted to organisation. - ''; - }; - - instanceRoles = mkOption { - type = types.listOf types.str; - default = []; - example = "[ \"IAM_OWNER\" ]"; - description = '' - List of roles granted to instance. - ''; - }; - }; - })); - }; }; - })); + }); }; }; config = let - _refTypeMap = { - org = { type = "org"; }; - project = { type = "project"; }; - user = { type = "user"; tfType = "human_user"; }; - }; - - mapRef' = { type, tfType ? type }: name: { "${type}Id" = "\${ resource.zitadel_${tfType}.${toSnakeCase name}.id }"; }; - mapRef = type: name: mapRef' (_refTypeMap.${type}) name; + mapRef = type: name: { "${type}Id" = "\${ resource.zitadel_${type}.${toSnakeCase name}.id }"; }; mapEnum = prefix: value: "${prefix}_${value |> toSnakeCase |> toUpper}"; mapValue = type: value: ({ @@ -201,7 +128,6 @@ in withName = name: attrs: attrs // { inherit name; }; withRef = type: name: attrs: attrs // (mapRef type name); - withDefaults = defaults: attrs: defaults // attrs; select = keys: callback: set: if (length keys) == 0 then @@ -230,7 +156,6 @@ in }; resource = { - # Organizations zitadel_org = cfg.organization |> select [] (name: value: value |> getAttrs [ "isDefault" ] @@ -238,7 +163,6 @@ in |> toResource name ); - # Projects per organization zitadel_project = cfg.organization |> select [ "project" ] (org: name: value: value |> getAttrs [ "hasProjectCheck" "privateLabelingSetting" "projectRoleAssertion" "projectRoleCheck" ] @@ -247,7 +171,6 @@ in |> toResource name ); - # Each OIDC app per project zitadel_application_oidc = cfg.organization |> select [ "project" "application" ] (org: project: name: value: value |> getAttrs [ "redirectUris" "grantTypes" "responseTypes" ] @@ -257,52 +180,14 @@ in |> toResource name ); - # Users - zitadel_human_user = cfg.organization |> select [ "user" ] (org: name: value: - value - |> getAttrs [ "email" "userName" "firstName" "lastName" ] - |> withRef "org" org - |> withDefaults { isEmailVerified = true; } - |> toResource name - ); - - # Global user roles - zitadel_instance_member = cfg.organization |> select [ "user" ] (org: name: value: - { roles = value.instanceRoles; } - |> withRef "user" name - |> toResource name - ); - - # Organazation specific roles - zitadel_org_member = cfg.organization |> select [ "user" ] (org: name: value: - value - |> getAttrs [ "roles" ] - |> withRef "org" org - |> withRef "user" name - |> toResource name - ); - - # SMTP config zitadel_smtp_config.default = { sender_address = "chris@kruining.eu"; sender_name = "no-reply (Zitadel)"; tls = true; - host = "black-mail.nl:587"; + host = "black-mail.nl"; user = "chris@kruining.eu"; - password = lib.tfRef "file(\"${config'.sops.secrets."email/chris_kruining_eu".path}\")"; - set_active = true; + password = "\${file(\"${config'.sops.templates."kaas".path}\")}"; }; - - # Client credentials per app - local_sensitive_file = cfg.organization |> select [ "project" "application" ] (org: project: name: value: - nameValuePair name { - content = '' - CLIENT_ID=${lib.tfRef "resource.zitadel_application_oidc.${name}.client_id"} - CLIENT_SECRET=${lib.tfRef "resource.zitadel_application_oidc.${name}.client_secret"} - ''; - filename = "/var/lib/zitadel/clients/${name}"; - } - ); }; }; }) @@ -318,7 +203,6 @@ in systemd.tmpfiles.rules = [ "d /tmp/zitadelApplyTerraform 0755 zitadel zitadel -" - "d /var/lib/zitadel/clients 0755 zitadel zitadel -" ]; systemd.services.zitadelApplyTerraform = { @@ -330,11 +214,6 @@ in script = '' #!/usr/bin/env bash - if [ "$(systemctl is-active zitadel)" != "active" ]; then - echo "Zitadel is not running" - exit 1 - fi - # Copy infra code into workspace cp -f ${terraformConfiguration} config.tf.json @@ -358,7 +237,8 @@ in zitadel = { enable = true; openFirewall = true; - masterKeyFile = config.sops.secrets."zitadel/masterKey".path; + # masterKeyFile = config.sops.secrets."zitadel/masterKey".path; + masterKeyFile = "/var/lib/zitadel/master_key"; tlsMode = "external"; settings = { Port = 9092; @@ -376,6 +256,31 @@ in SecretHasher.Hasher.Algorithm = "argon2id"; }; + DefaultInstance = { + # PasswordComplexityPolicy = { + # MinLength = 0; + # HasLowercase = false; + # HasUppercase = false; + # HasNumber = false; + # HasSymbol = false; + # }; + # LoginPolicy = { + # AllowRegister = false; + # ForceMFA = true; + # }; + # LockoutPolicy = { + # MaxPasswordAttempts = 5; + # MaxOTPAttempts = 10; + # }; + SMTPConfiguration = { + SMTP = { + Host = "black-mail.nl:587"; + User = "chris@kruining.eu"; + }; + FromName = "Amarth Zitadel"; + }; + }; + Database.postgres = { Host = "localhost"; # Zitadel will report error if port is not set @@ -430,9 +335,9 @@ in }; }; }; - # extraStepsPaths = [ - # config.sops.templates."secrets.yaml".path - # ]; + extraStepsPaths = [ + config.sops.templates."secrets.yaml".path + ]; }; postgresql = { @@ -481,6 +386,23 @@ in restartUnits = [ "zitadel.service" ]; }; }; + + templates."secrets.yaml" = { + owner = "zitadel"; + group = "zitadel"; + content = '' + DefaultInstance: + SMTPConfiguration: + SMTP: + Password: ${config.sops.placeholder."email/chris_kruining_eu"} + ''; + }; + + templates."kaas" = { + owner = "zitadel"; + group = "zitadel"; + content = config.sops.placeholder."email/chris_kruining_eu"; + }; }; }; } diff --git a/systems/x86_64-linux/ulmo/default.nix b/systems/x86_64-linux/ulmo/default.nix index e776927..4845e73 100644 --- a/systems/x86_64-linux/ulmo/default.nix +++ b/systems/x86_64-linux/ulmo/default.nix @@ -43,18 +43,9 @@ enable = true; organization = { + thisIsMyAwesomeOrg = {}; + nix = { - user = { - chris = { - email = "chris@kruining.eu"; - firstName = "Chris"; - lastName = "Kruining"; - - roles = [ "ORG_OWNER" ]; - instanceRoles = [ "IAM_OWNER" ]; - }; - }; - project = { ulmo = { application = { @@ -69,12 +60,6 @@ grantTypes = [ "authorizationCode" ]; responseTypes = [ "code" ]; }; - - matrix = { - redirectUris = [ "https://matrix.kruining.eu/_synapse/client/oidc/callback" ]; - grantTypes = [ "authorizationCode" ]; - responseTypes = [ "code" ]; - }; }; }; }; diff --git a/systems/x86_64-linux/ulmo/secrets.yml b/systems/x86_64-linux/ulmo/secrets.yml index f9e4a82..6add209 100644 --- a/systems/x86_64-linux/ulmo/secrets.yml +++ b/systems/x86_64-linux/ulmo/secrets.yml @@ -1,8 +1,9 @@ email: + info@amarth.cloud: ENC[AES256_GCM,data:xwR3XS/zxr85e8wQLqIJfc8b3CaRlMqts3kWQpQTy6c=,iv:6N48IIRhFvgPtzP7/w6ZQM80mHCZ7ZHAsvv2tHFP9mE=,tag:FK2OboYbnmgq6eJp5Oyjng==,type:str] chris_kruining_eu: ENC[AES256_GCM,data:/JS+dQ6ABlkdjRZP+sGeUY3js30swS4=,iv:d5CcoY6DD3DJ/e3t0OU/KUULccJpTN0uBQPQzl/3R0s=,tag:aTN7RdzXkIpci9tEBjevSA==,type:str] info_amarth_cloud: ENC[AES256_GCM,data:/x7aAFAxXYYf79tB08VQmmuTIy2TvdSTFfAzIWdIr+I=,iv:plNxS6oOin+oEql+1xsePOsUfLJkf+ZPBviPRTbIghE=,tag:hjtK3rysd2NNBA2mWdv8cw==,type:str] zitadel: - masterKey: ENC[AES256_GCM,data:4MPvBo407qrS7NF4oUTf84tZoPkSRmiHdD7qpkYeHME=,iv:H2NIAN0xBUDqnyco9gA3zYAsKtSeA/JpqYrPhc1eqc0=,tag:6OFGDfsucG5gDerImgpuXA==,type:str] + masterKey: ENC[AES256_GCM,data:DyBNWV+4HmPa1mA4I3TERWmrIEn/c4/XYlgfmel7Ag==,iv:CjS5kAHH8j0ExCNFZf3dnyBsDPnAShRt55onPcUfkwU=,tag:CeINNaH5hOprAxm/DZFDPA==,type:str] sops: age: - recipient: age19qfpf980tadguqq44zf6xwvjvl428dyrj46ha3n6aeqddwhtnuqqml7etq @@ -23,7 +24,7 @@ sops: TTRWaHhpNWlkVDFmMFN4ZTNHMUxyNVkKV693pzTKRkZboQCMPr9IyMGSgxfuHXcb Y6BNcp6Qg6PWtX5QI7wRkPNINAK1TEbRBba+b8h6gMmVU4DliQyFiQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-10-27T13:11:41Z" - mac: ENC[AES256_GCM,data:0LS7xQlkfIZRVwAZPE33KmPA19CpnXj/t4hpDrVW+BbESpnBku2oxPB/Cvp0dY5MGnDFgU4Htp0JoppHCgKvkaSBhvjxjW2DT1Nkk5PBmAtuzZLW4qc25ZVlqiKgzj1LE3XPTbqUJyp+X3U23BnU1ViTGgHuBcdEV7TFNHjmnwk=,iv:HpVIDAU1FbrUKXW8klWq0Kn9ZtKcgwR1jKXLkGtDd5A=,tag:50P0UZtj77npD92zxCaZHw==,type:str] + lastmodified: "2025-10-23T14:25:59Z" + mac: ENC[AES256_GCM,data:p3A1ZSr6S21SUjEZbL4V0uh3HVqcRhFi1N93IeUKs2yVbBYAXzWJ+2ejSxfM+W9MSCAYxx27i0ZoBPjQJu/xQzwmW8HWn4rRfCsa2TGqOw25PLvkHgnBUc70X759cKxvR0Pm7ha22JCnzJVrzvUMlBVs61wxHT57x0El9Gan8eY=,iv:SKN+R4wsN/L2pZW/s5ocEtCXXZB5wK4tgFIYWGWtRPA=,tag:CNLl4lVO06gAcsSCfU2KjA==,type:str] unencrypted_suffix: _unencrypted version: 3.11.0