Files
homelab/hosts/neptun/secrets.nix
T
darmanandClaude Sonnet 5 c4702b577c neptun: serve Headplane at vpn.mgaction.town/admin, auth via Zitadel OIDC
Path-route Headplane under /admin on the same vhost as headscale instead of
its own subdomain - Caddy handle blocks split on the prefix, headscale gets
everything else. base_url drops to the site root since Headplane appends
/admin (and the OIDC callback path) itself.

Wire Zitadel as the OIDC provider. client_id/client_secret/the headscale
API key can't be real until Zitadel and headscale are actually deployed and
an application/key exist, so those are REPLACE_ME placeholders for now
(documented in services/headplane.nix) - direct API-key login stays enabled
as a fallback so this can't lock anyone out in the meantime.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 22:42:03 +02:00

48 lines
1.9 KiB
Nix

{ config, ... }:
# sops-nix wiring for neptun (netcup VPS). Encrypted values in ../../secrets/neptun.yaml,
# decrypted with the VPS's own SSH host key (recipient in ../../.sops.yaml).
# The host key is pre-generated on the laptop and shipped at install
# (nixos-anywhere --extra-files -> /etc/ssh/ssh_host_ed25519_key).
{
sops.defaultSopsFile = ../../secrets/neptun.yaml;
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.secrets.tailscale_authkey = { };
# darman's console password (own hash = distinct from jupiter/mercury).
sops.secrets.darman_password.neededForUsers = true;
users.users.darman.hashedPasswordFile = config.sops.secrets.darman_password.path;
# Zitadel: masterKeyFile takes a path natively (no store leak). The admin
# bootstrap password is different — services.zitadel.steps would render it
# into a world-readable store path, so render a FirstInstance steps file
# from the secret instead and point extraStepsPaths at it (see
# services/zitadel.nix and the pihole.env template on mercury for the same
# pattern).
sops.secrets.zitadel_master_key = { };
sops.secrets.zitadel_admin_password = { };
sops.templates."zitadel-first-instance.yaml".content = ''
FirstInstance:
Org:
Name: mgaction
Human:
UserName: admin
FirstName: Admin
LastName: Admin
Email:
Address: erik.simon.me@gmail.com
Verified: true
Password: ${config.sops.placeholder.zitadel_admin_password}
PasswordChangeRequired: false
'';
# Headplane: cookie_secret_path takes a path natively (no store leak).
# oidc.client_secret + the headscale API key are still REPLACE_ME
# placeholders (see services/headplane.nix) until Zitadel/headscale are
# actually deployed and those get created for real.
sops.secrets.headplane_cookie_secret = { };
sops.secrets.headplane_oidc_client_secret = { };
sops.secrets.headplane_headscale_api_key = { };
}