---
title: "Blueprints"
icon: "file-code"
description: "Pangolin Blueprints are declarative configurations that allow you to define your resources and their settings in a structured format"
---
Blueprints provide a way to define your Pangolin resources and their configurations in a structured, declarative format. This allows for easier management, version control, and automation of your resource setups.
## Overview
Pangolin supports two blueprint formats:
1. **YAML Configuration Files**: Standalone configuration files
2. **Docker Labels**: Configuration embedded in Docker Compose files
Some features in this documentation are marked with **(EE)**, indicating they are available only in the Enterprise Edition of Pangolin.
## YAML Configuration Format
YAML config can be applied using Docker labels, API, from a Newt site, or in the UI. _Application through a CLI tool is planned._
You can apply blueprints directly through the Pangolin CLI.
```bash
pangolin apply blueprint --file /path/to/blueprint.yaml
```
You can also apply blueprints directly in the Pangolin UI. Navigate to **Settings > Blueprints** and paste your YAML configuration into the provided text area.
Newt automatically discovers and applies blueprints defined in YAML format when passing the `--blueprint-file` argument. For example
```bash
newt --blueprint-file /path/to/blueprint.yaml
```
You can also apply blueprints directly through the Pangolin API with an API key. [Take a look at the API documentation for more details.](https://api.pangolin.net/v1/docs/#/Organization/put_org__orgId__blueprint)
PUT to `/org/{orgId}/blueprint` with a base64 encoded JSON body like the following:
```json
{
"blueprint": "base64-encoded-json-content"
}
```
[See this python example](https://github.com/fosrl/pangolin/blob/dev/blueprint.py)
### Public Resources
Public resources are used to expose HTTP, TCP, or UDP services through Pangolin. Below is an example configuration for public resources:
```yaml
public-resources:
resource-nice-id-uno:
name: this is a http resource
protocol: http
full-domain: uno.example.com
host-header: example.com
tls-server-name: example.com
headers:
- name: X-Example-Header
value: example-value
- name: X-Another-Header
value: another-value
rules:
- action: allow
match: ip
value: 1.1.1.1
priority: 1
- action: deny
match: cidr
value: 2.2.2.2/32
priority: 2
- action: allow
match: asn
value: AS13335
priority: 3
- action: pass
match: path
value: /admin
targets:
- site: lively-yosemite-toad
hostname: localhost
method: http
port: 8000
- site: slim-alpine-chipmunk
hostname: localhost
path: /admin
path-match: exact
method: https
port: 8001
resource-nice-id-dos:
name: this is a raw resource
protocol: tcp
proxy-port: 3000
targets:
- site: lively-yosemite-toad
hostname: localhost
port: 3000
```
### Authentication Configuration
Authentication is off by default. You can enable it by adding the relevant fields in the `auth` section as shown in the example below.
```yaml
public-resources:
secure-resource:
name: Secured Resource
protocol: http
full-domain: secure.example.com
auth:
pincode: 123456
password: your-secure-password
basic-auth:
user: asdfa
password: sadf
sso-enabled: true
sso-roles:
- Member
- Admin
sso-users:
- user@example.com
whitelist-users:
- admin@example.com
```
### Targets-Only Resources
You can define simplified resources that contain only target configurations. This is useful for adding targets to existing resources or for simple configurations:
```yaml
public-resources:
additional-targets:
targets:
- site: another-site
hostname: backend-server
method: https
port: 8443
- site: another-site
hostname: backup-server
method: http
port: 8080
```
When using targets-only resources, the `name` and `protocol` fields are not required. All other resource-level validations are skipped for these simplified configurations.
### Maintenance Page Configuration **(EE)**
This is an Enterprise Edition (EE) feature only. It allows you to display a maintenance page for a public resource when it's under maintenance or when targets are unhealthy.
```yaml
public-resources:
production-app:
name: Production Application
protocol: http
full-domain: app.example.com
maintenance:
enabled: true
type: forced
title: Scheduled Maintenance
message: We are performing system upgrades to improve performance. The service will be back online shortly.
estimated-time: 2 hours
targets:
- site: my-site
hostname: app-server
method: https
port: 443
```
**Maintenance Types:**
- **`forced`**: Always displays the maintenance page regardless of target health status
- **`automatic`**: Displays the maintenance page only when all targets are unhealthy or the sites are offline
### Private Resources
Private resources define proxied resources accessible when connected via an client:
```yaml
private-resources:
private-resource-nice-id-uno:
name: SSH Server
mode: host
destination: 192.168.1.100
site: lively-yosemite-toad
tcp-ports: "22,3389"
udp-ports: "*"
disable-icmp: false
roles:
- Developer
- DevOps
users:
- user@example.com
machines:
- machine-id-1
- machine-id-2
private-resource-nice-id-duo:
name: Internal Network
mode: cidr
destination: 10.0.0.0/24
site: lively-yosemite-toad
tcp-ports: "80,443,8000-9000"
udp-ports: "53,123"
disable-icmp: true
users:
- admin@example.com
```
## Docker Labels Format
For containerized applications, you can define blueprints using Docker labels.
Blueprints will **continuously apply** from changes in the docker stack, newt restarting, or when viewing the resource in the dashboard.
### Enabling Docker Socket Access
To use Docker labels, enable the Docker socket when running Newt:
```bash
newt --docker-socket /var/run/docker.sock
```
or using the environment variable:
```bash
DOCKER_SOCKET=/var/run/docker.sock
```
### Docker Compose Example
The compose file will be the source of truth, any edits through the resources dashboard will be **overwritten** by the blueprint labels defined in the compose stack.
```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:
# Public Resource Configuration
- 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
# Target Configuration - the port and hostname will be auto-detected
- 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:
# Additional target for the same resource where the port and hostname are explicit
- 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 will create a resource that looks like the following:
### Docker Labels Considerations
When hostname and internal port are not explicitly defined in labels, Pangolin will automatically detect them from the container configuration.
If no site is specified in the labels, the resource will be assigned to the Newt site that discovered the container.
Configuration across different containers is automatically merged to form complete resource definitions. This allows you to distribute targets across multiple containers while maintaining a single logical resource.
## Configuration Properties
### Public Resources
| Property | Type | Required | Description | Constraints |
|----------|------|----------|-------------|-------------|
| `name` | string | Conditional | Human-readable name for the resource | Required unless targets-only resource |
| `protocol` | string | Conditional | Protocol type (`http`, `tcp`, or `udp`) | Required unless targets-only resource |
| `full-domain` | string | HTTP only | Full domain name for HTTP resources | Required for HTTP protocol, must be unique |
| `proxy-port` | number | TCP/UDP only | Port for raw TCP/UDP resources | Required for TCP/UDP, 1-65535, must be unique within public-resources |
| `ssl` | boolean | No | Enable SSL/TLS for the resource | - |
| `enabled` | boolean | No | Whether the resource is enabled | Defaults to `true` |
| `host-header` | string | No | Custom Host header for requests | - |
| `tls-server-name` | string | No | SNI name for TLS connections | - |
| `headers` | array | No | Custom headers to add to requests | Each header requires `name` and `value` (min 1 char each) |
| `rules` | array | No | Access control rules | See Rules section below |
| `auth` | object | HTTP only | Authentication configuration | See Authentication section below |
| `maintenance` | object | No | Maintenance page configuration **(EE)** | Enterprise Edition only. See Maintenance Configuration section below |
| `targets` | array | Yes | Target endpoints for the resource | See Targets section below |
### Target Configuration
| Property | Type | Required | Description | Constraints |
|----------|------|----------|-------------|-------------|
| `site` | string | No | Site identifier where the target is located | - |
| `hostname` | string | Yes | Target hostname or IP address | - |
| `port` | number | Yes | Port on the target system | 1-65535 |
| `method` | string | HTTP only | Protocol method (`http`, `https`, or `h2c`) | Required for HTTP protocol targets |
| `enabled` | boolean | No | Whether the target is enabled | Defaults to `true` |
| `internal-port` | number | No | Internal port mapping | 1-65535 |
| `path` | string | HTTP only | Path prefix, exact path, or regex pattern | - |
| `path-match` | string | HTTP only | Path matching type (`prefix`, `exact`, or `regex`) | - |
| `rewrite-path` | string | No | Path to rewrite the request to | - |
| `rewrite-match` | string | No | Rewrite matching type (`exact`, `prefix`, `regex`, or `stripPrefix`) | - |
| `priority` | number | No | Target priority for load balancing | 1-1000, defaults to 100 |
| `healthcheck` | object | No | Health check configuration for the target | See Health Check Configuration below |
### Health Check Configuration
Health checks can be configured for individual targets to monitor their availability. Add a `healthcheck` object to any target:
```yaml
public-resources:
monitored-service:
name: Monitored Service
protocol: http
full-domain: service.example.com
targets:
- site: my-site
hostname: backend-server
method: https
port: 8443
healthcheck:
hostname: backend-server
port: 8443
enabled: true
path: /health
interval: 30
timeout: 5
method: GET
status: 200
headers:
- name: X-Health-Check
value: true
```
| Property | Type | Required | Description | Constraints |
|----------|------|----------|-------------|-------------|
| `hostname` | string | Yes | Hostname for health check | - |
| `port` | number | Yes | Port for health check | 1-65535 |
| `enabled` | boolean | No | Whether health check is enabled | Defaults to `true` |
| `path` | string | No | Path to check | - |
| `scheme` | string | No | Protocol scheme for the health check | - |
| `mode` | string | No | Health check mode | Defaults to `http` |
| `interval` | number | No | Seconds between health checks | Defaults to 30 |
| `unhealthy-interval` | number | No | Seconds between checks when unhealthy | Defaults to 30 |
| `timeout` | number | No | Timeout in seconds | Defaults to 5 |
| `headers` | array | No | Headers to send with health check | Array of objects with `name` and `value` |
| `follow-redirects` | boolean | No | Whether to follow redirects | Defaults to `true` |
| `method` | string | No | HTTP method for health check | Defaults to `GET` |
| `status` | number | No | Expected HTTP status code | - |
### Authentication Configuration
Not allowed on TCP/UDP resources.
| Property | Type | Required | Description | Constraints |
|----------|------|----------|-------------|-------------|
| `pincode` | number | No | 6-digit PIN for access | Must be exactly 6 digits |
| `password` | string | No | Password for access | - |
| `basic-auth` | object | No | Basic authentication configuration | Requires `user` and `password` fields |
| `sso-enabled` | boolean | No | Enable SSO authentication | Defaults to `false` |
| `sso-roles` | array | No | Allowed SSO roles | Cannot include "Admin" role |
| `sso-users` | array | No | Allowed SSO usernames | Must be valid usernames |
| `whitelist-users` | array | No | Whitelisted user emails | Must be valid email addresses |
| `auto-login-idp` | number | No | Automatic login identity provider ID | Must be a positive integer |
### Maintenance Configuration **(EE)**
This is an Enterprise Edition (EE) feature only. It allows you to display a maintenance page for a public resource.
The `maintenance` object can be added to any public resource to display a maintenance page to users:
```yaml
public-resources:
my-service:
name: My Service
protocol: http
full-domain: service.example.com
maintenance:
enabled: true
type: automatic
title: Scheduled Maintenance
message: We are performing scheduled maintenance. Service will resume shortly.
estimated-time: 2 hours
targets:
- site: my-site
hostname: backend-server
method: https
port: 8443
```
| Property | Type | Required | Description | Constraints |
|----------|------|----------|-------------|-------------|
| `enabled` | boolean | No | Whether the maintenance page is enabled | Defaults to `false` |
| `type` | string | No | Maintenance type (`forced` or `automatic`) | `forced` always shows maintenance page; `automatic` shows only when all targets are unhealthy or sites offline |
| `title` | string | No | Title text for the maintenance page | Maximum 255 characters, can be null |
| `message` | string | No | Message text explaining the maintenance | Maximum 2000 characters, can be null |
| `estimated-time` | string | No | Estimated time for maintenance completion | Maximum 100 characters, can be null |
**Maintenance Types:**
- **`forced`**: Always displays the maintenance page regardless of target health status
- **`automatic`**: Displays the maintenance page only when all targets are unhealthy
### Rules Configuration
| Property | Type | Required | Description | Constraints |
|----------|------|----------|-------------|-------------|
| `action` | string | Yes | Rule action (`allow`, `deny`, or `pass`) | - |
| `match` | string | Yes | Match type (`cidr`, `path`, `ip`, or `country`) | - |
| `value` | string | Yes | Value to match against | Format depends on match type. For `country` match, use `ALL` to match all countries |
| `priority` | number | No | Processing priority of the rule. | If not set, the priority is auto-assigned sequentially based on the rule order. |
If no priority is defined, it is auto-assigned sequentially starting at 1 based on the rule order.
Each rule consumes one priority slot, including rules with manually assigned priorities.
Manual and auto-assigned priorities must be unique.
### Private Resources
These are resources used with Pangolin clients (e.g., SSH, RDP).
| Property | Type | Required | Description | Constraints |
|----------|------|----------|-------------|-------------|
| `name` | string | Yes | Human-readable name for the resource | 1-255 characters |
| `mode` | string | Yes | Resource mode (`host` or `cidr`) | - |
| `destination` | string | Yes | Target IP address, hostname, or CIDR block | For `host` mode: IP address or domain. For `cidr` mode: valid CIDR notation |
| `site` | string | Yes | Site identifier where the resource is located | - |
| `tcp-ports` | string | No | TCP port ranges to allow | Port range string (e.g., `"80,443,8000-9000"`), defaults to `"*"` (all ports) |
| `udp-ports` | string | No | UDP port ranges to allow | Port range string (e.g., `"53,123,5000-6000"`), defaults to `"*"` (all ports) |
| `disable-icmp` | boolean | No | Disable ICMP (ping) for this resource | Defaults to `false` |
| `alias` | string | No | Fully qualified domain name alias | Must be a valid FQDN (e.g., example.com). Required when destination is a domain in `host` mode |
| `roles` | array | No | Allowed SSO roles | Cannot include "Admin" role |
| `users` | array | No | Allowed user emails | Must be valid email addresses |
| `machines` | array | No | Allowed machine identifiers | Array of strings |
## Validation Rules and Constraints
### Resource-Level Validations
1. **Targets-Only Resources**: A resource can contain only the `targets` field, in which case `name` and `protocol` are not required.
2. **Protocol-Specific Requirements**:
- **HTTP Protocol**: Must have `full-domain` and all targets must have `method` field
- **TCP/UDP Protocol**: Must have `proxy-port` and targets must NOT have `method` field
- **TCP/UDP Protocol**: Cannot have `auth` configuration
3. **Alias Uniqueness**: `alias` values must be unique across all private resources within the same blueprint and in the org
4. **Domain Uniqueness**: `full-domain` values must be unique across all public resources
5. **Proxy Port Uniqueness**: `proxy-port` values must be unique per protocol within public resources (e.g., TCP port 3000 and UDP port 3000 can coexist)
6. **Target Method Requirements**: When protocol is `http`, all non-null targets must specify a `method`
## Common Validation Errors
When working with blueprints, you may encounter these validation errors:
### "Admin role cannot be included in sso-roles"
The `Admin` role is reserved and cannot be included in the `sso-roles` array for authentication configuration.
### "Duplicate 'full-domain' values found"
Each `full-domain` must be unique across all public resources. If you need multiple resources for the same domain, use different subdomains or paths.
### "Duplicate 'proxy-port' values found in public-resources"
Port numbers in `proxy-port` must be unique per protocol within public-resources (e.g., you can't have two TCP resources using port 3000, but TCP port 3000 and UDP port 3000 can coexist).
### "When protocol is 'http', all targets must have a 'method' field"
All targets in HTTP proxy resources must specify whether they use `http`, `https`, or `h2c`.
### "When protocol is 'tcp' or 'udp', targets must not have a 'method' field"
TCP and UDP targets should not include the `method` field as it's only applicable to HTTP resources.
### "When protocol is 'tcp' or 'udp', 'auth' must not be provided"
Authentication is only supported for HTTP resources, not TCP or UDP.
### "Resource must either be targets-only or have both 'name' and 'protocol' fields"
Resources must either contain only the `targets` field (targets-only) or include both `name` and `protocol` for complete resource definitions.
### "Duplicate 'alias' values found in private-resources"
Alias values in private resources must be unique within the blueprint.
### "Destination must be a valid IP address or valid domain AND alias is required"
For private resources in `host` mode, the destination must be a valid IP address or domain. When using a domain, an `alias` field is required.
### "Destination must be a valid CIDR notation for cidr mode"
For private resources in `cidr` mode, the destination must be a valid CIDR notation (e.g., 10.0.0.0/24).
### "Admin role cannot be included in roles"
The `Admin` role is reserved and cannot be included in the `roles` array for private resource configuration.