Files
homelab/services/identity/zitadel.nix
T
darmanandClaude Sonnet 5 d7a66f3e3b Reorganize services/ into category subfolders
Group service modules by category (media, network, vpn, identity,
dev, desktop) to make the growing services/ dir easier to navigate.
containers.nix stays at the top level since it's a shared backend,
not a single-category service.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 06:08:43 +02:00

61 lines
1.8 KiB
Nix

{ config, ... }:
# Zitadel — self-hosted identity/OIDC provider. Local Postgres (peer-authed
# over the unix socket, no password anywhere) since Zitadel is latency-
# sensitive to its DB. TLS terminates at Caddy; Zitadel itself only listens
# on localhost:8080.
#
# The "zitadel" Postgres role doubles as both User (runtime queries) and
# Admin (bootstrap: creates db/extensions on first start) — granted
# createdb+createrole rather than using the postgres superuser, per
# Zitadel's own guidance to scope bootstrap privileges to a dedicated role.
#
# Needs, wired via sops in the host's secrets.nix:
# - masterKeyFile: 32 raw bytes, e.g. `openssl rand -hex 16`
# - extraStepsPaths: a FirstInstance admin bootstrap file (keeps the admin
# password out of the Nix store — settings.steps would leak it, since
# it's rendered into a world-readable store path)
{
services.postgresql = {
enable = true;
ensureDatabases = [ "zitadel" ];
ensureUsers = [
{
name = "zitadel";
ensureDBOwnership = true;
ensureClauses = {
createdb = true;
createrole = true;
};
}
];
};
services.zitadel = {
enable = true;
tlsMode = "external";
masterKeyFile = config.sops.secrets.zitadel_master_key.path;
extraStepsPaths = [ config.sops.templates."zitadel-first-instance.yaml".path ];
settings = {
Port = 8080;
ExternalPort = 443;
ExternalSecure = true;
Database.postgres = {
Host = "/run/postgresql";
Port = 5432;
Database = "zitadel";
User = {
Username = "zitadel";
SSL.Mode = "disable";
};
Admin = {
Username = "zitadel";
SSL.Mode = "disable";
};
};
};
};
}