diff --git a/content/docs/manage/blueprints.mdx b/content/docs/manage/blueprints.mdx index 3b1011e..cfd2159 100644 --- a/content/docs/manage/blueprints.mdx +++ b/content/docs/manage/blueprints.mdx @@ -217,9 +217,10 @@ public-resources: full-domain: app.example.com host-header: app.internal tls-server-name: app.internal + forward-identity-headers: true response-headers: - name: Access-Control-Allow-Origin - value: * + value: "*" rules: - action: allow match: country @@ -282,6 +283,55 @@ public-resources: When a resource is targets-only, `name` and `mode` are not required. +### Load Balancing Example + +When a resource has more than one target, `load-balancing-strategy` controls how requests are spread across them. + +```yaml +public-resources: + app: + name: App + mode: http + full-domain: app.example.com + load-balancing-strategy: hrw + targets: + - site: site-a + hostname: app + port: 8080 + method: http + - site: site-b + hostname: app + port: 8080 + method: http +``` + +Strategy values: + +- **`wrr`** (default): Round robin. Requests rotate evenly across targets. +- **`p2c`**: Power of two choices. Pangolin picks two random targets and sends the request to the one with fewer active connections. +- **`hrw`**: Client IP hash. The same client IP is consistently routed to the same target. +- **`leasttime`**: Least response time. Requests go to the target with the fastest response time and fewest active connections. + +### Identity Headers Example + +By default, Pangolin forwards the authenticated user's identity to the backend in the `Remote-User`, `Remote-Email`, `Remote-Name`, `Remote-Role`, and `Remote-User-Id` headers. Set `forward-identity-headers: false` to stop sending them, for example when the backend should not see user details. See [Forwarded Headers](/manage/access-control/forwarded-headers). + +```yaml +public-resources: + app: + name: App + mode: http + full-domain: app.example.com + forward-identity-headers: false + auth: + sso-enabled: true + targets: + - site: my-site + hostname: app + port: 8080 + method: http +``` + ### Authentication Example Authentication is configured inside `auth` and is supported only for HTTP resources. @@ -307,6 +357,42 @@ public-resources: - admin@example.com ``` +### Mutual TLS (mTLS) **(EE)** + +Set `auth.mtls` to require clients to present a TLS client certificate signed by one of the trusted CAs you list. mTLS is only supported on `http` resources, and `ssl` must not be set to `false`. + +```yaml +public-resources: + internal-api: + name: Internal API + mode: http + full-domain: api.example.com + auth: + mtls: + enabled: true + ca-certificates: + - | + -----BEGIN CERTIFICATE----- + MIIBszCCAVmgAwIBAgIU... + -----END CERTIFICATE----- + targets: + - site: my-site + hostname: api + port: 8080 + method: http +``` + +- Each `ca-certificates` entry is a PEM-encoded CA certificate. An entry can also be a bundle of several certificates; Pangolin splits it and removes duplicates. +- Only public CA certificates are accepted. An entry that contains a private key is rejected. +- A resource can trust up to 20 CA certificates. +- When `ca-certificates` is set, it replaces the full list of trusted CAs on each apply. When it is omitted, the existing CAs are left as they are. +- `enabled: true` requires at least one entry in `ca-certificates`. +- `mtls` can also be set on a [resource policy](#resource-policy-object-public-policies) so every resource using that policy shares the same trusted CAs. + + +A top-level `mtls` key on the resource is still accepted for backward compatibility. Put it under `auth` in new blueprints. + + ### Maintenance Page **(EE)** The `maintenance` object lets you present a maintenance page for a public HTTP resource. @@ -664,24 +750,36 @@ public-resources: - production host-header: internal.example.local tls-server-name: internal.example.local + forward-identity-headers: true + load-balancing-strategy: wrr request-headers: - name: X-Env value: prod response-headers: - name: Access-Control-Allow-Origin - value: * + value: "*" rules: - action: allow match: country value: US - action: deny match: region - value: 019 + value: "019" + - action: deny + match: method + value: DELETE auth: pincode: 123456 sso-enabled: true whitelist-users: - admin@example.com + mtls: + enabled: true + ca-certificates: + - | + -----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE----- maintenance: enabled: true type: automatic @@ -698,6 +796,8 @@ public-resources: hostname: app port: 8080 path: /health + healthy-threshold: 2 + unhealthy-threshold: 3 ``` @@ -907,6 +1007,30 @@ public-resources: Container label: `pangolin.public-resources.web-app.tls-server-name=internal.example.local` + + Forwards the authenticated user's identity to the backend in the `Remote-User`, `Remote-Email`, `Remote-Name`, `Remote-Role`, and `Remote-User-Id` headers. Set to `false` to stop sending them. See [Forwarded Headers](/manage/access-control/forwarded-headers). + + **Default**: `true` + + YAML: `forward-identity-headers: false` + Container label: `pangolin.public-resources.web-app.forward-identity-headers=false` + + + + How requests are distributed across the resource's targets. + + - `wrr`: Round robin. Requests rotate evenly across targets. + - `p2c`: Power of two choices. Pick two random targets and send the request to the one with fewer active connections. + - `hrw`: Client IP hash. The same client IP is consistently routed to the same target. + - `leasttime`: Least response time. Send requests to the target with the fastest response time and fewest active connections. + + **Options**: `wrr`, `p2c`, `hrw`, `leasttime` + **Default**: `wrr` + + YAML: `load-balancing-strategy: hrw` + Container label: `pangolin.public-resources.web-app.load-balancing-strategy=hrw` + + Static headers added to proxied requests. @@ -961,6 +1085,14 @@ public-resources: Deprecated alias for `request-headers`. + + Deprecated alias for `request-headers`. + + + + Deprecated alias for `response-headers`. + + Ordered access rules for public resources. @@ -982,14 +1114,16 @@ public-resources: Match type for the rule. - **Options**: `cidr`, `path`, `ip`, `country`, `asn`, `region` + **Options**: `cidr`, `path`, `ip`, `country`, `country_is_not`, `asn`, `region`, `method` + + `country_is_not` matches requests from any country except the one given. `method` matches the request's HTTP method. YAML: `match: country` Container label: `pangolin.public-resources.web-app.rules[0].match=country` - Value to compare against, such as an IP, CIDR, path, two letter country code, ASN, or region. + Value to compare against, such as an IP, CIDR, path, two letter country code, ASN, region, or a comma-separated list of HTTP methods (for example `POST,PUT`). YAML: `value: US` Container label: `pangolin.public-resources.web-app.rules[0].value=US` @@ -1142,9 +1276,38 @@ public-resources: + + + Mutual TLS settings **(EE)**. Requires clients to present a certificate signed by one of the trusted CAs. Only allowed when `mode: http`, and `ssl` must not be `false`. See [Mutual TLS (mTLS)](#mutual-tls-mtls-ee). + + YAML: `mtls: { enabled: true, ca-certificates: [...] }` + Container label: `pangolin.public-resources.web-app.auth.mtls.enabled=true` + + + + Turns mTLS on for the resource. Requires at least one entry in `ca-certificates`. + + YAML: `enabled: true` + Container label: `pangolin.public-resources.web-app.auth.mtls.enabled=true` + + + + PEM-encoded CA certificates that client certificates must chain to. An entry may contain a bundle of several certificates. Up to 20 certificates in total. When set, replaces the resource's trusted CAs; when omitted, the existing CAs are kept. + + Container labels for arrays must include an index (`[0]`, `[1]`, ...). + + YAML: `ca-certificates: ["-----BEGIN CERTIFICATE-----\n..."]` + Container label: `pangolin.public-resources.web-app.auth.mtls.ca-certificates[0]=-----BEGIN CERTIFICATE-----...` + + + + + Deprecated. Use `auth.mtls` instead. Same shape as `auth.mtls`. + + Maintenance page configuration for public resources **(EE)**. @@ -1371,6 +1534,20 @@ public-resources: Expected HTTP status code. + + + Number of consecutive successful checks before an unhealthy target is marked healthy again. + + **Minimum**: `1` + **Default**: `1` + + + + Number of consecutive failed checks before a healthy target is marked unhealthy. + + **Minimum**: `1` + **Default**: `1` + @@ -1649,6 +1826,8 @@ public-policies: match: country value: US enabled: true + mtls: + enabled: false ``` @@ -1725,6 +1904,20 @@ public-policies: Policy rule list using the same rule schema as public resource rules. + + + Mutual TLS settings **(EE)** shared by every resource that uses this policy. Same shape as `auth.mtls` on [public resources](#mutual-tls-mtls-ee). + + + + Turns mTLS on for the policy. Requires at least one entry in `ca-certificates`. + + + + PEM-encoded CA certificates that client certificates must chain to. Up to 20 certificates in total. When set, replaces the policy's trusted CAs; when omitted, the existing CAs are kept. + + + @@ -1745,6 +1938,7 @@ public-policies: 10. `alias` values must be unique across private resources in the blueprint. 11. `mode: inference` (public or private) requires `full-domain`, must not have `targets`, and is the only mode that may set `ai-providers`. 12. `ai-budget` entries on a resource must each use a unique `unit`/`period` combination. +13. When `auth.mtls.enabled` is `true`, the resource must use `mode: http`, must not set `ssl: false`, and must list at least one entry in `ca-certificates`. Policies with `mtls.enabled: true` also need at least one CA certificate. ### Common Validation Errors @@ -1819,3 +2013,15 @@ Each entry in `ai-budget` must use a distinct `unit`/`period` pair, such as one ### "'models' can only be set on a provider with access-mode 'select'" Set `models` only when the `ai-providers` entry uses `access-mode: select`. Entries using `access-mode: inherit` must leave `models` empty. + +### "mTLS is only supported when mode is 'http'" + +`auth.mtls` can only be enabled on HTTP public resources. + +### "mTLS requires 'ssl' to be enabled" + +Remove `ssl: false` from a resource that enables mTLS. Client certificates are checked during the TLS handshake. + +### "mTLS requires at least one entry in 'ca-certificates'" + +When `mtls.enabled` is `true` on a resource or policy, list at least one PEM-encoded CA certificate in `ca-certificates`.