12 KiB
OIDC Service Analysis & Setup Requirements
This document analyzes the services defined in this repository (specifically within platforms/nixos/modules/nmasur/presets/services/ and related server profiles like flame and swan), evaluates their OpenID Connect (OIDC) compatibility, and details the requirements for configuring OIDC logins.
Identity Provider Context: Pocket ID
The configuration already includes a central self-hosted identity provider: Pocket ID (platforms/nixos/modules/nmasur/presets/services/pocket-id/pocket-id.nix), hosted on the communications server (flame) behind Caddy at https://auth.masu.rs.
Pocket ID is an OpenID Connect (OIDC) provider with WebAuthn/Passkey support. It exposes the following standard OIDC endpoints:
- Issuer URL:
https://auth.masu.rs - Discovery Endpoint:
https://auth.masu.rs/.well-known/openid-configuration - Authorization Endpoint:
https://auth.masu.rs/authorize - Token Endpoint:
https://auth.masu.rs/api/oidc/token - Userinfo Endpoint:
https://auth.masu.rs/api/oidc/userinfo - JWKS Endpoint:
https://auth.masu.rs/.well-known/jwks.json
1. Service Compatibility Breakdown
Tier 1: First-Class / Native OIDC Support
These services support OpenID Connect natively without requiring external authentication proxies or custom code:
| Service | Hostname | OIDC Support Level | Configuration Method |
|---|---|---|---|
| Immich | photos.masu.rs |
Native core feature | NixOS config (services.immich.settings.oauth) |
| Gitea | git.masu.rs |
Native core feature | NixOS config / CLI or Web UI |
| Nextcloud | cloud.masu.rs |
Native (official user_oidc app) |
Nextcloud app + nextcloud-occ user_oidc:provider |
| Grafana | metrics.masu.rs |
Native (Generic OAuth) | NixOS config (services.grafana.settings."auth.generic_oauth") |
| Paperless-ngx | paper.masu.rs |
Native (django-allauth) |
NixOS env vars (PAPERLESS_SOCIALACCOUNT_PROVIDERS) |
| Mealie | cooking.masu.rs |
Native core feature | NixOS env vars (OIDC_AUTH_ENABLED, etc.) |
| Karakeep / Hoarder | keep.masu.rs |
Native (NextAuth OIDC) | NixOS env vars (OAUTH_WELLKNOWN_URL, etc.) |
| Audiobookshelf | read.masu.rs |
Native core feature (v2.3+) | Web UI (Settings → Authentication) |
| Actual Budget | money.masu.rs |
Native core feature (v24.3+) | NixOS env vars (ACTUAL_LOGIN_METHOD=openid) |
Tier 2: OIDC via Plugins or Reverse Proxy Header Auth
These services do not have generic OIDC in their core web UI, but can support single sign-on through plugins or reverse proxy headers (Remote-User / X-Forwarded-User):
| Service | Hostname | Strategy | Notes |
|---|---|---|---|
| Jellyfin | stream.masu.rs |
jellyfin-plugin-sso |
Web clients work well; TV and native apps typically rely on Quick Connect. |
| Calibre-Web | books.masu.rs |
Reverse proxy header auth | Set services.calibre-web.options.reverseProxyAuth.enable = true behind an authenticating reverse proxy. |
| File Browser | files.masu.rs |
Reverse proxy header auth | Set auth.method = "proxy" and auth.header = "X-Forwarded-User" behind an authenticating reverse proxy. |
| Navidrome | music.masu.rs |
Reverse proxy header auth | Supports ReverseProxyUserHeader for web UI; Subsonic API clients (Feishin, etc.) still require native user passwords. |
| Stalwart | contacts.masu.rs |
OIDC Directory / SASL OAuth | Stalwart supports OIDC directories, but CardDAV/CalDAV clients usually require HTTP Basic Auth or application passwords. |
Tier 3: Incompatible or No Native OIDC Support
- Vaultwarden (
vault.masu.rs): Incompatible for vault decryption. Vaultwarden uses client-side zero-knowledge encryption where vault keys are derived from the user's master password. Bitwarden Enterprise SSO relies on a proprietary Key Connector that Vaultwarden does not implement. - n8n (
n8n.masu.rs): SAML/OIDC SSO is an Enterprise / commercial-only feature; it is disabled in the free self-hosted Community edition. - The Arr Stack (
download.masu.rs): Radarr, Sonarr, Lidarr, Readarr, Prowlarr, Bazarr, and Sabnzbd only support API keys, Basic Auth, or Forms. - Transmission (
transmission.masu.rs): BitTorrent daemon; supports only HTTP Basic Auth / RPC whitelist. - Uptime Kuma (
status.masu.rs), ntfy (ntfy.masu.rs), The Lounge (irc.masu.rs), Pgweb (pg.masu.rs), Mathesar (mathesar.masu.rs), Hister (hister.masu.rs): No native generic OIDC login mechanism. - Infrastructure / Daemon Services: PostgreSQL, InfluxDB, bind, avahi, cloudflared, wireguard, litestream (no user web UI).
2. General Setup Requirements
Configuring OIDC requires setup across four layers:
A. Pocket ID Setup
For each service, an OIDC client application must be registered in the Pocket ID admin interface:
- Client ID: A unique identifier slug (e.g.
gitea,immich,paperless). - Client Secret: A cryptographically secure random token.
- Redirect URIs / Callback URLs: The exact target URLs the service exposes for authorization code callbacks.
- Scopes: Usually
openid,profile, andemail.
B. Secrets Management (agenix)
All client secrets should be encrypted with agenix under the respective service directory:
- Example:
platforms/nixos/modules/nmasur/presets/services/<service>/<service>-oidc.age - Defined in NixOS under
config.secrets.<service>-oidcwith appropriate owner/group permissions.
C. Network & Reverse Proxy (Caddy)
- Back-Channel Connectivity: When a user logs in, the service backend makes a server-to-server HTTPS call to
https://auth.masu.rs/api/oidc/tokento exchange the authorization code for tokens. Services hosted onswan(NAS) must be able to resolve and reachauth.masu.rsover HTTPS. - Proxy Headers: Caddy's
reverse_proxyhandlesX-Forwarded-Proto,X-Forwarded-Host, andX-Forwarded-Forby default. Services should have reverse proxy trust enabled (e.g.,trusted_proxies = ["127.0.0.1"]) so generated redirect URIs preserve thehttps://scheme.
3. Detailed Setup Requirements for Tier 1 Services
1. Immich (photos.masu.rs)
- Pocket ID Redirect URIs:
- Web:
https://photos.masu.rs/auth/login - Mobile:
app.immich:///oauth-callback
- Web:
- NixOS Configuration (
immich.nix):services.immich.settings.oauth = { enabled = true; issuerUrl = "https://auth.masu.rs"; clientId = "immich"; clientSecret = "..."; # or IMMICH_OAUTH_CLIENT_SECRET via environment file scope = "openid profile email"; autoRegister = true; buttonText = "Login with Pocket ID"; };
2. Gitea (git.masu.rs)
- Pocket ID Redirect URI:
https://git.masu.rs/user/oauth2/pocket-id/callback - Setup in Gitea:
Can be configured in the Web UI under Site Administration → Authentication Sources or via CLI:
gitea admin auth add-oauth \ --name "Pocket ID" \ --provider openidConnect \ --key "<client_id>" \ --secret "<client_secret>" \ --auto-discover-url "https://auth.masu.rs/.well-known/openid-configuration"- Optional: Enable automatic account linking by matching email.
3. Nextcloud (cloud.masu.rs)
- Pocket ID Redirect URI:
https://cloud.masu.rs/apps/user_oidc/code - Setup in
nextcloud/nextcloud.nix:- Add
user_oidctoservices.nextcloud.extraApps. - Configure the provider via
nextcloud-occ:nextcloud-occ user_oidc:provider pocket-id \ --clientid="<client_id>" \ --clientsecret="<client_secret>" \ --discoveryuri="https://auth.masu.rs/.well-known/openid-configuration" \ --scope="openid profile email"
- Add
4. Grafana (metrics.masu.rs)
- Pocket ID Redirect URI:
https://metrics.masu.rs/login/generic_oauth - Setup in
grafana/grafana.nix:services.grafana.settings = { auth.oauth_allow_insecure_email_lookup = true; "auth.generic_oauth" = { enabled = true; name = "Pocket ID"; allow_sign_up = true; client_id = "85d879ed-1a86-4984-b33d-43806500ef98"; client_secret = "$__file{${config.secrets.grafana-oidc-secret.dest}}"; scopes = "openid profile email"; auth_url = "https://${hostnames.auth}/authorize"; token_url = "https://${hostnames.auth}/api/oidc/token"; api_url = "https://${hostnames.auth}/api/oidc/userinfo"; login_attribute_path = "preferred_username"; skip_org_role_sync = true; }; };
5. Paperless-ngx (paper.masu.rs)
- Pocket ID Redirect URI:
https://paper.masu.rs/accounts/oidc/pocket-id/login/callback/ - Setup in
paperless/paperless.nix:services.paperless.settings = { PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect"; PAPERLESS_SOCIALACCOUNT_PROVIDERS = builtins.toJSON { openid_connect = { SERVERS = [ { id = "pocket-id"; name = "Pocket ID"; server_url = "https://auth.masu.rs"; token_auth_method = "client_secret_basic"; APP = { client_id = "paperless"; secret = "..."; # or via environmentFile }; } ]; }; }; PAPERLESS_REDIRECT_LOGIN_TO_SSO = "true"; # Optional: bypass local login };
6. Mealie (cooking.masu.rs)
- Pocket ID Redirect URI:
https://cooking.masu.rs/login - Setup in
mealie.nix:systemd.services.mealie.environment = { OIDC_AUTH_ENABLED = "true"; OIDC_SIGNUP_ENABLED = "true"; OIDC_CONFIGURATION_URL = "https://auth.masu.rs/.well-known/openid-configuration"; OIDC_CLIENT_ID = "mealie"; OIDC_CLIENT_SECRET = "..."; OIDC_PROVIDER_NAME = "Pocket ID"; OIDC_USER_CLAIM = "email"; };
7. Karakeep / Hoarder (keep.masu.rs)
- Pocket ID Redirect URI:
https://keep.masu.rs/api/auth/callback/custom - Setup in
karakeep.nix:services.karakeep.extraEnvironment = { OAUTH_WELLKNOWN_URL = "https://auth.masu.rs/.well-known/openid-configuration"; OAUTH_CLIENT_ID = "hoarder"; OAUTH_CLIENT_SECRET = "..."; OAUTH_PROVIDER_NAME = "Pocket ID"; OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING = "true"; };
8. Audiobookshelf (read.masu.rs)
- Pocket ID Redirect URIs:
- Web:
https://read.masu.rs/auth/openid/callback - Mobile:
audiobookshelf://oauth
- Web:
- Setup in Audiobookshelf:
Configured in the Web UI (Settings → Authentication → OpenID Connect):
- Issuer URL:
https://auth.masu.rs - Client ID & Client Secret
- Match user by email or username
- Issuer URL:
9. Actual Budget (money.masu.rs)
- Pocket ID Redirect URI:
https://money.masu.rs/oauth/callback - Setup in
actualbudget/actualbudget.nix:Note: The optional end-to-end budget encryption password remains separate from the server authentication.services.actual.settings = { # Passed via environment or configuration ACTUAL_LOGIN_METHOD = "openid"; ACTUAL_OPENID_DISCOVERY_URL = "https://auth.masu.rs/.well-known/openid-configuration"; ACTUAL_OPENID_CLIENT_ID = "actual"; ACTUAL_OPENID_CLIENT_SECRET = "..."; ACTUAL_OPENID_SERVER_HOSTNAME = "https://money.masu.rs"; };
4. Forward Auth Architecture for Remaining Services
For services without native OIDC support (such as Calibre-Web, File Browser, Uptime Kuma, and the Arr stack), you can implement Forward Auth via Caddy:
- Deploy an authenticating proxy (such as OAuth2-Proxy or Authelia) configured with Pocket ID as its OIDC provider.
- Configure Caddy routes using the
forward_authdirective to verify user sessions with the proxy before forwarding requests to the target service. - For services supporting reverse proxy authentication (Calibre-Web and File Browser), Caddy injects identity headers (e.g.
Remote-User: noahorX-Forwarded-User: noah), enabling seamless single sign-on without requiring separate logins.