services/clanServices/zitadel/default.nix

208 lines
6 KiB
Nix

{ lib, pkgs, ... }:
let
inherit (builtins) readFile;
inherit (lib) mkOption types;
in
{
_class = "clan.service";
manifest = {
name = "amarth-services/zitadel";
description = "Zitadel service module";
categories = [ "System" "Identity" "IAM" ];
readme = readFile ./README.md;
};
#==============================================================================================================
# Controller configuration
#==============================================================================================================
roles.controller = {
interface = {
options = {
hostName = mkOption {
type = types.str;
example = "auth.example.com";
description = ''
The domain at which zitadel will be hosted
'';
};
displayName = mkOption {
type = types.str;
example = "My awesome org";
description = ''
The Name of the zitadel organisation
'';
};
};
};
perInstance = { instanceName, settings, machine, roles, ... }: {
nixosModule = { config, pkgs, inputs, system, ... }:
let
terraform = inputs.terranix.lib.terranixConfiguration {
inherit pkgs system;
modules = [
({ config, ... }: {
config = {
terraform.required_providers.zitadel = {
source = "zitadel/zitadel";
version = "2.2.0";
};
provider.zitadel = {
domain = "localhost";
insecure = "true";
port = "8080";
jwt_profile_file = "local-token";
};
resource.zitadel_human_user.default = {
org_id = "";
};
};
})
];
};
in
{
clan.core.vars.generators.zitadel = {
share = false;
files.masterKey = { deploy = true; secret = true; owner = "zitadel"; group = "zitadel"; mode = "0400"; };
files.initialAdminPassword = { deploy = false; secret = true; };
files.emailPassword = { deploy = false; secret = true; };
runtimeInputs = with pkgs; [ pwgen ];
script = ''
pwgen 50 1 > "$out/initialAdminPassword"
# https://zitadel.com/docs/self-hosting/manage/configure#masterkey
# The master key has to be 32 bytes
head -c 32 /dev/urandom > "$out/masterKey"
touch $out/emailPassword
'';
};
services.zitadel = {
enable = true;
openFirewall = true;
masterKeyFile = config.clan.core.vars.generators.zitadel.files.masterKey.path;
tlsMode = "external";
settings = {
Port = 9092;
ExternalDomain = settings.hostName;
ExternalPort = 443;
ExternalSecure = true;
Metrics.Type = "otel";
Tracing.Type = "otel";
Telemetry.Enabled = true;
SystemDefaults = {
PasswordHasher.Hasher.Algorithm = "argon2id";
SecretHasher.Hasher.Algorithm = "argon2id";
};
DefaultInstance = {
PasswordComplexityPolicy = {
MinLength = 20;
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";
Password = config.clan.core.vars.generators.zitadel.files.masterKey.value;
};
FromName = "Amarth Zitadel";
};
};
Database.postgres = {
Host = "localhost";
# Zitadel will report error if port is not set
Port = 5432;
Database = "zitadel";
User = {
Username = "zitadel";
SSL.Mode = "disable";
};
Admin = {
Username = "postgres";
SSL.Mode = "disable";
};
};
};
steps.FirstInstance = {
InstanceName = settings.hostName;
Org = {
Name = settings.displayName;
Human = {
UserName = "chris";
FirstName = "Chris";
LastName = "Kruining";
Email = {
Address = "chris@kruining.eu";
Verified = true;
};
Password = config.clan.core.vars.generators.zitadel.files.initialAdminPassword.value;
};
};
};
};
services.postgresql = {
enable = true;
authentication = ''
# Generated file, do not edit!
# TYPE DATABASE USER ADDRESS METHOD
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
'';
ensureDatabases = [ "zitadel" ];
ensureUsers = [
{
name = "zitadel";
ensureDBOwnership = true;
}
];
};
};
};
};
#==============================================================================================================
# Peer configuration
#==============================================================================================================
roles.peer = {
interface = {
options = {};
};
perInstance = { instanceName, settings, machine, roles, ... }: {
nixosModule = {};
};
};
}