Problema
Muchos usuarios que autohospedan Navidrome quieren evitar la gestión de credenciales locales y delegar la autenticación a un proveedor externo (por ejemplo, Authentik). El reto surge cuando el reverse proxy no está configurado para reenviar la información de sesión o cuando el flujo OAuth2 no se completa porque falta un contenedor de “auth‑proxy”. El síntoma típico es que Navidrome muestra la página de login pero nunca redirige al usuario, o que la cabecera X-User esperada por Navidrome está vacía.
Causa
- Ausencia de un endpoint de autorización – Authentik expone un endpoint
/application/o/authorize/que debe ser llamado por el proxy. Si el proxy solo hace passthrough, el flujo OAuth2 se rompe. - Cabeceras no propagadas – Navidrome necesita la cabecera
X-Forwarded-User(oX-User) con el nombre de usuario autenticado. NPMPlus, por defecto, no la agrega. - Configuración de cliente OAuth incompleta – En Authentik se debe crear una Application del tipo “OAuth2 Provider” y asociarla a un Provider que incluya los scopes
openid email profile. Sin estos scopes Authentik no envía los claims requeridos. - TLS/Redirect loops – Cuando el proxy fuerza HTTPS pero la URL de callback de Authentik está registrada como HTTP, Authentik rechaza la petición y Navidrome nunca recibe el token.
Solución
1. Preparar Authentik
- Crear un Provider → OAuth2/OpenID Connect → habilitar
openid,email,profile. Guardar el Client ID y Client Secret. - Crear una Application → tipo OAuth2 Provider → asignar el Provider anterior. En Redirect URIs colocar la URL que NPMPlus usará para recibir el código, por ejemplo:
https://navidrome.tudominio.com/_auth/callback - Activar la opción “Allow public clients” solo si no se quiere usar secret. En la mayoría de los setups se mantiene el secret.
2. Configurar Navidrome
En navidrome.toml habilitar la autenticación externa:
[auth]
method = "external"
externalHeader = "X-User"
externalUserHeader = "X-User"
Asegurarse de que listenaddr apunte al puerto que NPMPlus expondrá (por ejemplo 127.0.0.1:4533).
3. Configurar NPMPlus (Nginx Proxy Manager)
En NPMPlus crear un Proxy Host para Navidrome:
- Domain Names:
navidrome.tudominio.com - Scheme:
http - Forward Hostname / IP:
127.0.0.1 - Forward Port:
4533 - Block Common Exploits: activado
- SSL: Let’s Encrypt (auto‑renew)
3.1 Añadir Custom Nginx Configuration para OAuth2
En la pestaña Advanced pegar la siguiente configuración:
# Redirige a Authentik si no hay cabecera X-User
location / {
auth_request /auth;
error_page 401 = @error401;
proxy_set_header X-User $http_x_user;
proxy_pass http://127.0.0.1:4533;
}
# Endpoint interno que valida la sesión con Authentik
location = /auth {
internal;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Forwarded-Method $request_method;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass https://authentik.tudominio.com/application/o/authorize/;
proxy_set_header X-User $upstream_http_x_user;
}
# Redirección a la página de login de Authentik
location @error401 {
return 302 https://authentik.tudominio.com/application/o/authorize/?client_id=<<CLIENT_ID>>&response_type=code&scope=openid%20email%20profile&redirect_uri=https://navidrome.tudominio.com/_auth/callback;
}
Reemplazar <<CLIENT_ID>> por el ID obtenido en el paso 1.2. La URL de redirect_uri debe coincidir exactamente con la registrada en Authentik.
4. Manejar el callback
Navidrome no implementa nativamente el endpoint / _auth / callback. Se puede usar un contenedor ligero de oauth2-proxy (solo para el callback) o crear un pequeño script en Nginx que intercambie el código por un token y establezca la cabecera X-User. La solución más simple es desplegar oauth2-proxy en modo standalone:
docker run -d --name oauth2-proxy \
-p 4180:4180 \
-e OAUTH2_PROXY_CLIENT_ID=<<CLIENT_ID>> \
-e OAUTH2_PROXY_CLIENT_SECRET=<<CLIENT_SECRET>> \
-e OAUTH2_PROXY_PROVIDER=oidc \
-e OAUTH2_PROXY_OIDC_ISSUER_URL=https://authentik.tudominio.com/application/o/ \
-e OAUTH2_PROXY_COOKIE_SECRET=$(openssl rand -base64 32) \
-e OAUTH2_PROXY_EMAIL_DOMAINS=* \
-e OAUTH2_PROXY_UPSTREAMS=http://127.0.0.1:4533 \
-e OAUTH2_PROXY_HTTP_ADDRESS=0.0.0.0:4180 \
quay.io/oauth2-proxy/oauth2-proxy:latest
En NPMPlus, cambiar el Proxy Host para que apunte a http://127.0.0.1:4180 en vez de directamente a Navidrome. oauth2-proxy se encargará de:
- Recibir el
codeen/oauth2/callback. - Intercambiarlo por un token.
- Extraer el claim
emailopreferred_username. - Inyectar la cabecera
X-Usery reenviar la petición a Navidrome.
5. Ajustes de DNS y certificados
- Asegurarse de que los registros A/CNAME de
navidrome.tudominio.comyauthentik.tudominio.comapunten al mismo host donde corre NPMPlus. - Let’s Encrypt de NPMPlus gestiona los certificados automáticamente; sin embargo, si Authentik corre en otro contenedor, también necesita su propio certificado o confiar en el certificado de NPMPlus (añadiendo
proxy_ssl_trusted_certificate).
Cuándo aplicar esta solución
- Entorno mixto LXC + Docker: cuando Navidrome se ejecuta en un LXC sin Docker y Authentik o el auth‑proxy se despliegan en Docker.
- Necesidad de SSO: cuando varios servicios (p.ej., Navidrome, Gitea, Home Assistant) comparten la misma identidad de Authentik.
- Política de TLS centralizada: si se quiere que NPMPlus sea el único punto que termina TLS.
No es necesario si:
- Solo se usa autenticación local de Navidrome.
- El reverse proxy ya es Caddy o Traefik con soporte nativo de OAuth2; en ese caso la configuración de NPMPlus resulta redundante.
Código
# 1. Crear Provider en Authentik (CLI opcional)
docker exec -it authentik python3 manage.py create_provider \
--name navidrome-provider \
--type oauth2 \
--client-id $(openssl rand -hex 12) \
--client-secret $(openssl rand -hex 24) \
--scope "openid email profile"
# 2. Crear Application vinculada al Provider
docker exec -it authentik python3 manage.py create_application \
--name navidrome-app \
--provider navidrome-provider \
--redirect-uris "https://navidrome.tudominio.com/_auth/callback"
# 3. Lanzar oauth2-proxy (solo para callback)
docker run -d --name oauth2-proxy \
-p 4180:4180 \
-e OAUTH2_PROXY_CLIENT_ID=$(cat client_id.txt) \
-e OAUTH2_PROXY_CLIENT_SECRET=$(cat client_secret.txt) \
-e OAUTH2_PROXY_PROVIDER=oidc \
-e OAUTH2_PROXY_OIDC_ISSUER_URL=https://authentik.tudominio.com/application/o/ \
-e OAUTH2_PROXY_COOKIE_SECRET=$(openssl rand -base64 32) \
-e OAUTH2_PROXY_UPSTREAMS=http://127.0.0.1:4533 \
quay.io/oauth2-proxy/oauth2-proxy:latest
Verificación
- Acceder a
https://navidrome.tudominio.com. - Debería redirigirte automáticamente a la página de login de Authentik.
- Tras autenticarse, Authentik redirige a
/ _auth / callback,oauth2-proxyintercambia el código y envía la petición a Navidrome con la cabeceraX-User. - Navidrome muestra la interfaz principal sin pedir credenciales locales.
- Revisar los logs de NPMPlus (
docker logs npmplus) y deoauth2-proxypara confirmar que no aparecen errores 401/403.
Notas adicionales
- En entornos LXC, el firewall interno puede bloquear el puerto 4180; abrirlo con `lxc config device