immich: fix OIDC clientId, redirect logout to immich's own login page
clientId was still the placeholder "immich" instead of Authentik's actual generated id, and the sops secret it points at (immich_oauth_client_secret) was never declared on jupiter. Wire both up, and set endSessionEndpoint so logout lands back on immich instead of Authentik's "logged out" page.
This commit is contained in:
@@ -26,4 +26,12 @@
|
||||
# Headscale pre-auth key for tailscale auto-registration (see configuration.nix).
|
||||
sops.secrets.tailscale_authkey = { };
|
||||
|
||||
# Immich's OIDC client secret, from its Authentik application (a SEPARATE
|
||||
# app from headscale's and headplane's — see hosts/neptun/secrets.nix).
|
||||
# Referenced as settings.oauth.clientSecret._secret in
|
||||
# services/media/immich.nix; the module resolves it through systemd
|
||||
# LoadCredential, which reads as root before dropping privileges, so the
|
||||
# sops default of root:root 0400 is correct — do NOT set `owner`.
|
||||
sops.secrets.immich_oauth_client_secret = { };
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ mediamanager_token_secret: ENC[AES256_GCM,data:g75vj1E6B029O076yV3DS/1z99Tq6wMhE
|
||||
sabnzbd_api_key: ENC[AES256_GCM,data:6UW1u2Ikmnq34t4H4k/4C44SJeFHRlaPjWwUjEfH1GQ=,iv:sGsd8Sd2pfUhTUDg6PlRzfVYejRbF69jmDTIa2fvY4M=,tag:3fOLgU1K1gKHxQ3J1+3oRQ==,type:str]
|
||||
prowlarr_api_key: ENC[AES256_GCM,data:ab1QACaagI8ACJXFUy8r9X9lgYwRo1byUmhBPSRWwKk=,iv:EcuF6EN/4mWxlXi6R1qDzv4rOw6AT+OGSNQaaBwjJHg=,tag:hixHrbQWU6QQZNMM5rNDsg==,type:str]
|
||||
cinephage_better_auth_secret: ENC[AES256_GCM,data:S1ilcQeC2HmXe/4xdLi6wm5RNz954SL3qVur6JCn5ekBVCbXMd1DGCafjhU=,iv:9rS5gDuazMOAq/hWp0onvHZPzKJgQM3oWIrtplJN/9I=,tag:xNqf/unY2v/98p4v52vUqw==,type:str]
|
||||
immich_oauth_client_secret: ENC[AES256_GCM,data:+NbUnwImwFTYNjz3luzczpCf7oMetzYBkj5ZnuG2QQf0Wpm6OtYS3amTC8dwoh9F/DAos5224etncfEgEu2k2iMUACLADnlCGppIx0F7Gl1Ve7UF2VzKJ3xQpgCDrXklU+o5NxfU/YBn1Vfa3580wT3tr2++SCSrcKq1XGtfhv4=,iv:tjaPDQbrA6TxsDebgNOtO/ITfXzU5wTKU9SkfC0TQcY=,tag:AnlJR0tLExkB7Aeo/ZVTng==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- enc: |
|
||||
@@ -25,7 +26,7 @@ sops:
|
||||
CzjSDQZTcseEXZNwuzZcfB5Mvq0BQvjOj7lGuxzuE4qwWkdJWGfVLQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1zak7glavmg4026p2389fyqe769vqm4jrryknuqckgqq4merz5f7q44rkkt
|
||||
lastmodified: "2026-07-20T18:42:14Z"
|
||||
mac: ENC[AES256_GCM,data:l9O/KAd/5KfC+LXwE2y5+ybflyy9Xl0PikoRfcOzIFu+fVWESyi0D22emWen6J4mpvsXgjAp4GCu4RKNTGyy47mfkaHh/KdxozEOmP8VlKOJXtqzU9lTgZwhHqkF9RKsRLKHvmREugwzWnpplJ8J7bg5Z3llBIM36FlElzQ9hUw=,iv:x0lM9Ctcn1XCsXftB9Ze8WV8Rp4YA26MQ/AdGC78MyY=,tag:gtfaSDQAcAkngRw2Ph2N0A==,type:str]
|
||||
lastmodified: "2026-07-20T23:19:56Z"
|
||||
mac: ENC[AES256_GCM,data:rxpctVvQPZF5+ylUgg/5UVdI4MfkSf5W2S1aSR1y5Na1juebM0+1kPGkyZxybm/hPl42DjiOmXsJbGS/Kf3np/y3vcYGpooDqxqGciYZDLcijd0M3ErODbfLgxgtGIl5nBS6cGUnabqgXRVTJwmupE7WllcIk6QM20PhnIAHzVU=,iv:I33VvRBp8iv16pRw0PA9+WiIOITPHoziwQC24x/rDh0=,tag:0gMQlEd5CzoAeDlUx99lBg==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.13.1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ pkgs, inputs, ... }:
|
||||
{ config, pkgs, inputs, ... }:
|
||||
|
||||
# Immich photo/video library. Native nixpkgs module (not the upstream compose
|
||||
# stack) — it owns its own postgres (with the pgvector + vectorchord extensions
|
||||
@@ -41,6 +41,66 @@ in
|
||||
port = 2283;
|
||||
mediaLocation = "/mnt/data/AppData/immich";
|
||||
machine-learning.enable = true;
|
||||
|
||||
# ⚠️ Setting `settings` at all switches immich to IMMICH_CONFIG_FILE, and
|
||||
# that is ALL-OR-NOTHING (dist/utils/config.js: the config is
|
||||
# `configFile ? loadFromFile(...) : metadataRepo.get(SystemConfig)` — the
|
||||
# database copy is IGNORED, not merged). Two consequences:
|
||||
# 1. Anything not declared here falls back to immich's DEFAULTS, not to
|
||||
# whatever the admin UI had. The old settings stay in the
|
||||
# system_metadata table, so deleting this block restores them.
|
||||
# 2. The admin settings UI goes read-only — saving throws "Cannot update
|
||||
# configuration while IMMICH_CONFIG_FILE is in use". Change settings
|
||||
# HERE and redeploy.
|
||||
# An unknown/misspelled key is a HARD startup failure under a config file
|
||||
# (the same code path only logs a warning without one), so keys below are
|
||||
# taken verbatim from `defaults` in immich's dist/config.js.
|
||||
settings = {
|
||||
server.externalDomain = "https://immich.mgaction.town";
|
||||
newVersionCheck.enabled = false; # nixpkgs pins the version, not immich
|
||||
|
||||
# OIDC via Authentik on neptun. The Authentik application/provider is
|
||||
# created BY HAND in its UI — same as headscale's and headplane's, which
|
||||
# are also separate apps (hosts/neptun/secrets.nix). Only the client
|
||||
# secret is managed here.
|
||||
oauth = {
|
||||
enabled = true;
|
||||
# Authentik's per-application issuer. Trailing slash matters: immich
|
||||
# appends /.well-known/openid-configuration to it.
|
||||
issuerUrl = "https://auth.mgaction.town/application/o/immich/";
|
||||
# Authentik generates this; not a secret (it is sent in the browser
|
||||
# redirect), so it lives here rather than in sops.
|
||||
clientId = "FxrkWFe8keBrN83tu03UbAshSck52he2GphJDYSQ";
|
||||
# Read at runtime via systemd LoadCredential — never lands in the
|
||||
# world-readable /nix/store copy of the rendered config.
|
||||
clientSecret._secret = config.sops.secrets.immich_oauth_client_secret.path;
|
||||
scope = "openid email profile";
|
||||
buttonText = "Login with Authentik";
|
||||
# Existing accounts (the 2 imported users) keep working: matching is by
|
||||
# email, so an Authentik user with the same address adopts that account
|
||||
# rather than creating a second one.
|
||||
autoRegister = true;
|
||||
# Leave the password form reachable — autoLaunch would bounce straight
|
||||
# to Authentik, locking everyone out if the OIDC app is misconfigured.
|
||||
autoLaunch = false;
|
||||
# Land back on immich's own login page after logout. Without this,
|
||||
# immich falls back to the IdP's discovered end_session_endpoint
|
||||
# (auth.service.js:320-326) and logout dumps you on Authentik's
|
||||
# "you've been logged out" page instead. Must be an ABSOLUTE url —
|
||||
# the config schema rejects a relative path — and mirrors immich's
|
||||
# internal LOGIN_URL, including autoLaunch=0.
|
||||
#
|
||||
# Note this ends the IMMICH session only; the Authentik SSO session
|
||||
# survives, so the next "Login with Authentik" click signs straight
|
||||
# back in without a credential prompt. To end both, drop this line and
|
||||
# let the IdP endpoint take over again.
|
||||
endSessionEndpoint = "https://auth.mgaction.town/application/o/immich/end-session?post_logout_redirect_url=https://immich.mgaction.town";
|
||||
# The mobile app can't follow a browser redirect back to a custom
|
||||
# scheme through Authentik, so immich bounces it via this endpoint.
|
||||
mobileOverrideEnabled = true;
|
||||
mobileRedirectUri = "https://immich.mgaction.town/api/oauth/mobile-redirect";
|
||||
};
|
||||
};
|
||||
# Hardware transcoding would need the iGPU passed in explicitly, e.g.
|
||||
# accelerationDevices = [ "/dev/dri/renderD128" ]; the default [ ] means
|
||||
# PrivateDevices=yes and CPU-only transcode. The ZimaBlade's Celeron does
|
||||
|
||||
Reference in New Issue
Block a user