2026-05-02 12:52:47 -04:00
|
|
|
{
|
|
|
|
|
config,
|
2026-05-02 13:16:44 -04:00
|
|
|
lib,
|
2026-05-02 12:52:47 -04:00
|
|
|
pkgs,
|
|
|
|
|
...
|
|
|
|
|
}:
|
|
|
|
|
let
|
|
|
|
|
domain = "nayeonie.com";
|
|
|
|
|
authDomain = "auth.${domain}";
|
2026-05-02 13:16:44 -04:00
|
|
|
aliceSshKeys = config.users.users.alice.openssh.authorizedKeys.keys;
|
2026-05-02 12:52:47 -04:00
|
|
|
in
|
|
|
|
|
{
|
|
|
|
|
services = {
|
|
|
|
|
kanidm = {
|
|
|
|
|
package = pkgs.kanidm_1_9.withSecretProvisioning;
|
|
|
|
|
|
|
|
|
|
server = {
|
|
|
|
|
enable = true;
|
|
|
|
|
|
|
|
|
|
settings = {
|
|
|
|
|
origin = "https://${authDomain}";
|
|
|
|
|
inherit domain;
|
|
|
|
|
bindaddress = "0.0.0.0:8443";
|
|
|
|
|
ldapbindaddress = "0.0.0.0:3890";
|
|
|
|
|
tls_chain = "/var/lib/acme/${domain}/fullchain.pem";
|
|
|
|
|
tls_key = "/var/lib/acme/${domain}/key.pem";
|
|
|
|
|
db_fs_type = "zfs";
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
# Reuse the existing secret during migration; rotate/rename in a follow-up.
|
|
|
|
|
provision = {
|
|
|
|
|
enable = true;
|
|
|
|
|
instanceUrl = "https://${authDomain}";
|
|
|
|
|
adminPasswordFile = config.sops.secrets."kanidm/admin_password".path;
|
|
|
|
|
idmAdminPasswordFile = config.sops.secrets."kanidm/admin_password".path;
|
|
|
|
|
acceptInvalidCerts = false;
|
|
|
|
|
|
|
|
|
|
groups = {
|
|
|
|
|
gitea-users = {
|
|
|
|
|
present = true;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
persons = {
|
|
|
|
|
alice = {
|
|
|
|
|
displayName = "Alice";
|
2026-05-02 13:16:44 -04:00
|
|
|
mailAddresses = [ "aliceghuston@gmail.com" ];
|
2026-05-02 12:52:47 -04:00
|
|
|
present = true;
|
|
|
|
|
groups = [ "gitea-users" ];
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
systems.oauth2.gitea = {
|
|
|
|
|
present = true;
|
|
|
|
|
displayName = "Gitea";
|
|
|
|
|
public = false;
|
|
|
|
|
basicSecretFile = config.sops.secrets."kanidm/gitea_oidc_client_secret".path;
|
|
|
|
|
originUrl = "https://nayeonie.com/user/oauth2/kanidm/callback";
|
|
|
|
|
originLanding = "https://nayeonie.com/";
|
|
|
|
|
preferShortUsername = true;
|
|
|
|
|
scopeMaps = {
|
|
|
|
|
gitea-users = [
|
|
|
|
|
"openid"
|
|
|
|
|
"email"
|
|
|
|
|
"profile"
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
claimMaps.groups.valuesByGroup = {
|
|
|
|
|
gitea-users = [ "gitea-users" ];
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
sops.secrets = {
|
|
|
|
|
"kanidm/admin_password".owner = "kanidm";
|
|
|
|
|
"kanidm/gitea_oidc_client_secret".owner = "kanidm";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
# Certs are currently group-readable by haproxy for docker HAProxy.
|
|
|
|
|
users.users.kanidm.extraGroups = [ "haproxy" ];
|
|
|
|
|
|
2026-05-02 13:16:44 -04:00
|
|
|
systemd.services.kanidm-person-ssh-keys-bootstrap = {
|
|
|
|
|
description = "Bootstrap Kanidm SSH public keys for alice";
|
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
|
requires = [ "kanidm.service" ];
|
|
|
|
|
after = [ "kanidm.service" ];
|
|
|
|
|
serviceConfig = {
|
|
|
|
|
Type = "oneshot";
|
|
|
|
|
User = "root";
|
|
|
|
|
Group = "root";
|
|
|
|
|
};
|
|
|
|
|
path = [
|
|
|
|
|
config.services.kanidm.package
|
|
|
|
|
pkgs.coreutils
|
|
|
|
|
pkgs.gawk
|
|
|
|
|
pkgs.gnugrep
|
|
|
|
|
];
|
|
|
|
|
script = ''
|
|
|
|
|
set -eu
|
|
|
|
|
|
|
|
|
|
url="https://${authDomain}"
|
|
|
|
|
password="$(<${config.sops.secrets."kanidm/admin_password".path})"
|
|
|
|
|
state_dir="/var/lib/kanidm/ssh-bootstrap"
|
|
|
|
|
mkdir -p "$state_dir"
|
|
|
|
|
chmod 700 "$state_dir"
|
|
|
|
|
export HOME="$state_dir"
|
|
|
|
|
|
|
|
|
|
# Authenticate idm_admin for CLI operations.
|
|
|
|
|
printf '%s\n' "$password" | kanidm login -H "$url" -D idm_admin >/dev/null
|
|
|
|
|
|
|
|
|
|
existing_keys="$(kanidm -H "$url" -D idm_admin person ssh list-publickeys alice || true)"
|
|
|
|
|
i=0
|
|
|
|
|
${lib.concatMapStringsSep "\n" (
|
|
|
|
|
key:
|
|
|
|
|
" i=$((i + 1))\n if ! printf '%s\\n' \"$existing_keys\" | grep -Fq ${lib.escapeShellArg key}; then\n kanidm -H \"$url\" -D idm_admin person ssh add-publickey alice \"home-key-$i\" ${lib.escapeShellArg key} >/dev/null\n fi"
|
|
|
|
|
) aliceSshKeys}
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-02 12:52:47 -04:00
|
|
|
networking.firewall.allowedTCPPorts = [
|
|
|
|
|
3890
|
|
|
|
|
8443
|
|
|
|
|
];
|
|
|
|
|
}
|