{
  config,
  lib,
  ...
}:
let
  name = "zitadel";

  hostDataDir = "/var/lib/${name}";

  hostAddress = "10.0.0.1";
  containerAddress = "10.0.0.3";
  hostAddress6 = "fc00::1";
  containerAddress6 = "fc00::3";

  hasSecret =
    secret:
    let
      secrets = config.age.secrets or { };
    in
    secrets ? ${secret} && secrets.${secret} != null;

  binds = [
    # Postgres data, must use postgres user in container and host
    {
      host = "${hostDataDir}/postgres";
      # Adjust based on container postgres data dir
      container = "/var/lib/postgresql/17";
      user = "postgres";
      uid = config.ids.uids.postgres;
      gid = config.ids.gids.postgres;
    }
    # Postgres backups
    {
      host = "${hostDataDir}/backups/postgres";
      container = "/var/backup/postgresql";
      user = "postgres";
      uid = config.ids.uids.postgres;
      gid = config.ids.gids.postgres;
    }
  ] ++ lib.optionals (hasSecret "zitadel_master_key") [
    # secret
    {
      host = config.age.secrets.zitadel_master_key.path;
      container = "/var/secrets/zitadel_master_key.age";
      readOnly = true;
    }
  ];
  bindsWithUsers = lib.filter (b: b ? user) binds;
  uniqueUsers = lib.foldl' (
    acc: bind: if lib.lists.any (item: item.user == bind.user) acc then acc else acc ++ [ bind ]
  ) [ ] bindsWithUsers;
  users = {
    users = lib.listToAttrs (
      lib.map (u: {
        name = u.user;
        value = {
          isSystemUser = true;
          name = u.user;
          uid = u.uid;
          group = u.user;
        };
      }) uniqueUsers
    );

    groups = lib.listToAttrs (
      lib.map (g: {
        name = g.user;
        value.gid = g.gid;
      }) uniqueUsers
    );
  };

in
{
  options = { };
  config = {
    services.nginx.virtualHosts."sso.joshuabell.xyz" = {
      addSSL = true;
      sslCertificate = "/var/lib/acme/joshuabell.xyz/fullchain.pem";
      sslCertificateKey = "/var/lib/acme/joshuabell.xyz/key.pem";
      locations = {
        "/" = {
          proxyWebsockets = true;
          recommendedProxySettings = true;
          proxyPass = "http://${containerAddress}:8080";
          extraConfig = ''
            proxy_set_header X-Forwarded-Proto https;
          '';
        };
      };
    };

    # Ensure users exist on host machine
    inherit users;

    # Ensure directories exist on host machine
    system.activationScripts."createDirsFor${name}" = ''
      ${lib.concatStringsSep "\n" (
        lib.map (bind: ''
          mkdir -p ${bind.host}
          chown -R ${toString bind.user}:${toString bind.gid} ${bind.host}
          chmod -R 750 ${bind.host}
        '') bindsWithUsers
      )}
    '';

    containers.${name} = {
      ephemeral = true;
      autoStart = true;
      privateNetwork = true;
      hostAddress = hostAddress;
      localAddress = containerAddress;
      hostAddress6 = hostAddress6;
      localAddress6 = containerAddress6;
      bindMounts = lib.foldl (
        acc: bind:
        {
          "${bind.container}" = {
            hostPath = bind.host;
            isReadOnly = bind.readOnly or false;
          };
        }
        // acc
      ) { } binds;
      config =
        { config, pkgs, ... }:
        {
          system.stateVersion = "25.05";

          networking = {
            firewall = {
              enable = true;
              allowedTCPPorts = [
                8080
              ];
            };
            # Use systemd-resolved inside the container
            # Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
            useHostResolvConf = lib.mkForce false;
          };
          services.resolved.enable = true;

          # Ensure users exist on container
          inherit users;

          services.postgresql = {
            enable = true;
            package = pkgs.postgresql_17.withJIT;
            enableJIT = true;
            authentication = ''
              local all all trust
              host all all 127.0.0.1/8 trust
              host all all ::1/128 trust
              host all all fc00::1/128 trust
            '';
            ensureDatabases = [ "zitadel" ];
            ensureUsers = [
              {
                name = "zitadel";
                ensureDBOwnership = true;
                ensureClauses.login = true;
                ensureClauses.superuser = true;
              }
            ];
          };

          # Backup database
          services.postgresqlBackup = {
            enable = true;
          };

          services.zitadel = {
            enable = true;
            masterKeyFile = "/var/secrets/zitadel_master_key.age";
            settings = {
              Port = 8080;
              Database.postgres = {
                Host = "/var/run/postgresql/";
                Port = 5432;
                Database = "zitadel";
                User = {
                  Username = "zitadel";
                  SSL.Mode = "disable";
                };
                Admin = {
                  Username = "zitadel";
                  SSL.Mode = "disable";
                  ExistingDatabase = "zitadel";
                };
              };
              ExternalDomain = "sso.joshuabell.xyz";
              ExternalPort = 443;
              ExternalSecure = true;
            };
            steps.FirstInstance = {
              InstanceName = "sso";
              Org = {
                Name = "SSO";
                Human = {
                  UserName = "admin@joshuabell.xyz";
                  FirstName = "admin";
                  LastName = "admin";
                  Email.Address = "admin@joshuabell.xuz";
                  Email.Verified = true;
                  Password = "Password1!";
                  PasswordChangeRequired = true;
                };
              };
              LoginPolicy.AllowRegister = false;
            };
            openFirewall = true;
          };

          systemd.services.zitadel = {
            requires = [ "postgresql.service" ];
            after = [ "postgresql.service" ];
          };
        };
    };
  };
}
