Header Authentication
Header authentication lets Dashy trust a reverse proxy in front of it to handle login. The proxy authenticates the user, then passes their username to Dashy in an HTTP header. Dashy reads that header and signs them in automatically, so there's no separate Dashy login page.
Use this when you already run something like Authelia, Authentik, Traefik's forwardAuth, Caddy's forward_auth, or nginx's auth_request in front of your services, and you want Dashy to pick up the same session.
Contentsβ
Configure Dashyβ
In /user-data/conf.yml, set the auth block under appConfig:
appConfig:
auth:
enableHeaderAuth: true
users:
- user: alice
hash: 0a7b1d4c2e... # SHA-256 hash, see below
type: admin
- user: bob
hash: 3f8e2b1a9d...
type: normal
headerAuth:
userHeader: Remote-User
proxyWhitelist:
- 172.18.0.2
enableHeaderAuth- turns the mode onuserHeader- the header holding the username. Defaults toRemote-User. Authelia sendsRemote-User, Authentik sendsX-authentik-username; use whatever yours forwards. The name is case-insensitiveproxyWhitelist- the IP(s) Dashy will accept the header from. Anything not on this list is rejected, which is what stops a client from setting the header itself. Required in practice: if it's empty, nothing gets throughusers- the people allowed in. The forwarded username is matched (case-insensitive) against this list to find theirtype(adminornormal). They still need an entry here even though the proxy did the actual auth
The hash is a SHA-256 of any string. Nobody types it, since the proxy already logged them in, but Dashy uses it to derive the session token it keeps in the browser, so each user needs one. Generate it the same way as for built-in auth.
Configure your proxyβ
Two things the proxy has to do:
- Forward the username header on every request to Dashy (e.g.
Remote-User: alice). On most forward-auth setups this is a one-line setting - Connect to Dashy from an IP that's in
proxyWhitelist
The whitelist is the security boundary, so Dashy must only be reachable through the proxy. If someone can hit Dashy directly and their IP happens to be whitelisted, they can forge the header. See Security notes.
Troubleshootingβ
401 "Unauthorized - not from trusted proxy"β
The request reached Dashy from an IP that isn't in proxyWhitelist. The check is on the direct connection IP, so with Docker that's the proxy container's address on the shared network, not the host or the client's IP. Find it with docker inspect <proxy-container> (or read the rejected IP from Dashy's logs) and add it.
401 "Unauthorized - missing user header"β
The request came from a trusted IP but had no username header. Either the proxy isn't forwarding it, or userHeader doesn't match the header name the proxy actually sends. Check the exact header in your proxy config.
"User '...' from upstream proxy was not found in conf.yml"β
The proxy sent a username with no matching entry in auth.users. Add a user whose user matches it (case doesn't matter).
Logged in but can't save the configβ
That user's type isn't admin. Saving is admin-only, so set type: admin on their entry.
Logging out just logs me back inβ
Expected. Logout clears Dashy's cookie, but you're still signed in at the proxy, so the next page load re-authenticates from the header. To fully sign out, log out at the proxy.
Security notesβ
- Header auth is only as strong as the proxy in front of it. Dashy trusts any whitelisted IP that sends the header, so the whole model depends on Dashy being unreachable except through the proxy. Lock that down at the network or firewall level
- Keep
proxyWhitelisttight: just the proxy's real connecting IP(s), nothing broader - The username and role come from
conf.yml. A user the proxy authenticates but that you haven't listed is refused, so removing someone fromauth.usersblocks them even if the proxy still lets them through
How it worksβ
- The user hits Dashy through the proxy. The proxy authenticates them and adds the username header
- On load, Dashy's frontend calls
/get-user. The server checks the request IP againstproxyWhitelist, and if it's trusted, reads the username fromuserHeaderand returns it - The frontend looks that username up in
auth.users, derives a session token from the user and hash, sets the auth cookie, and stores the username - From there it's normal Dashy auth:
isLoggedIn, the admin check, and the per-page, section and item visibility rules all work as usual
Server-side, the same proxy-whitelist middleware guards the config and API routes, so a request from an untrusted IP is rejected before it reaches anything. Writes (saving config) additionally require the matched user to be type: admin.
The relevant code is src/utils/auth/HeaderAuth.js on the frontend, and services/app.js with services/get-user.js on the server.