Renaming to remote-nodes

This commit is contained in:
Owen
2025-10-14 10:46:25 -07:00
parent d2fe75bab7
commit dfd2349c7a
34 changed files with 30 additions and 30 deletions

View File

@@ -1,56 +0,0 @@
---
title: "Cloudflare Proxy"
---
Pangolin works with Cloudflare proxy (orange cloud) enabled, but requires specific configuration:
<Warning>
**Terms of Service**: Enabling Cloudflare proxy binds you to Cloudflare's terms of service as traffic routes through their network.
</Warning>
### SSL Configuration
**Recommended setup:**
1. **Use wildcard certificates** with DNS-01 challenge
2. **Set SSL/TLS mode to Full (Strict)**
3. **Disable port 80** (not needed with wildcard certs)
<Info>
Pangolin will **not work** with Cloudflare's Full or Automatic SSL/TLS modes. Only Full (Strict) mode is supported.
</Info>
### WireGuard Configuration
Since Cloudflare proxy obscures the destination IP, you must explicitly set your VPS IP in the [config file](/self-host/advanced/config-file):
```yaml
gerbil:
base_endpoint: "YOUR_VPS_IP_ADDRESS" # Required with Cloudflare proxy
```
<Steps>
<Step title="Get your VPS IP">
Find your VPS public IP address:
```bash
curl ifconfig.io
```
</Step>
<Step title="Update configuration">
Add the IP to your `config.yml`:
```yaml
gerbil:
base_endpoint: "104.21.16.1" # Replace with your actual IP
```
</Step>
<Step title="Restart services">
Restart Pangolin to apply the changes:
```bash
docker-compose restart
```
</Step>
</Steps>

View File

@@ -1,689 +0,0 @@
---
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"
app:
dashboard_url: "https://pangolin.example.com"
domains:
domain1:
base_domain: "pangolin.example.com"
cert_resolver: "letsencrypt"
server:
secret: "your-strong-secret"
gerbil:
base_endpoint: "pangolin.example.com"
flags:
require_email_verification: false
disable_signup_without_invite: true
disable_user_create_org: true
```
In managed mode:
```yaml title="config.yml"
gerbil:
start_port: 51820
base_endpoint: "154.123.45.67" # REPLACE WITH YOUR IP OR DOMAIN
managed:
id: "he4g78wevj25msf"
secret: "n7sd18twfko0q0vrb7wyclqzbvvnx1fqt7ezv8xewhdb9s7d"
```
<Warning>
Generate a strong secret for `server.secret`. Use at least 32 characters with a mix of letters, numbers, and special characters.
</Warning>
## Reference
This section contains the complete reference for all configuration options in `config.yml`.
### Application Settings
<ResponseField name="app" type="object" required>
Core application configuration including dashboard URL, logging, and general settings.
<Expandable title="App">
<ResponseField name="dashboard_url" type="string" required>
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.
</ResponseField>
<ResponseField name="log_level" type="string">
The logging level for the application.
**Options**: `debug`, `info`, `warn`, `error`
**Default**: `info`
</ResponseField>
<ResponseField name="save_logs" type="boolean">
Whether to save logs to files in the `config/logs/` directory.
**Default**: `false`
<Note>
When enabled, logs rotate automatically:
- Max file size: 20MB
- Max files: 7 days
</Note>
</ResponseField>
<ResponseField name="log_failed_attempts" type="boolean">
Whether to log failed authentication attempts for security monitoring.
**Default**: `false`
</ResponseField>
<ResponseField name="telemetry" type="object">
Telemetry configuration settings.
<Expandable title="Telemetry">
<ResponseField name="anonymous_usage" type="boolean">
Whether to enable anonymous usage telemetry.
**Default**: `true`
</ResponseField>
</Expandable>
</ResponseField>
</Expandable>
</ResponseField>
### Server Configuration
<ResponseField name="server" type="object" required>
Server ports, networking, and authentication settings.
<Expandable title="Server">
<ResponseField name="external_port" type="integer">
The port for the front-end API that handles external requests.
**Example**: `3000`
</ResponseField>
<ResponseField name="internal_port" type="integer">
The port for the internal private-facing API.
**Example**: `3001`
</ResponseField>
<ResponseField name="next_port" type="integer">
The port for the frontend server (Next.js).
**Example**: `3002`
</ResponseField>
<ResponseField name="integration_port" type="integer">
The port for the integration API (optional).
**Example**: `3004`
</ResponseField>
<ResponseField name="internal_hostname" type="string">
The hostname of the Pangolin container for internal communication.
**Example**: `pangolin`
<Tip>
If using Docker Compose, this should match your container name.
</Tip>
</ResponseField>
<ResponseField name="session_cookie_name" type="string">
The name of the session cookie for storing authentication tokens.
**Example**: `p_session_token`
**Default**: `p_session_token`
</ResponseField>
<ResponseField name="resource_access_token_param" type="string">
Query parameter name for passing access tokens in requests.
**Example**: `p_token`
**Default**: `p_token`
</ResponseField>
<ResponseField name="resource_access_token_headers" type="object">
HTTP headers for passing access tokens in requests.
<Expandable title="Headers">
<ResponseField name="id" type="string">
Header name for access token ID.
**Example**: `P-Access-Token-Id`
</ResponseField>
<ResponseField name="token" type="string">
Header name for access token.
**Example**: `P-Access-Token`
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="resource_session_request_param" type="string">
Query parameter for session request tokens.
**Example**: `p_session_request`
**Default**: `p_session_request`
</ResponseField>
<ResponseField name="cors" type="object">
Cross-Origin Resource Sharing (CORS) configuration.
<Expandable title="CORS">
<ResponseField name="origins" type="array of strings">
Allowed origins for cross-origin requests.
**Example**: `["https://pangolin.example.com"]`
</ResponseField>
<ResponseField name="methods" type="array of strings">
Allowed HTTP methods for CORS requests.
**Example**: `["GET", "POST", "PUT", "DELETE", "PATCH"]`
</ResponseField>
<ResponseField name="allowed_headers" type="array of strings">
Allowed HTTP headers in CORS requests.
**Example**: `["X-CSRF-Token", "Content-Type"]`
</ResponseField>
<ResponseField name="credentials" type="boolean">
Whether to allow credentials in CORS requests.
**Default**: `true`
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="trust_proxy" type="integer">
Number of proxy headers to trust for client IP detection.
**Example**: `1`
**Default**: `1`
<Tip>
Use `1` if running behind a single reverse proxy like Traefik.
</Tip>
</ResponseField>
<ResponseField name="dashboard_session_length_hours" type="integer">
Dashboard session duration in hours.
**Example**: `720` (30 days)
**Default**: `720`
</ResponseField>
<ResponseField name="resource_session_length_hours" type="integer">
Resource session duration in hours.
**Example**: `720` (30 days)
**Default**: `720`
</ResponseField>
<ResponseField name="secret" type="string" required>
Secret key for encrypting sensitive data.
**Environment Variable**: `SERVER_SECRET`
**Minimum Length**: 8 characters
**Example**: `"d28@a2b.2HFTe2bMtZHGneNYgQFKT2X4vm4HuXUXBcq6aVyNZjdGt6Dx-_A@9b3y"`
<Warning>
Generate a strong, random secret. This is used for encrypting sensitive data and should be kept secure.
</Warning>
</ResponseField>
</Expandable>
</ResponseField>
### Domain Configuration
<ResponseField name="domains" type="object" required>
Domain settings for SSL certificates and routing.
At least one domain must be configured.
<Expandable title="Domains">
<ResponseField name="<domain_key>" type="object">
Domain configuration with a unique key of your choice.
<Expandable title="Domain Settings">
<ResponseField name="base_domain" type="string" required>
The base domain for this configuration.
**Example**: `example.com`
</ResponseField>
<ResponseField name="cert_resolver" type="string" required>
The Traefik certificate resolver name.
**Example**: `letsencrypt`
<Note>
This must match the certificate resolver name in your Traefik configuration.
</Note>
</ResponseField>
<ResponseField name="prefer_wildcard_cert" type="boolean">
Whether to prefer wildcard certificates for this domain.
**Example**: `true`
<Tip>
Useful for domains with many subdomains to reduce certificate management overhead.
</Tip>
</ResponseField>
</Expandable>
</ResponseField>
</Expandable>
</ResponseField>
### Traefik Integration
<ResponseField name="traefik" type="object">
Traefik reverse proxy configuration settings.
<Expandable title="Traefik">
<ResponseField name="http_entrypoint" type="string">
The Traefik entrypoint name for HTTP traffic.
**Example**: `web`
<Note>
Must match the entrypoint name in your Traefik configuration.
</Note>
</ResponseField>
<ResponseField name="https_entrypoint" type="string">
The Traefik entrypoint name for HTTPS traffic.
**Example**: `websecure`
<Note>
Must match the entrypoint name in your Traefik configuration.
</Note>
</ResponseField>
<ResponseField name="cert_resolver" type="string">
The default certificate resolver for domains created through the UI.
**Example**: `letsencrypt`
<Note>
This only applies to domains created through the Pangolin dashboard.
</Note>
</ResponseField>
<ResponseField name="prefer_wildcard_cert" type="boolean">
Whether to prefer wildcard certificates for UI-created domains.
**Example**: `true`
<Note>
This only applies to domains created through the Pangolin dashboard.
</Note>
</ResponseField>
<ResponseField name="additional_middlewares" type="array of strings">
Additional Traefik middlewares to apply to resource routers.
**Example**: `["middleware1", "middleware2"]`
<Note>
These middlewares must be defined in your Traefik dynamic configuration.
</Note>
</ResponseField>
<ResponseField name="certificates_path" type="string">
Path where SSL certificates are stored. This is used only with managed Pangolin deployments.
**Example**: `/var/certificates`
**Default**: `/var/certificates`
</ResponseField>
<ResponseField name="monitor_interval" type="integer">
Interval in milliseconds for monitoring configuration changes.
**Example**: `5000`
**Default**: `5000`
</ResponseField>
<ResponseField name="dynamic_cert_config_path" type="string">
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`
</ResponseField>
<ResponseField name="dynamic_router_config_path" type="string">
Path to the dynamic router configuration file.
**Example**: `/var/dynamic/router_config.yml`
**Default**: `/var/dynamic/router_config.yml`
</ResponseField>
<ResponseField name="site_types" type="array of strings">
Supported site types for Traefik configuration.
**Example**: `["newt", "wireguard", "local"]`
**Default**: `["newt", "wireguard", "local"]`
</ResponseField>
<ResponseField name="file_mode" type="boolean">
Whether to use file-based configuration mode for Traefik.
**Example**: `false`
**Default**: `false`
<Note>
When enabled, uses file-based dynamic configuration instead of API-based updates.
</Note>
</ResponseField>
</Expandable>
</ResponseField>
### Gerbil Tunnel Controller
<ResponseField name="gerbil" type="object" required>
Gerbil tunnel controller settings for WireGuard tunneling.
<Expandable title="Gerbil">
<ResponseField name="base_endpoint" type="string" required>
Domain name included in WireGuard configuration for tunnel connections.
**Example**: `pangolin.example.com`
</ResponseField>
<ResponseField name="start_port" type="integer">
Starting port for WireGuard tunnels.
**Example**: `51820`
</ResponseField>
<ResponseField name="use_subdomain" type="boolean">
Whether to assign unique subdomains to Gerbil exit nodes.
**Default**: `false`
<Warning>
Keep this set to `false` for most deployments.
</Warning>
</ResponseField>
<ResponseField name="subnet_group" type="string">
IP address CIDR range for Gerbil exit node subnets.
**Example**: `10.0.0.0/8`
</ResponseField>
<ResponseField name="block_size" type="integer">
Block size for Gerbil exit node CIDR ranges.
**Example**: `24`
</ResponseField>
<ResponseField name="site_block_size" type="integer">
Block size for site CIDR ranges connected to Gerbil.
**Example**: `26`
</ResponseField>
</Expandable>
</ResponseField>
### Rate Limiting
<ResponseField name="rate_limits" type="object">
Rate limiting configuration for API requests.
<Expandable title="Rate Limits">
<ResponseField name="global" type="object">
Global rate limit settings for all external API requests.
<Expandable title="Global">
<ResponseField name="window_minutes" type="integer">
Time window for rate limiting in minutes.
**Example**: `1`
</ResponseField>
<ResponseField name="max_requests" type="integer">
Maximum number of requests allowed in the time window.
**Example**: `100`
</ResponseField>
</Expandable>
</ResponseField>
</Expandable>
</ResponseField>
### Email Configuration
<ResponseField name="email" type="object">
SMTP settings for sending transactional emails.
<Expandable title="Email">
<ResponseField name="smtp_host" type="string">
SMTP server hostname.
**Example**: `smtp.gmail.com`
</ResponseField>
<ResponseField name="smtp_port" type="integer">
SMTP server port.
**Example**: `587` (TLS) or `465` (SSL)
</ResponseField>
<ResponseField name="smtp_user" type="string">
SMTP username.
**Example**: `no-reply@example.com`
</ResponseField>
<ResponseField name="smtp_pass" type="string">
SMTP password.
**Environment Variable**: `EMAIL_SMTP_PASS`
</ResponseField>
<ResponseField name="smtp_secure" type="boolean">
Whether to use secure connection (SSL/TLS).
**Default**: `false`
<Tip>
Enable this when using port 465 (SSL).
</Tip>
</ResponseField>
<ResponseField name="no_reply" type="string">
From address for sent emails.
**Example**: `no-reply@example.com`
<Note>
Usually the same as `smtp_user`.
</Note>
</ResponseField>
<ResponseField name="smtp_tls_reject_unauthorized" type="boolean">
Whether to fail on invalid server certificates.
**Default**: `true`
</ResponseField>
</Expandable>
</ResponseField>
### Feature Flags
<ResponseField name="flags" type="object">
Feature flags to control application behavior.
<Expandable title="Flags">
<ResponseField name="require_email_verification" type="boolean">
Whether to require email verification for new users.
**Default**: `false`
<Warning>
Only enable this if you have email configuration set up.
</Warning>
</ResponseField>
<ResponseField name="disable_signup_without_invite" type="boolean">
Whether to disable public user registration.
**Default**: `false`
<Note>
Users can still sign up with valid invites when enabled.
</Note>
</ResponseField>
<ResponseField name="disable_user_create_org" type="boolean">
Whether to prevent users from creating organizations.
**Default**: `false`
<Note>
Server admins can always create organizations.
</Note>
</ResponseField>
<ResponseField name="allow_raw_resources" type="boolean">
Whether to allow raw TCP/UDP resource creation.
**Default**: `true`
<Note>
If set to `false`, users will only be able to create http/https resources.
</Note>
</ResponseField>
<ResponseField name="enable_integration_api" type="boolean">
Whether to enable the integration API.
**Default**: `false`
</ResponseField>
</Expandable>
</ResponseField>
### Database Configuration
<ResponseField name="postgres" type="object">
PostgreSQL database configuration (optional).
<Expandable title="PostgreSQL">
<ResponseField name="connection_string" type="string" required>
PostgreSQL connection string.
**Example**: `postgresql://user:password@host:port/database`
<Note>
See [PostgreSQL documentation](/self-host/advanced/database-options#postgresql) for setup instructions.
</Note>
</ResponseField>
</Expandable>
</ResponseField>
### Managed Configuration
<ResponseField name="managed" type="object">
Managed deployment configuration for connecting self-hosted instances to managed services.
<Expandable title="Managed">
{/* <ResponseField name="name" type="string">
Display name for the managed deployment.
**Example**: `My Self-Hosted Instance`
</ResponseField> */}
<ResponseField name="id" type="string">
Unique identifier for the managed deployment. Generated from the installer or the [Pangolin dashboard](https://pangolin.fossorial.io).
**Example**: `he4g78wevj25msf`
</ResponseField>
<ResponseField name="secret" type="string">
Secret key for authenticating with the managed service. Generated from the installer or the [Pangolin dashboard](https://pangolin.fossorial.io).
**Example**: `n7sd18twfko0q0vrb7wyclqzbvvnx1fqt7ezv8xewhdb9s7d`
<Warning>
Keep this secret secure and do not share it publicly.
</Warning>
</ResponseField>
<ResponseField name="endpoint" type="string">
The managed service endpoint to connect to. This can only change with enterprise deployments.
**Example**: `https://pangolin.fossorial.io`
**Default**: `https://pangolin.fossorial.io`
</ResponseField>
<ResponseField name="redirect_endpoint" type="string">
Custom redirect endpoint for authentication flows. This can only change for enterprise deployments.
**Example**: `https://my-pangolin.example.com`
<Note>
If not specified, the default dashboard URL will be used.
</Note>
</ResponseField>
</Expandable>
</ResponseField>
## Environment Variables
Some configuration values can be set using environment variables for enhanced security:
<CardGroup cols={2}>
<Card title="Server Secret" icon="key">
**Variable**: `SERVER_SECRET`
**Config**: `server.secret`
Use this to avoid hardcoding secrets in your config file.
</Card>
<Card title="Email Password" icon="mail">
**Variable**: `EMAIL_SMTP_PASS`
**Config**: `email.smtp_pass`
Keep SMTP passwords secure using environment variables.
</Card>
</CardGroup>

View File

@@ -1,34 +0,0 @@
---
title: "Internal CLI (pangctl)"
description: "Command-line tool for managing your Pangolin instance"
---
The Pangolin container includes a CLI tool called `pangctl` that provides commands to help you manage your Pangolin instance.
## Accessing the CLI
Run the following command on the host where the Pangolin container is running:
```bash
docker exec -it pangolin pangctl <command>
```
## Available Commands
To see all available commands:
```bash
docker exec -it pangolin pangctl --help
```
## Set Admin Credentials
Set or reset admin credentials for your Pangolin instance:
```bash
docker exec -it pangolin pangctl set-admin-credentials --email "admin@example.com" --password "Password123!"
```
<Warning>
Use a strong password and keep your admin credentials secure.
</Warning>

View File

@@ -1,100 +0,0 @@
---
title: "Database Options"
description: "Configure SQLite or PostgreSQL database for Pangolin"
---
Pangolin supports two database options: SQLite for simplicity and PostgreSQL for production deployments.
<CardGroup cols={2}>
<Card title="SQLite (Default)" icon="database">
- No configuration required
- Easy to use and portable
- Built into the main image
- Perfect for development
</Card>
<Card title="PostgreSQL" icon="database">
- Production-ready database
- Better performance at scale
- Requires separate image
- Advanced configuration options
</Card>
</CardGroup>
## SQLite
By default, Pangolin uses SQLite for its ease of use and portability.
**Docker Image**: `fosrl/pangolin:<version>`
<Note>
No configuration is required to use SQLite with Pangolin.
</Note>
## PostgreSQL
You can optionally use PostgreSQL for production deployments.
**Docker Image**: `fosrl/pangolin:postgresql-<version>`
### Configuration
Add the following section to your Pangolin configuration file:
```yaml title="config.yml"
postgres:
connection_string: postgresql://<user>:<password>@<host>:<port>/<database>
```
<Warning>
Replace the placeholders with your actual PostgreSQL connection details.
</Warning>
### Docker Compose Example
This example sets up PostgreSQL with health checks to ensure the database is ready before Pangolin starts:
```yaml title="docker-compose.yml"
name: pangolin
services:
pangolin:
image: fosrl/pangolin:postgresql-latest # Don't use latest in production
container_name: pangolin
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "10s"
timeout: "10s"
retries: 15
# ... other services ...
postgres:
image: postgres:17
container_name: postgres
restart: unless-stopped
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- ./config/postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
```
<Warning>
This example is not necessarily production-ready. Adjust the configuration according to your needs and security requirements.
</Warning>
<Note>
Do not use `latest` tags in production. Use specific version tags for stability.
</Note>

View File

@@ -1,73 +0,0 @@
---
title: "Enable Integration API"
description: "Enable and configure the Integration API for external access"
---
The Integration API provides programmatic access to Pangolin functionality. It includes OpenAPI documentation via Swagger UI.
## Enable Integration API
Update your Pangolin configuration file:
```yaml title="config.yml"
flags:
enable_integration_api: true
```
If you want to specify a port other than the default `3004`, you can do so in the config as well:
```yaml title="config.yml"
server:
integration_port: 3004 # Specify different port
```
## Configure Traefik Routing
Add the following configuration to your `dynamic_config.yml` to expose the Integration API at `https://api.example.com/v1`:
```yaml title="dynamic_config.yml"
http:
middlewares:
redirect-to-https:
redirectScheme:
scheme: https
routers:
int-api-router-redirect:
rule: "Host(`api.example.com`)"
service: int-api-service
entryPoints:
- web
middlewares:
- redirect-to-https
int-api-router:
rule: "Host(`api.example.com`)"
service: int-api-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
services:
int-api-service:
loadBalancer:
servers:
- url: "http://pangolin:3004"
```
## Access Documentation
Once configured, access the Swagger UI documentation at:
```
https://api.example.com/v1/docs
```
<Frame caption="Swagger UI documentation interface">
<img src="/images/swagger.png" alt="Swagger UI Preview"/>
</Frame>
<Note>
The Integration API will be accessible at `https://api.example.com/v1` for external applications.
</Note>

View File

@@ -1,101 +0,0 @@
---
title: "Database Options"
description: "Configure SQLite or PostgreSQL database for Pangolin"
---
## Overview
> Choose between SQLite (default) or PostgreSQL for your database
Pangolin supports two database options: SQLite for simplicity and PostgreSQL for production deployments.
<CardGroup cols={2}>
<Card title="SQLite (Default)" icon="database">
- No configuration required
- Easy to use and portable
- Built into the main image
- Perfect for development
</Card>
<Card title="PostgreSQL" icon="postgres">
- Production-ready database
- Better performance at scale
- Requires separate image
- Advanced configuration options
</Card>
</CardGroup>
## SQLite
By default, Pangolin uses SQLite for its ease of use and portability.
**Docker Image**: `fosrl/pangolin:<version>`
<Note>
No configuration is required to use SQLite with Pangolin.
</Note>
## PostgreSQL
You can optionally use PostgreSQL for production deployments.
**Docker Image**: `fosrl/pangolin:postgresql-<version>`
### Configuration
Add the following section to your Pangolin configuration file:
```yaml title="config.yml"
postgres:
connection_string: postgresql://<user>:<password>@<host>:<port>/<database>
```
<Warning>
Replace the placeholders with your actual PostgreSQL connection details.
</Warning>
### Docker Compose Example
This example sets up PostgreSQL with health checks to ensure the database is ready before Pangolin starts:
```yaml title="docker-compose.yml"
name: pangolin
services:
pangolin:
image: fosrl/pangolin:postgresql-latest
container_name: pangolin
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "10s"
timeout: "10s"
retries: 15
postgres:
image: postgres:17
container_name: postgres
restart: unless-stopped
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- ./config/postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
```
<Warning>
This example is not necessarily production-ready. Adjust the configuration according to your needs and security requirements.
</Warning>
<Note>
Do not use `latest` tags in production. Use specific version tags for stability.
</Note>

View File

@@ -1,42 +0,0 @@
---
title: "Container Timezone"
description: "Configure the timezone for Pangolin, Gerbil, and Traefik containers to match your local time."
---
By default, Docker containers report logs and timestamps in **UTC**. If you want the containers and their log output to use your local timezone, you need to set the timezone in both the container environment and mount the host timezone files.
## Updating your `docker-compose.yml`
Add the following to your `pangolin`, `gerbil`, and `traefik` services in `docker-compose.yml`:
```yaml title="docker-compose.yml"
services:
pangolin:
environment:
- TZ=America/New_York # Set your local timezone
volumes:
- /etc/localtime:/etc/localtime:ro # Sync host timezone
- /etc/timezone:/etc/timezone:ro # Optional: some apps read this file
gerbil:
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
traefik:
environment:
- TZ=America/New_York
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
```
### Notes
- **Environment variable `TZ`** ensures most applications inside the container use the correct local timezone.
- **`/etc/localtime` volume** ensures that system utilities (e.g., `date`) inside the container show the correct time.
- **`/etc/timezone` volume** is optional, but some scripts and apps on Debian-based images read it to determine the timezone.
- Logs generated by the containers (including Traefik and Gerbil) will now reflect your local time instead of UTC.
<Warning>
Make sure that the host system has the correct timezone configured, as the containers will reference these host files.
</Warning>

View File

@@ -1,249 +0,0 @@
---
title: "Wildcard Domains"
description: "Configure wildcard SSL certificates for automatic subdomain security with DNS-01 challenge"
---
Wildcard certificates allow you to secure unlimited subdomains with a single SSL certificate, eliminating the need to generate individual certificates for each subdomain. Pangolin uses Traefik's built-in Let's Encrypt integration to automatically manage these certificates.
<Warning>
Before setting up wildcard certificates, you must have a domain that you own and control. You must also have access to the DNS records for this domain.
</Warning>
<Info>
Since Pangolin uses Traefik as a reverse proxy, it has built-in support for Let's Encrypt certificates. This allows you to easily secure your Pangolin instance and all proxied resources with HTTPS. Let's Encrypt provides free SSL certificates, which are automatically renewed.
</Info>
If you used the default settings during installation, your Traefik instance should be set up to use `HTTP-01` challenge for certificate generation. This challenge is the easiest to configure and requires that the Traefik instance be accessible from the internet on port 80.
<Note>
It is highly recommended that you read the [official Traefik documentation](https://doc.traefik.io/traefik/https/acme/) on ACME and Let's Encrypt before proceeding.
</Note>
## Benefits of Wildcard Certificates
<CardGroup cols={3}>
<Card title="Single Certificate" icon="certificate">
Secure unlimited subdomains with one certificate, reducing management overhead.
</Card>
<Card title="Instant Subdomains" icon="bolt">
Add new subdomains without waiting for certificate generation (up to a few minutes).
</Card>
<Card title="Rate Limit Friendly" icon="shield">
Reduce Let's Encrypt rate limit impact by using fewer certificate requests.
</Card>
</CardGroup>
### Examples
- A wildcard cert `*.example.com` could protect:
- `api.example.com`
- `blog.example.com`
- `dashboard.example.com`
- Another wildcard `*.subdomain.example.com` could protect:
- `api.subdomain.example.com`
- `blog.subdomain.example.com`
<Info>
The [rate limits](https://letsencrypt.org/docs/rate-limits/) for Let's Encrypt are per domain. Using a wildcard certificate reduces the number of domains you have, which can help you avoid hitting these limits.
</Info>
## Setting Up Wildcard Certificates
<Steps>
<Step title="Stop the stack">
Make sure the stack is not running before making configuration changes.
</Step>
<Step title="Update Traefik configuration">
Update the Traefik configuration to use the DNS-01 challenge instead of the HTTP-01 challenge. This tells Traefik to use your DNS provider to create the DNS records needed for the challenge.
</Step>
<Step title="Configure Pangolin">
Set the `prefer_wildcard_cert` flag to `true` in the Pangolin configuration file for your domain.
</Step>
</Steps>
<Note>
This setting will try to encourage Traefik to request one wildcard certificate for each level of the domain used by your existing resources.
**Example**: If you have two resources `blog.example.com` and `blog.subdomain.example.com`, Traefik should try to request a wildcard certificate for `*.example.com` and `*.subdomain.example.com` automatically for you.
</Note>
## Traefik Configuration
### Default Config for HTTP-01 Challenge
This is the default config generated by the installer. This is shown here for reference to compare with the wildcard config below.
<AccordionGroup>
<Accordion title="1. HTTP Challenge Configuration">
Tell Traefik to use the `web` entrypoint for the HTTP challenge.
```yaml title="traefik_config.yml" highlight={4,5}
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: admin@example.com
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
```
</Accordion>
<Accordion title="2. Dynamic Configuration">
Set the cert resolver to `letsencrypt` and the entrypoint to `websecure` in the dynamic config.
```yaml title="dynamic_config.yml"
next-router:
rule: "Host(`pangolin.example.com`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
```
</Accordion>
</AccordionGroup>
### Wildcard Config for DNS-01 Challenge
<Steps>
<Step title="1. Configure DNS Challenge">
Tell Traefik to use your DNS provider for the DNS challenge. In this example, we are using Cloudflare.
```yaml title="traefik_config.yml" highlight={4,5}
certificatesResolvers:
letsencrypt:
acme:
dnsChallenge:
provider: "cloudflare" # your DNS provider
# see https://doc.traefik.io/traefik/https/acme/#providers
email: "admin@example.com"
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
```
</Step>
<Step title="2. Add Wildcard Domains">
Add the domain and wildcard domain to the domains section of the next (front end) router in the dynamic config. This tells Traefik to generate a wildcard certificate for the base domain and all subdomains.
```yaml title="dynamic_config.yml" highlight={9-12}
next-router:
rule: "Host(`pangolin.example.com`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
domains:
- main: "example.com"
sans:
- "*.example.com"
```
</Step>
<Step title="3. Add Environment Variables">
Add the environment variables for your DNS provider to the Traefik service in the docker compose file. This allows Traefik to authenticate with your DNS provider to create the DNS records needed for the challenge.
```yaml title="docker-compose.yml" highlight={11-13}
traefik:
image: traefik:v3.4.0
container_name: traefik
restart: unless-stopped
network_mode: service:gerbil
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
# Add the environment variables for your DNS provider.
environment:
CLOUDFLARE_DNS_API_TOKEN: "your-cloudflare-api-token"
volumes:
- ./config/traefik:/etc/traefik:ro
- ./config/letsencrypt:/letsencrypt
```
</Step>
</Steps>
<Warning>
If you're using Cloudflare, make sure your API token has the permissions Zone/Zone/Read and Zone/DNS/Edit and make sure it applies to all zones.
</Warning>
<Info>
Traefik supports most DNS providers. You can find a full list of supported providers and how to configure them in the [Traefik documentation on providers](https://doc.traefik.io/traefik/https/acme/#providers).
</Info>
## Verify it Works
<Tips>
<Tip title="Clear Old Certificates">
You can ensure Traefik doesn't try to use the old certs by deleting the previously used `acme.json` file. This will force Traefik to generate a new certificate on the next start.
</Tip>
</Tips>
<Steps>
<Step title="Start the stack">
Start the stack and watch the logs. You should notice that Traefik is making calls to your DNS provider to create the necessary records to complete the challenge.
</Step>
<Step title="Check logs">
For debugging purposes, you may find it useful to set the log level of Traefik to `debug` in the `traefik_config.yml` file.
</Step>
<Step title="Test new resource">
After Traefik is done waiting for the cert to verify, try to create a new resource with an unused subdomain. Traefik should not try to generate a new certificate, but instead use the wildcard certificate. The domain should also be secured immediately instead of waiting for a new certificate to be generated.
</Step>
<Step title="Verify certificate">
You can also check the volume (in the example above at `config/letsencrypt/`) for the correct certificates. In the `acme.json` file you should see something similar to the following. Note the `*.` in the domain.
</Step>
</Steps>
```json highlight={5}
{
"Certificates": [
{
"domain": {
"main": "*.example.com"
},
"certificate": "...",
"key": "...",
"Store": "default"
}
]
}
```
## Troubleshooting
<AccordionGroup>
<Accordion title="Certificate not generating">
**Problem**: Wildcard certificate not being created.
**Solutions**:
- Verify DNS provider credentials are correct
- Check that API token has proper permissions
- Ensure domain ownership and DNS access
- Review Traefik logs for specific error messages
</Accordion>
<Accordion title="DNS challenge failing">
**Problem**: DNS-01 challenge not completing.
**Solutions**:
- Verify DNS provider is supported by Traefik
- Check API token permissions and scope
- Ensure DNS propagation has completed
- Review provider-specific configuration
</Accordion>
<Accordion title="Old certificates still being used">
**Problem**: Traefik using old HTTP-01 certificates.
**Solution**: Delete the `acme.json` file to force new certificate generation.
</Accordion>
</AccordionGroup>

View File

@@ -1,30 +0,0 @@
---
title: "Without Tunneling"
description: "Use Pangolin as a local reverse proxy without Gerbil tunneling"
---
Use Pangolin as a local reverse proxy and authentication manager
You can use Pangolin without Gerbil and tunneling. In this configuration, Pangolin acts as a normal reverse proxy and authentication manager that can be deployed on your local network to provide access to resources.
<Note>
You can also use "local" sites to expose resources on the same VPS as Pangolin in addition to remote sites.
</Note>
## Setup
### Using the Installer
When asked if you want to install Gerbil for tunneling, select **No**. Gerbil will be removed from the Docker Compose configuration.
### Manual Installation
Follow the [manual install steps](/self-host/manual/docker-compose), but **Gerbil is not required**. Your Docker Compose should not include the Gerbil container.
## How It Works
When Gerbil starts up, it registers itself with Pangolin. By not installing Gerbil, you will only have the option to choose the "Local" connection method. This means Traefik will use the local network to reach your resources.
<Warning>
All setup remains the same, except Pangolin and Traefik must now be on the same network as the resources you want to proxy to.
</Warning>