Reverse proxy authentication
Configuration
By default, reverse proxy authentication is disabled. To enable the feature, configure a trusted reverse proxy with the ReverseProxyWhitelist
option. This option takes a comma-separated list of either:
- An IPv4 or IPv6 range in CIDR notation.
- An
@
(at sign) when listening on a UNIX socket (see theAddress
option).
When enabled via the ReverseProxyWhitelist
option, Navidrome validates the requests’ source IP address against the ranges configured in ReverseProxyWhitelist
. If no range matches the address, reverse proxy authentication is not used even if the reverse proxy user header is present (see below), and falls back to a standard authentication mechanism. For requests received through a UNIX socket, IPs can’t be validated and Navidrome will use the reverse proxy user header if and only if ReverseProxyWhitelist
contains @
.
With reverse proxy authentication enabled, Navidrome gets the username of the authenticated user from incoming requests’ Remote-User
HTTP header. The header can be changed via the ReverseProxyUserHeader
configuration option.
If a user is successfully authenticated by the proxy but does not exist in the Navidrome DB, it will be created with a random password.
You might also be interested in the EnableUserEditing
option, which allows disabling the User page that lets users change their Navidrome password.
Sharing endpoint
If you plan to use the Sharing feature, where you can create unauthenticated links to parts of your library, you’ll need to whitelist the /share/*
URLs.
Subsonic endpoint
The subsonic endpoint also supports reverse proxy authentication, and will ignore the subsonic authentication parameters (u
, p
, t
and s
) if the reverse proxy user header is present. If the header is absent or has an empty value, Navidrome will fall back to the standard subsonic authentication scheme.
If your reverse proxy does not support the standard subsonic authentication scheme, or if the subsonic clients you want to use don’t support an alternate authentication mechanism also supported by your proxy (such as BasicAuth), you can still configure your proxy to bypass authentication on /rest/*
URLs and let Navidrome perform authentication for those requests. In that case, your users will have to update their (initially random) password in Navidrome, to use it with their subsonic client.
Note
Most reverse proxies and authentication services don’t support the subsonic authentication scheme out of the box.
A handful of clients claim to support BasicAuth (e.g. DSub and Symfonium on Android, and play:Sub on iOS), but even then it might not work as you expect (as it is not standardized by the subsonic specification): you will likely need to generate a subsonic error response instead of a proper BasicAuth authentication failure response. Otherwise, some clients might display an unexpected error such as “server unreachable” when the credentials are incorrect, and other clients might refuse to connect altogether even with valid credentials.
Navidrome Web App
The Navidrome web app uses a mix of internal and subsonic APIs, and receives subsonic credentials from the server to use for requests against the subsonic API. As the credentials received from the server likely won’t match those in your dedicated authentication service, you need to handle subsonic requests from the Navidrome web app (identified as the subsonic client NavidromeUI
via the c
query parameter) in a special way. You can either:
- Ignore the subsonic authentication parameters and authenticate those requests the same way as non-subsonic requests. This relies on the fact that requests to the subsonic API will look the same to the proxy as requests to the internal API (e.g. same session cookies).
- Bypass authentication on your proxy for those requests and let Navidrome handle it. This relies on the fact that the web app receives the subsonic credentials from the server when it loads, and it can load only if the proxy has already authenticated the user.
Note that if you don’t intend to support third-party subsonic clients, you can simply place the subsonic endpoint behind the same protection rule as the rest of the application, i.e. you don’t need any special handling to bypass authentication.
Security
Make sure to check the reverse proxy authentication section in the dedicated Security Considerations page.
Examples
For the examples below, it is assumed that you are familiar with the various products in use, i.e. reverse proxy, authentication service but also Navidrome.
The examples focus on the integration between the products, and provide configuration snippets stripped down to the relevant parts, which you can adapt to the specifics of your deployment.
Caddy with forward_auth
In this example, Navidrome is behind the Caddy reverse proxy, and Authentik is used to authenticate requests, with the help of Caddy’s forward_auth middleware.
Caddyfile
excerpt stripped down to the relevant parts:
example.com
reverse_proxy /outpost.goauthentik.io/* http://authentik:9000
@protected not path /share/* /rest/*
forward_auth @protected http://authentik:9000 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers X-Authentik-Username>Remote-User
}
# Authentik uses the Authorization header if present, so should be able to
# authenticate subsonic clients that support BasicAuth. Requests from the
# Navidrome Web App will be authenticated via the existing session cookie.
# If you want to have Navidrome authenticate subsonic requests, remove this
# forward_auth block.
@subsonic path /rest/*
forward_auth @subsonic http://authentik:9000 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers X-Authentik-Username>Remote-User
# Some clients that claim to support basicauth still expect a subsonic
# response in case of authentication failure instead of a proper basicauth
# response.
@error status 1xx 3xx 4xx 5xx
handle_response @error {
respond <<SUBSONICERR
<subsonic-response xmlns="http://subsonic.org/restapi" status="failed" version="1.16.1" type="proxy-auth" serverVersion="n/a" openSubsonic="true">
<error code="40" message="Invalid credentials or unsupported client"></error>
</subsonic-response>
SUBSONICERR 200
}
}
reverse_proxy navidrome:4533
Note that if you want to whitelist the unprotected paths as part of your Authentik configuration instead of doing it in Caddy, the copy_headers
subdirective won’t work as expected: Authentik won’t set the X-Authentik-Username
header for whitelisted paths, but Caddy will still copy the header with an incorrect value. In order to make it work, you need a workaround:
forward_auth http://authentik:9000 {
uri /outpost.goauthentik.io/auth/caddy
# copy_headers subdirective removed
}
# Only set the Remote-User header if the request was actually authentified (user
# header set by Authentik), as opposed to whitelisted (user header not set).
@hasUsername `{http.reverse_proxy.header.X-Authentik-Username} != null`
request_header @hasUsername Remote-User {http.reverse_proxy.header.X-Authentik-Username}
Traefik with ForwardAuth
In this example, Navidrome is behind the Traefik reverse proxy, and Authelia is used to authenticate requests, with the help of Traefik’s ForwardAuth middleware. Each service has its own subdomain. Docker Compose is used to deploy the whole thing.
The error response rewriting for subsonic authentication failure is not implemented, which means that subsonic clients are expected to handle correctly BasicAuth error responses (HTTP 401 with WWW-Authenticate
header).
docker-compose.yml
excerpt stripped down to the relevant parts:
services:
authelia:
image: authelia/authelia:4.38.8
labels:
# The login page and user dashboard need to be reachable from the web
traefik.http.routers.authelia.rule: Host(`auth.example.com`)
traefik.http.routers.authelia.entrypoints: https
# Standard authentication middleware to be used by web services
traefik.http.middlewares.authelia.forwardauth.address: http://authelia:9091/api/verify?rd=https://auth.example.com/
traefik.http.middlewares.authelia.forwardauth.authResponseHeaders: Remote-User
# Basicauth middleware for subsonic clients
traefik.http.middlewares.authelia-basicauth.forwardauth.address: http://authelia:9091/api/verify?auth=basic
traefik.http.middlewares.authelia-basicauth.forwardauth.authResponseHeaders: Remote-User
navidrome:
image: deluan/navidrome:0.52.0
labels:
# Default rule which uses Authelia's web-based authentication. If you enable
# navidrome's Sharing feature, you can configure Authelia to bypass
# authentication for /share/* URLs, so you don't need an extra rule here.
traefik.http.routers.navidrome.rule: Host(`music.example.com`)
traefik.http.routers.navidrome.entrypoints: https
traefik.http.routers.navidrome.middlewares: authelia@docker
# Requests to the subsonic endpoint use the basicauth middleware, unless
# they come from the Navidrome Web App ("NavidromeUI" subsonic client), in
# which case the default authelia middleware is used.
traefik.http.routers.navidrome-subsonic.rule: Host(`music.example.com`) && PathPrefix(`/rest/`) && !Query(`c`, `NavidromeUI`)
traefik.http.routers.navidrome-subsonic.entrypoints: https
traefik.http.routers.navidrome-subsonic.middlewares: authelia-basicauth@docker
environment:
# Navidrome does not resolve hostnames in this option, and by default
# traefik will get assigned an IP address dynamically, so all IPs must be
# trusted.
# This means that any other service in the same docker network can make
# requests to navidrome, and easily impersonate an admin.
# If you assign a static IP to your traefik service, configure it here.
ND_REVERSEPROXYWHITELIST: 0.0.0.0/0
# Since authentication is entirely handled by Authelia, users don't need to
# manage their password in Navidrome anymore.
ND_ENABLEUSEREDITING: false
If you want to add support for the subsonic authentication scheme in order to support all subsonic clients, you can have a look at the Traefik plugin BasicAuth adapter for Subsonic which transforms subsonic authentication parameters into a BasicAuth header that Authelia can handle, and performs the error response rewriting.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can make it even better.
Sorry to hear that. Please tell us how we can improve.