mirror of
https://github.com/tale/headplane.git
synced 2026-07-26 07:48:14 +00:00
feat(auth): support reverse-proxy driven proxy auth
Closes HP-353.
This commit is contained in:
@@ -50,7 +50,11 @@ export default defineConfig({
|
||||
{
|
||||
text: "Features",
|
||||
items: [
|
||||
{ text: "Single Sign-On (SSO)", link: "/features/sso" },
|
||||
{
|
||||
text: "Single Sign-On (SSO)",
|
||||
link: "/features/sso",
|
||||
items: [{ text: "Proxy Authentication", link: "/features/proxy-auth" }],
|
||||
},
|
||||
{ text: "Headplane Agent", link: "/features/agent" },
|
||||
{ text: "Browser SSH", link: "/features/ssh" },
|
||||
],
|
||||
|
||||
@@ -350,3 +350,82 @@ _Description:_ The port to listen on.
|
||||
_Type:_ 16 bit unsigned integer; between 0 and 65535 (both inclusive)
|
||||
|
||||
_Default:_ `3000`
|
||||
|
||||
## settings.server.proxy_auth
|
||||
|
||||
_Description:_ Proxy authentication configuration.
|
||||
|
||||
_Type:_ submodule
|
||||
|
||||
_Default:_ `{ }`
|
||||
|
||||
## settings.server.proxy_auth.allowed_cidrs
|
||||
|
||||
_Description:_ Direct client CIDR ranges allowed to bypass Headplane's login flow.
|
||||
These should be the addresses your trusted reverse proxy uses to connect
|
||||
to Headplane. Requires headscale.api_key_path.
|
||||
|
||||
_Type:_ list of string
|
||||
|
||||
_Default:_ `[ "127.0.0.1/32" "::1/128" ]`
|
||||
|
||||
_Example:_ `[ "10.0.0.0/24" ]`
|
||||
|
||||
## settings.server.proxy_auth.email_header
|
||||
|
||||
_Description:_ Optional header containing the authenticated user's email address.
|
||||
|
||||
_Type:_ null or string
|
||||
|
||||
_Default:_ `null`
|
||||
|
||||
## settings.server.proxy_auth.enabled
|
||||
|
||||
_Description:_ Whether to trust reverse proxy authentication for allowed client CIDRs.
|
||||
|
||||
_Type:_ boolean
|
||||
|
||||
_Default:_ `false`
|
||||
|
||||
## settings.server.proxy_auth.ip_header
|
||||
|
||||
_Description:_ Optional header containing the original client IP, such as X-Forwarded-For or X-Real-IP.
|
||||
|
||||
_Type:_ null or string
|
||||
|
||||
_Default:_ `null`
|
||||
|
||||
## settings.server.proxy_auth.name_header
|
||||
|
||||
_Description:_ Optional header containing the authenticated user's display name.
|
||||
|
||||
_Type:_ null or string
|
||||
|
||||
_Default:_ `null`
|
||||
|
||||
## settings.server.proxy_auth.picture_header
|
||||
|
||||
_Description:_ Optional header containing the authenticated user's profile picture URL.
|
||||
|
||||
_Type:_ null or string
|
||||
|
||||
_Default:_ `null`
|
||||
|
||||
## settings.server.proxy_auth.user_header
|
||||
|
||||
_Description:_ Header containing the stable authenticated proxy user identity.
|
||||
|
||||
_Type:_ string
|
||||
|
||||
_Default:_ `"Remote-User"`
|
||||
|
||||
## settings.server.proxy_auth.trusted_proxy_cidrs
|
||||
|
||||
_Description:_ Direct proxy CIDR ranges trusted to supply ip_header.
|
||||
Only used when ip_header is set.
|
||||
|
||||
_Type:_ list of string
|
||||
|
||||
_Default:_ `[ "127.0.0.1/32" "::1/128" ]`
|
||||
|
||||
_Example:_ `[ "127.0.0.1/32" ]`
|
||||
|
||||
@@ -58,8 +58,8 @@ The following configuration options in Headplane are treated as secret paths:
|
||||
- _Note:_ Either `cookie_secret` or `cookie_secret_path` must be provided for web session security.
|
||||
|
||||
- **Headscale Connection Settings (`headscale.*`):**
|
||||
- `api_key_path` (Headscale API key for server-side operations like OIDC and agent sync)
|
||||
- _Note:_ Either `api_key` or `api_key_path` must be provided when using OIDC or the agent.
|
||||
- `api_key_path` (Headscale API key for server-side operations like OIDC, proxy authentication, and agent sync)
|
||||
- _Note:_ Either `api_key` or `api_key_path` must be provided when using OIDC, proxy authentication, or the agent.
|
||||
- `tls_cert_path` (custom TLS certificate for connecting to Headscale)
|
||||
- _Note:_ This is treated as a regular path, not a secret path, so it will not have its content loaded.
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
title: Proxy Authentication
|
||||
description: Delegate Headplane authentication to a trusted reverse proxy.
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
:::warning
|
||||
Proxy authentication is **dangerously powerful**. If misconfigured, it can allow
|
||||
anyone to impersonate users and gain access to Headplane.
|
||||
|
||||
It is recommended to use Headplane'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 Headplane delegate user authentication to a trusted
|
||||
reverse proxy. This is useful when Headplane 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 Headplane separately.
|
||||
|
||||
Proxy authentication is intentionally opt-in and requires `headscale.api_key`.
|
||||
When enabled, Headplane 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 Headplane as
|
||||
`proxy:<value>`. `email_header`, `name_header`, and `picture_header` are
|
||||
optional profile metadata headers.
|
||||
|
||||
The first proxy-authenticated user is created as the Headplane 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, Headplane trusts only localhost. By default, this
|
||||
CIDR check uses the socket address connected to Headplane, 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
|
||||
Headplane.
|
||||
|
||||
## 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, Headplane 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 Headplane is not directly reachable by
|
||||
untrusted clients. Anyone who can connect to Headplane 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
|
||||
|
||||
| Field | Description |
|
||||
| --------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
| `server.proxy_auth.enabled` | Enables proxy authentication. |
|
||||
| `server.proxy_auth.user_header` | Header containing the stable authenticated user identity. Defaults to `Remote-User`. |
|
||||
| `server.proxy_auth.email_header` | Optional header containing the authenticated user's email address. |
|
||||
| `server.proxy_auth.name_header` | Optional header containing the authenticated user's display name. |
|
||||
| `server.proxy_auth.picture_header` | Optional header containing the authenticated user's profile picture URL. |
|
||||
| `server.proxy_auth.allowed_cidrs` | Client CIDRs allowed to authenticate. Defaults to localhost. |
|
||||
| `server.proxy_auth.ip_header` | Optional original-client-IP header such as `X-Forwarded-For` or `X-Real-IP`. |
|
||||
| `server.proxy_auth.trusted_proxy_cidrs` | Direct proxy CIDRs trusted to supply `ip_header`. Defaults to localhost. |
|
||||
@@ -17,6 +17,9 @@ Identity Provider (IdP) using the OpenID Connect (OIDC) protocol. When enabled,
|
||||
users sign in through your IdP and Headplane automatically links them to their
|
||||
Headscale identity, assigns a role, and manages their session.
|
||||
|
||||
If your reverse proxy already performs authentication and can pass trusted user
|
||||
headers to Headplane, see [Proxy Authentication](./proxy-auth.md) instead.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Requirements
|
||||
|
||||
Reference in New Issue
Block a user