---
title: "Configuration File"
description: "Configure Pangolin using the config.yml file with detailed settings for all components"
---
The `config.yml` file controls all aspects of your Pangolin deployment, including server settings, domain configuration, email setup, and security options. This file is mounted at `config/config.yml` in your Docker container.
## Setting up your `config.yml`
To get started, create a basic configuration file with the essential settings:
Minimal Pangolin configuration:
```yaml title="config.yml"
gerbil:
start_port: 51820
base_endpoint: "pangolin.example.com" # REPLACE WITH YOUR DOMAIN
# Optional network settings (defaults shown):
# subnet_group: "100.89.137.0/20"
# block_size: 24
# site_block_size: 30
app:
dashboard_url: "https://pangolin.example.com" # REPLACE WITH YOUR DOMAIN
log_level: "info"
telemetry:
anonymous_usage: true
domains:
domain1:
base_domain: "example.com" # REPLACE WITH YOUR DOMAIN
cert_resolver: "letsencrypt"
server:
secret: "your-strong-secret" # REPLACE
cors:
origins: ["https://pangolin.example.com"] # REPLACE WITH YOUR DOMAIN
methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]
allowed_headers: ["X-CSRF-Token", "Content-Type"]
credentials: false
# Optional organization network settings (defaults shown):
# orgs:
# block_size: 24
# subnet_group: "100.90.128.0/20"
# utility_subnet_group: "100.96.128.0/20"
flags:
require_email_verification: false
disable_signup_without_invite: true
disable_user_create_org: false
allow_raw_resources: true
```
Generate a strong secret for `server.secret`. Use at least 32 characters with a mix of letters, numbers, and special characters.
If you need to CHANGE the server secret after the server has been started you must use the `pangctl rotate-server-secret` command to re-encrypt sensitive data. [Follow docs here](/self-host/advanced/container-cli-tool#rotate-server-secret).
## Reference
This section contains the complete reference for all configuration options in `config.yml`.
### Application Settings
Core application configuration including dashboard URL, logging, and general settings.
The URL where your Pangolin dashboard is hosted.
**Examples**: `https://example.com`, `https://pangolin.example.com`
This URL is used for generating links, redirects, and authentication flows. You can run Pangolin on a subdomain or root domain.
The logging level for the application.
**Options**: `debug`, `info`, `warn`, `error`
**Default**: `info`
Whether to save logs to files in the `config/logs/` directory.
**Default**: `false`
When enabled, logs rotate automatically:
- Max file size: 20MB
- Max files: 7 days
Whether to log failed authentication attempts for security monitoring.
**Default**: `false`
Telemetry configuration settings.
Whether to enable anonymous usage telemetry.
**Default**: `true`
Notification configuration settings.
Whether to enable showing product updates notifications on the UI.
**Default**: `true`
Whether to enable showing new releases notifications on the UI.
**Default**: `true`
### Server Configuration
Server ports, networking, and authentication settings.
The port for the front-end API that handles external requests.
**Example**: `3000`
The port for the internal private-facing API.
**Example**: `3001`
The port for the frontend server (Next.js).
**Example**: `3002`
The port for the integration API (optional).
**Example**: `3003`
The port for the AI Gateway service.
**Example**: `3005`
**Default**: `3005`
The hostname of the Pangolin container for internal communication.
**Example**: `pangolin`
If using Docker Compose, this should match your container name.
The name of the session cookie for storing authentication tokens.
**Example**: `p_session_token`
**Default**: `p_session_token`
Query parameter name for passing access tokens in requests.
**Example**: `p_token`
**Default**: `p_token`
HTTP headers for passing access tokens in requests.
Header name for access token ID.
**Example**: `P-Access-Token-Id`
Header name for access token.
**Example**: `P-Access-Token`
Names of the HTTP headers Badger injects into proxied requests to identify an authenticated user or virtual API key. Also used by the AI Gateway to attach the identified user to a request once it has passed Badger's session/key verification.
Header name for the authenticated user's ID.
**Default**: `Remote-User-Id`
Header name for the virtual API key ID.
**Default**: `Remote-Virtual-Api-Key-Id`
Header name for the authenticated username.
**Default**: `Remote-User`
Header name for the authenticated user's email.
**Default**: `Remote-Email`
Header name for the authenticated user's display name.
**Default**: `Remote-Name`
Header name for the authenticated user's role.
**Default**: `Remote-Role`
Query parameter for session request tokens.
**Default**: `resource_session_request_param`
Cross-Origin Resource Sharing (CORS) configuration.
Allowed origins for cross-origin requests.
**Example**: `["https://pangolin.example.com"]`
Allowed HTTP methods for CORS requests.
**Example**: `["GET", "POST", "PUT", "DELETE", "PATCH"]`
Allowed HTTP headers in CORS requests.
**Example**: `["X-CSRF-Token", "Content-Type"]`
Whether to allow credentials in CORS requests.
**Default**: `true`
Number of proxy headers to trust for client IP detection.
**Example**: `1`
**Default**: `1`
Use `1` if running behind a single reverse proxy like Traefik.
Whether to have Badger stamp the resolved client IP into a dedicated `X-Pangolin-Client-Ip` header on the site-resource AI Gateway route.
**Default**: `false`
**Environment Variable**: `ENABLE_AI_GATEWAY_CLIENT_IP_HEADER`
Useful when an intermediary proxy sits between Traefik and the AI Gateway and overwrites `X-Forwarded-For`/`X-Real-Ip` instead of appending to them. Requires a Badger version that supports `realIpHeader`.
Dashboard session duration in hours.
**Example**: `720` (30 days)
**Default**: `720`
Resource session duration in hours.
**Example**: `720` (30 days)
**Default**: `720`
Secret key for encrypting sensitive data.
**Environment Variable**: `SERVER_SECRET`
**Minimum Length**: 8 characters
**Example**: `"d28@a2b.2HFTe2bMtZHGneNYgQFKT2X4vm4HuXUXBcq6aVyNZjdGt6Dx-_A@9b3y"`
Generate a strong, random secret. This is used for encrypting sensitive data and should be kept secure.
If you need to CHANGE the server secret after the server has been started you must use the `pangctl rotate-server-secret` command to re-encrypt sensitive data. [Follow docs here](/self-host/advanced/container-cli-tool#rotate-server-secret).
Path to the MaxMind GeoIP database file for geolocation features.
**Example**: `./config/GeoLite2-Country.mmdb`
Used for IP geolocation functionality. Requires a MaxMind GeoLite2 or GeoIP2 database file.
Path to the MaxMind ASN database file for ASN lookups.
**Example**: `./config/GeoLite2-ASN.mmdb`
Sibling setting to `maxmind_db_path`. Used to resolve the ASN for an IP address.
### Domain Configuration
Domain settings for SSL certificates and routing.
At least one domain must be configured.
It is best to add it in the UI for ease of use or when you want the
domain to *only be present in the org it was created in*.
You should create it in the config file for permanence across installs
and if you want the domain to be present in all orgs.
Domain configuration with a unique key of your choice.
The base domain for this configuration.
**Example**: `example.com`
The Traefik certificate resolver name.
**Example**: `letsencrypt`
This must match the certificate resolver name in your Traefik configuration. If omitted, falls back to `traefik.cert_resolver`.
Whether to prefer wildcard certificates for this domain.
**Example**: `true`
Useful for domains with many subdomains to reduce certificate management overhead.
### Traefik Integration
Traefik reverse proxy configuration settings.
The Traefik entrypoint name for HTTP traffic.
**Example**: `web`
Must match the entrypoint name in your Traefik configuration.
The Traefik entrypoint name for HTTPS traffic.
**Example**: `websecure`
Must match the entrypoint name in your Traefik configuration.
The default certificate resolver for domains created through the UI.
**Example**: `letsencrypt`
This only applies to domains created through the Pangolin dashboard.
Whether to prefer wildcard certificates for UI-created domains.
**Example**: `true`
This only applies to domains created through the Pangolin dashboard.
Additional Traefik middlewares to apply to resource routers.
**Example**: `["middleware1", "middleware2"]`
These middlewares must be defined in your Traefik dynamic configuration.
Path where SSL certificates are stored. This is used only with managed Pangolin deployments.
**Example**: `/var/certificates`
**Default**: `/var/certificates`
Interval in milliseconds for monitoring configuration changes.
**Example**: `5000`
**Default**: `5000`
Path to the dynamic certificate configuration file. This is used only with managed Pangolin deployments.
**Example**: `/var/dynamic/cert_config.yml`
**Default**: `/var/dynamic/cert_config.yml`
Path to the dynamic router configuration file.
**Example**: `/var/dynamic/router_config.yml`
**Default**: `/var/dynamic/router_config.yml`
Additional fully-qualified domains that are always included in the list sent to the SNI proxy, alongside domains discovered from resources.
**Example**: `["static.example.com"]`
**Default**: `[]`
Useful for domains that need to be routable through the SNI proxy but aren't tied to a resource that Pangolin would otherwise discover automatically.
Supported site types for Traefik configuration.
**Example**: `["newt", "wireguard", "local"]`
**Default**: `["newt", "wireguard", "local"]`
Whether Traefik generates routes for raw TCP/UDP (non-HTTP) resources.
**Default**: `true`
This gates Traefik's config generation and is distinct from `flags.allow_raw_resources`, which gates the API from accepting new raw resources.
Whether to use file-based configuration mode for Traefik.
**Example**: `false`
**Default**: `false`
When enabled, uses file-based dynamic configuration instead of API-based updates.
Prefix used for transport-related configurations. References servers transport config in dynamic Traefik file.
**Example**: `pp-transport-v`
**Default**: `pp-transport-v`
Rate limit settings for the browser gateway Traefik middleware.
Average number of requests per second allowed.
**Default**: `30`
Maximum burst size allowed above the average rate.
**Default**: `50`
### Gerbil Tunnel Controller
Gerbil tunnel controller settings for WireGuard tunneling.
Domain name included in WireGuard configuration for tunnel connections.
**Example**: `pangolin.example.com`
Name of the exit node record that identifies this server's own Gerbil exit node.
Used to look up (or create, if missing) this instance's exit node in the database. Useful when running multiple exit nodes so this server can find its own.
Starting port for WireGuard tunnels.
**Example**: `51820`
Starting port for client WireGuard relay and hole punch port.
**Example**: `21820`
IP address CIDR range for Gerbil exit node subnets.
**Default**: `100.89.137.0/20`
The default uses the CGNAT range to avoid conflicts with typical private networks.
If you change this on an existing install you will need to delete the exit node to refresh it in the database which is best practice. Use the [pangctl command to clear the exit nodes](https://docs.pangolin.net/self-host/advanced/container-cli-tool#clear-exit-nodes).
Block size for Gerbil exit node CIDR ranges.
**Default**: `24`
A /24 block provides 256 IP addresses for the Gerbil network.
If you change this on an existing install you will need to delete the exit node to refresh it in the database which is best practice. Use the [pangctl command to clear the exit nodes](https://docs.pangolin.net/self-host/advanced/container-cli-tool#clear-exit-nodes).
Block size for site CIDR ranges connected to Gerbil.
**Default**: `30`
A /30 block provides 4 IP addresses per site. Consider using /29 (8 IPs) or /28 (16 IPs) for sites with heavy WireGuard usage.
If you change this on an existing install you will need to delete the exit node to refresh it in the database which is best practice. Use the [pangctl command to clear the exit nodes](https://docs.pangolin.net/self-host/advanced/container-cli-tool#clear-exit-nodes).
### Organization Settings
Organization network configuration settings.
Block size for organization CIDR ranges.
**Default**: `24`
A /24 block provides 256 IP addresses per organization. Determines the subnet size allocated to each organization for network isolation.
IP address CIDR range for organization subnets.
**Default**: `100.90.128.0/20`
**Example**: `100.90.128.0/20`
Base subnet from which organization-specific subnets are allocated. Uses CGNAT range by default.
IP address CIDR range for utility subnets used by organizations.
**Default**: `100.96.128.0/20`
Separate subnet range for utility network functions within organizations.
### Rate Limiting
Rate limiting configuration for API requests.
Global rate limit settings for all external API requests.
Time window for rate limiting in minutes.
**Default**: `1`
Maximum number of requests allowed in the time window.
**Default**: `500`
Rate limit settings specifically for authentication endpoints.
Time window for authentication rate limiting in minutes.
**Example**: `1`
**Default**: `1`
Maximum number of authentication requests allowed in the time window.
**Example**: `10`
**Default**: `500`
Consider setting this lower than global limits for security.
### Email Configuration
SMTP settings for sending transactional emails.
SMTP server hostname.
**Example**: `smtp.gmail.com`
SMTP server port.
**Example**: `587` (TLS) or `465` (SSL)
SMTP username.
**Environment Variable**: `EMAIL_SMTP_USER`
**Example**: `no-reply@example.com`
SMTP password.
**Environment Variable**: `EMAIL_SMTP_PASS`
Whether to use secure connection (SSL/TLS).
**Default**: `false`
Enable this when using port 465 (SSL).
From address for sent emails.
**Example**: `no-reply@example.com`
Usually the same as `smtp_user`.
Whether to fail on invalid server certificates.
**Default**: `true`
### Feature Flags
Feature flags to control application behavior.
Whether to require email verification for new users.
**Default**: `false`
Only enable this if you have email configuration set up.
Enable automatic synchronization of ACME certificates for TLS termination on private resources.
```yaml
flags:
enable_acme_cert_sync: true
```
Whether to disable public user registration.
**Default**: `false`
Users can still sign up with valid invites when enabled.
Whether to prevent users from creating organizations.
**Default**: `false`
Server admins can always create organizations.
Whether to allow raw TCP/UDP resource creation.
**Default**: `true`
If set to `false`, users will only be able to create http/https resources.
Whether to enable the integration API.
**Default**: `false`
Whether to disable local site creation and management.
**Default**: `false`
When enabled, users cannot create sites that connect to local networks.
Whether to disable basic WireGuard site functionality.
**Default**: `false`
When enabled, only advanced WireGuard configurations are allowed.
Whether to disable product help banners in the UI at the top of screens.
**Default**: `false`
Whether to disable domains managed through the configuration file.
**Default**: `false`
When enabled, only domains created through the UI are allowed.
Whether to disable features that are only available in the Enterprise Edition from showing in the UI.
**Default**: `false`
When enabled, Enterprise-only features are hidden from the UI.
When set to true Pangolin will not generate publicly facing placeholder pages for private HTTP resources. This can impact the ability for Pangolin to generate nessicary certificates.
**Default**: `false`
Whether to hide the virtual API keys UI.
**Default**: `false`
When enabled, virtual API key management is hidden from the dashboard.
### Database Configuration
PostgreSQL database configuration (optional).
PostgreSQL connection string.
**Example**: `postgresql://user:password@host:port/database`
See [PostgreSQL documentation](/self-host/advanced/database-options#postgresql) for setup instructions.
Read-only replica database configurations for load balancing.
Connection string for the read replica database.
**Example**: `postgresql://user:password@replica-host:port/database`
Database connection pool settings.
Maximum number of connections to the primary database.
**Default**: `20`
**Example**: `50`
Maximum number of connections to replica databases.
**Default**: `10`
**Example**: `25`
Time in milliseconds before idle connections are closed.
**Default**: `30000` (30 seconds)
**Example**: `60000`
Time in milliseconds to wait for a database connection.
**Default**: `5000` (5 seconds)
**Example**: `10000`
Whether to allow Postgres query JIT compilation on pooled connections.
**Default**: `true`
Set to `false` when connecting through a pooler (e.g. PgBouncer) that rejects the JIT startup option. When disabled, `SET jit = off` is run on each new connection.
### Logs Database
Configuration for an optional, separate PostgreSQL database dedicated to logs, kept apart from the main application database.
Connection string for the dedicated logs database.
**Environment Variable**: `POSTGRES_LOGS_CONNECTION_STRING`
**Example**: `postgresql://user:password@host:port/logs_database`
If not set, logging falls back to the main `postgres` database.
Read-only replica configurations for the logs database.
Connection string for the read replica logs database.
**Example**: `postgresql://user:password@replica-host:port/logs_database`
Connection pool settings for the logs database. Falls back to `postgres.pool` values when omitted.
Maximum number of connections to the primary logs database.
**Default**: `20`
Maximum number of connections to logs replica databases.
**Default**: `10`
Time in milliseconds before idle connections are closed.
**Default**: `30000` (30 seconds)
Time in milliseconds to wait for a database connection.
**Default**: `5000` (5 seconds)
### ACME Configuration
The ACME config for syncing the certs used to be in the private config file but has moved to the public config file here. Please update config accordingly.
Configuration for ACME certificate synchronization. Used in conjunction with `flags.enable_acme_cert_sync` to synchronize TLS certificates issued by Traefik (or another ACME client) into Pangolin for use on private resources.
Path to the `acme.json` file or a directory containing more than one acme json file produced by Traefik (or another ACME client). Pangolin reads this file to extract certificates for synchronization and will look for all files in the specified directory if a directory is provided. The file must be in the format produced by Traefik's ACME integration. This file is typically mounted as a volume from your ACME client container.
```yaml
acme:
acme_json_path: "config/letsencrypt/acme.json"
```
Interval in milliseconds at which Pangolin polls the `acme.json` file for certificate changes.
```yaml
acme:
sync_interval_ms: 5000
```
HTTP endpoint where Pangolin can pull SSL certificates from to load into the database. Provided in the following format:
```json
[
{
"wildcard": false,
"altName": "subdomain.example.com",
"certName": "subdomain.example.com",
"commonName": "subdomain.example.com",
"certFile": "",
"keyFile": ""
}
]
```
```yaml
acme:
acme_http_endpoint: "http://controller-api.pangolin.svc.cluster.local/api/v1/certificates"
```
### AI Model Catalog
The catalog feeds Known Models pickers, wildcard discovery, provider selection, and usage pricing. See [Model Catalog](/manage/ai/model-catalog) for the JSON format, catalog providers, and how budgets use pricing.
AI Gateway catalog settings. Omit this block to use the defaults.
Where Pangolin loads the model catalog from, and how often it refreshes.
HTTP endpoint that returns catalog JSON. Point this at your own API to serve a custom catalog.
```yaml
ai:
model_catalog:
upstream_url: "https://api.fossorial.io/api/v1/models"
```
Path to a local catalog JSON file. When set, this file is the base catalog instead of `upstream_url`.
```yaml
ai:
model_catalog:
file: "config/ai-models.json"
```
Path to a local JSON file whose entries are merged into the base catalog. Base entries win on duplicates; the merge file only adds models that are not already present.
```yaml
ai:
model_catalog:
merge_file: "config/ai-models-extra.json"
```
Lower bound, in hours, for the jittered background refresh interval.
Upper bound, in hours, for the jittered background refresh interval. Pangolin waits a random duration between min and max so many instances do not hit the upstream at the same moment.
## Environment Variables
Some configuration values can be set using environment variables for enhanced security:
| Name | Variable | Config |
|------|----------|--------|
| Server Secret | `SERVER_SECRET` | `server.secret` |
| Email Username | `EMAIL_SMTP_USER` | `email.smtp_user` |
| Email Password | `EMAIL_SMTP_PASS` | `email.smtp_pass` |
| PostgreSQL Connection String | `POSTGRES_CONNECTION_STRING` | `postgres.connection_string` |
| PostgreSQL Replica Connection Strings | `POSTGRES_REPLICA_CONNECTION_STRINGS` | `postgres.replicas` (comma-separated list of connection strings) |
| PostgreSQL Logs Connection String | `POSTGRES_LOGS_CONNECTION_STRING` | `postgres_logs.connection_string` |
| PostgreSQL Logs Replica Connection Strings | `POSTGRES_LOGS_REPLICA_CONNECTION_STRINGS` | `postgres_logs.replicas` (comma-separated list of connection strings) |
| Enable SQLite WAL Mode | `ENABLE_SQLITE_WAL_MODE` | *(SQLite only)* Set to `true` to enable [WAL mode](https://www.sqlite.org/wal.html) for improved SQLite concurrency |
| Enable AI Gateway Client IP Header | `ENABLE_AI_GATEWAY_CLIENT_IP_HEADER` | `server.enable_ai_gateway_client_ip_header` |