deploy test

This commit is contained in:
miloschwartz
2025-07-31 14:45:36 -07:00
parent 3556d40d47
commit b918f105b5
64 changed files with 3397 additions and 1943 deletions

BIN
self-host/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,56 @@
---
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

@@ -0,0 +1,566 @@
---
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: "http://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
```
<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>
</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**: `3003`
</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>
</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_base_domain_resources" type="boolean">
Whether to allow resources on base domains.
**Default**: `true`
<Note>
When disabled, only subdomain resources are allowed.
</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](../database/postgres) for setup instructions.
</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

@@ -0,0 +1,34 @@
---
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

@@ -0,0 +1,100 @@
---
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

@@ -0,0 +1,71 @@
---
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 `3003`, you can do so in the config as well:
```yaml title="config.yml"
server:
integration_port: 3003 # 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:3003"
```
## Access Documentation
Once configured, access the Swagger UI documentation at:
```
https://api.example.com/v1/docs
```
<img src="/images/swagger.png" alt="Swagger UI Preview"/>
<Note>
The Integration API will be accessible at `https://api.example.com/v1` for external applications.
</Note>

View File

@@ -0,0 +1,101 @@
---
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

@@ -0,0 +1,249 @@
---
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

@@ -0,0 +1,30 @@
---
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>

View File

@@ -0,0 +1,113 @@
---
title: "Choosing a VPS"
description: "Compare hosting options and find the best VPS for your Pangolin deployment"
---
Pangolin generally requires minimal resources to run effectively. A basic VPS with **1 vCPU, 1GB RAM, and 8GB SSD** is sufficient for most deployments.
<CardGroup cols={2}>
<Card title="Minimum Requirements">
- **CPU**: 1 vCPU
- **RAM**: 1GB
- **Storage**: 8GB SSD
- **Bandwidth**: 1TB/month
</Card>
<Card title="Recommended Specs">
- **CPU**: 2 vCPU
- **RAM**: 2GB
- **Storage**: 20GB SSD
- **Bandwidth**: 2TB/month
</Card>
</CardGroup>
## Recommended Options
<Tip>
We're part of RackNerd's affiliate program. Using our links helps support Pangolin development at no extra cost to you.
</Tip>
<CardGroup cols={2}>
<Card title="RackNerd Starter Plan" href="https://my.racknerd.com/aff.php?aff=13788&pid=912">
**$0.91/month** - Perfect for personal use and small deployments
- 1 vCPU, 1GB RAM, 20GB SSD
- Excellent performance for the price
- Reliable uptime and support
</Card>
<Card title="RackNerd Basic Plan" href="https://my.racknerd.com/aff.php?aff=13788&pid=913">
**$1.47/month** - Ideal for small teams and growing deployments
- 2 vCPU, 2GB RAM, 30GB SSD
- Great value for performance
</Card>
<Card title="RackNerd Standard Plan" href="https://my.racknerd.com/aff.php?aff=13788&pid=914">
**$2.49/month** - Best for larger teams and production use
- 3 vCPU, 3.5GB RAM, 60GB SSD
- Room for growth and scaling
</Card>
</CardGroup>
## VPS Provider Comparison
| Provider | Plan | CPU | RAM | Storage | Price/Month | Price/Year | Best For |
|----------|------|-----|-----|---------|-------------|------------|----------|
| **[RackNerd](https://my.racknerd.com/aff.php?aff=13788)** | Starter | 1 vCPU | 1GB | 20GB SSD | $0.91 | $10.96 | Budget users |
| **[RackNerd](https://my.racknerd.com/aff.php?aff=13788)** | Basic | 2 vCPU | 2GB | 30GB SSD | $1.47 | $17.66 | Small teams |
| **[RackNerd](https://my.racknerd.com/aff.php?aff=13788)** | Standard | 3 vCPU | 3.5GB | 60GB SSD | $2.49 | $29.89 | Growing teams |
| **[Hetzner Cloud](https://www.hetzner.com/cloud)** | CX11 | 2 vCPU | 4GB | 40GB SSD | $4.59 | $55.08 | Performance |
| **[UpCloud](https://upcloud.com/pricing/)** | 1xCPU | 1 vCPU | 1GB | 10GB SSD | $3.30 | $39.60 | European users |
| **[Vultr](https://www.vultr.com/pricing)** | Cloud Compute | 1 vCPU | 1GB | 25GB SSD | $5.00 | $60.00 | Global presence |
| **[Linode](https://www.linode.com/pricing/)** | Nanode | 1 vCPU | 1GB | 25GB SSD | $5.00 | $60.00 | Developer friendly |
| **[DigitalOcean](https://www.digitalocean.com/pricing/droplets)** | Basic | 1 vCPU | 1GB | 25GB SSD | $6.00 | $72.00 | Easy setup |
| **[OVHcloud](https://www.ovhcloud.com/en/vps/)** | Starter | 2 vCPU | 2GB | 40GB SSD | $5.50 | $66.00 | European users |
| **[AWS EC2](https://instances.vantage.sh/)** | t3.micro | 2 vCPU | 1GB | 8GB SSD | $8.50 | $102.00 | Enterprise |
<Info>
Prices shown are approximate and may vary based on location, promotions, and currency exchange rates. Check provider websites for current pricing.
</Info>
## Selection Criteria
When choosing your VPS provider, consider these factors:
<AccordionGroup>
<Accordion title="Performance Requirements">
**Resource usage depends on several key factors:**
**Primary factors:**
- **Number of connected sites**: More sites = higher CPU and memory usage
- **Data throughput**: Amount of traffic transiting through the server
**Secondary factors:**
- **Dashboard UI usage**: Active admin sessions and configuration changes
- **Database activity**: User management, logging, and analytics queries
</Accordion>
<Accordion title="Geographic Location">
**Choose a data center close to your users:**
- **North America**: RackNerd, DigitalOcean, Vultr
- **Europe**: Hetzner, OVHcloud, UpCloud
- **Asia Pacific**: Vultr, Linode, DigitalOcean
- **Global**: AWS, Google Cloud, Azure
</Accordion>
<Accordion title="Support and Reliability">
**Consider these factors:**
- **Uptime guarantees**: Most providers offer 99.9%+
- **Support quality**: 24/7 support vs. community forums
- **Backup options**: Automated backups vs. manual
- **Monitoring**: Built-in monitoring tools
</Accordion>
<Accordion title="Cost Considerations">
**Hidden costs to watch for:**
- **Bandwidth overages**: Most plans include 1-2TB/month
- **Backup storage**: Additional charges for automated backups
- **IPv4 addresses**: Some providers charge extra
- **Support tiers**: Premium support may cost extra
</Accordion>
</AccordionGroup>

View File

@@ -0,0 +1,201 @@
---
title: "DNS & Networking"
description: "Configure your domain, DNS records, and network settings for Pangolin deployment"
---
Pangolin requires proper DNS configuration and network setup to function correctly. This guide covers domain setup, DNS records, port configuration, and networking considerations.
## DNS Configuration
### Basic DNS Records
You'll need to create A (or AAAA for IPv6) records pointing to your VPS IP address.
<Steps>
<Step title="Create wildcard record">
Create a wildcard subdomain record for your domain:
```
Type: A
Name: *
Value: YOUR_VPS_IP_ADDRESS
TTL: 300 (or default)
```
<Check>
This allows any subdomain (e.g., `app.example.com`, `api.example.com`) to resolve to your VPS.
</Check>
</Step>
<Step title="Create root domain record (optional)">
If you plan to use your root domain as a resource:
```
Type: A
Name: @ (or leave blank)
Value: YOUR_VPS_IP_ADDRESS
TTL: 300 (or default)
```
<Info>
This is only needed if you want to use `example.com` (not just subdomains) as a resource.
</Info>
</Step>
<Step title="Wait for propagation">
DNS changes can take 5 minutes to 48 hours to propagate globally.
<Tip>
Use Google DNS (8.8.8.8) or your provider's DNS to test changes faster.
</Tip>
</Step>
</Steps>
## Port Configuration
### Required Ports
Pangolin requires these ports to be open on your VPS:
<CardGroup cols={3}>
<Card title="TCP Port 80">
**HTTP/SSL Verification**
- Let's Encrypt domain validation
- Non-SSL resources
- Can be disabled with wildcard certs
</Card>
<Card title="TCP Port 443">
**HTTPS Traffic**
- Pangolin web dashboard
- SSL-secured resources
- Essential for operation
</Card>
<Card title="UDP Port 51820">
**WireGuard Tunnel**
- Newt client connections
- Gerbil tunnel endpoint
- Secure traffic routing
</Card>
</CardGroup>
### Docker Port Exposure
By default, Pangolin exposes these ports on all interfaces:
```yaml
gerbil:
ports:
- "80:80" # HTTP/SSL verification and non-SSL resources
- "443:443" # HTTPS for web UI and SSL resources
- "51820:51820" # WireGuard for Newt and client connections
```
### Firewall Configuration
Ensure your VPS firewall allows these ports:
<Tabs>
<Tab title="Cloud Provider">
Configure security groups/firewall rules in your cloud provider's dashboard to allow:
- TCP ports 80 and 443
- UDP port 51820
</Tab>
<Tab title="UFW (Ubuntu)">
```bash
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 51820/udp
sudo ufw enable
```
</Tab>
<Tab title="firewalld (CentOS/RHEL)">
```bash
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=443/tcp
sudo firewall-cmd --permanent --add-port=51820/udp
sudo firewall-cmd --reload
```
</Tab>
</Tabs>
## Internal Network Configuration
### Default Subnet Settings
Pangolin uses these default network settings:
```yaml
gerbil:
block_size: 24
site_block_size: 30
subnet_group: 100.89.137.0/20
```
**What this means:**
- **Gerbil network**: Uses first /24 subnet in `100.89.137.0/20` range
- **Site allocation**: Each site gets a /30 subnet (4 IPs)
- **CGNAT range**: Avoids conflicts with most private networks
<Info>
The `100.89.137.0/20` range is in the CGNAT (Carrier-Grade NAT) space, which should avoid conflicts with typical private networks (192.168.x.x, 10.x.x.x, 172.16-31.x.x).
</Info>
<Warning>
**Important**: If this subnet conflicts with your network, change it in your config **before** registering your first Gerbil.
</Warning>
### Customizing Network Settings
If you need to change the default network:
```yaml
gerbil:
block_size: 24 # Size of Gerbil's network block
site_block_size: 30 # Size of each site's network block
subnet_group: 10.0.0.0/8 # Custom subnet range
start_port: 51820 # WireGuard server port
```
<Tip>
For heavy WireGuard usage, consider increasing `site_block_size` to 29 (8 IPs) or 28 (16 IPs) per site.
</Tip>
## Docker Networking
### Local Services
When deploying services in Docker alongside Pangolin:
<AccordionGroup>
<Accordion title="Container Communication">
**For services in the same Docker Compose:**
- Use service names as hostnames
- Example: `http://pangolin:8080`
- Docker Compose creates internal network automatically
</Accordion>
<Accordion title="Host Machine Access">
**To access services on the host machine:**
- Use `172.17.0.1` (Docker bridge gateway)
- Or use `host.docker.internal` (Docker Desktop)
- Example: `http://172.17.0.1:3000`
</Accordion>
<Accordion title="External Services">
**For services outside Docker:**
- Use the host's public IP address
- Ensure firewall allows the required ports
- Consider using VPN or secure tunnels
</Accordion>
</AccordionGroup>

100
self-host/how-to-update.mdx Normal file
View File

@@ -0,0 +1,100 @@
---
title: "How to Update"
description: "Keep your Pangolin deployment up to date with the latest features and security patches"
---
Updating Pangolin is straightforward since it's a collection of Docker images. Simply pull the latest images and restart the stack. Migration scripts run automatically to update your database and configuration files when needed.
## Before You Update
<Warning>
**Always backup your data before updating.** Copy your `config` directory to a safe location so you can roll back if needed.
</Warning>
<Tip>
**Recommended**: Update incrementally between major versions. For example, update from 1.0.0 → 1.1.0 → 1.2.0 instead of jumping directly from 1.0.0 → 1.2.0.
</Tip>
## Update Process
<Steps>
<Step title="Stop the stack">
Stop all running containers:
```bash
sudo docker compose down
```
</Step>
<Step title="Check latest versions">
Find the latest version numbers:
- **Pangolin**: [GitHub Releases](https://github.com/fosrl/pangolin/releases)
- **Gerbil**: [GitHub Releases](https://github.com/fosrl/gerbil/releases)
- **Traefik**: [Docker Hub](https://hub.docker.com/_/traefik)
<Info>
Look for the latest stable release (not pre-release or beta versions).
</Info>
</Step>
<Step title="Update version numbers">
Edit your `docker-compose.yml` file and update the image versions:
```yaml title="docker-compose.yml"
services:
pangolin:
image: fosrl/pangolin:1.7.3 # Update to latest version
# ... rest of config
gerbil:
image: fosrl/gerbil:1.2.1 # Update to latest version
# ... rest of config
traefik:
image: traefik:v3.4.0 # Update if needed
# ... rest of config
```
<Warning>
Update each service you want to upgrade. You can update them individually or all at once.
</Warning>
</Step>
<Step title="Pull new images">
Download the updated Docker images:
```bash
sudo docker compose pull
```
</Step>
<Step title="Start the stack">
Start the updated containers:
```bash
sudo docker compose up -d
```
</Step>
<Step title="Monitor the update">
Watch the logs to ensure everything starts correctly:
```bash
sudo docker compose logs -f
```
</Step>
<Step title="Verify functionality">
Test that everything is working:
1. Access your Pangolin dashboard
2. Check that all sites are accessible
3. Verify tunnel connections (if using Gerbil)
4. Test any custom configurations
<Check>
If everything works, your update is complete!
</Check>
</Step>
</Steps>

View File

@@ -0,0 +1,308 @@
---
title: "Docker Compose"
description: "Deploy Pangolin manually using Docker Compose without the automated installer"
---
This guide walks you through setting up Pangolin manually using Docker Compose without the automated installer. This approach gives you full control over the configuration and deployment process.
This guide assumes you already have a Linux server with Docker and Docker Compose installed. If you don't, please refer to the [official Docker documentation](https://docs.docker.com/get-docker/) for installation instructions. You must also have root access to the server.
## Prerequisites
Checkout the [quick install guide](self-host/quick-install) for more info regarding what is needed before you install Pangolin.
## File Structure
Create the following directory structure for your Pangolin deployment:
```
.
├── config/
│ ├── config.yml (*)
│ ├── db/
│ │ └── db.sqlite
│ ├── key
│ ├── letsencrypt/
│ │ └── acme.json
│ ├── logs/
│ └── traefik/
│ ├── traefik_config.yml (*)
│ └── dynamic_config.yml (*)
└── docker-compose.yml (*)
```
<Info>
Files marked with `(*)` must be created manually. Volumes and other files are generated automatically by the services.
</Info>
<AccordionGroup>
<Accordion title="Configuration Files">
**`config/config.yml`**: Main Pangolin configuration file
- Contains all Pangolin settings and options
- See [Configuration Guide](/pangolin/configuration/config) for details
**`config/traefik/traefik_config.yml`**: Traefik static configuration
- Global Traefik settings and entry points
- SSL certificate resolver configuration
**`config/traefik/dynamic_config.yml`**: Traefik dynamic configuration
- HTTP routers and services for Pangolin
- Load balancer and middleware configuration
</Accordion>
<Accordion title="Generated Files">
**`config/db/db.sqlite`**: SQLite database file
- Created automatically on first startup
- Contains all Pangolin data and settings
**`config/key`**: Private key file
- Generated by Gerbil service
- Used for WireGuard tunnel encryption
**`config/letsencrypt/acme.json`**: SSL certificate storage
- Managed by Traefik
- Contains Let's Encrypt certificates
</Accordion>
<Accordion title="Docker Files">
**`docker-compose.yml`**: Service definitions
- Defines Pangolin, Gerbil, and Traefik services
- Network configuration and volume mounts
- Health checks and dependencies
</Accordion>
</AccordionGroup>
<Steps>
<Step title="Create configuration directory">
```bash
mkdir -p config/traefik config/db config/letsencrypt config/logs
```
</Step>
<Step title="Create configuration files">
Create the main configuration files (see below):
- `docker-compose.yml` (in project root)
- `config/traefik/traefik_config.yml`
- `config/traefik/dynamic_config.yml`
- `config/config.yml`
</Step>
<Step title="Update domain and email">
Edit the configuration files to replace:
- `pangolin.example.com` with your actual domain
- `admin@example.com` with your email address
<Warning>
Ensure your domain DNS is properly configured to point to your server's IP address.
</Warning>
</Step>
</Steps>
## Starting the Stack
<Steps>
<Step title="Start the services">
```bash
sudo docker compose up -d
```
</Step>
<Step title="Monitor startup">
```bash
sudo docker compose logs -f
```
</Step>
<Step title="Verify services">
```bash
sudo docker compose ps
```
All services should show "Up" status after a few minutes.
</Step>
<Step title="Access the dashboard">
Navigate to `https://your-domain.com/auth/initial-setup` to complete the initial setup.
<Check>
The dashboard should load with SSL certificate automatically configured.
</Check>
</Step>
</Steps>
## Docker Compose Configuration
Create `docker-compose.yml` in your project root:
```yaml title="docker-compose.yml"
services:
pangolin:
image: fosrl/pangolin:latest # https://github.com/fosrl/pangolin/releases
container_name: pangolin
restart: unless-stopped
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "3s"
timeout: "3s"
retries: 15
gerbil:
image: fosrl/gerbil:latest # https://github.com/fosrl/gerbil/releases
container_name: gerbil
restart: unless-stopped
depends_on:
pangolin:
condition: service_healthy
command:
- --reachableAt=http://gerbil:3003
- --generateAndSaveKeyTo=/var/config/key
- --remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config
- --reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth
volumes:
- ./config/:/var/config
cap_add:
- NET_ADMIN
- SYS_MODULE
ports:
- 51820:51820/udp
- 443:443 # Port for traefik because of the network_mode
- 80:80 # Port for traefik because of the network_mode
traefik:
image: traefik:v3.4.0
container_name: traefik
restart: unless-stopped
network_mode: service:gerbil # Ports appear on the gerbil service
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
volumes:
- ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration
- ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
networks:
default:
driver: bridge
name: pangolin
```
## Traefik Static Configuration
Create `config/traefik/traefik_config.yml`:
```yaml title="config/traefik/traefik_config.yml"
api:
insecure: true
dashboard: true
providers:
http:
endpoint: "http://pangolin:3001/api/v1/traefik-config"
pollInterval: "5s"
file:
filename: "/etc/traefik/dynamic_config.yml"
experimental:
plugins:
badger:
moduleName: "github.com/fosrl/badger"
version: "latest"
log:
level: "INFO"
format: "common"
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: admin@example.com # REPLACE WITH YOUR EMAIL
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: "30m"
http:
tls:
certResolver: "letsencrypt"
serversTransport:
insecureSkipVerify: true
```
## Traefik Dynamic Configuration
Create `config/traefik/dynamic_config.yml`:
```yaml title="config/traefik/dynamic_config.yml"
http:
middlewares:
redirect-to-https:
redirectScheme:
scheme: https
routers:
# HTTP to HTTPS redirect router
main-app-router-redirect:
rule: "Host(`pangolin.example.com`)" # REPLACE WITH YOUR DOMAIN
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
# Next.js router (handles everything except API and WebSocket paths)
next-router:
rule: "Host(`pangolin.example.com`) && !PathPrefix(`/api/v1`)" # REPLACE WITH YOUR DOMAIN
service: next-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
# API router (handles /api/v1 paths)
api-router:
rule: "Host(`pangolin.example.com`) && PathPrefix(`/api/v1`)" # REPLACE WITH YOUR DOMAIN
service: api-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
# WebSocket router
ws-router:
rule: "Host(`pangolin.example.com`)" # REPLACE WITH YOUR DOMAIN
service: api-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Next.js server
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API/WebSocket server
```
## Pangolin Configuration
Create `config/config.yml` with your Pangolin settings. See the [configuration guide](/self-host/advanced/config-file) for detailed options and examples.

356
self-host/manual/unraid.mdx Normal file
View File

@@ -0,0 +1,356 @@
---
title: "Unraid Deployment"
description: "Deploy Pangolin on Unraid for local reverse proxy and tunneling"
---
## Overview
This guide explains how to use Pangolin and Traefik as a local reverse proxy without Gerbil and its tunneling features. The second (optional) part will expand on this and show how to enable tunneling by setting up Gerbil.
All containers are available in the Unraid Community Apps (CA) store. If you're not familiar with Unraid, you can find more information on their [website](https://unraid.net/).
This installation has a lot of moving parts and is a bit non-standard for Unraid because Pangolin and its components were designed to run as micro-services on a VPS in tunneling mode. However, some may want to use "Local" reverse proxying on their Unraid server or use their Unraid server as a tunnel controller with Gerbil. For either of these use cases, follow the steps outlined in this guide.
## Prerequisites
- A working Unraid server.
- A domain name with access to configure DNS and the ability to port forward on your network.
- The networking is the same as for the VPS, just on your local network, so please refer to [networking page](/self-host/dns-and-networking) for more info.
## Create a Docker Network
Before starting, create a new docker network on Unraid. This will simplify things, and allow the containers to communicate with each other via their container names. If you already have a network, there is no need to create another one.
1. Open the web terminal in Unraid.
2. Run the following command:
<Info>
You can use any name you want for the network. We will use `mynetwork` in this guide.
</Info>
```bash
docker network create mynetwork
```
For more info on this, see this [tutorial by IBRACORP](https://www.youtube.com/watch?v=7fzBDCI8O2w).
## 1. Setup Pangolin and Traefik
This first part will enable Pangolin to work in "Local" reverse proxy mode. Newt and WireGuard will **not** be able to be used after finishing this first part. However, if you want to use those features, you still need to follow this first part of the tutorial because we show how to set up Pangolin and Traefik first.
### Install and Setup Pangolin
#### 1. Create the Config Files
Pangolin uses a yaml file for configuration. If this is not present on start up, the container will throw an error and exit.
Create a `config.yml` file in the `config` folder.
See the [Configuration](/pangolin/configuration/config) section for what to put in this file.
```
pangolin/
├─ config/
│ ├─ config.yml
```
#### 2. Install Pangolin via the CA Store
#### 3. Configure Pangolin
Set the network to the one you created earlier.
<img
src="/images/pangolin_config.png"
alt="Pangolin configuration settings in Unraid"
/>
**Ports:**
Due to the way Pangolin was designed to work with docker compose and a config file, the way it handles ports is a little different as compared to other popular Unraid containers. For all host ports:
The host ports, container ports, and ports in the config should match for simplicity. This is because the Pangolin config also has ports in it. If you decide to use a non-default port, you would need to edit the port in the template and the config file.
For example, to change the port for the WebUI:
- Click edit on the port
- Set the "Container Port" to the new port you want to use
- Set the "Host Port" to the new port you want to use
- Edit Pangolin's config file and set `server.next_port` to the new port you want to use
#### 4. Start the Pangolin Container
<Warning>
Pangolin will not start without a config file. If you have not created the config file or the config file is invalid, the container will throw an error and exit.
</Warning>
#### 5. Log in to the dashboard
After successful installation:
1. Complete the initial admin user setup via the dashboard at `https://<your-domain>/auth/initial-setup`
2. You can log in using the admin email and password you provided
3. Create your first "Local" site for local reverse proxying
### Install and Setup Traefik
Before starting with Traefik, shut down the Pangolin container.
#### 1. Create the Config Files
Update the appdata path with new files for Traefik. At this point there may be some extra files generated by Pangolin.
```
pangolin/
├─ config/
│ ├─ config.yml
│ ├─ letsencrypt/
│ ├─ traefik/
│ │ ├─ dynamic_config.yml
│ │ ├─ traefik_config.yml
```
**`pangolin/config/traefik/traefik_config.yml`:**
```yaml title="pangolin/config/traefik/traefik_config.yml
api:
insecure: true
dashboard: true
providers:
http:
endpoint: "http://pangolin:3001/api/v1/traefik-config"
pollInterval: "5s"
file:
filename: "/etc/traefik/dynamic_config.yml"
experimental:
plugins:
badger:
moduleName: "github.com/fosrl/badger"
version: "latest"
log:
level: "INFO"
format: "common"
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: admin@example.com # REPLACE THIS WITH YOUR EMAIL
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: "30m"
http:
tls:
certResolver: "letsencrypt"
serversTransport:
insecureSkipVerify: true
```
**`pangolin/config/traefik/dynamic_config.yml`:**
The dynamic configuration file is where you define the HTTP routers and services for the Pangolin frontend and backend. Below is an example configuration for a Next.js frontend and an API backend.
The domain you enter here is what will be used to access the main Pangolin dashboard. Make sure you have the DNS set up correctly for this domain. Point it to the IP address of the server running Pangolin.
```yaml title="pangolin/config/traefik/dynamic_config.yml"
http:
middlewares:
redirect-to-https:
redirectScheme:
scheme: https
routers:
# HTTP to HTTPS redirect router
main-app-router-redirect:
rule: "Host(`pangolin.example.com`)" # REPLACE THIS WITH YOUR DOMAIN
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
# Next.js router (handles everything except API and WebSocket paths)
next-router:
rule: "Host(`pangolin.example.com`) && !PathPrefix(`/api/v1`)" # REPLACE THIS WITH YOUR DOMAIN
service: next-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
# API router (handles /api/v1 paths)
api-router:
rule: "Host(`pangolin.example.com`) && PathPrefix(`/api/v1`)" # REPLACE THIS WITH YOUR DOMAIN
service: api-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
# WebSocket router
ws-router:
rule: "Host(`pangolin.example.com`)" # REPLACE THIS WITH YOUR DOMAIN
service: api-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Next.js server
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API/WebSocket server
```
#### 2. Install Traefik via the CA Store
This section will use the Traefik template from the "IBRACORP" repository. If you already have a Traefik installation running, you should manually configure your Traefik config to work with Pangolin.
<img
src="/images/traefik_repo.png"
width="400"
alt="Traefik repository selection in Community Apps"
/>
#### 3. Configure Traefik
<img
src="/images/traefik_config.png"
alt="Traefik configuration settings in Unraid"
/>
<Info>
Please refer to the official Traefik docs for more information on the Traefik configuration beyond this guide.
</Info>
**Match your config to the one above. You will have to remove some of the default variables in the template that are not needed. You can always add them back if you need them later.**
**Network Type:**
Set the network type to the one you created earlier.
**Post Arguments:**
Tell Traefik where the config file is located by adding the following to the "Post Arguments" field. This is not the host path, but the path inside the container.
```bash
--configFile=/etc/traefik/traefik_config.yml
```
**Config Folder:**
If you're using the Traefik config generated by Pangolin, point this to the same appdata path as Pangolin, but append `/traefik`, like this: `<appdata>/config/traefik`.
**Lets Encrypt (Host Path 2 in screenshot):**
Traefik will store the certification information here. You can make this path anywhere you want. For simplicity, we're placing it in the same config path at `<appdata>/config/letsencrypt`.
**Ports:**
You will need to port forward the https and http ports listed in the config on your network's router.
#### 4. Port Forwarding
You will need to port forward the ports you set in the Traefik config on your network's router. This is so that Traefik can receive traffic from the internet. You should forward 443 to the https port and 80 to the http port you set in the Traefik config.
## 2. Add Gerbil for Tunneling (Optional)
<Info>
If you do not want to use the tunneling feature of Pangolin and only want to use it as a local reverse proxy, you can stop here.
</Info>
Before setting up Gerbil, shut down Traefik and Pangolin.
If you plan to use tunneling features of Pangolin with Newt or WireGuard, you will need to add Gerbil to the stack. Gerbil is the tunnel controller for Pangolin and is used to manage the tunnels between the Pangolin server and the client.
Luckily, adding Gerbil is fairly easy.
The important concept to understand going forward, is we need to network Traefik through Gerbil. All Traefik traffic goes through the Gerbil container and exits.
#### 1. Install Gerbil via the CA Store
#### 2. Configure Gerbil
Set the network to the one you created earlier.
<img
src="/images/gerbil_config.png"
alt="Gerbil configuration settings in Unraid"
/>
**Important things to consider:**
**Internal Communication:**
Anywhere you see `http://pangolin:3001` must match. The hostname should be the name of the Pangolin container on the docker network you're using. This is because it is routed using the internal docker DNS address. The port must also match the port you have set for the internal port in Pangolin. These defaults will work unless you changed these values earlier when setting up Pangolin.
**WireGuard Port:**
The port you use for WireGuard must also match what you set the port to in the Pangolin config. By default we use a slightly different port than the standard WireGuard port to avoid conflicts with the built in WireGuard server in Unraid.
**HTTP and HTTPS Ports:**
You must open these ports because Traefik will be routed through Gerbil. These ports should match the ports you set in the Traefik config earlier. In the next step, we will set the network mode for Traefik which will close the ports on the Traefik side, and prevent conflicts. Before doing this, if you start the Traefik container at the same time as the Gerbil container with the same ports mapped to the host, you will get an error.
#### 3. Network Traefik Through Gerbil
As discussed earlier we need to network Traefik through Gerbil. This is pretty easy. We will do all of this in the Traefik container settings.
Toggle advanced settings, and add the following to the "Extra Parameters" section.
```bash
--net=container:Gerbil
```
Then, set "Network Type" to "None".
<img
src="/images/traefik_networking.png"
alt="Traefik networking configuration through Gerbil"
/>
#### 4. Start the stack
We recommend to start the whole stack in the following order:
1. Pangolin
2. Gerbil
3. Traefik
#### 5. Port Forwarding
You will need to port forward the WireGuard port you set in the Gerbil config on your network's router. This is so that the client can connect to the server.
#### 6. Verify Tunnels are Functional
Your logs for Gerbil should look something like this:
<Info>
You probably won't have the peer connection messages but in general, you should see the WireGuard interface being started.
</Info>
<img
src="/images/gerbil_logs.png"
alt="Gerbil logs showing WireGuard interface startup"
/>
Log back into the Pangolin dashboard and create a new site with Newt or basic WireGuard. Copy the credentials to your client and connect. You should see the tunnel status change to "Online" after a few moments if the connection is successful. Remember to also monitor the logs on the client and server.

155
self-host/quick-install.mdx Normal file
View File

@@ -0,0 +1,155 @@
---
title: "Quick Install Guide"
description: "Deploy your own Pangolin reverse proxy server in under 10 minutes with our automated installer"
---
## Prerequisites
Before you begin, ensure you have:
- **Linux server** with root access and public IP address
- **Domain name** pointing to your server's IP address for the dashboard
- **Email address** for Let's Encrypt SSL certificates and admin log in
- **Open ports on firewall** for 80 (TCP), 443 (TCP), and 51820 (UDP)
<Tip>
**Recommended**: Ubuntu 20.04+ or Debian 11+ for best compatibility and performance.
</Tip>
## Choose Your Server
Need help choosing? See our [complete VPS guide](/self-host/choosing-a-vps) for suggestions.
## DNS & Networking
Before installing Pangolin, ensure you've set up DNS for your domain(s) and opened the required port on your firewall. See our guide on [DNS & networking](/self-host/dns-and-networking) for more information.
## Installation Process
<Steps>
<Step title="Download the installer">
Connect to your server via SSH and download the installer:
```bash
wget -O installer "https://github.com/fosrl/pangolin/releases/download/${release}/installer_linux_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')"
chmod +x ./installer
```
The installer supports both AMD64 (x86_64) and ARM64 architectures.
</Step>
<Step title="Run the installer">
Execute the installer with root privileges:
```bash
sudo ./installer
```
The installer places all files in the current directory. Move the installer to your desired installation directory before running it.
</Step>
<Step title="Configure basic settings">
The installer will prompt you for essential configuration:
- **Base Domain**: Enter your root domain without subdomains (e.g., `example.com`)
- **Dashboard Domain**: Press Enter to accept the default `pangolin.example.com` or enter a custom domain
- **Let's Encrypt Email**: Provide an email for SSL certificates and admin login
- **Tunneling**: Choose whether to install Gerbil for tunneled connections (default: yes). You can run Pangolin without tunneling. It will function as a standard reverse proxy.
</Step>
<Step title="Configure email (optional)">
<Tip>
Email functionality is optional and can be added later.
</Tip>
Choose whether to enable SMTP email functionality:
- **Default**: No (recommended for initial setup)
- **If enabled**: You'll need SMTP server details (host, port, username, password)
</Step>
<Step title="Start installation">
Confirm that you want to install and start the containers:
- The installer will pull Docker images (pangolin, gerbil, traefik)
- Containers will be started automatically
- This process takes 2-3 minutes depending on your internet connection
You'll see progress indicators as each container is pulled and started.
</Step>
<Step title="Install CrowdSec (optional)">
The installer will ask if you want to install CrowdSec for additional security:
- **Default**: No (recommended for initial setup)
- **If enabled**: You'll need to confirm you're willing to manage CrowdSec configuration
<Warning>
CrowdSec adds complexity and requires manual configuration for optimal security. Only enable if you're comfortable managing it.
</Warning>
<Info>
CrowdSec can be installed later if needed. The basic installation provides sufficient security for most use cases.
</Info>
</Step>
</Steps>
## Post-Installation Setup
Once installation completes successfully, you'll see:
```
Installation complete!
To complete the initial setup, please visit:
https://pangolin.example.com/auth/initial-setup
```
<Steps>
<Step title="Access the dashboard">
Navigate to the URL shown in the installer output:
```
https://<your-dashboard-domain>/auth/initial-setup
```
<Check>
The dashboard should load with SSL certificate automatically configured. It might take a few minutes for the first cert to validate, so don't worry if the brwoser throws an insecure warning.
</Check>
</Step>
<Step title="Create admin account">
Complete the initial admin user setup:
- Enter your admin email address
- Set a strong password
- Verify your email (if email is configured)
<Warning>
Use a strong, unique password for your admin account. This account has full system access.
</Warning>
</Step>
<Step title="Create your first organization">
After logging in:
1. Click "Create Organization"
2. Enter organization name and description
<Check>
You're now ready to start adding applications and configuring your reverse proxy!
</Check>
</Step>
</Steps>
## Video Walkthrough
<iframe
className="w-full aspect-video rounded-xl"
src="https://www.youtube.com/embed/W0uVLjTyAn8"
title="Pangolin Quick Install Guide"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></iframe>

View File

@@ -0,0 +1,128 @@
---
title: "Supporter Program"
description: "Support Pangolin development and remove UI elements with a supporter key"
---
Pangolin self-hosted will always be free and open source, but maintaining the project takes time and resources. The supporter program helps fund ongoing development — including bug fixes, new features, and community support.
## Supporter Tiers
<Tabs>
<Tab title="Limited Supporter ($25)">
**Perfect for small teams**
- **User limit**: 5 or fewer users
- **Support button**: Removed from UI
- **Usage**: Unlimited servers and installations
- **Upgrade**: Available to Full Supporter
<Warning>
Once you add your 6th user, the support button will return. Remove a user or upgrade to Full Supporter to hide it again.
</Warning>
</Tab>
<Tab title="Full Supporter ($95)">
**Perfect for larger teams**
- **User limit**: Unlimited users
- **Support button**: Permanently removed
- **Usage**: Unlimited servers and installations
- **Best value**: For growing teams
<Check>
The support button and other marks will never return, regardless of user count.
</Check>
</Tab>
</Tabs>
<img
src="/images/supporter-tiers.png"
alt="Supporter tier comparison showing Limited vs Full Supporter benefits"
/>
## How to Get Your Supporter Key
<Steps>
<Step title="Purchase a tier">
Go to our [GitHub Sponsors page](https://github.com/sponsors/fosrl) and purchase either:
- **Limited Supporter**: $25 one-time
- **Full Supporter**: $95 one-time
</Step>
<Step title="Get your key">
After purchase, visit [supporters.fossorial.io](https://supporters.fossorial.io) and:
1. Log in with your GitHub account
2. Copy your supporter key
</Step>
<Step title="Redeem in Pangolin">
In your Pangolin dashboard:
1. Click the supporter button
2. Enter your supporter key
3. Click "Redeem"
</Step>
</Steps>
<img
src="/images/redeem-key.png"
alt="Pangolin supporter key redemption interface"
/>
## Frequently Asked Questions
<AccordionGroup>
<Accordion title="How many servers can I use my key on?">
**Unlimited usage**
You can use your supporter key on as many servers and installations as you want. There are no restrictions on the number of deployments.
</Accordion>
<Accordion title="Can I upgrade my tier?">
**Yes, but requires new purchase**
To upgrade from Limited to Full Supporter:
1. Purchase the Full Supporter ($95) tier on GitHub
2. Your account will be automatically upgraded
3. Restart your Pangolin server to update the status
<Warning>
Due to GitHub's tier system, you must purchase the higher tier even if you already have the lower one. This results in an extra donation, which we appreciate!
</Warning>
</Accordion>
<Accordion title="Can I hide the button without paying?">
**Temporary hiding available**
You can click "Hide for 7 days" at the bottom of the supporter dialog to temporarily hide the button without purchasing a supporter key.
</Accordion>
<Accordion title="What if I buy the same tier again?">
**Thanks for the extra donation!**
You can only obtain one supporter key per tier. Additional purchases of the same tier won't change your key, but we appreciate the extra support!
</Accordion>
<Accordion title="Can I get a refund?">
**No refunds available**
GitHub Sponsors does not allow us to refund donations. Please make sure you're comfortable supporting the project before purchasing a tier.
</Accordion>
<Accordion title="What happens if I exceed my user limit?">
**Limited Supporter restrictions**
If you have a Limited Supporter key and add your 6th user:
- The support button will return to the UI
- You can either remove a user or upgrade to Full Supporter
- Your key remains valid for other installations
<Info>
Full Supporter keys have no user limits.
</Info>
</Accordion>
</AccordionGroup>