Compare commits

..

No commits in common. "84cc5ff5c4586136e091c3c087b787c9326fd869" and "f390d4195562e69aa43fc326ca6efb33167cc6ad" have entirely different histories.

6 changed files with 61 additions and 161 deletions

View file

@ -6,4 +6,4 @@
[doc('Update the target machine')] [doc('Update the target machine')]
update machine: update machine:
nixos-rebuild switch --use-remote-sudo --target-host {{ machine }} --flake ..#{{ machine }} nixos-rebuild switch --use-remote-sudo --target-host {{ machine }} --flake .#{{ machine }}

View file

@ -1,6 +1,5 @@
base_path := invocation_directory() / "systems/x86_64-linux" base_path := invocation_directory() / "systems/x86_64-linux"
sops := "nix shell nixpkgs#sops --command sops" sops := "nix shell nixpkgs#sops --command sops"
yq := "nix shell nixpkgs#yq --command yq"
@_default: @_default:
just --list just --list
@ -20,9 +19,6 @@ list machine:
echo "Done" echo "Done"
@get machine key:
{{ sops }} decrypt {{ base_path }}/{{ machine }}/secrets.yml | {{ yq }} ".$(echo "{{ key }}" | sed -E 's/\//./g')"
@remove machine key: @remove machine key:
{{ sops }} unset {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')" {{ sops }} unset {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')"

View file

@ -15,8 +15,4 @@ mod machine '.just/machine.just'
@update: @update:
nix flake update nix flake update
git commit -m 'chore: update dependencies' -- ./flake.lock > /dev/null git commit -m 'chore: update dependencies' -- ./flake.lock > /dev/null
echo "Done" echo "Done"
[doc('Introspection on flake output')]
@select key:
nix eval --json .#{{ key }} | jq .

View file

@ -12,12 +12,8 @@ in
enable = mkEnableOption "Zitadel"; enable = mkEnableOption "Zitadel";
organization = mkOption { organization = mkOption {
type = types.attrsOf (types.submodule ({ name, ... }: { type = types.attrsOf (types.submodule {
options = options = {
let
org = name;
in
{
isDefault = mkOption { isDefault = mkOption {
type = types.bool; type = types.bool;
default = false; 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 config = let
_refTypeMap = { mapRef = type: name: { "${type}Id" = "\${ resource.zitadel_${type}.${toSnakeCase name}.id }"; };
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;
mapEnum = prefix: value: "${prefix}_${value |> toSnakeCase |> toUpper}"; mapEnum = prefix: value: "${prefix}_${value |> toSnakeCase |> toUpper}";
mapValue = type: value: ({ mapValue = type: value: ({
@ -201,7 +128,6 @@ in
withName = name: attrs: attrs // { inherit name; }; withName = name: attrs: attrs // { inherit name; };
withRef = type: name: attrs: attrs // (mapRef type name); withRef = type: name: attrs: attrs // (mapRef type name);
withDefaults = defaults: attrs: defaults // attrs;
select = keys: callback: set: select = keys: callback: set:
if (length keys) == 0 then if (length keys) == 0 then
@ -230,7 +156,6 @@ in
}; };
resource = { resource = {
# Organizations
zitadel_org = cfg.organization |> select [] (name: value: zitadel_org = cfg.organization |> select [] (name: value:
value value
|> getAttrs [ "isDefault" ] |> getAttrs [ "isDefault" ]
@ -238,7 +163,6 @@ in
|> toResource name |> toResource name
); );
# Projects per organization
zitadel_project = cfg.organization |> select [ "project" ] (org: name: value: zitadel_project = cfg.organization |> select [ "project" ] (org: name: value:
value value
|> getAttrs [ "hasProjectCheck" "privateLabelingSetting" "projectRoleAssertion" "projectRoleCheck" ] |> getAttrs [ "hasProjectCheck" "privateLabelingSetting" "projectRoleAssertion" "projectRoleCheck" ]
@ -247,7 +171,6 @@ in
|> toResource name |> toResource name
); );
# Each OIDC app per project
zitadel_application_oidc = cfg.organization |> select [ "project" "application" ] (org: project: name: value: zitadel_application_oidc = cfg.organization |> select [ "project" "application" ] (org: project: name: value:
value value
|> getAttrs [ "redirectUris" "grantTypes" "responseTypes" ] |> getAttrs [ "redirectUris" "grantTypes" "responseTypes" ]
@ -257,52 +180,14 @@ in
|> toResource name |> 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 = { zitadel_smtp_config.default = {
sender_address = "chris@kruining.eu"; sender_address = "chris@kruining.eu";
sender_name = "no-reply (Zitadel)"; sender_name = "no-reply (Zitadel)";
tls = true; tls = true;
host = "black-mail.nl:587"; host = "black-mail.nl";
user = "chris@kruining.eu"; user = "chris@kruining.eu";
password = lib.tfRef "file(\"${config'.sops.secrets."email/chris_kruining_eu".path}\")"; password = "\${file(\"${config'.sops.templates."kaas".path}\")}";
set_active = true;
}; };
# 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 = [ systemd.tmpfiles.rules = [
"d /tmp/zitadelApplyTerraform 0755 zitadel zitadel -" "d /tmp/zitadelApplyTerraform 0755 zitadel zitadel -"
"d /var/lib/zitadel/clients 0755 zitadel zitadel -"
]; ];
systemd.services.zitadelApplyTerraform = { systemd.services.zitadelApplyTerraform = {
@ -330,11 +214,6 @@ in
script = '' script = ''
#!/usr/bin/env bash #!/usr/bin/env bash
if [ "$(systemctl is-active zitadel)" != "active" ]; then
echo "Zitadel is not running"
exit 1
fi
# Copy infra code into workspace # Copy infra code into workspace
cp -f ${terraformConfiguration} config.tf.json cp -f ${terraformConfiguration} config.tf.json
@ -358,7 +237,8 @@ in
zitadel = { zitadel = {
enable = true; enable = true;
openFirewall = 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"; tlsMode = "external";
settings = { settings = {
Port = 9092; Port = 9092;
@ -376,6 +256,31 @@ in
SecretHasher.Hasher.Algorithm = "argon2id"; 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 = { Database.postgres = {
Host = "localhost"; Host = "localhost";
# Zitadel will report error if port is not set # Zitadel will report error if port is not set
@ -430,9 +335,9 @@ in
}; };
}; };
}; };
# extraStepsPaths = [ extraStepsPaths = [
# config.sops.templates."secrets.yaml".path config.sops.templates."secrets.yaml".path
# ]; ];
}; };
postgresql = { postgresql = {
@ -481,6 +386,23 @@ in
restartUnits = [ "zitadel.service" ]; 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";
};
}; };
}; };
} }

View file

@ -43,18 +43,9 @@
enable = true; enable = true;
organization = { organization = {
thisIsMyAwesomeOrg = {};
nix = { nix = {
user = {
chris = {
email = "chris@kruining.eu";
firstName = "Chris";
lastName = "Kruining";
roles = [ "ORG_OWNER" ];
instanceRoles = [ "IAM_OWNER" ];
};
};
project = { project = {
ulmo = { ulmo = {
application = { application = {
@ -69,12 +60,6 @@
grantTypes = [ "authorizationCode" ]; grantTypes = [ "authorizationCode" ];
responseTypes = [ "code" ]; responseTypes = [ "code" ];
}; };
matrix = {
redirectUris = [ "https://matrix.kruining.eu/_synapse/client/oidc/callback" ];
grantTypes = [ "authorizationCode" ];
responseTypes = [ "code" ];
};
}; };
}; };
}; };

View file

@ -1,8 +1,9 @@
email: 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] 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] info_amarth_cloud: ENC[AES256_GCM,data:/x7aAFAxXYYf79tB08VQmmuTIy2TvdSTFfAzIWdIr+I=,iv:plNxS6oOin+oEql+1xsePOsUfLJkf+ZPBviPRTbIghE=,tag:hjtK3rysd2NNBA2mWdv8cw==,type:str]
zitadel: 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: sops:
age: age:
- recipient: age19qfpf980tadguqq44zf6xwvjvl428dyrj46ha3n6aeqddwhtnuqqml7etq - recipient: age19qfpf980tadguqq44zf6xwvjvl428dyrj46ha3n6aeqddwhtnuqqml7etq
@ -23,7 +24,7 @@ sops:
TTRWaHhpNWlkVDFmMFN4ZTNHMUxyNVkKV693pzTKRkZboQCMPr9IyMGSgxfuHXcb TTRWaHhpNWlkVDFmMFN4ZTNHMUxyNVkKV693pzTKRkZboQCMPr9IyMGSgxfuHXcb
Y6BNcp6Qg6PWtX5QI7wRkPNINAK1TEbRBba+b8h6gMmVU4DliQyFiQ== Y6BNcp6Qg6PWtX5QI7wRkPNINAK1TEbRBba+b8h6gMmVU4DliQyFiQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-10-27T13:11:41Z" lastmodified: "2025-10-23T14:25:59Z"
mac: ENC[AES256_GCM,data:0LS7xQlkfIZRVwAZPE33KmPA19CpnXj/t4hpDrVW+BbESpnBku2oxPB/Cvp0dY5MGnDFgU4Htp0JoppHCgKvkaSBhvjxjW2DT1Nkk5PBmAtuzZLW4qc25ZVlqiKgzj1LE3XPTbqUJyp+X3U23BnU1ViTGgHuBcdEV7TFNHjmnwk=,iv:HpVIDAU1FbrUKXW8klWq0Kn9ZtKcgwR1jKXLkGtDd5A=,tag:50P0UZtj77npD92zxCaZHw==,type:str] mac: ENC[AES256_GCM,data:p3A1ZSr6S21SUjEZbL4V0uh3HVqcRhFi1N93IeUKs2yVbBYAXzWJ+2ejSxfM+W9MSCAYxx27i0ZoBPjQJu/xQzwmW8HWn4rRfCsa2TGqOw25PLvkHgnBUc70X759cKxvR0Pm7ha22JCnzJVrzvUMlBVs61wxHT57x0El9Gan8eY=,iv:SKN+R4wsN/L2pZW/s5ocEtCXXZB5wK4tgFIYWGWtRPA=,tag:CNLl4lVO06gAcsSCfU2KjA==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.11.0 version: 3.11.0