Skip to content

WARNING

Proxy authentication is dangerously powerful. If misconfigured, it can allow anyone to impersonate users and gain access to Headtower.

It is recommended to use Headtower's built-in SSO integrations over proxy authentication if possible. No guarantees are made about the security of proxy authentication.

Proxy Authentication

Proxy authentication lets Headtower delegate user authentication to a trusted reverse proxy. This is useful when Headtower is already protected by middleware such as nginx basic auth, Authelia, Authentik, or another SSO-aware proxy and you do not want users to log in to Headtower separately.

Proxy authentication is intentionally opt-in and requires headscale.api_key. When enabled, Headtower trusts identity headers only on requests whose client IP matches server.proxy_auth.allowed_cidrs; all Headscale API calls then use the configured headscale.api_key.

Basic Configuration

yaml
headscale:
  api_key: "<your-headscale-api-key>"

server:
  proxy_auth:
    enabled: true
    user_header: "Remote-User"
    email_header: "Remote-Email"
    name_header: "Remote-Name"
    allowed_cidrs:
      - "127.0.0.1/32"
      - "::1/128"

user_header is required for a request to authenticate and defaults to Remote-User. The value becomes the stable proxy identity in Headtower as proxy:<value>. email_header, name_header, and picture_header are optional profile metadata headers.

The first proxy-authenticated user is created as the Headtower owner, matching the normal SSO first-user behavior. Subsequent users are created as members and can be reassigned from the Users page.

Client IP Checks

If allowed_cidrs is omitted, Headtower trusts only localhost. By default, this CIDR check uses the socket address connected to Headtower, not X-Forwarded-For, X-Real-IP, or other forwarded headers. Configure allowed_cidrs for the direct address range your proxy uses to connect to Headtower.

Forwarded Client IP Headers

If you need to check the original client IP from a proxy header, set ip_header to X-Forwarded-For, X-Real-IP, or another header your proxy controls. When ip_header is set, Headtower only reads that header if the direct socket peer matches trusted_proxy_cidrs (default localhost). The first IP in the header is then checked against allowed_cidrs:

yaml
server:
  proxy_auth:
    enabled: true
    ip_header: "X-Forwarded-For"
    trusted_proxy_cidrs:
      - "127.0.0.1/32"
    allowed_cidrs:
      - "10.0.0.0/8"

WARNING

Only enable proxy authentication when Headtower is not directly reachable by untrusted clients. Anyone who can connect to Headtower from an allowed CIDR will be able to spoof the configured identity headers. Only configure ip_header for headers set or overwritten by your trusted reverse proxy.

Header Reference

FieldDescription
server.proxy_auth.enabledEnables proxy authentication.
server.proxy_auth.user_headerHeader containing the stable authenticated user identity. Defaults to Remote-User.
server.proxy_auth.email_headerOptional header containing the authenticated user's email address.
server.proxy_auth.name_headerOptional header containing the authenticated user's display name.
server.proxy_auth.picture_headerOptional header containing the authenticated user's profile picture URL.
server.proxy_auth.allowed_cidrsClient CIDRs allowed to authenticate. Defaults to localhost.
server.proxy_auth.ip_headerOptional original-client-IP header such as X-Forwarded-For or X-Real-IP.
server.proxy_auth.trusted_proxy_cidrsDirect proxy CIDRs trusted to supply ip_header. Defaults to localhost.