mirror of
https://github.com/fosrl/docs-v2.git
synced 2026-10-13 16:19:09 +02:00
1138 lines
36 KiB
Plaintext
1138 lines
36 KiB
Plaintext
---
|
|
title: "Definition"
|
|
description: "Define Pangolin resources and site settings declaratively with YAML or container labels"
|
|
---
|
|
|
|
import PangolinCloudTocCta from "/snippets/pangolin-cloud-toc-cta.mdx";
|
|
|
|
<PangolinCloudTocCta />
|
|
|
|
Blueprints let you define Pangolin resources as code. Instead of configuring every site, target, and access rule manually in the dashboard, you describe the desired state in YAML or container labels and let Pangolin apply it consistently.
|
|
|
|
Use blueprints when you want:
|
|
|
|
- Repeatable rollouts across many sites
|
|
- Version control for infrastructure and access settings
|
|
- A source of truth that can be reviewed, templated, and automated
|
|
|
|
<Note type="info">
|
|
Some features in this documentation are marked with **(EE)**, which means they require [Enterprise Edition](/self-host/enterprise-edition).
|
|
</Note>
|
|
|
|
## Blueprint Mental Model
|
|
|
|
A blueprint can contain up to three top-level sections:
|
|
|
|
- **`public-resources`**: Internet-facing HTTP, TCP, or UDP resources
|
|
- **`private-resources`**: Client-only access to hosts or CIDR ranges
|
|
- **`sites`**: Site-level settings such as container label discovery
|
|
|
|
```yaml
|
|
public-resources:
|
|
<resource_key>:
|
|
...
|
|
|
|
private-resources:
|
|
<resource_key>:
|
|
...
|
|
|
|
sites:
|
|
<site_key>:
|
|
...
|
|
```
|
|
|
|
Think of the resource key as your stable ID inside the blueprint. The fields under that key describe what Pangolin should create or maintain.
|
|
|
|
## Choose A Format
|
|
|
|
Pangolin supports two blueprint formats:
|
|
|
|
### YAML
|
|
|
|
Use YAML when you want a readable file that can be committed to git, applied through Newt, pasted into the UI, or sent through the API.
|
|
|
|
### Container Labels
|
|
|
|
Use container labels when the resource definition should live inside your Compose stack. This is especially useful when a container and its Pangolin resource should be managed together.
|
|
|
|
## How YAML Blueprints Are Applied
|
|
|
|
<Card title="UI">
|
|
Paste YAML into **Settings > Blueprints** in the Pangolin dashboard.
|
|
|
|
<Frame>
|
|
<img src="/images/create_blueprint.png" width="400" centered/>
|
|
</Frame>
|
|
</Card>
|
|
|
|
<Card title="Newt">
|
|
Run Newt with `--blueprint-file` to keep the file declarative and continuously applied:
|
|
|
|
```bash
|
|
newt --blueprint-file /path/to/blueprint.yaml <other-args>
|
|
```
|
|
|
|
If you only want a one-time bootstrap during provisioning, use [`--provisioning-blueprint-file`](/manage/sites/site-provisioning) instead.
|
|
</Card>
|
|
|
|
<Card title="API">
|
|
Apply a blueprint through the Pangolin API with an API key. See the [API documentation](https://api.pangolin.net/v1/docs/#/Organization/put_org__orgId__blueprint).
|
|
|
|
`PUT /org/{orgId}/blueprint`
|
|
|
|
```json
|
|
{
|
|
"blueprint": "base64-encoded-json-content"
|
|
}
|
|
```
|
|
|
|
[Python example](https://github.com/fosrl/pangolin/blob/dev/blueprint.py)
|
|
</Card>
|
|
|
|
<Card title="CLI">
|
|
If your Pangolin CLI build includes blueprint commands, you can apply a file directly:
|
|
|
|
```bash
|
|
pangolin apply blueprint --file /path/to/blueprint.yaml
|
|
```
|
|
</Card>
|
|
|
|
<Note>
|
|
`--blueprint-file` in Newt and container labels behave as an ongoing source of truth. Dashboard edits can be overwritten the next time the blueprint is applied. UI, API, and CLI applies are typically one-off operations.
|
|
</Note>
|
|
|
|
## Quick Start YAML Example
|
|
|
|
This example shows all three top-level sections in one file:
|
|
|
|
```yaml
|
|
public-resources:
|
|
web-app:
|
|
name: Web App
|
|
protocol: http
|
|
full-domain: app.example.com
|
|
auth:
|
|
sso-enabled: true
|
|
whitelist-users:
|
|
- admin@example.com
|
|
targets:
|
|
- site: my-site
|
|
hostname: app
|
|
port: 8080
|
|
method: http
|
|
healthcheck:
|
|
hostname: app
|
|
port: 8080
|
|
path: /health
|
|
|
|
private-resources:
|
|
ssh-host:
|
|
name: SSH Host
|
|
mode: host
|
|
site: my-site
|
|
destination: 192.168.1.10
|
|
tcp-ports: "22"
|
|
roles:
|
|
- DevOps
|
|
|
|
sites:
|
|
my-site:
|
|
name: My Site
|
|
docker-socket-enabled: true
|
|
```
|
|
|
|
## Public Resources
|
|
|
|
Public resources expose services through Pangolin.
|
|
|
|
- Use **`http`** for websites, APIs, and dashboards
|
|
- Use **`tcp`** or **`udp`** for raw public services bound to a port on the Pangolin server
|
|
|
|
### HTTP Resource Example
|
|
|
|
```yaml
|
|
public-resources:
|
|
app:
|
|
name: App
|
|
protocol: http
|
|
full-domain: app.example.com
|
|
host-header: app.internal
|
|
tls-server-name: app.internal
|
|
headers:
|
|
- name: X-Env
|
|
value: production
|
|
rules:
|
|
- action: allow
|
|
match: country
|
|
value: US
|
|
- action: deny
|
|
match: path
|
|
value: /admin
|
|
auth:
|
|
sso-enabled: true
|
|
whitelist-users:
|
|
- admin@example.com
|
|
targets:
|
|
- site: my-site
|
|
hostname: app
|
|
port: 8080
|
|
method: http
|
|
```
|
|
|
|
<Note>
|
|
When applying a blueprint via Newt (using `--blueprint-file` or container labels), `site` on each target is optional. If omitted, the target is assigned to the site of the Newt that applied the blueprint.
|
|
</Note>
|
|
|
|
### Raw TCP Or UDP Example
|
|
|
|
```yaml
|
|
public-resources:
|
|
mqtt:
|
|
name: Mosquitto MQTT
|
|
protocol: tcp
|
|
proxy-port: 1883
|
|
targets:
|
|
- site: my-site
|
|
hostname: mqtt-server
|
|
port: 1883
|
|
```
|
|
|
|
For raw resources:
|
|
|
|
- `proxy-port` is required
|
|
- Target `method` must not be set
|
|
- `auth` is not supported
|
|
|
|
### Targets-Only Resources
|
|
|
|
A public resource can contain only `targets`. This is useful when you want to add or manage targets for an existing resource definition without repeating all resource-level fields.
|
|
|
|
```yaml
|
|
public-resources:
|
|
extra-targets:
|
|
targets:
|
|
- site: secondary-site
|
|
hostname: app-2
|
|
port: 8080
|
|
method: http
|
|
- site: tertiary-site
|
|
hostname: app-3
|
|
port: 8080
|
|
method: http
|
|
```
|
|
|
|
When a resource is targets-only, `name` and `protocol` are not required.
|
|
|
|
### Authentication Example
|
|
|
|
Authentication is configured inside `auth` and is supported only for HTTP resources.
|
|
|
|
```yaml
|
|
public-resources:
|
|
secure-app:
|
|
name: Secure App
|
|
protocol: http
|
|
full-domain: secure.example.com
|
|
auth:
|
|
pincode: 123456
|
|
password: strong-password
|
|
basic-auth:
|
|
user: demo
|
|
password: change-me
|
|
sso-enabled: true
|
|
sso-roles:
|
|
- Member
|
|
sso-users:
|
|
- user@example.com
|
|
whitelist-users:
|
|
- admin@example.com
|
|
```
|
|
|
|
### Maintenance Page **(EE)**
|
|
|
|
The `maintenance` object lets you present a maintenance page for a public HTTP resource.
|
|
|
|
```yaml
|
|
public-resources:
|
|
app:
|
|
name: App
|
|
protocol: http
|
|
full-domain: app.example.com
|
|
maintenance:
|
|
enabled: true
|
|
type: automatic
|
|
title: Scheduled Maintenance
|
|
message: We are upgrading the service.
|
|
estimated-time: 2 hours
|
|
targets:
|
|
- site: my-site
|
|
hostname: app
|
|
port: 8080
|
|
method: http
|
|
```
|
|
|
|
Maintenance `type` values:
|
|
|
|
- **`forced`**: Always show the maintenance page
|
|
- **`automatic`**: Show it only when all targets are unhealthy or the sites are offline
|
|
|
|
## Private Resources
|
|
|
|
Private resources define what Pangolin clients can reach after they connect to your organization.
|
|
|
|
- Use **`mode: host`** for a single host or DNS name
|
|
- Use **`mode: cidr`** for an entire network range
|
|
|
|
<Note>
|
|
When applying a blueprint via Newt (using `--blueprint-file` or container labels), `site` is optional. If omitted, the resource is assigned to the site of the Newt that applied the blueprint.
|
|
</Note>
|
|
|
|
```yaml
|
|
private-resources:
|
|
internal-net:
|
|
name: Internal Network
|
|
mode: cidr
|
|
destination: 10.0.0.0/24
|
|
site: my-site
|
|
tcp-ports: "22,443,8000-9000"
|
|
udp-ports: "53,123"
|
|
disable-icmp: false
|
|
alias: "*.internal.example.com"
|
|
roles:
|
|
- Developer
|
|
users:
|
|
- user@example.com
|
|
machines:
|
|
- machine-id-1
|
|
```
|
|
|
|
## Container Labels Format
|
|
|
|
Container labels are the same blueprint schema flattened into dot-separated keys:
|
|
|
|
- Start every label with `pangolin.`
|
|
- Keep the same object path as YAML
|
|
- Use array indexes for lists, such as `[0]`
|
|
|
|
Example YAML:
|
|
|
|
```yaml
|
|
public-resources:
|
|
my-app:
|
|
headers:
|
|
- name: X-Env
|
|
value: prod
|
|
```
|
|
|
|
Equivalent Compose labels:
|
|
|
|
```yaml
|
|
labels:
|
|
- pangolin.public-resources.my-app.headers[0].name=X-Env
|
|
- pangolin.public-resources.my-app.headers[0].value=prod
|
|
```
|
|
|
|
<Note>
|
|
Container labels are continuously applied. Treat the Compose file as the source of truth because dashboard edits can be overwritten.
|
|
</Note>
|
|
|
|
### Enable Container Label Discovery
|
|
|
|
To use container labels, Newt must be able to read the Docker socket:
|
|
|
|
```bash
|
|
newt --docker-socket /var/run/docker.sock <other-args>
|
|
```
|
|
|
|
Or with an environment variable:
|
|
|
|
```bash
|
|
DOCKER_SOCKET=/var/run/docker.sock
|
|
```
|
|
|
|
### Docker Compose Example
|
|
|
|
```yaml
|
|
services:
|
|
newt:
|
|
image: fosrl/newt
|
|
container_name: newt
|
|
restart: unless-stopped
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
environment:
|
|
- PANGOLIN_ENDPOINT=https://app.pangolin.net
|
|
- NEWT_ID=h1rbsgku89wf9z3
|
|
- NEWT_SECRET=z7g54mbcwkglpx1aau9gb8mzcccoof2fdbs97keoakg2pp5z
|
|
- DOCKER_SOCKET=/var/run/docker.sock
|
|
|
|
nginx1:
|
|
image: nginxdemos/hello
|
|
container_name: nginx1
|
|
labels:
|
|
- pangolin.public-resources.nginx.name=nginx
|
|
- pangolin.public-resources.nginx.full-domain=nginx.fosrl.io
|
|
- pangolin.public-resources.nginx.protocol=http
|
|
- pangolin.public-resources.nginx.headers[0].name=X-Example-Header
|
|
- pangolin.public-resources.nginx.headers[0].value=example-value
|
|
- pangolin.public-resources.nginx.targets[0].method=http
|
|
- pangolin.public-resources.nginx.targets[0].path=/path
|
|
- pangolin.public-resources.nginx.targets[0].path-match=prefix
|
|
|
|
nginx2:
|
|
image: nginxdemos/hello
|
|
container_name: nginx2
|
|
labels:
|
|
- pangolin.public-resources.nginx.targets[1].method=http
|
|
- pangolin.public-resources.nginx.targets[1].hostname=nginx2
|
|
- pangolin.public-resources.nginx.targets[1].port=80
|
|
|
|
networks:
|
|
default:
|
|
name: pangolin_default
|
|
```
|
|
|
|
This creates a single Pangolin resource with multiple targets:
|
|
|
|
<Frame caption="Pangolin UI showing Docker Compose blueprint example">
|
|
<img src="/images/docker-compose-blueprint-example.png" alt="Example resource"/>
|
|
</Frame>
|
|
|
|
### Container Label Behavior
|
|
|
|
<Card title="Automatic Discovery">
|
|
If `hostname` or `port` are not set explicitly, Pangolin can detect them from the container configuration. The hostname typically defaults to the container name, and port detection is based on the container's `expose` configuration.
|
|
</Card>
|
|
|
|
<Card title="Site Assignment">
|
|
If no `site` is specified on a target (public resource) or on a private resource, it is assigned to the site of the Newt that applied the blueprint — whether through container labels or `--blueprint-file`.
|
|
</Card>
|
|
|
|
<Card title="Merged Configuration">
|
|
Labels from multiple containers can be merged into one logical resource, which is useful when different containers contribute different targets.
|
|
</Card>
|
|
|
|
## Configuration Reference
|
|
|
|
Use this section when you need the full schema. The order below mirrors the blueprint structure rather than the dashboard UI.
|
|
|
|
### Top-Level Object
|
|
|
|
```yaml
|
|
public-resources:
|
|
app:
|
|
name: App
|
|
protocol: http
|
|
full-domain: app.example.com
|
|
targets:
|
|
- hostname: app
|
|
port: 80
|
|
method: http
|
|
|
|
private-resources:
|
|
ssh-host:
|
|
name: SSH Host
|
|
mode: host
|
|
site: my-site
|
|
destination: 192.168.1.10
|
|
tcp-ports: "22"
|
|
|
|
sites:
|
|
my-site:
|
|
name: My Site
|
|
docker-socket-enabled: true
|
|
```
|
|
|
|
<Expandable title="Top-level object reference">
|
|
<ResponseField name="public-resources" type="object">
|
|
Public proxy resources keyed by resource ID.
|
|
|
|
YAML: `public-resources: { web-app: { ... } }`
|
|
Container label: `pangolin.public-resources.web-app.name=Web App`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="private-resources" type="object">
|
|
Private resources keyed by resource ID.
|
|
|
|
YAML: `private-resources: { internal-net: { ... } }`
|
|
Container label: `pangolin.private-resources.internal-net.mode=cidr`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="sites" type="object">
|
|
Site-level settings keyed by site ID.
|
|
|
|
YAML: `sites: { my-site: { name: My Site } }`
|
|
Container label: `pangolin.sites.my-site.name=My Site`
|
|
|
|
<Expandable title="Site object">
|
|
<ResponseField name="name" type="string" required>
|
|
Display name for the site.
|
|
|
|
YAML: `name: My Site`
|
|
Container label: `pangolin.sites.my-site.name=My Site`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="docker-socket-enabled" type="boolean">
|
|
Enables blueprint discovery from container labels for that site.
|
|
|
|
**Default**: `true`
|
|
|
|
YAML: `docker-socket-enabled: true`
|
|
Container label: `pangolin.sites.my-site.docker-socket-enabled=true`
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
</Expandable>
|
|
|
|
### Public Resource Object (`public-resources`)
|
|
|
|
```yaml
|
|
public-resources:
|
|
web-app:
|
|
name: Web App
|
|
protocol: http
|
|
full-domain: app.example.com
|
|
enabled: true
|
|
host-header: internal.example.local
|
|
tls-server-name: internal.example.local
|
|
headers:
|
|
- name: X-Env
|
|
value: prod
|
|
rules:
|
|
- action: allow
|
|
match: country
|
|
value: US
|
|
- action: deny
|
|
match: region
|
|
value: 019
|
|
auth:
|
|
pincode: 123456
|
|
sso-enabled: true
|
|
whitelist-users:
|
|
- admin@example.com
|
|
maintenance:
|
|
enabled: true
|
|
type: automatic
|
|
targets:
|
|
- site: my-site
|
|
hostname: app
|
|
port: 8080
|
|
method: http
|
|
path: /
|
|
path-match: prefix
|
|
rewrite-path: /
|
|
rewrite-match: prefix
|
|
healthcheck:
|
|
hostname: app
|
|
port: 8080
|
|
path: /health
|
|
```
|
|
|
|
<Expandable title="Public resource reference">
|
|
<ResponseField name="<resource_key>" type="object">
|
|
A single public resource definition.
|
|
|
|
<Expandable title="Resource fields">
|
|
<ResponseField name="name" type="string">
|
|
Human-readable resource name. Required unless the resource is targets-only.
|
|
|
|
YAML: `name: Web App`
|
|
Container label: `pangolin.public-resources.web-app.name=Web App`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="protocol" type="string">
|
|
Resource type.
|
|
|
|
**Options**: `http`, `tcp`, `udp`
|
|
|
|
YAML: `protocol: http`
|
|
Container label: `pangolin.public-resources.web-app.protocol=http`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="ssl" type="boolean">
|
|
Optional SSL/TLS flag present in the schema.
|
|
|
|
YAML: `ssl: true`
|
|
Container label: `pangolin.public-resources.web-app.ssl=true`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="full-domain" type="string">
|
|
Public hostname for HTTP resources. Required when `protocol: http`.
|
|
|
|
YAML: `full-domain: app.example.com`
|
|
Container label: `pangolin.public-resources.web-app.full-domain=app.example.com`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="proxy-port" type="integer">
|
|
Public port for raw TCP or UDP resources. Required when `protocol` is `tcp` or `udp`.
|
|
|
|
YAML: `proxy-port: 3000`
|
|
Container label: `pangolin.public-resources.raw-api.proxy-port=3000`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="enabled" type="boolean">
|
|
Disables the resource without removing it.
|
|
|
|
YAML: `enabled: true`
|
|
Container label: `pangolin.public-resources.web-app.enabled=true`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="host-header" type="string">
|
|
Overrides the upstream `Host` header sent to the target.
|
|
|
|
YAML: `host-header: internal.example.local`
|
|
Container label: `pangolin.public-resources.web-app.host-header=internal.example.local`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="tls-server-name" type="string">
|
|
Overrides the TLS SNI hostname used for upstream TLS connections.
|
|
|
|
YAML: `tls-server-name: internal.example.local`
|
|
Container label: `pangolin.public-resources.web-app.tls-server-name=internal.example.local`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="headers" type="array of objects">
|
|
Static headers added to proxied requests.
|
|
|
|
Container labels for arrays must include an index (`[0]`, `[1]`, ...).
|
|
|
|
YAML: `headers: [{ name: X-Env, value: prod }]`
|
|
Container label: `pangolin.public-resources.web-app.headers[0].name=X-Env`
|
|
|
|
<Expandable title="Header object">
|
|
<ResponseField name="name" type="string" required>
|
|
Header name.
|
|
|
|
YAML: `name: X-Env`
|
|
Container label: `pangolin.public-resources.web-app.headers[0].name=X-Env`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="value" type="string" required>
|
|
Header value.
|
|
|
|
YAML: `value: prod`
|
|
Container label: `pangolin.public-resources.web-app.headers[0].value=prod`
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
|
|
<ResponseField name="rules" type="array of objects">
|
|
Ordered access rules for public resources.
|
|
|
|
Container labels for arrays must include an index (`[0]`, `[1]`, ...).
|
|
|
|
YAML: `rules: [{ action: allow, match: country, value: US }]`
|
|
Container label: `pangolin.public-resources.web-app.rules[0].action=allow`
|
|
|
|
<Expandable title="Rule object">
|
|
<ResponseField name="action" type="string" required>
|
|
What Pangolin should do when the rule matches.
|
|
|
|
**Options**: `allow`, `deny`, `pass`
|
|
|
|
YAML: `action: allow`
|
|
Container label: `pangolin.public-resources.web-app.rules[0].action=allow`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="match" type="string" required>
|
|
Match type for the rule.
|
|
|
|
**Options**: `cidr`, `path`, `ip`, `country`, `asn`, `region`
|
|
|
|
YAML: `match: country`
|
|
Container label: `pangolin.public-resources.web-app.rules[0].match=country`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="value" type="string" required>
|
|
Value to compare against, such as an IP, CIDR, path, country code, ASN, or region.
|
|
|
|
YAML: `value: US`
|
|
Container label: `pangolin.public-resources.web-app.rules[0].value=US`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="priority" type="integer">
|
|
Explicit rule priority. If omitted, priority is assigned from the rule order.
|
|
|
|
YAML: `priority: 10`
|
|
Container label: `pangolin.public-resources.web-app.rules[0].priority=10`
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
|
|
<ResponseField name="auth" type="object">
|
|
Authentication settings for HTTP resources. Not allowed for `tcp` or `udp`.
|
|
|
|
<Expandable title="Auth object">
|
|
<ResponseField name="pincode" type="number">
|
|
Numeric PIN required before access is granted.
|
|
|
|
YAML: `pincode: 123456`
|
|
Container label: `pangolin.public-resources.web-app.auth.pincode=123456`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="password" type="string">
|
|
Shared password gate for the resource.
|
|
|
|
YAML: `password: super-secret`
|
|
Container label: `pangolin.public-resources.web-app.auth.password=super-secret`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="sso-enabled" type="boolean">
|
|
Enables Pangolin sign-in for the resource.
|
|
|
|
YAML: `sso-enabled: true`
|
|
Container label: `pangolin.public-resources.web-app.auth.sso-enabled=true`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="sso-roles" type="array of strings">
|
|
Roles allowed through SSO.
|
|
|
|
Container labels for arrays must include an index (`[0]`, `[1]`, ...).
|
|
|
|
YAML: `sso-roles: [Member]`
|
|
Container label: `pangolin.public-resources.web-app.auth.sso-roles[0]=Member`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="sso-users" type="array of strings">
|
|
Specific user identifiers allowed through SSO.
|
|
|
|
Container labels for arrays must include an index (`[0]`, `[1]`, ...).
|
|
|
|
YAML: `sso-users: [user@example.com]`
|
|
Container label: `pangolin.public-resources.web-app.auth.sso-users[0]=user@example.com`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="whitelist-users" type="array of strings">
|
|
Whitelisted emails or patterns allowed for email-based access flows.
|
|
|
|
Container labels for arrays must include an index (`[0]`, `[1]`, ...).
|
|
|
|
YAML: `whitelist-users: [admin@example.com]`
|
|
Container label: `pangolin.public-resources.web-app.auth.whitelist-users[0]=admin@example.com`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="auto-login-idp" type="integer">
|
|
Identity provider ID to redirect to automatically.
|
|
|
|
YAML: `auto-login-idp: 1`
|
|
Container label: `pangolin.public-resources.web-app.auth.auto-login-idp=1`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="basic-auth" type="object">
|
|
HTTP basic auth settings.
|
|
|
|
<Expandable title="Basic auth">
|
|
<ResponseField name="user" type="string" required>
|
|
Basic auth username.
|
|
|
|
YAML: `user: demo`
|
|
Container label: `pangolin.public-resources.web-app.auth.basic-auth.user=demo`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="password" type="string" required>
|
|
Basic auth password.
|
|
|
|
YAML: `password: change-me`
|
|
Container label: `pangolin.public-resources.web-app.auth.basic-auth.password=change-me`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="extendedCompatibility" type="boolean">
|
|
Compatibility flag for basic auth behavior.
|
|
|
|
**Default**: `true`
|
|
|
|
YAML: `extendedCompatibility: true`
|
|
Container label: `pangolin.public-resources.web-app.auth.basic-auth.extendedCompatibility=true`
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
|
|
<ResponseField name="maintenance" type="object">
|
|
Maintenance page configuration for public resources **(EE)**.
|
|
|
|
YAML: `maintenance: { enabled: true, type: forced }`
|
|
Container label: `pangolin.public-resources.web-app.maintenance.enabled=true`
|
|
|
|
<Expandable title="Maintenance object">
|
|
<ResponseField name="enabled" type="boolean">
|
|
Turns the maintenance page feature on for the resource.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="type" type="string">
|
|
When Pangolin should show the page.
|
|
|
|
**Options**: `forced`, `automatic`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="title" type="string">
|
|
Main heading shown on the maintenance page.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="message" type="string">
|
|
Message shown to users while the resource is unavailable.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="estimated-time" type="string">
|
|
Optional estimate for when the service will return.
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
|
|
<ResponseField name="targets" type="array of objects">
|
|
Backend destinations for the resource.
|
|
|
|
Container labels for arrays must include an index (`[0]`, `[1]`, ...).
|
|
|
|
YAML: `targets: [{ hostname: app, port: 8080, method: http }]`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].hostname=app`
|
|
|
|
<Expandable title="Target object">
|
|
<ResponseField name="site" type="string">
|
|
Site that hosts the target. Optional when deploying from a Newt — if omitted, the target is assigned to the site of the Newt that applied the blueprint.
|
|
|
|
YAML: `site: my-site`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].site=my-site`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="method" type="string">
|
|
Upstream protocol for HTTP resources.
|
|
|
|
**Options**: `http`, `https`, `h2c`
|
|
|
|
YAML: `method: http`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].method=http`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="hostname" type="string" required>
|
|
Target hostname or IP address.
|
|
|
|
YAML: `hostname: app`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].hostname=app`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="port" type="integer" required>
|
|
Target port.
|
|
|
|
YAML: `port: 8080`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].port=8080`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="enabled" type="boolean">
|
|
Disables the target without deleting it.
|
|
|
|
YAML: `enabled: true`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].enabled=true`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="internal-port" type="integer">
|
|
Internal port override used in container-oriented setups.
|
|
|
|
YAML: `internal-port: 8080`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].internal-port=8080`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="path" type="string">
|
|
Path condition used for HTTP routing.
|
|
|
|
YAML: `path: /`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].path=/`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="path-match" type="string">
|
|
Matching mode for `path`.
|
|
|
|
**Options**: `exact`, `prefix`, `regex`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="rewrite-path" type="string">
|
|
Replacement path or prefix used during path rewriting.
|
|
|
|
YAML: `rewrite-path: /`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].rewrite-path=/`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="rewritePath" type="string">
|
|
Deprecated alias for `rewrite-path`.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="rewrite-match" type="string">
|
|
Rewrite mode.
|
|
|
|
**Options**: `exact`, `prefix`, `regex`, `stripPrefix`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="priority" type="integer">
|
|
Target priority used in routing decisions.
|
|
|
|
**Range**: `1-1000`
|
|
**Default**: `100`
|
|
|
|
YAML: `priority: 100`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].priority=100`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="healthcheck" type="object">
|
|
Health monitoring for the target.
|
|
|
|
<Expandable title="Healthcheck object">
|
|
<ResponseField name="hostname" type="string" required>
|
|
Hostname or IP used for the health check.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="port" type="integer" required>
|
|
Port used for the health check.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="enabled" type="boolean">
|
|
Enables health checking for the target.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="path" type="string">
|
|
HTTP path to check, such as `/health`.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="scheme" type="string">
|
|
Scheme to use for the check.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="mode" type="string">
|
|
Health check mode supported by the schema.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="interval" type="integer">
|
|
Check interval while the target is healthy.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="unhealthy-interval" type="integer">
|
|
Check interval while the target is unhealthy.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="unhealthyInterval" type="integer">
|
|
Deprecated alias for `unhealthy-interval`.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="timeout" type="integer">
|
|
Timeout for each health check attempt.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="headers" type="array of objects">
|
|
Headers sent with the health check request.
|
|
|
|
Container labels for arrays must include an index (`[0]`, `[1]`, ...).
|
|
|
|
YAML: `headers: [{ name: X-Health-Check, value: true }]`
|
|
Container label: `pangolin.public-resources.web-app.targets[0].healthcheck.headers[0].name=X-Health-Check`
|
|
|
|
<Expandable title="Healthcheck header object">
|
|
<ResponseField name="name" type="string" required>
|
|
Header name.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="value" type="string" required>
|
|
Header value.
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
|
|
<ResponseField name="follow-redirects" type="boolean">
|
|
Whether redirects should be followed.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="followRedirects" type="boolean">
|
|
Deprecated alias for `follow-redirects`.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="method" type="string">
|
|
HTTP method for the check request.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="status" type="integer">
|
|
Expected HTTP status code.
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
</Expandable>
|
|
|
|
### Private Resource Object (`private-resources`)
|
|
|
|
```yaml
|
|
private-resources:
|
|
internal-net:
|
|
name: Internal Network
|
|
mode: cidr
|
|
site: my-site
|
|
destination: 10.0.0.0/24
|
|
tcp-ports: "22,443"
|
|
udp-ports: "53"
|
|
disable-icmp: false
|
|
alias: "*.internal.example.com"
|
|
roles:
|
|
- Member
|
|
users:
|
|
- user@example.com
|
|
machines:
|
|
- machine-id-1
|
|
```
|
|
|
|
<Expandable title="Private resource reference">
|
|
<ResponseField name="<resource_key>" type="object">
|
|
A single private resource definition.
|
|
|
|
<Expandable title="Resource fields">
|
|
<ResponseField name="name" type="string" required>
|
|
Display name for the resource.
|
|
|
|
YAML: `name: Internal Network`
|
|
Container label: `pangolin.private-resources.internal-net.name=Internal Network`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="mode" type="string" required>
|
|
Private resource type.
|
|
|
|
**Options**: `host`, `cidr`
|
|
|
|
YAML: `mode: cidr`
|
|
Container label: `pangolin.private-resources.internal-net.mode=cidr`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="site" type="string">
|
|
Site that hosts the resource. Optional when deploying from a Newt — if omitted, the resource is assigned to the site of the Newt that applied the blueprint.
|
|
|
|
YAML: `site: my-site`
|
|
Container label: `pangolin.private-resources.internal-net.site=my-site`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="destination" type="string" required>
|
|
Host, IP, or CIDR block the client should reach.
|
|
|
|
YAML: `destination: 10.0.0.0/24`
|
|
Container label: `pangolin.private-resources.internal-net.destination=10.0.0.0/24`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="tcp-ports" type="string">
|
|
Allowed TCP ports or ranges. Use comma-separated values for multiple ports or ranges, such as `22,443,8000-9000` or `*` for all ports or leave empty for no ports.
|
|
|
|
**Default**: `*`
|
|
|
|
YAML: `tcp-ports: "22,443"`
|
|
Container label: `pangolin.private-resources.internal-net.tcp-ports=22,443`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="udp-ports" type="string">
|
|
Allowed UDP ports or ranges. Use comma-separated values for multiple ports or ranges, such as `22,443,8000-9000` or `*` for all ports or leave empty for no ports.
|
|
|
|
**Default**: `*`
|
|
|
|
YAML: `udp-ports: "53"`
|
|
Container label: `pangolin.private-resources.internal-net.udp-ports=53`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="disable-icmp" type="boolean">
|
|
Prevents ICMP traffic such as ping.
|
|
|
|
**Default**: `false`
|
|
|
|
YAML: `disable-icmp: false`
|
|
Container label: `pangolin.private-resources.internal-net.disable-icmp=false`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="alias" type="string">
|
|
Internal DNS alias for the resource.
|
|
|
|
YAML: `alias: "*.internal.example.com"`
|
|
Container label: `pangolin.private-resources.internal-net.alias=*.internal.example.com`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="roles" type="array of strings">
|
|
Roles allowed to access the resource.
|
|
|
|
Container labels for arrays must include an index (`[0]`, `[1]`, ...).
|
|
|
|
YAML: `roles: [Member]`
|
|
Container label: `pangolin.private-resources.internal-net.roles[0]=Member`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="users" type="array of strings">
|
|
Individual users allowed to access the resource.
|
|
|
|
Container labels for arrays must include an index (`[0]`, `[1]`, ...).
|
|
|
|
YAML: `users: [user@example.com]`
|
|
Container label: `pangolin.private-resources.internal-net.users[0]=user@example.com`
|
|
</ResponseField>
|
|
|
|
<ResponseField name="machines" type="array of strings">
|
|
Machine identities allowed to access the resource.
|
|
|
|
Container labels for arrays must include an index (`[0]`, `[1]`, ...).
|
|
|
|
YAML: `machines: [machine-id-1]`
|
|
Container label: `pangolin.private-resources.internal-net.machines[0]=machine-id-1`
|
|
</ResponseField>
|
|
</Expandable>
|
|
</ResponseField>
|
|
</Expandable>
|
|
|
|
## Validation Rules And Constraints
|
|
|
|
### Core Rules
|
|
|
|
1. A public resource can be **targets-only**. In that case it may contain only `targets`, and `name` plus `protocol` are not required.
|
|
2. When `protocol` is `http`, the resource must have `full-domain` and each target must include `method`.
|
|
3. When `protocol` is `tcp` or `udp`, the resource must have `proxy-port`, targets must not include `method`, and `auth` is not allowed.
|
|
4. `full-domain` values must be unique across public resources.
|
|
5. `proxy-port` values must be unique per protocol within `public-resources`. TCP `3000` and UDP `3000` can coexist, but two TCP resources cannot both use `3000`.
|
|
6. `alias` values must be unique across private resources in the blueprint.
|
|
|
|
### Common Validation Errors
|
|
|
|
### "Admin role cannot be included in sso-roles"
|
|
|
|
`Admin` is reserved and cannot be used in `auth.sso-roles`.
|
|
|
|
### "Duplicate 'full-domain' values found"
|
|
|
|
Every public HTTP resource must have its own unique `full-domain`.
|
|
|
|
### "Duplicate 'proxy-port' values found in public-resources"
|
|
|
|
Two public resources with the same protocol cannot reuse the same `proxy-port`.
|
|
|
|
### "When protocol is 'http', all targets must have a 'method' field"
|
|
|
|
Each HTTP target must specify `http`, `https`, or `h2c`.
|
|
|
|
### "When protocol is 'tcp' or 'udp', targets must not have a 'method' field"
|
|
|
|
Raw targets do not use HTTP methods.
|
|
|
|
### "When protocol is 'tcp' or 'udp', 'auth' must not be provided"
|
|
|
|
Authentication settings apply only to HTTP public resources.
|
|
|
|
### "Resource must either be targets-only or have both 'name' and 'protocol' fields"
|
|
|
|
Provide both fields for a full public resource definition, or remove everything except `targets`.
|
|
|
|
### "Duplicate 'alias' values found in private-resources"
|
|
|
|
Private resource aliases must be unique within the blueprint.
|
|
|
|
### "Destination must be a valid IP address or valid domain AND alias is required"
|
|
|
|
In `host` mode, the destination must be a valid host or IP. If you use a domain, provide `alias` as well.
|
|
|
|
### "Destination must be a valid CIDR notation for cidr mode"
|
|
|
|
In `cidr` mode, `destination` must be a valid CIDR block such as `10.0.0.0/24`.
|
|
|
|
### "Admin role cannot be included in roles"
|
|
|
|
`Admin` is reserved and cannot be used in private resource `roles`.
|