amir20/dozzle · error
Unauthorized user
Error message
Unauthorized user
What it means
In forward-proxy auth mode, executeTemplate requires the authenticating proxy to inject Remote-Email, Remote-User, and Remote-Name headers. When none are present the request is rejected with 401 "Unauthorized user" because Dozzle cannot identify the user.
Solutions
- Access Dozzle only through the authenticating reverse proxy, not its exposed port.
- Configure the proxy to forward Remote-Email, Remote-User, and Remote-Name headers.
- Re-authenticate with the proxy provider if the session expired.
Example fix
# before (nginx, no headers) proxy_pass http://dozzle:8080; # after proxy_set_header Remote-User $remote_user; proxy_set_header Remote-Email $remote_user@example.com; proxy_set_header Remote-Name $remote_user; proxy_pass http://dozzle:8080;
Defensive patterns
Strategy: validation
Validate before calling
// client-side: detect the 401 and redirect through the proxy login
const res = await fetch('/', { redirect: 'manual' });
if (res.status === 401) location.href = '/login-path-of-your-proxy'; Prevention
- Never expose Dozzle's port directly; route all traffic through the auth proxy.
- Verify the proxy forwards Remote-User, Remote-Email, Remote-Name headers.
- Check proxy logs when 401s cluster around session expiry.
When it happens
Trigger: Accessing any Dozzle page through a forward-proxy setup where the proxy does not set the Remote-* headers (unauthenticated request, misconfigured authelia/authentik bypass, direct access bypassing the proxy).
Common situations: Reaching Dozzle directly on its port instead of through the auth proxy; proxy configured but its forwarded header names customized without mapping; auth provider session expired and proxy let the request through unauthenticated.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07).
Data as JSON: /api/errors/7e456d9de55a7a16.
Report an issue: GitHub.
Appendix: source
Thrown at internal/web/index.go:80
func (h *handler) executeTemplate(w http.ResponseWriter, req *http.Request) {
base := ""
if h.config.Base != "/" {
base = h.config.Base
}
user := auth.UserFromContext(req.Context())
// Handle unauthorized cases early
if user == nil {
switch h.config.Authorization.Provider {
case FORWARD_PROXY:
log.Error().Msg("Unable to find remote user. Please check your proxy configuration. Expecting headers Remote-Email, Remote-User, Remote-Name.")
log.Debug().Str("url", req.URL.String()).Msg("Dumping all headers for request")
for k, v := range req.Header {
log.Debug().Strs(k, v).Send()
}
http.Error(w, "Unauthorized user", http.StatusUnauthorized)
return
case SIMPLE:
if req.URL.Path != "login" {
log.Debug().Str("url", req.URL.String()).Msg("Redirecting to login page")
http.Redirect(w, req, path.Clean(h.config.Base+"/login")+"?redirectUrl=/"+req.URL.String(), http.StatusTemporaryRedirect)
return
}
}
}
config := map[string]any{
"base": base,
}
// Build full config when authorized (no auth or authenticated user)
if h.config.Authorization.Provider == NONE || user != nil {
hosts := h.hostService.Hosts()
sort.Slice(hosts, func(i, j int) bool {View on GitHub (pinned to d9463cbe21)