docs: add new Access Control and Logs documentation pages
- Documented Access Control features (e.g., Device Approvals, Password Rotation, 2FA, Custom Login Pages). - Added detailed descriptions for Logs & Analytics (Access Logs, Request Logs, Action Logs). - Included configuration instructions and feature-specific notes for Pangolin Cloud and Enterprise Edition. Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
+163
@@ -0,0 +1,163 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Cloudflare Proxy
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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 theme={null}
|
||||
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 theme={null}
|
||||
curl ifconfig.io
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Update configuration">
|
||||
Add the IP to your `config.yml`:
|
||||
|
||||
```yaml theme={null}
|
||||
gerbil:
|
||||
base_endpoint: "104.21.16.1" # Replace with your actual IP
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Restart services">
|
||||
Restart Pangolin to apply the changes:
|
||||
|
||||
```bash theme={null}
|
||||
docker-compose restart
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Getting the Real Client IP
|
||||
|
||||
Pangolin needs to know the original client IP address for features like rate limiting and logging. When Cloudflare proxy
|
||||
is enabled, the API server sees Cloudflare's IP instead of the real client IP.
|
||||
|
||||
**Badger**, Pangolin's middleware for Traefik, automatically handles Cloudflare proxy IP extraction. Badger versions
|
||||
1.3.0 and later automatically:
|
||||
|
||||
* Trust Cloudflare IP ranges
|
||||
* Extract the real client IP from the `CF-Connecting-IP` header
|
||||
* Set `X-Real-IP` and `X-Forwarded-For` headers for downstream services
|
||||
|
||||
<Info>
|
||||
**Automatic Configuration**: Pangolin installer versions 1.14.0 and greater automatically add Badger to all Pangolin routes in Traefik. If you're using a newer installer, no manual configuration is needed.
|
||||
</Info>
|
||||
|
||||
#### Manual Configuration
|
||||
|
||||
If you're using an older installer or need to manually configure Badger, add it to your Traefik configuration. Badger
|
||||
must be applied to all routers that handle Pangolin traffic (API, dashboard, and WebSocket routes):
|
||||
|
||||
```yaml title="dynamic_config.yml" theme={null}
|
||||
http:
|
||||
middlewares:
|
||||
badger:
|
||||
plugin:
|
||||
badger:
|
||||
disableForwardAuth: true
|
||||
|
||||
routers:
|
||||
# Next.js router (handles dashboard)
|
||||
next-router:
|
||||
rule: "Host(`pangolin.example.com`) && !PathPrefix(`/api/v1`)"
|
||||
service: next-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
middlewares:
|
||||
- badger
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
|
||||
# API router (handles /api/v1 paths)
|
||||
api-router:
|
||||
rule: "Host(`pangolin.example.com`) && PathPrefix(`/api/v1`)"
|
||||
service: api-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
middlewares:
|
||||
- badger
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
|
||||
# WebSocket router
|
||||
ws-router:
|
||||
rule: "Host(`pangolin.example.com`)"
|
||||
service: api-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
middlewares:
|
||||
- badger
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
```
|
||||
|
||||
**Why Badger is needed**: When `disableForwardAuth: true` is set, Badger extracts the real client IP from Cloudflare
|
||||
proxy headers without performing authentication. This is necessary because forward authentication is only needed for
|
||||
resources controlled by Pangolin, not for the main application routes. However, the main Pangolin containers and APIs
|
||||
still need the real client IP for proper rate limiting and IP tracking.
|
||||
|
||||
#### Pangolin Configuration
|
||||
|
||||
Set `trust_proxy: 2` in your Pangolin config file. This tells Pangolin to trust the second-level proxy (Traefik is proxy
|
||||
1, Cloudflare is proxy 2):
|
||||
|
||||
```yaml theme={null}
|
||||
server:
|
||||
trust_proxy: 2
|
||||
```
|
||||
|
||||
<Warning>
|
||||
**Update Badger**: Ensure you're running Badger version 1.3.0 or later to get real IP addresses in logs for Public resources. Update Badger if you're using an older version.
|
||||
</Warning>
|
||||
|
||||
After making these changes, restart both Traefik and Pangolin for the configuration to take effect.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
If websockets are not connecting like from newt or clients, ensure that websockets are enabled in Cloudflare:
|
||||
|
||||
<Frame>
|
||||
<img src="https://mintcdn.com/fossorial/VqiOoRUR8g1Tf03J/images/cf_websocket_box.png?fit=max&auto=format&n=VqiOoRUR8g1Tf03J&q=85&s=f107b9da12af22813deca776b8f2551e" width="600" centered data-og-width="1100" data-og-height="247" data-path="images/cf_websocket_box.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/VqiOoRUR8g1Tf03J/images/cf_websocket_box.png?w=280&fit=max&auto=format&n=VqiOoRUR8g1Tf03J&q=85&s=adbcd090cb9d1c52973a416aec8edcfc 280w, https://mintcdn.com/fossorial/VqiOoRUR8g1Tf03J/images/cf_websocket_box.png?w=560&fit=max&auto=format&n=VqiOoRUR8g1Tf03J&q=85&s=384b68f10a1253ea2ea2b729a6ac857b 560w, https://mintcdn.com/fossorial/VqiOoRUR8g1Tf03J/images/cf_websocket_box.png?w=840&fit=max&auto=format&n=VqiOoRUR8g1Tf03J&q=85&s=c8b28b64b577908e1b8503e08660e517 840w, https://mintcdn.com/fossorial/VqiOoRUR8g1Tf03J/images/cf_websocket_box.png?w=1100&fit=max&auto=format&n=VqiOoRUR8g1Tf03J&q=85&s=f958b0f1d0850a2719c6929e8ca54093 1100w, https://mintcdn.com/fossorial/VqiOoRUR8g1Tf03J/images/cf_websocket_box.png?w=1650&fit=max&auto=format&n=VqiOoRUR8g1Tf03J&q=85&s=71eafa9f2822cec53e703071adddb595 1650w, https://mintcdn.com/fossorial/VqiOoRUR8g1Tf03J/images/cf_websocket_box.png?w=2500&fit=max&auto=format&n=VqiOoRUR8g1Tf03J&q=85&s=a88c0baa21142f8a6abeeaf2b6436199 2500w" />
|
||||
</Frame>
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Clustering for High Availability
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Note>
|
||||
Clustering is only available in [Enterprise Edition](/self-host/enterprise-edition). [Please reach out to us to deploy](https://pangolin.net/talk-to-us).
|
||||
</Note>
|
||||
|
||||
Deploy multiple Pangolin servers enterprise-grade high availability and performance in large deployments.
|
||||
|
||||
## Overview
|
||||
|
||||
For organizations requiring maximum uptime and performance, Pangolin supports clustered deployments where multiple
|
||||
server instances work together as a unified system. This architecture enables regional distribution, automatic failover,
|
||||
and horizontal scaling to handle demanding production workloads.
|
||||
|
||||
## How Clustering Works
|
||||
|
||||
In a clustered configuration, multiple Pangolin server instances operate together, sharing state and coordinating
|
||||
through a Postgres database and Valkey server. Each instance can independently serve user requests, manage
|
||||
authentication, and coordinate with multiple Gerbil instances to support thousands of sites.
|
||||
|
||||
### Shared Database Backend
|
||||
|
||||
All Pangolin instances connect to a shared PostgreSQL database that stores the system's persistent state - including
|
||||
user accounts, site configurations, resources, access policies, and organizational settings. This ensures that changes
|
||||
made through any server instance are immediately available across the entire cluster.
|
||||
|
||||
### Real-time State Synchronization
|
||||
|
||||
Redis or Valkey provides real-time state synchronization and pub sub between cluster nodes like active sessions,
|
||||
WebSocket connections, and tunnel status. When a user authenticates or a site connector establishes a connection to one
|
||||
Pangolin instance, Redis ensures other nodes are aware of these active sessions for failover.
|
||||
|
||||
### Tunnel Management with Gerbil
|
||||
|
||||
Each Pangolin instance runs alongside its own Gerbil tunnel manager, which handles WireGuard connections to site
|
||||
connectors. When a site connector needs to establish a tunnel, it can connect to any available Gerbil instance in the
|
||||
cluster. For public resources, Gerbil instances are aware of all of the other nodes in the network and can route
|
||||
incoming requests to any other Gerbil to exit through the right site. The distributed architecture ensures that tunnel
|
||||
connectivity remains available even if individual nodes fail.
|
||||
|
||||
## Benefits of Clustering
|
||||
|
||||
**High Availability**: Eliminate single points of failure. If one server instance fails, traffic automatically routes to
|
||||
healthy nodes without user disruption.
|
||||
|
||||
**Regional Distribution**: Deploy servers closer to your users and sites across different geographic regions to minimize
|
||||
latency and improve performance.
|
||||
|
||||
**Horizontal Scaling**: Add more server instances to handle increased load as your organization grows, without
|
||||
architectural changes.
|
||||
|
||||
**Zero-Downtime Updates**: Perform rolling updates by taking nodes offline one at a time while others continue serving
|
||||
traffic.
|
||||
|
||||
## Enterprise Support
|
||||
|
||||
Clustered deployments require careful planning around database replication, Redis configuration, network topology, and
|
||||
monitoring. These advanced architectures are available as part of
|
||||
Pangolin's [Enterprise Edition](/self-host/enterprise-edition) with dedicated support for design, deployment, and
|
||||
ongoing operations.
|
||||
|
||||
For organizations interested in clustering for high availability or regional distribution,
|
||||
please [contact our enterprise team](https://pangolin.net/talk-to-us) to discuss your requirements and receive
|
||||
implementation guidance.
|
||||
|
||||
+859
@@ -0,0 +1,859 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Configuration File
|
||||
|
||||
> Configure Pangolin using the config.yml file with detailed settings for all components
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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" theme={null}
|
||||
# To see all available options, please visit the docs:
|
||||
# https://docs.pangolin.net/
|
||||
|
||||
gerbil:
|
||||
start_port: 51820
|
||||
base_endpoint: "pangolin.example.com" # REPLACE WITH YOUR DOMAIN
|
||||
|
||||
app:
|
||||
dashboard_url: "https://pangolin.example.com" # REPLACE WITH YOUR DOMAIN
|
||||
log_level: "info"
|
||||
telemetry:
|
||||
anonymous_usage: true
|
||||
|
||||
domains:
|
||||
domain1:
|
||||
base_domain: "example.com" # REPLACE WITH YOUR DOMAIN
|
||||
cert_resolver: "letsencrypt"
|
||||
|
||||
server:
|
||||
secret: "your-strong-secret" # REPLACE
|
||||
cors:
|
||||
origins: ["https://pangolin.example.com"] # REPLACE WITH YOUR DOMAIN
|
||||
methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]
|
||||
allowed_headers: ["X-CSRF-Token", "Content-Type"]
|
||||
credentials: false
|
||||
|
||||
flags:
|
||||
require_email_verification: false
|
||||
disable_signup_without_invite: true
|
||||
disable_user_create_org: false
|
||||
allow_raw_resources: true
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Generate a strong secret for `server.secret`. Use at least 32 characters with a mix of letters, numbers, and special characters.
|
||||
|
||||
If you need to CHANGE the server secret after the server has been started you must use the
|
||||
`pangctl rotate-server-secret` command to re-encrypt sensitive
|
||||
data. [Follow docs here](/self-host/advanced/container-cli-tool#rotate-server-secret).
|
||||
</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>
|
||||
|
||||
<ResponseField name="notifications" type="object">
|
||||
Notification configuration settings.
|
||||
|
||||
<Expandable title="Notification">
|
||||
<ResponseField name="product_updates" type="boolean">
|
||||
Whether to enable showing product updates notifications on the UI.
|
||||
|
||||
**Default**: `true`
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="new_releases" type="boolean">
|
||||
Whether to enable showing new releases notifications on the UI.
|
||||
|
||||
**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**: `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.
|
||||
|
||||
If you need to CHANGE the server secret after the server has been started you must use the `pangctl rotate-server-secret` command to re-encrypt sensitive data. [Follow docs here](/self-host/advanced/container-cli-tool#rotate-server-secret).
|
||||
</Warning>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="maxmind_db_path" type="string">
|
||||
Path to the MaxMind GeoIP database file for geolocation features.
|
||||
|
||||
**Example**: `./config/GeoLite2-Country.mmdb`
|
||||
|
||||
<Note>
|
||||
Used for IP geolocation functionality. Requires a MaxMind GeoLite2 or GeoIP2 database file.
|
||||
</Note>
|
||||
</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.
|
||||
|
||||
It is best to add it in the UI for ease of use or when you want the
|
||||
domain to *only be present in the org it was created in*.
|
||||
|
||||
You should create it in the config file for permanence across installs
|
||||
and if you want the domain to be present in all orgs.
|
||||
|
||||
<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>
|
||||
|
||||
<ResponseField name="pp_transport_prefix" type="string">
|
||||
Prefix used for transport-related configurations. References servers transport config in dynamic Traefik file.
|
||||
|
||||
**Example**: `pp-transport-v`
|
||||
|
||||
**Default**: `pp-transport-v`
|
||||
</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="clients_start_port" type="integer">
|
||||
Starting port for client WireGuard relay and hole punch port.
|
||||
|
||||
**Example**: `21820`
|
||||
</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>
|
||||
|
||||
### Organization Settings
|
||||
|
||||
<ResponseField name="orgs" type="object">
|
||||
Organization network configuration settings.
|
||||
|
||||
<Expandable title="Organizations">
|
||||
<ResponseField name="block_size" type="integer">
|
||||
Block size for organization CIDR ranges.
|
||||
|
||||
**Example**: `24`
|
||||
|
||||
**Default**: `24`
|
||||
|
||||
<Note>
|
||||
Determines the subnet size allocated to each organization for network isolation.
|
||||
</Note>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="subnet_group" type="string">
|
||||
IP address CIDR range for organization subnets.
|
||||
|
||||
**Example**: `100.90.128.0/24`
|
||||
|
||||
**Default**: `100.90.128.0/24`
|
||||
|
||||
<Note>
|
||||
Base subnet from which organization-specific subnets are allocated.
|
||||
</Note>
|
||||
</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>
|
||||
|
||||
<ResponseField name="auth" type="object">
|
||||
Rate limit settings specifically for authentication endpoints.
|
||||
|
||||
<Expandable title="Auth Rate Limits">
|
||||
<ResponseField name="window_minutes" type="integer">
|
||||
Time window for authentication rate limiting in minutes.
|
||||
|
||||
**Example**: `1`
|
||||
|
||||
**Default**: `1`
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="max_requests" type="integer">
|
||||
Maximum number of authentication requests allowed in the time window.
|
||||
|
||||
**Example**: `10`
|
||||
|
||||
**Default**: `500`
|
||||
|
||||
<Note>
|
||||
Consider setting this lower than global limits for security.
|
||||
</Note>
|
||||
</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>
|
||||
|
||||
<ResponseField name="disable_local_sites" type="boolean">
|
||||
Whether to disable local site creation and management.
|
||||
|
||||
**Default**: `false`
|
||||
|
||||
<Note>
|
||||
When enabled, users cannot create sites that connect to local networks.
|
||||
</Note>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="disable_basic_wireguard_sites" type="boolean">
|
||||
Whether to disable basic WireGuard site functionality.
|
||||
|
||||
**Default**: `false`
|
||||
|
||||
<Note>
|
||||
When enabled, only advanced WireGuard configurations are allowed.
|
||||
</Note>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="disable_product_help_banners" type="boolean">
|
||||
Whether to disable product help banners in the UI at the top of screens.
|
||||
|
||||
**Default**: `false`
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="disable_config_managed_domains" type="boolean">
|
||||
Whether to disable domains managed through the configuration file.
|
||||
|
||||
**Default**: `false`
|
||||
|
||||
<Note>
|
||||
When enabled, only domains created through the UI are allowed.
|
||||
</Note>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="disable_enterprise_features" type="boolean">
|
||||
Whether to disable features that are only available in the Enterprise Edition from showing in the UI.
|
||||
|
||||
**Default**: `false`
|
||||
|
||||
<Note>
|
||||
When enabled, Enterprise-only features are hidden from the UI.
|
||||
</Note>
|
||||
</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>
|
||||
|
||||
<ResponseField name="replicas" type="array of objects">
|
||||
Read-only replica database configurations for load balancing.
|
||||
|
||||
<Expandable title="Replica Configuration">
|
||||
<ResponseField name="connection_string" type="string" required>
|
||||
Connection string for the read replica database.
|
||||
|
||||
**Example**: `postgresql://user:password@replica-host:port/database`
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="pool" type="object">
|
||||
Database connection pool settings.
|
||||
|
||||
<Expandable title="Pool Settings">
|
||||
<ResponseField name="max_connections" type="integer">
|
||||
Maximum number of connections to the primary database.
|
||||
|
||||
**Default**: `20`
|
||||
|
||||
**Example**: `50`
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="max_replica_connections" type="integer">
|
||||
Maximum number of connections to replica databases.
|
||||
|
||||
**Default**: `10`
|
||||
|
||||
**Example**: `25`
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="idle_timeout_ms" type="integer">
|
||||
Time in milliseconds before idle connections are closed.
|
||||
|
||||
**Default**: `30000` (30 seconds)
|
||||
|
||||
**Example**: `60000`
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="connection_timeout_ms" type="integer">
|
||||
Time in milliseconds to wait for a database connection.
|
||||
|
||||
**Default**: `5000` (5 seconds)
|
||||
|
||||
**Example**: `10000`
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Some configuration values can be set using environment variables for enhanced security:
|
||||
|
||||
| Name | Variable | Config |
|
||||
|------------------------------|------------------------------|------------------------------|
|
||||
| Server Secret | `SERVER_SECRET` | `server.secret` |
|
||||
| Email Password | `EMAIL_SMTP_PASS` | `email.smtp_pass` |
|
||||
| PostgreSQL Connection String | `POSTGRES_CONNECTION_STRING` | `postgres.connection_string` |
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Database Options
|
||||
|
||||
> Configure SQLite or PostgreSQL database for Pangolin
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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" theme={null}
|
||||
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" theme={null}
|
||||
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>
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Enable ASN Blocking
|
||||
|
||||
> Configuration requirements to enable ASN blocking in Pangolin
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
To enable ASN blocking in Pangolin Community you must download and place the Maxmind ASN database into the `config/`
|
||||
directory and update the config file. This can be done for free.
|
||||
|
||||
<Tip>
|
||||
Remember to keep the ASN database updated regularly, as ASN assignments and network mappings can change over time. You can just repeat the download and extraction steps periodically to ensure your database is current.
|
||||
</Tip>
|
||||
|
||||
<Tip>
|
||||
It is possible to automate this process with a Docker container from Maxmind themself.
|
||||
Have a look at this [Community guide](/self-host/community-guides/geolite2automation) on how to implement this!
|
||||
</Tip>
|
||||
|
||||
You can use the installer to download and place the database for you, just grab the latest installer:
|
||||
|
||||
```bash theme={null}
|
||||
curl -fsSL https://static.pangolin.net/get-installer.sh | bash
|
||||
```
|
||||
|
||||
Then run the installer again:
|
||||
|
||||
```bash theme={null}
|
||||
./installer
|
||||
```
|
||||
|
||||
### Manual Installation Steps
|
||||
|
||||
<Steps>
|
||||
<Step title="Download and extract the ASN database">
|
||||
Download and extract the GeoLite2 ASN database using the following commands:
|
||||
|
||||
```bash theme={null}
|
||||
# Download the GeoLite2 ASN database
|
||||
curl -L -o GeoLite2-ASN.tar.gz https://github.com/GitSquared/node-geolite2-redist/raw/refs/heads/master/redist/GeoLite2-ASN.tar.gz
|
||||
|
||||
# Extract the database
|
||||
tar -xzf GeoLite2-ASN.tar.gz
|
||||
|
||||
# Move the .mmdb file to the config directory
|
||||
mv GeoLite2-ASN_*/GeoLite2-ASN.mmdb config/
|
||||
|
||||
# Clean up the downloaded files
|
||||
rm -rf GeoLite2-ASN.tar.gz GeoLite2-ASN_*
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Update the Pangolin config file">
|
||||
Update your Pangolin configuration to point to the new ASN database file. Edit your `config/config.yml` file to include the following entry:
|
||||
|
||||
```yaml theme={null}
|
||||
server:
|
||||
maxmind_asn_path: "./config/GeoLite2-ASN.mmdb"
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Restart Pangolin">
|
||||
Restart your Pangolin instance to apply the changes:
|
||||
|
||||
```bash theme={null}
|
||||
docker compose restart pangolin
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
Alternatively you can create an account at [Maxmind](https://www.maxmind.com/en/geolite2/signup) to get a license key
|
||||
and download the database directly from them.
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Enable Geo-blocking
|
||||
|
||||
> Configuration requirements to enable geoblocking in Pangolin
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
To enable geoblocking in Pangolin Community you must download and place the Maxmind geoip database into the `config/`
|
||||
directory and update the config file. This can be done for free.
|
||||
|
||||
<Tip>
|
||||
Remember to keep the GeoIP database updated regularly, as IP-to-country mappings can change over time. You can just repeat the download and extraction steps periodically to ensure your database is current.
|
||||
</Tip>
|
||||
|
||||
<Tip>
|
||||
It is possible to automate this process with a Docker container from Maxmind themself.
|
||||
Have a look at this [Community guide](/self-host/community-guides/geolite2automation) on how to implement this!
|
||||
</Tip>
|
||||
|
||||
You can use the installer to download and place the database for you, just grab the latest installer:
|
||||
|
||||
```bash theme={null}
|
||||
curl -fsSL https://static.pangolin.net/get-installer.sh | bash
|
||||
```
|
||||
|
||||
Then run the installer again:
|
||||
|
||||
```bash theme={null}
|
||||
./installer
|
||||
```
|
||||
|
||||
### Manual Installation Steps
|
||||
|
||||
<Steps>
|
||||
<Step title="Download and extract the GeoIP database">
|
||||
Download and extract the GeoLite2 Country database using the following commands:
|
||||
|
||||
```bash theme={null}
|
||||
# Download the GeoLite2 Country database
|
||||
curl -L -o GeoLite2-Country.tar.gz https://github.com/GitSquared/node-geolite2-redist/raw/refs/heads/master/redist/GeoLite2-Country.tar.gz
|
||||
|
||||
# Extract the database
|
||||
tar -xzf GeoLite2-Country.tar.gz
|
||||
|
||||
# Move the .mmdb file to the config directory
|
||||
mv GeoLite2-Country_*/GeoLite2-Country.mmdb config/
|
||||
|
||||
# Clean up the downloaded files
|
||||
rm -rf GeoLite2-Country.tar.gz GeoLite2-Country_*
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Update the Pangolin config file">
|
||||
Update your Pangolin configuration to point to the new GeoIP database file. Edit your `config/config.yml` file to include the following entry:
|
||||
|
||||
```yaml theme={null}
|
||||
server:
|
||||
maxmind_db_path: "./config/GeoLite2-Country.mmdb"
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Restart Pangolin">
|
||||
Restart your Pangolin instance to apply the changes:
|
||||
|
||||
```bash theme={null}
|
||||
docker compose restart pangolin
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
Alternatively, you can create an account at [Maxmind](https://www.maxmind.com/en/geolite2/signup) to get a license key
|
||||
and download the database directly from them.
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Enable Integration API
|
||||
|
||||
> Enable and configure the Integration API for external access
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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" theme={null}
|
||||
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" theme={null}
|
||||
server:
|
||||
integration_port: 3003 # Specify different port
|
||||
```
|
||||
|
||||
## Configure Traefik Routing
|
||||
|
||||
Add the following configuration to your `config/traefik/dynamic_config.yml` to expose the Integration API at
|
||||
`https://api.example.com/v1`:
|
||||
|
||||
```yaml title="dynamic_config.yml" theme={null}
|
||||
routers:
|
||||
# Add the following two routers
|
||||
int-api-router-redirect:
|
||||
rule: "Host(`api.example.com`)"
|
||||
service: int-api-service
|
||||
entryPoints:
|
||||
- web
|
||||
middlewares:
|
||||
- redirect-to-https
|
||||
- badger # If you have Badger >=1.3.0 and it's enabled in the middlewares section of the dynamic config
|
||||
|
||||
int-api-router:
|
||||
rule: "Host(`api.example.com`)"
|
||||
service: int-api-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
|
||||
services:
|
||||
# Add the following service
|
||||
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
|
||||
```
|
||||
|
||||
<Frame caption="Swagger UI documentation interface">
|
||||
<img src="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/swagger.png?fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=a64ee1f3a7c40bf4f2bd19fe3cc16de9" alt="Swagger UI Preview" data-og-width="4556" width="4556" data-og-height="2692" height="2692" data-path="images/swagger.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/swagger.png?w=280&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=163c4b68c9f9d9ee2589898f8af8fedf 280w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/swagger.png?w=560&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=6a88ca1b59f96467740945db31eeb486 560w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/swagger.png?w=840&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=336609c2ced100ba26453265a2bcb898 840w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/swagger.png?w=1100&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=2f48f7afc56f2708e0e47e39c22fe14c 1100w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/swagger.png?w=1650&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=5477b386ed0be57412eb78a0cd813ff6 1650w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/swagger.png?w=2500&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=502b80fffd80cb3dc1b8b7ad0a174112 2500w" />
|
||||
</Frame>
|
||||
|
||||
<Note>
|
||||
The Integration API will be accessible at `https://api.example.com/v1` for external applications.
|
||||
</Note>
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Internal CLI (pangctl)
|
||||
|
||||
> Command-line tool for managing your Pangolin instance
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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 theme={null}
|
||||
docker exec -it pangolin pangctl <command>
|
||||
```
|
||||
|
||||
## Available Commands
|
||||
|
||||
To see all available commands:
|
||||
|
||||
```bash theme={null}
|
||||
docker exec -it pangolin pangctl --help
|
||||
```
|
||||
|
||||
## Set Admin Credentials
|
||||
|
||||
Set or reset admin credentials for your Pangolin instance:
|
||||
|
||||
```bash theme={null}
|
||||
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>
|
||||
|
||||
## Clear Exit Nodes
|
||||
|
||||
Clear all exit nodes from the database:
|
||||
|
||||
```bash theme={null}
|
||||
docker exec -it pangolin pangctl clear-exit-nodes
|
||||
```
|
||||
|
||||
<Warning>
|
||||
This command permanently deletes all exit nodes from the database. This action cannot be undone.
|
||||
</Warning>
|
||||
|
||||
## Reset User Security Keys
|
||||
|
||||
Reset a user's security keys (passkeys) by deleting all their webauthn credentials:
|
||||
|
||||
```bash theme={null}
|
||||
docker exec -it pangolin pangctl reset-user-security-keys --email "user@example.com"
|
||||
```
|
||||
|
||||
<Warning>
|
||||
This command permanently deletes all security keys for the specified user. The user will need to re-register their security keys to use passkey authentication again.
|
||||
</Warning>
|
||||
|
||||
## Rotate Server Secret
|
||||
|
||||
Rotate the server secret by decrypting all encrypted values with the old secret and re-encrypting with a new secret.
|
||||
This command updates OIDC IdP configurations and license keys in the database, as well as the config file.
|
||||
|
||||
```bash theme={null}
|
||||
docker exec -it pangolin pangctl rotate-server-secret --old-secret "current-secret" --new-secret "new-secret"
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
* `--old-secret` (required): The current server secret (for verification)
|
||||
* `--new-secret` (required): The new server secret to use (must be at least 8 characters long)
|
||||
* `--force` (optional): Force rotation even if the old secret doesn't match the config file. Use this if you know the
|
||||
old secret is correct but the config file is out of sync.
|
||||
|
||||
<Warning>
|
||||
This command performs a critical operation that affects all encrypted data in your database. Ensure you have a backup before running this command.
|
||||
|
||||
**Important considerations:**
|
||||
|
||||
* The new secret must be at least 8 characters long
|
||||
* The new secret must be different from the old secret
|
||||
* The command verifies the old secret matches the config file (unless `--force` is used)
|
||||
* After rotation, you must restart the server for the new secret to take effect
|
||||
* Using `--force` with an incorrect old secret will cause the rotation to fail or corrupt encrypted data
|
||||
</Warning>
|
||||
|
||||
## Clear License Keys
|
||||
|
||||
Clear all license keys from the database:
|
||||
|
||||
```bash theme={null}
|
||||
docker exec -it pangolin pangctl clear-license-keys
|
||||
```
|
||||
|
||||
<Warning>
|
||||
This command permanently deletes all license keys from the database. This action cannot be undone.
|
||||
</Warning>
|
||||
|
||||
## Delete Client
|
||||
|
||||
Delete a client and all associated data (OLMs, current fingerprint, userClients, approvals). Snapshots are preserved.
|
||||
|
||||
```bash theme={null}
|
||||
docker exec -it pangolin pangctl delete-client --orgId "org-123" --niceId "client-identifier"
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
* `--orgId` (required): The organization ID
|
||||
* `--niceId` (required): The client niceId (identifier)
|
||||
|
||||
<Warning>
|
||||
This command permanently deletes the client and its associated data:
|
||||
|
||||
* All OLMs (One-time Login Mechanisms) associated with the client
|
||||
* Current fingerprint entries
|
||||
* Approval records
|
||||
* UserClient associations
|
||||
|
||||
**Note:** Snapshots are preserved and will not be deleted.
|
||||
|
||||
This action cannot be undone. Ensure you have backups if needed.
|
||||
</Warning>
|
||||
|
||||
@@ -0,0 +1,868 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Metrics
|
||||
|
||||
> Enable and consume OpenTelemetry & vendor specific metrics
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
We provide metrics in the **OpenTelemetry** (OTel) format and additionally support the following vendor backends:
|
||||
|
||||
* **Prometheus** (native scrape and via OTel Collector)
|
||||
|
||||
## Why Metrics & OTel
|
||||
|
||||
Observability enables:
|
||||
|
||||
1. **Incident detection** (latency spikes, reconnect storms)
|
||||
2. **Capacity planning** (bytes, active sessions)
|
||||
3. **User‑experience SLAs** (p95 tunnel latency, auth latency)
|
||||
4. **Faster RCA** (dimensions like `error_type`, `result`)
|
||||
|
||||
OpenTelemetry provides a **vendor‑neutral** pipeline so you can change backends without retouching instrumented code.
|
||||
|
||||
## Availability
|
||||
|
||||
Newt exposes metrics starting from specific releases, but metrics are disabled in their default configuration.
|
||||
|
||||
* Newt: metrics implemented since Newt 1.6.0 (disabled by default)
|
||||
|
||||
## Open Telemetry
|
||||
|
||||
Push metrics and traces to an **OTel Collector** or any backend that accepts OTLP.
|
||||
|
||||
<Tip>
|
||||
If you only enable Prometheus scrape, leave `*_METRICS_OTLP_ENABLED=false` and omit OTLP vars.
|
||||
</Tip>
|
||||
|
||||
<Note>
|
||||
The OTel Collector commonly uses port <code>4317</code> for gRPC and <code>4318</code> for HTTP. Set <code>OTEL\_EXPORTER\_OTLP\_PROTOCOL</code> to <code>http/protobuf</code> for HTTP or <code>grpc</code> for gRPC, and point <code>OTEL\_EXPORTER\_OTLP\_ENDPOINT</code> accordingly.
|
||||
For further customization, see the [OTel Collector documentation](https://opentelemetry.io/docs/collector/).
|
||||
</Note>
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Newt Configuration">
|
||||
<Tabs>
|
||||
<Tab title="Environment Variables">
|
||||
```text theme={null}
|
||||
NEWT_METRICS_OTLP_ENABLED=true # enable OTLP exporter
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT=otel-collector:4317
|
||||
OTEL_EXPORTER_OTLP_INSECURE=true # or false + TLS vars
|
||||
OTEL_METRIC_EXPORT_INTERVAL=15s
|
||||
# Optional auth / TLS
|
||||
OTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer%20XYZ
|
||||
OTEL_EXPORTER_OTLP_CERTIFICATE=/etc/otel/ca.pem
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="CLI Args">
|
||||
```text theme={null}
|
||||
newt \
|
||||
--metrics-otlp-enabled=true \ # alias for otel
|
||||
--otel=true \
|
||||
--otel-exporter-otlp-endpoint=otel-collector:4317 \
|
||||
--otel-exporter-otlp-insecure=true \
|
||||
--otel-metric-export-interval=15s \
|
||||
--otel-exporter-otlp-headers=authorization=Bearer%20XYZ \
|
||||
--otel-exporter-otlp-certificate=/etc/otel/ca.pem
|
||||
```
|
||||
|
||||
See the [CLI reference](../../manage/sites/configure-site) for all available flags.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Newt Configuration Examples">
|
||||
<Tabs>
|
||||
<Tab title="CLI (gRPC)">
|
||||
```bash theme={null}
|
||||
# Enable OTLP exporters and point to your Collector's gRPC receiver.
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317"
|
||||
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
|
||||
|
||||
newt \
|
||||
--otlp=true
|
||||
--id saz281jfa8z37zg
|
||||
--secret ssfdfsder33rrerrwe
|
||||
--endpoint http://pangolin.example.com
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Docker Compose">
|
||||
```yaml title="docker-compose.metrics.yaml" theme={null}
|
||||
services:
|
||||
otel-collector:
|
||||
image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:latest # DO NOT use 'latest' in production
|
||||
command: ["--config=/etc/otel/config.yaml"]
|
||||
volumes:
|
||||
- ./otel-config.yaml:/etc/otel/config.yaml:ro
|
||||
ports:
|
||||
- "4317:4317" # gRPC
|
||||
- "4318:4318" # HTTP
|
||||
- "8888:8888" # Prometheus exporter (from the Collector) - Optional
|
||||
|
||||
newt:
|
||||
image: fosrl/newt:latest # DO NOT use 'latest' in production
|
||||
environment:
|
||||
NEWT_METRICS_OTLP_ENABLED: "true"
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: otel-collector:4317
|
||||
OTEL_EXPORTER_OTLP_INSECURE: "true"
|
||||
PANGOLIN_ENDPOINT: https://example.com
|
||||
NEWT_ID: heresmynewtid
|
||||
NEWT_SECRET: yoursupersecretkeyhere
|
||||
```
|
||||
|
||||
```yaml title="otel-config.yaml" theme={null}
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:4317
|
||||
http:
|
||||
endpoint: 0.0.0.0:4318
|
||||
|
||||
processors: {}
|
||||
|
||||
# Example exporters:
|
||||
exporters:
|
||||
otlp:
|
||||
endpoint: otel-collector:4317
|
||||
insecure: true
|
||||
prometheus:
|
||||
endpoint: "0.0.0.0:8889"
|
||||
|
||||
service:
|
||||
pipelines:
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
processors: []
|
||||
exporters: [prometheus]
|
||||
```
|
||||
|
||||
Forward to Remote Write Backend
|
||||
|
||||
```yaml title="otel-config-remote.yaml" theme={null}
|
||||
exporters:
|
||||
prometheusremotewrite:
|
||||
endpoint: https://prom-remote.example.com/api/v1/write
|
||||
headers:
|
||||
X-Scope-OrgID: tenant-a
|
||||
tls:
|
||||
insecure_skip_verify: false
|
||||
service:
|
||||
pipelines:
|
||||
metrics/remote:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [prometheusremotewrite]
|
||||
```
|
||||
|
||||
<Note>
|
||||
Combine exporters (e.g. local Prometheus + remote write) to retain fast local dashboards and ship long‑term retention externally.
|
||||
</Note>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Prometheus (without OTel Collector)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Newt Configuration">
|
||||
Each service listens on an admin HTTP address (example Newt default `:2112`).
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Environment Variables">
|
||||
```text theme={null}
|
||||
NEWT_METRICS_PROMETHEUS_ENABLED=true # /metrics endpoint
|
||||
NEWT_ADMIN_ADDR=:2112 # admin HTTP address
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="CLI Args">
|
||||
```text theme={null}
|
||||
newt \
|
||||
--metrics-prometheus-enabled=true \ # alias for metrics
|
||||
--metrics=true
|
||||
--admin-addr=:2112 \
|
||||
```
|
||||
|
||||
See the [CLI reference](../../manage/sites/configure-site) for all available flags.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Newt Configuration Examples">
|
||||
<Tabs>
|
||||
<Tab title="CLI">
|
||||
```bash theme={null}
|
||||
newt \
|
||||
--metrics-prometheus-enabled=true \
|
||||
--admin-addr=:2112 \
|
||||
--id saz281jfa8z37zg \
|
||||
--secret ssfdfsder33rrerrwe \
|
||||
--endpoint https://pangolin.example.com
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Docker Compose">
|
||||
```yaml title="docker-compose.metrics.yaml" theme={null}
|
||||
services:
|
||||
newt:
|
||||
image: fosrl/newt:latest # DO NOT use 'latest' in production
|
||||
environment:
|
||||
NEWT_METRICS_OTLP_ENABLED: "true"
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: otel-collector:4317
|
||||
OTEL_EXPORTER_OTLP_INSECURE: "true"
|
||||
PANGOLIN_ENDPOINT: https://example.com
|
||||
NEWT_ID: saz281jfa8z37zg
|
||||
NEWT_SECRET: ssfdfsder33rrerrwe
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Prometheus Scrape Config">
|
||||
```yaml title="prometheus.yml (fragment)" theme={null}
|
||||
scrape_configs:
|
||||
- job_name: pangolin
|
||||
static_configs: [{ targets: ["pangolin:2112"] }]
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Full Metric Reference
|
||||
|
||||
**Version 1.0.0 from 2025-10-28**
|
||||
|
||||
Below are currently implemented metrics for **Newt**.
|
||||
|
||||
* **Metric**: exact metric name
|
||||
* **Instrument & unit**: OTel instrument type and canonical unit
|
||||
* **Purpose**: what the metric conveys / recommended use
|
||||
* **Emission path**: subsystem responsible (for troubleshooting missing data)
|
||||
* **Example series**: representative sample including labels
|
||||
|
||||
<Warning>
|
||||
Names/labels can change between major versions. Avoid hard‑coding full label sets in alerts; prefer existence checks and aggregate functions.
|
||||
</Warning>
|
||||
|
||||
### Newt metrics
|
||||
|
||||
<Tabs>
|
||||
<Tab title="OpenTelemetry (OTel)">
|
||||
<ResponseField name="newt">
|
||||
OpenTelemetry metric instruments exposed by Newt. Expand each section to see individual metrics with labels, units, emission points, and examples.
|
||||
|
||||
<Expandable title="Site & Build">
|
||||
<ResponseField name="newt_site_registrations_total" type="Counter">
|
||||
Counts Pangolin registration attempts keyed by result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `result` (`success`|`failure`), `site_id`\
|
||||
**Emission path:** `telemetry.IncSiteRegistration`\
|
||||
**Example:** `newt_site_registrations_total{result="success",site_id="abc"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_site_online" type="ObservableGauge">
|
||||
0/1 heartbeat for the active site.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `site_id`\
|
||||
**Emission path:** `state.TelemetryView` (callback)\
|
||||
**Example:** `newt_site_online{site_id="self"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_site_last_heartbeat_seconds" type="ObservableGauge">
|
||||
Seconds since last Pangolin heartbeat.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** seconds\
|
||||
**Labels:** `site_id`\
|
||||
**Emission path:** `TouchHeartbeat` (callback)\
|
||||
**Example:** `newt_site_last_heartbeat_seconds{site_id="self"} 3.2`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_build_info" type="ObservableGauge">
|
||||
Constant 1 with build metadata labels.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `version`, `commit`\
|
||||
**Emission path:** Build info registration\
|
||||
**Example:** `newt_build_info{version="1.2.3",commit="abc123"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_restart_count_total" type="Counter">
|
||||
Process boot indicator (increments once per process start).
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** —\
|
||||
**Emission path:** `RegisterBuildInfo`\
|
||||
**Example:** `newt_restart_count_total 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_cert_rotation_total" type="Counter">
|
||||
Certificate rotation events keyed by result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `result`\
|
||||
**Emission path:** `IncCertRotation`\
|
||||
**Example:** `newt_cert_rotation_total{result="success"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_config_reloads_total" type="Counter">
|
||||
Config reload attempts keyed by result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `result`\
|
||||
**Emission path:** `telemetry.IncConfigReload`\
|
||||
**Example:** `newt_config_reloads_total{result="success"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_config_apply_seconds" type="Histogram (s)">
|
||||
Duration per config-apply phase keyed by `phase` and `result`.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** seconds\
|
||||
**Labels:** `phase`, `result`\
|
||||
**Emission path:** `telemetry.ObserveConfigApply`\
|
||||
**Example:** `newt_config_apply_seconds_bucket{phase="peer",result="success",le="0.1"} 3`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
|
||||
<Expandable title="Tunnel">
|
||||
<ResponseField name="newt_tunnel_sessions" type="ObservableGauge">
|
||||
Active sessions per tunnel (or collapsed).
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `site_id`, `tunnel_id`\
|
||||
**Emission path:** `RegisterStateView`\
|
||||
**Example:** `newt_tunnel_sessions{site_id="self",tunnel_id="wgpub"} 2`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_tunnel_bytes_total" type="Counter (bytes)">
|
||||
Traffic per tunnel, direction, and protocol.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** bytes\
|
||||
**Labels:** `tunnel_id`, `direction` (`ingress`|`egress`), `protocol` (`tcp`|`udp`)\
|
||||
**Emission path:** Proxy manager\
|
||||
**Example:** `newt_tunnel_bytes_total{direction="egress",protocol="tcp",tunnel_id="wgpub"} 8192`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_tunnel_latency_seconds" type="Histogram (s)">
|
||||
RTT samples per tunnel/transport.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** seconds\
|
||||
**Labels:** `tunnel_id`, `transport`\
|
||||
**Emission path:** Health checks\
|
||||
**Example:** `newt_tunnel_latency_seconds_bucket{transport="wireguard",le="0.05",tunnel_id="wgpub"} 4`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_tunnel_reconnects_total" type="Counter">
|
||||
Reconnect attempts keyed by initiator & reason.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `tunnel_id`, `initiator` (`client`|`server`), `reason`\
|
||||
**Emission path:** `telemetry.IncReconnect`\
|
||||
**Example:** `newt_tunnel_reconnects_total{initiator="client",reason="timeout",tunnel_id="wgpub"} 3`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
|
||||
<Expandable title="Connection & Auth">
|
||||
<ResponseField name="newt_connection_attempts_total" type="Counter">
|
||||
Auth/WebSocket connection attempts keyed by transport & result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `transport`, `result`\
|
||||
**Emission path:** `telemetry.IncConnAttempt`\
|
||||
**Example:** `newt_connection_attempts_total{transport="websocket",result="failure"} 2`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_connection_errors_total" type="Counter">
|
||||
Connection errors keyed by transport and type.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `transport`, `error_type`\
|
||||
**Emission path:** `telemetry.IncConnError`\
|
||||
**Example:** `newt_connection_errors_total{transport="auth",error_type="auth_failed"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
|
||||
<Expandable title="WebSocket">
|
||||
<ResponseField name="newt_websocket_connect_latency_seconds" type="Histogram (s)">
|
||||
Dial latency for Pangolin WebSocket.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** seconds\
|
||||
**Labels:** `result`, `transport`\
|
||||
**Emission path:** `ObserveWSConnectLatency`\
|
||||
**Example:** `newt_websocket_connect_latency_seconds_bucket{result="success",transport="websocket",le="0.5"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_disconnects_total" type="Counter">
|
||||
WebSocket disconnects keyed by reason.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `reason`, `tunnel_id`\
|
||||
**Emission path:** `IncWSDisconnect`\
|
||||
**Example:** `newt_websocket_disconnects_total{reason="remote_close",tunnel_id="wgpub"} 2`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_keepalive_failures_total" type="Counter">
|
||||
Ping/Pong failures observed by keepalive.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `reason` (e.g., `ping_write`, `pong_timeout`)\
|
||||
**Emission path:** `telemetry.IncWSKeepaliveFailure(ctx, "ping_write")`\
|
||||
**Example:** `newt_websocket_keepalive_failures_total{reason="ping_write"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_session_duration_seconds" type="Histogram (s)">
|
||||
Duration of established WS sessions keyed by result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** seconds\
|
||||
**Labels:** `result` (`success`|`error`)\
|
||||
**Emission path:** `telemetry.ObserveWSSessionDuration(ctx, time.Since(start).Seconds(), "error")`\
|
||||
**Example:** `newt_websocket_session_duration_seconds_bucket{result="error",le="60"} 3`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_connected" type="ObservableGauge">
|
||||
Current WS connection state (0/1).
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** —\
|
||||
**Emission path:** `telemetry.SetWSConnectionState(true|false)`\
|
||||
**Example:** `newt_websocket_connected 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_reconnects_total" type="Counter">
|
||||
WebSocket reconnect attempts keyed by reason.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `reason`\
|
||||
**Emission path:** `telemetry.IncWSReconnect(ctx, "ping_write")`\
|
||||
**Example:** `newt_websocket_reconnects_total{reason="ping_write"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_messages_total" type="Counter">
|
||||
In/out WS messages keyed by direction & type.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `direction` (`in`|`out`), `msg_type` (`ping`|`pong`|`text`|...)\
|
||||
**Emission path:** `IncWSMessage`\
|
||||
**Example:** `newt_websocket_messages_total{direction="out",msg_type="ping"} 4`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
|
||||
<Expandable title="Proxy">
|
||||
<ResponseField name="newt_proxy_active_connections" type="ObservableGauge">
|
||||
Active TCP/UDP proxy connections per tunnel/protocol.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `protocol`, `tunnel_id`\
|
||||
**Emission path:** Proxy callback\
|
||||
**Example:** `newt_proxy_active_connections{protocol="tcp",tunnel_id="wgpub"} 3`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_buffer_bytes" type="ObservableGauge (bytes)">
|
||||
Proxy buffer pool size.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** bytes\
|
||||
**Labels:** `protocol`, `tunnel_id`\
|
||||
**Emission path:** Proxy callback\
|
||||
**Example:** `newt_proxy_buffer_bytes{protocol="tcp",tunnel_id="wgpub"} 10240`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_async_backlog_bytes" type="ObservableGauge (bytes)">
|
||||
Unflushed async byte backlog.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** bytes\
|
||||
**Labels:** `protocol`, `tunnel_id`\
|
||||
**Emission path:** Proxy callback\
|
||||
**Example:** `newt_proxy_async_backlog_bytes{protocol="udp",tunnel_id="wgpub"} 4096`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_drops_total" type="Counter">
|
||||
Proxy write drops keyed by protocol/tunnel.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `protocol`, `tunnel_id`\
|
||||
**Emission path:** `IncProxyDrops`\
|
||||
**Example:** `newt_proxy_drops_total{protocol="udp",tunnel_id="wgpub"} 2`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_accept_total" type="Counter">
|
||||
Proxy accept events keyed by result/reason.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `tunnel_id`, `protocol`, `result`, `reason`\
|
||||
**Emission path:** `telemetry.IncProxyAccept(ctx, tunnelID, "tcp", "failure", "timeout")`\
|
||||
**Example:** `newt_proxy_accept_total{protocol="tcp",result="failure",reason="timeout"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_connections_total" type="Counter">
|
||||
Lifecycle events (opened/closed) per connection.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** 1\
|
||||
**Labels:** `tunnel_id`, `protocol`, `event` (`opened`|`closed`)\
|
||||
**Emission path:** `telemetry.IncProxyConnectionEvent(ctx, tunnelID, "tcp", telemetry.ProxyConnectionOpened)`\
|
||||
**Example:** `newt_proxy_connections_total{protocol="tcp",event="opened"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_connection_duration_seconds" type="Histogram (s)">
|
||||
Duration of completed proxy connections.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Unit:** seconds\
|
||||
**Labels:** `tunnel_id`, `protocol`, `result`\
|
||||
**Emission path:** `telemetry.ObserveProxyConnectionDuration(ctx, tunnelID, "tcp", "success", seconds)`\
|
||||
**Example:** `newt_proxy_connection_duration_seconds_bucket{protocol="tcp",result="success",le="1"} 3`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="Prometheus">
|
||||
<ResponseField name="newt">
|
||||
Prometheus-style series for the same Newt metrics. Names, labels, and examples mirror the OTel tab.
|
||||
|
||||
<Expandable title="Site & Build">
|
||||
<ResponseField name="newt_site_registrations_total" type="counter">
|
||||
Counts Pangolin registration attempts keyed by result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `result`, `site_id` • **Unit:** 1 • **Path:** `telemetry.IncSiteRegistration`\
|
||||
**Example:** `newt_site_registrations_total{result="success",site_id="abc"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_site_online" type="gauge">
|
||||
0/1 heartbeat for the active site.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `site_id` • **Unit:** 1 • **Path:** `state.TelemetryView`\
|
||||
**Example:** `newt_site_online{site_id="self"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_site_last_heartbeat_seconds" type="gauge">
|
||||
Seconds since last Pangolin heartbeat.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `site_id` • **Unit:** seconds • **Path:** `TouchHeartbeat`\
|
||||
**Example:** `newt_site_last_heartbeat_seconds{site_id="self"} 3.2`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_build_info" type="gauge">
|
||||
Constant 1 with build metadata labels.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `version`, `commit` • **Unit:** 1 • **Path:** Build info registration\
|
||||
**Example:** `newt_build_info{version="1.2.3",commit="abc123"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_restart_count_total" type="counter">
|
||||
Process boot indicator (increments once).
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** — • **Unit:** 1 • **Path:** `RegisterBuildInfo`\
|
||||
**Example:** `newt_restart_count_total 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_cert_rotation_total" type="counter">
|
||||
Certificate rotation events keyed by result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `result` • **Unit:** 1 • **Path:** `IncCertRotation`\
|
||||
**Example:** `newt_cert_rotation_total{result="success"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_config_reloads_total" type="counter">
|
||||
Config reload attempts keyed by result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `result` • **Unit:** 1 • **Path:** `telemetry.IncConfigReload`\
|
||||
**Example:** `newt_config_reloads_total{result="success"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_config_apply_seconds" type="histogram">
|
||||
Duration per config-apply phase & result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `phase`, `result` • **Unit:** seconds • **Path:** `telemetry.ObserveConfigApply`\
|
||||
**Example:** `newt_config_apply_seconds_bucket{phase="peer",result="success",le="0.1"} 3`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
|
||||
<Expandable title="Tunnel">
|
||||
<ResponseField name="newt_tunnel_sessions" type="gauge">
|
||||
Active sessions per tunnel (or collapsed).
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `site_id`, `tunnel_id` • **Unit:** 1 • **Path:** `RegisterStateView`\
|
||||
**Example:** `newt_tunnel_sessions{site_id="self",tunnel_id="wgpub"} 2`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_tunnel_bytes_total" type="counter">
|
||||
Traffic per tunnel/direction/protocol.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `tunnel_id`, `direction`, `protocol` • **Unit:** bytes • **Path:** Proxy manager\
|
||||
**Example:** `newt_tunnel_bytes_total{direction="egress",protocol="tcp",tunnel_id="wgpub"} 8192`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_tunnel_latency_seconds" type="histogram">
|
||||
RTT samples per tunnel/transport.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `tunnel_id`, `transport` • **Unit:** seconds • **Path:** Health checks\
|
||||
**Example:** `newt_tunnel_latency_seconds_bucket{transport="wireguard",le="0.05",tunnel_id="wgpub"} 4`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_tunnel_reconnects_total" type="counter">
|
||||
Reconnect attempts by initiator & reason.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `tunnel_id`, `initiator`, `reason` • **Unit:** 1 • **Path:** `telemetry.IncReconnect`\
|
||||
**Example:** `newt_tunnel_reconnects_total{initiator="client",reason="timeout",tunnel_id="wgpub"} 3`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
|
||||
<Expandable title="Connection & Auth">
|
||||
<ResponseField name="newt_connection_attempts_total" type="counter">
|
||||
Auth/WebSocket attempts by transport & result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `transport`, `result` • **Unit:** 1 • **Path:** `telemetry.IncConnAttempt`\
|
||||
**Example:** `newt_connection_attempts_total{transport="websocket",result="failure"} 2`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_connection_errors_total" type="counter">
|
||||
Connection errors by transport and type.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `transport`, `error_type` • **Unit:** 1 • **Path:** `telemetry.IncConnError`\
|
||||
**Example:** `newt_connection_errors_total{transport="auth",error_type="auth_failed"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
|
||||
<Expandable title="WebSocket">
|
||||
<ResponseField name="newt_websocket_connect_latency_seconds" type="histogram">
|
||||
Dial latency for Pangolin WebSocket.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `result`, `transport` • **Unit:** seconds • **Path:** `ObserveWSConnectLatency`\
|
||||
**Example:** `newt_websocket_connect_latency_seconds_bucket{result="success",transport="websocket",le="0.5"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_disconnects_total" type="counter">
|
||||
WS disconnects by reason.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `reason`, `tunnel_id` • **Unit:** 1 • **Path:** `IncWSDisconnect`\
|
||||
**Example:** `newt_websocket_disconnects_total{reason="remote_close",tunnel_id="wgpub"} 2`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_keepalive_failures_total" type="counter">
|
||||
Keepalive Ping/Pong failures.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `reason` • **Unit:** 1 • **Path:** `telemetry.IncWSKeepaliveFailure(ctx, "ping_write")`\
|
||||
**Example:** `newt_websocket_keepalive_failures_total{reason="ping_write"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_session_duration_seconds" type="histogram">
|
||||
Duration of established WebSocket sessions by result.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `result` • **Unit:** seconds • **Path:** `telemetry.ObserveWSSessionDuration(...)`\
|
||||
**Example:** `newt_websocket_session_duration_seconds_bucket{result="error",le="60"} 3`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_connected" type="gauge">
|
||||
Current WS connection status (0/1).
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** — • **Unit:** 1 • **Path:** `telemetry.SetWSConnectionState(true|false)`\
|
||||
**Example:** `newt_websocket_connected 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_reconnects_total" type="counter">
|
||||
Reconnect attempts by reason.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `reason` • **Unit:** 1 • **Path:** `telemetry.IncWSReconnect(ctx, "ping_write")`\
|
||||
**Example:** `newt_websocket_reconnects_total{reason="ping_write"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_websocket_messages_total" type="counter">
|
||||
In/out WS messages by direction & type.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `direction`, `msg_type` • **Unit:** 1 • **Path:** `IncWSMessage`\
|
||||
**Example:** `newt_websocket_messages_total{direction="out",msg_type="ping"} 4`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
|
||||
<Expandable title="Proxy">
|
||||
<ResponseField name="newt_proxy_active_connections" type="gauge">
|
||||
Active TCP/UDP proxy connections per tunnel/protocol.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `protocol`, `tunnel_id` • **Unit:** 1 • **Path:** Proxy callback\
|
||||
**Example:** `newt_proxy_active_connections{protocol="tcp",tunnel_id="wgpub"} 3`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_buffer_bytes" type="gauge">
|
||||
Proxy buffer pool size.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `protocol`, `tunnel_id` • **Unit:** bytes • **Path:** Proxy callback\
|
||||
**Example:** `newt_proxy_buffer_bytes{protocol="tcp",tunnel_id="wgpub"} 10240`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_async_backlog_bytes" type="gauge">
|
||||
Unflushed async byte backlog.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `protocol`, `tunnel_id` • **Unit:** bytes • **Path:** Proxy callback\
|
||||
**Example:** `newt_proxy_async_backlog_bytes{protocol="udp",tunnel_id="wgpub"} 4096`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_drops_total" type="counter">
|
||||
Proxy write drops per protocol/tunnel.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `protocol`, `tunnel_id` • **Unit:** 1 • **Path:** `IncProxyDrops`\
|
||||
**Example:** `newt_proxy_drops_total{protocol="udp",tunnel_id="wgpub"} 2`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_accept_total" type="counter">
|
||||
Proxy accept events by result/reason.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `tunnel_id`, `protocol`, `result`, `reason` • **Unit:** 1 • **Path:** `telemetry.IncProxyAccept(...)`\
|
||||
**Example:** `newt_proxy_accept_total{protocol="tcp",result="failure",reason="timeout"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_connections_total" type="counter">
|
||||
Connection lifecycle events (opened/closed).
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `tunnel_id`, `protocol`, `event` • **Unit:** 1 • **Path:** `telemetry.IncProxyConnectionEvent(...)`\
|
||||
**Example:** `newt_proxy_connections_total{protocol="tcp",event="opened"} 1`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="newt_proxy_connection_duration_seconds" type="histogram">
|
||||
Duration of completed proxy connections.
|
||||
|
||||
<Expandable title="Details">
|
||||
**Labels:** `tunnel_id`, `protocol`, `result` • **Unit:** seconds • **Path:** `telemetry.ObserveProxyConnectionDuration(...)`\
|
||||
**Example:** `newt_proxy_connection_duration_seconds_bucket{protocol="tcp",result="success",le="1"} 3`
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
***
|
||||
|
||||
## References
|
||||
|
||||
* <Link href="https://opentelemetry.io/docs/">OpenTelemetry Documentation</Link>
|
||||
* <Link href="https://prometheus.io/docs/introduction/overview/">Prometheus Documentation</Link>
|
||||
|
||||
<Tip>
|
||||
Have improvements or a missing metric? Open an issue or PR referencing this page.
|
||||
</Tip>
|
||||
|
||||
+240
@@ -0,0 +1,240 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Private Configuration File
|
||||
|
||||
> Configure advanced Pangolin settings using the privateConfig.yml file for enterprise features
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
The `privateConfig.yml` file provides advanced configuration options for enterprise deployments. This file is mounted at
|
||||
`config/privateConfig.yml` in your Docker container.
|
||||
|
||||
<Note>
|
||||
The private configuration file is only used on enterprise deployments. If you're using Pangolin Community, refer to the [main configuration file documentation](/self-host/advanced/config-file) instead. The private config file is not required.
|
||||
</Note>
|
||||
|
||||
## Setting up your `privateConfig.yml`
|
||||
|
||||
Here's a basic example with common settings:
|
||||
|
||||
```yaml title="private-config.yml" theme={null}
|
||||
app:
|
||||
identity_provider_mode: "org"
|
||||
|
||||
branding:
|
||||
app_name: "My Company Portal"
|
||||
hide_auth_layout_footer: false
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
This section contains the complete reference for all configuration options in `private-config.yml`.
|
||||
|
||||
### Application Settings
|
||||
|
||||
<ResponseField name="app" type="object">
|
||||
Regional and base domain configuration for multi-region deployments.
|
||||
|
||||
<Expandable title="properties">
|
||||
<ResponseField name="identity_provider_mode" type="string" default="global">
|
||||
Set the identity provider (IdP) mode for authentication. By default both global and org pages will show until set. See the [Identity Providers documentation](/manage/identity-providers/add-an-idp#identity-provider-types) for more details on how this affects authentication and user management.
|
||||
|
||||
Possible values:
|
||||
|
||||
* `global`: (default) Both global and organization-level IdP login pages are available. Users can authenticate using either global or organization-specific identity providers.
|
||||
* `org`: Only organization-level IdP login pages are available. Users must authenticate using identity providers defined at the organization
|
||||
|
||||
```yaml theme={null}
|
||||
app:
|
||||
identity_provider_mode: "org"
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="region" type="string" default="default">
|
||||
The region identifier for this Pangolin instance. Used for multi-region deployments.
|
||||
|
||||
```yaml theme={null}
|
||||
app:
|
||||
region: "us-east-1"
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
### Server Configuration
|
||||
|
||||
<ResponseField name="server" type="object">
|
||||
Advanced server configuration including encryption keys and API integrations.
|
||||
|
||||
<Expandable title="properties">
|
||||
<ResponseField name="encryption_key" type="string" default="./config/encryption.pem" required>
|
||||
Path to the RSA private key used for encrypting sensitive data. Must be at least 8 characters long. THIS IS ONLY USED WITH pangolin\_dns FEATURE FLAG ENABLED AND REQUIRES EXTERNAL COMPONENTS.
|
||||
|
||||
```yaml theme={null}
|
||||
server:
|
||||
encryption_key_path: "./config/encryption.pem"
|
||||
```
|
||||
|
||||
<Warning>
|
||||
The `encryption_key_path` must point to a valid RSA key file. Generate one using:
|
||||
|
||||
```bash theme={null}
|
||||
openssl genrsa -out encryption.pem 4096
|
||||
```
|
||||
|
||||
Keep this key secure and backed up - it encrypts sensitive data in your database.
|
||||
</Warning>
|
||||
</ResponseField>
|
||||
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
### Redis Configuration
|
||||
|
||||
<ResponseField name="redis" type="object">
|
||||
Redis connection settings for caching, sessions, and rate limiting. Useful for clustering Pangolin nodes.
|
||||
|
||||
<Expandable title="properties">
|
||||
<ResponseField name="host" type="string" required>
|
||||
Redis server hostname or IP address.
|
||||
|
||||
```yaml theme={null}
|
||||
redis:
|
||||
host: "redis.example.com"
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="port" type="number" required>
|
||||
Redis server port (1-65535).
|
||||
|
||||
```yaml theme={null}
|
||||
redis:
|
||||
port: 6379
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="password" type="string">
|
||||
Redis authentication password.
|
||||
|
||||
```yaml theme={null}
|
||||
redis:
|
||||
password: "your-secure-password"
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="db" type="number" default="0">
|
||||
Redis database number (0-15 typically).
|
||||
|
||||
```yaml theme={null}
|
||||
redis:
|
||||
db: 0
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="replicas" type="array">
|
||||
Array of read replica configurations for high-availability deployments.
|
||||
|
||||
```yaml theme={null}
|
||||
redis:
|
||||
host: "redis-primary"
|
||||
port: 6379
|
||||
replicas:
|
||||
- host: "redis-replica-1"
|
||||
port: 6379
|
||||
password: "replica-password"
|
||||
db: 0
|
||||
- host: "redis-replica-2"
|
||||
port: 6379
|
||||
password: "replica-password"
|
||||
db: 0
|
||||
```
|
||||
|
||||
<Expandable title="replica properties">
|
||||
<ResponseField name="host" type="string" required>
|
||||
Replica server hostname.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="port" type="number" required>
|
||||
Replica server port.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="password" type="string">
|
||||
Replica authentication password.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="db" type="number" default="0">
|
||||
Database number on replica.
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
### Gerbil Tunnel Configuration
|
||||
|
||||
<ResponseField name="gerbil" type="object">
|
||||
Configuration for the Gerbil tunnel exit node integration.
|
||||
|
||||
<Expandable title="properties">
|
||||
<ResponseField name="local_exit_node_reachable_at" type="string" default="http://gerbil:3004">
|
||||
URL where the local Gerbil exit node can be reached by Pangolin. Useful when clustering multiple pangolin nodes. Overrides the value stored in the database. Useful when using Docker and address the local gerbil container using the host's address.
|
||||
|
||||
```yaml theme={null}
|
||||
gerbil:
|
||||
local_exit_node_reachable_at: "http://gerbil:3004"
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
### Feature Flags
|
||||
|
||||
<ResponseField name="flags" type="object">
|
||||
Feature toggles for advanced functionality.
|
||||
|
||||
<Expandable title="properties">
|
||||
<ResponseField name="use_org_only_idp" type="boolean" default="false">
|
||||
**DEPRECATED**! See `app.identity_provider_mode: "org"` instead.
|
||||
|
||||
Restrict identity provider (IdP) authentication to organization-level only.
|
||||
|
||||
```yaml theme={null}
|
||||
flags:
|
||||
use_org_only_idp: true
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="enable_redis" type="boolean" default="false">
|
||||
Enable Redis for caching and session management. Requires `redis` configuration.
|
||||
|
||||
```yaml theme={null}
|
||||
flags:
|
||||
enable_redis: true
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="use_pangolin_dns" type="boolean" default="false">
|
||||
Use Pangolin DNS servers for client connections instead of external DNS servers for DNS delegation and CNAME setups. Used for clustering Pangolin nodes. REQUIRES EXTERNAL COMPONENTS. PLEASE CONTACT SUPPORT TO OBTAIN ACCESS BEFORE ENABLING.
|
||||
|
||||
```yaml theme={null}
|
||||
flags:
|
||||
use_pangolin_dns: true
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
### Branding Configuration
|
||||
|
||||
Please refer to the [branding configuration documentation](/manage/branding).
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Telemetry
|
||||
|
||||
> Understanding Pangolin's anonymous usage data collection
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
Pangolin collects anonymous usage telemetry to help us understand how the software is used and guide future improvements
|
||||
and feature development.
|
||||
|
||||
## What We Collect
|
||||
|
||||
The telemetry system collects **anonymous, aggregated data** about your Pangolin deployment. For example:
|
||||
|
||||
* **System metrics**: Number of sites, users, resources, and clients
|
||||
* **Usage patterns**: Resource types, protocols, and SSO configurations
|
||||
* **Performance data**: Site traffic volumes and online status
|
||||
* **Deployment info**: App version and installation timestamp
|
||||
|
||||
## Privacy & Anonymity
|
||||
|
||||
**No personal information is ever collected or transmitted.** All data is:
|
||||
|
||||
* **Anonymized**: Identifying info is hashed using SHA-256
|
||||
* **Non-identifying**: Cannot be used to identify specific users or organizations
|
||||
|
||||
## Configuration
|
||||
|
||||
You can control telemetry collection in your `config.yml`:
|
||||
|
||||
```yaml theme={null}
|
||||
app:
|
||||
telemetry:
|
||||
anonymous_usage: true # Set to false to disable
|
||||
```
|
||||
|
||||
## What This Helps
|
||||
|
||||
Anonymous usage data helps us:
|
||||
|
||||
* Identify popular features and usage patterns
|
||||
* Prioritize development efforts
|
||||
* Improve performance and reliability
|
||||
* Make Pangolin better for everyone
|
||||
|
||||
If you have concerns about telemetry collection, you can disable it entirely by setting `anonymous_usage: false` in your
|
||||
configuration.
|
||||
|
||||
+286
@@ -0,0 +1,286 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Wildcard Domains
|
||||
|
||||
> Configure wildcard SSL certificates for automatic subdomain security with DNS-01 challenge
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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. This is also configurable in the Pangolin dashboard (once restarted).
|
||||
|
||||
```yaml title="config.yml" highlight={4} theme={null}
|
||||
domains:
|
||||
domain1:
|
||||
base_domain: "example.com"
|
||||
prefer_wildcard_cert: true
|
||||
```
|
||||
|
||||
</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} theme={null}
|
||||
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" theme={null}
|
||||
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} theme={null}
|
||||
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={8-12} theme={null}
|
||||
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} theme={null}
|
||||
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} theme={null}
|
||||
{
|
||||
"Certificates": [
|
||||
{
|
||||
"domain": {
|
||||
"main": "example.com",
|
||||
"sans": [
|
||||
"*.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>
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Without Tunneling
|
||||
|
||||
> Use Pangolin as a local reverse proxy without Gerbil tunneling
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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>
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Choosing a VPS
|
||||
|
||||
> Compare hosting options and find the best VPS for your Pangolin deployment
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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
|
||||
</Card>
|
||||
|
||||
<Card title="Recommended Specs">
|
||||
* **CPU**: 2 vCPU
|
||||
* **RAM**: 2GB
|
||||
* **Storage**: 20GB SSD
|
||||
</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 - 1GB RAM VPS" href="https://my.racknerd.com/aff.php?aff=13788&pid=903">
|
||||
**\$11.29/Year**
|
||||
|
||||
* 1 vCPU, 1GB RAM, 24GB SSD, 2TB Bandwidth
|
||||
|
||||
</Card>
|
||||
|
||||
<Card title="RackNerd - 2GB RAM VPS" href="https://my.racknerd.com/aff.php?aff=13788&pid=904">
|
||||
**\$18.29/Year**
|
||||
|
||||
* 1 vCPU, 2GB RAM, 40GB SSD, 3.5TB Bandwidth
|
||||
* Great value for performance
|
||||
|
||||
</Card>
|
||||
|
||||
<Card title="RackNerd - 3.5GB RAM VPS" href="https://my.racknerd.com/aff.php?aff=13788&pid=905">
|
||||
**\$32.49/Year**
|
||||
|
||||
* 2 vCPU, 3.5GB RAM, 65GB SSD, 7TB Bandwidth
|
||||
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## DigitalOcean Marketplace
|
||||
|
||||
Deploy Pangolin with a single click using the DigitalOcean marketplace. The one-click installer automatically provisions
|
||||
a DigitalOcean droplet with Pangolin pre-installed and firewall rules configured.
|
||||
|
||||
<Tip>
|
||||
We're part of the DigitalOcean affiliate program. Using our links helps support Pangolin development at no extra cost to you. If you decide to use the DigitalOcean one-click installer, please use our link.
|
||||
</Tip>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="View App Listing" href="https://marketplace.digitalocean.com/apps/pangolin-ce-1?refcode=edf0480eeb81">
|
||||
View Pangolin on the DigitalOcean marketplace
|
||||
</Card>
|
||||
|
||||
<Card title="Deploy Now (Affiliate Link)" href="https://marketplace.digitalocean.com/apps/pangolin-ce-1?refcode=edf0480eeb81&action=deploy">
|
||||
Create your droplet with Pangolin pre-installed
|
||||
</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 | 24GB SSD | \$0.94 | \$11.29 | Budget users |
|
||||
| **[RackNerd](https://my.racknerd.com/aff.php?aff=13788)** | Basic | 1 vCPU | 2GB | 40GB SSD | \$1.52 | \$18.29 | Small teams |
|
||||
| **[RackNerd](https://my.racknerd.com/aff.php?aff=13788)** | Standard | 2 vCPU | 3.5GB | 65GB SSD | \$2.71 | \$32.49 | 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>
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# CrowdSec
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Note>
|
||||
This is a community guide and is not officially supported. If you have any issues, please reach out to the [author](https://github.com/Lokowitz).
|
||||
</Note>
|
||||
|
||||
CrowdSec is a modern, open-source, collaborative behavior detection engine, integrated with a global IP reputation
|
||||
network. It functions as a massively multiplayer firewall, analyzing visitor behavior and responding appropriately to
|
||||
various types of attacks.
|
||||
|
||||
## Installation
|
||||
|
||||
Crowdsec can be installed using the Pangolin Installer.
|
||||
|
||||
## Configuration
|
||||
|
||||
By default, Crowdsec is installed with a basic configuration, which includes
|
||||
the [Crowdsec Bouncer Traefik plugin](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin).
|
||||
|
||||
### Choose the right logs
|
||||
|
||||
#### Syslog
|
||||
|
||||
For systems utilizing Syslog, the following volumes should be added to the `docker-compose.yml` file:
|
||||
|
||||
```yaml theme={null}
|
||||
service:
|
||||
crowdsec:
|
||||
volumes:
|
||||
- /var/log/auth.log:/var/log/auth.log:ro
|
||||
- /var/log/syslog:/var/log/syslog:ro
|
||||
```
|
||||
|
||||
Create a `syslog.yaml` file under `/config/crowdsec/acquis.d` with the following content:
|
||||
|
||||
```yaml theme={null}
|
||||
filenames:
|
||||
- /var/log/auth.log
|
||||
- /var/log/syslog
|
||||
labels:
|
||||
type: syslog
|
||||
```
|
||||
|
||||
#### Journalctl
|
||||
|
||||
To log iptables to journalctl, execute the following command on your host system:
|
||||
|
||||
```bash theme={null}
|
||||
iptables -A INPUT -j LOG --log-prefix "iptables: "
|
||||
```
|
||||
|
||||
Update the `docker-compose.yml` file as follows:
|
||||
|
||||
```yaml theme={null}
|
||||
service:
|
||||
crowdsec:
|
||||
image: crowdsecurity/crowdsec:latest-debian
|
||||
environment:
|
||||
COLLECTIONS: crowdsecurity/traefik crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules crowdsecurity/linux crowdsecurity/iptables
|
||||
volumes:
|
||||
- ./config/crowdsec:/etc/crowdsec
|
||||
- ./config/crowdsec/db:/var/lib/crowdsec/data
|
||||
- ./config/traefik/logs:/var/log/traefik:ro
|
||||
- /var/log/journal:/var/log/host:ro
|
||||
```
|
||||
|
||||
Create a `journalctl.yaml` file under `/config/crowdsec/acquis.d` with the following content:
|
||||
|
||||
```yaml theme={null}
|
||||
source: journalctl
|
||||
journalctl_filter:
|
||||
- "--directory=/var/log/host/"
|
||||
labels:
|
||||
type: syslog
|
||||
```
|
||||
|
||||
### Securing the Host System (SSH)
|
||||
|
||||
By default, only Traefik requests are secured through the Crowdsec bouncer. To extend protection to your host system (
|
||||
e.g., SSH), follow these steps to add a firewall bouncer:
|
||||
|
||||
1. Install the Crowdsec repositories. Refer to
|
||||
the [installation documentation](https://docs.crowdsec.net/docs/next/getting_started/install_crowdsec/#install-our-repositories):
|
||||
|
||||
```bash theme={null}
|
||||
curl -s https://install.crowdsec.net | sudo sh
|
||||
```
|
||||
|
||||
2. Install the firewall bouncer. For Debian/Ubuntu systems using IPTables, refer to
|
||||
the [documentation](https://docs.crowdsec.net/u/bouncers/firewall/):
|
||||
|
||||
```bash theme={null}
|
||||
sudo apt install crowdsec-firewall-bouncer-iptables
|
||||
```
|
||||
|
||||
3. Create an API key for the firewall bouncer to communicate with your CrowdSec Docker container. ("vps-firewall" is a
|
||||
placeholder name for the key):
|
||||
|
||||
```bash theme={null}
|
||||
docker exec -it crowdsec cscli bouncers add vps-firewall
|
||||
```
|
||||
|
||||
4. Copy the dispalyed API key and insert it into the bouncer's configuration file:
|
||||
|
||||
```bash theme={null}
|
||||
nano /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
|
||||
```
|
||||
|
||||
5. Restart the firewall bouncer:
|
||||
|
||||
```bash theme={null}
|
||||
systemctl restart crowdsec-firewall-bouncer
|
||||
```
|
||||
|
||||
6. Update the `docker-compose.yml` file to expose communication port `8080` for the CrowdSec container and restart the
|
||||
container:
|
||||
|
||||
```yaml theme={null}
|
||||
service:
|
||||
crowdsec:
|
||||
ports:
|
||||
- 6060:6060 # Metrics port
|
||||
- 8080:8080 # Local API port
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Docker’s NAT-based port publishing feature automatically exposes all `ports:` defined in the `docker-compose` file on all network interfaces. This behavior can bypass your host firewall settings, potentially exposing services that you did not intend to make public.
|
||||
Please see [complete warning about exposing ports](/self-host/dns-and-networking).
|
||||
</Warning>
|
||||
|
||||
7. Verify communication between the firewall bouncer and the CrowdSec container by running:
|
||||
|
||||
```bash theme={null}
|
||||
docker exec crowdsec cscli metrics
|
||||
```
|
||||
|
||||
The output should look like this:
|
||||
|
||||
```bash theme={null}
|
||||
+------------------------------------------------------------------+
|
||||
| Local API Bouncers Metrics |
|
||||
+---------------------------+----------------------+--------+------+
|
||||
| Bouncer | Route | Method | Hits |
|
||||
+---------------------------+----------------------+--------+------+
|
||||
| traefik-bouncer | /v1/decisions/stream | HEAD | 2 |
|
||||
| traefik-bouncer@10.0.4.20 | /v1/decisions | GET | 3 |
|
||||
| vps-firewall | /v1/decisions/stream | GET | 84 | <---------
|
||||
+---------------------------+----------------------+--------+------+
|
||||
```
|
||||
|
||||
## Custom Ban Page
|
||||
|
||||
To display a custom ban page to attackers, follow these steps:
|
||||
|
||||
1. Place a `ban.html` page in the `/config/traefik` directory. If you prefer not to create your own, you can download
|
||||
the official example:
|
||||
|
||||
```bash theme={null}
|
||||
wget https://raw.githubusercontent.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/refs/heads/main/ban.html
|
||||
```
|
||||
|
||||
2. Update the `/config/traefik/dynamic_config.yml` file to include the following:
|
||||
|
||||
```yaml theme={null}
|
||||
http:
|
||||
middlewares:
|
||||
crowdsec:
|
||||
plugin:
|
||||
crowdsec:
|
||||
banHTMLFilePath: /etc/traefik/ban.html
|
||||
```
|
||||
|
||||
## Custom Captcha Page
|
||||
|
||||
To use a custom captcha page, follow these steps:
|
||||
|
||||
1. Place a `captcha.html` page in the `/config/traefik` directory. If you don't want to create your own, you can
|
||||
download the official example:
|
||||
|
||||
```bash theme={null}
|
||||
wget https://raw.githubusercontent.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/refs/heads/main/captcha.html
|
||||
```
|
||||
|
||||
2. Update the `/config/traefik/dynamic_config.yml` file with the following configuration, replacing `<SERVICE>` with
|
||||
your captcha provider (MUST BE either `hcaptcha`, `recaptcha`, or `turnstile`), and `<KEY>` with the appropriate site
|
||||
and secret keys:
|
||||
|
||||
```yaml theme={null}
|
||||
http:
|
||||
middlewares:
|
||||
crowdsec:
|
||||
plugin:
|
||||
crowdsec:
|
||||
captchaHTMLFilePath: /etc/traefik/captcha.html
|
||||
captchaGracePeriodSeconds: 300
|
||||
captchaProvider: <SERVICE>
|
||||
captchaSiteKey: <KEY>
|
||||
captchaSecretKey: <KEY>
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
You can test your configuration by adding a temporary ban or captcha for your IP. The ban will last for one minute.
|
||||
|
||||
To add a ban:
|
||||
|
||||
```bash theme={null}
|
||||
docker exec crowdsec cscli decisions add --ip <YOUR IP> -d 1m --type ban
|
||||
```
|
||||
|
||||
To trigger a captcha challenge:
|
||||
|
||||
```bash theme={null}
|
||||
docker exec crowdsec cscli decisions add --ip <YOUR IP> -d 1m --type captcha
|
||||
```
|
||||
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# GeoLite2 Automation
|
||||
|
||||
> A simple automation to download & update your GeoLite2 databases with geoipupdate
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Note>
|
||||
This is a community guide and is not officially supported. If you have any issues, please reach out to the [author](https://github.com/txwgnd).
|
||||
</Note>
|
||||
|
||||
This automation lets your system automatically download & upgrade the `GeoLite2-Country` and `GeoLite2-ASN` databases
|
||||
from Maxmind to use for geoblocking and ASN blocking on your Pangolin host. It's utilizing Maxmind'
|
||||
s [geoipupdate](https://github.com/maxmind/geoipupdate/tree/main) Docker container to achieve this.
|
||||
|
||||
Maxmind's service is free of charge for development, personal or community
|
||||
use. [Quote](https://support.maxmind.com/knowledge-base/articles/create-a-maxmind-account#h_01G4G4NG5C63BQ6HRG6MSS50T3)
|
||||
|
||||
# Table of Contents
|
||||
|
||||
1. **[Requirements](#1-requirements)**
|
||||
2. **[Maxmind Account](#2-maxmind-account)**
|
||||
3. **[API key creation](#3-api-key-creation)**
|
||||
4. **[Modification of Pangolin's `docker-compose.yml`](#4-modification-of-pangolin’s-docker-compose-yml)**
|
||||
5. **[Modification of Pangolin's `config.yml`](#5-modification-of-pangolin’s-config-yml)**
|
||||
|
||||
## 1. Requirements
|
||||
|
||||
* A Maxmind account for API access
|
||||
* Pangolin version 1.11.0 or higher
|
||||
|
||||
## 2. Maxmind Account
|
||||
|
||||
To be able to use Maxmind's service you need to request access to the GeoLite2 databases and create an account on
|
||||
their [website](https://www.maxmind.com/en/geolite2/signup?utm_source=kb\&utm_medium=kb-link\&utm_campaign=kb-create-account).
|
||||
|
||||
After you successfully created an account visit the mainpage again and login to your new account.
|
||||
|
||||
## 3. API key creation
|
||||
|
||||
The next step is to create an API key for `geoipupdate`. You'll find an entry called `Manage license keys` in the menu
|
||||
on the left side. Head to this page and click on `Generate new license key`.
|
||||
|
||||
<Frame caption="Maxmind's Manage license keys page">
|
||||
<img src="https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_manage-license-keys.jpeg?fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=45cc57507e2f28814baceabeac81da9a" alt="Maxmind's Manage license keys page" data-og-width="2792" width="2792" data-og-height="1634" height="1634" data-path="images/maxmind_manage-license-keys.jpeg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_manage-license-keys.jpeg?w=280&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=8180cc300150dfcb01c08083bf78524e 280w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_manage-license-keys.jpeg?w=560&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=d82f7823cc52940ab01c187cb5011a43 560w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_manage-license-keys.jpeg?w=840&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=3a837b0adaa483fe95b414f83765d72b 840w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_manage-license-keys.jpeg?w=1100&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=bbbba78330b1c69004368cad6ada0ef3 1100w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_manage-license-keys.jpeg?w=1650&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=301d34d12c0619bdb1de32a3cc4db17c 1650w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_manage-license-keys.jpeg?w=2500&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=48b6917e61cda0a1b7bb0de946983cb2 2500w" />
|
||||
</Frame>
|
||||
|
||||
Give your new key a name. E.g. `Pangolin`.
|
||||
|
||||
<Frame caption="Choose a name for the key">
|
||||
<img src="https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_create-key-page.jpeg?fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=0558ff4f3da32cc7622bb516b736e72a" alt="Maxmind's key creation page" data-og-width="2014" width="2014" data-og-height="624" height="624" data-path="images/maxmind_create-key-page.jpeg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_create-key-page.jpeg?w=280&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=6e0a7d0eb4fb01c71b06deaf18c3cd24 280w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_create-key-page.jpeg?w=560&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=413dac8ceb1247709542e95be4b5bbdb 560w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_create-key-page.jpeg?w=840&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=dbbd65d58084dfc7151c21663fc041b2 840w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_create-key-page.jpeg?w=1100&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=528a07b151c87eec1fee9a214f969116 1100w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_create-key-page.jpeg?w=1650&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=df460bb545e889b4d92e2ce5fea26c64 1650w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_create-key-page.jpeg?w=2500&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=bec43d2ae69d890c3d61558294bcfdb3 2500w" />
|
||||
</Frame>
|
||||
|
||||
After your key got created the webpage will show you your Account ID as well as the API key. Save the key now because it
|
||||
can only be seen once. Don't panic if something goes wrong, you can easily create new keys.
|
||||
|
||||
<Frame caption="Key successfully created">
|
||||
<img src="https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_key-created.jpeg?fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=538be94f872890457482ecb8ec9289f1" alt="The key got created successfully" data-og-width="1960" width="1960" data-og-height="570" height="570" data-path="images/maxmind_key-created.jpeg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_key-created.jpeg?w=280&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=c45add128f333755e926de48ba54eb50 280w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_key-created.jpeg?w=560&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=0937bac3fecd007a211cd032b9dbda39 560w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_key-created.jpeg?w=840&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=62c6d99d867cdcf78dccc840d5405642 840w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_key-created.jpeg?w=1100&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=8426121d796b806c89453fe8fffee084 1100w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_key-created.jpeg?w=1650&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=3601e6b1ce3c49eb7cccbfb84f93ed29 1650w, https://mintcdn.com/fossorial/WZ4OcypdChdYMxya/images/maxmind_key-created.jpeg?w=2500&fit=max&auto=format&n=WZ4OcypdChdYMxya&q=85&s=fa3446ea791ff59cb1758739a745e37b 2500w" />
|
||||
</Frame>
|
||||
|
||||
After you clicked on `Return to list` you should see an overview of your keys bundled with some metadata.
|
||||
|
||||
## 4. Modification of Pangolin's `docker-compose.yml`
|
||||
|
||||
Now login to your Pangolin host and navigate to `/pangolin` in your user directory:
|
||||
|
||||
```bash theme={null}
|
||||
cd pangolin
|
||||
```
|
||||
|
||||
Shut down Pangolin with:
|
||||
|
||||
```bash theme={null}
|
||||
docker compose down
|
||||
```
|
||||
|
||||
Open `docker-compose.yml` with your favorite text editor.
|
||||
E.g. nano:
|
||||
|
||||
```bash theme={null}
|
||||
nano docker-compose.yml
|
||||
```
|
||||
|
||||
Append this Docker compose service at the end of your stack and add your Account ID as well as your API key you created
|
||||
in the last step:
|
||||
|
||||
```yaml theme={null}
|
||||
services:
|
||||
(...)
|
||||
geoipupdate:
|
||||
container_name: geoipupdate
|
||||
image: ghcr.io/maxmind/geoipupdate
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- 'GEOIPUPDATE_ACCOUNT_ID=' # Account ID
|
||||
- 'GEOIPUPDATE_LICENSE_KEY=' # API key
|
||||
- 'GEOIPUPDATE_EDITION_IDS=GeoLite2-Country GeoLite2-ASN' # Which dbs should be downloaded
|
||||
- 'GEOIPUPDATE_FREQUENCY=72' # Update intervall in hours
|
||||
volumes:
|
||||
- './config/GeoLite2:/usr/share/GeoIP'
|
||||
```
|
||||
|
||||
#### Note
|
||||
|
||||
If you use the standard Pangolin deployment you shouldn't need to modify the path.
|
||||
This is the bare minimum to run the container. There are other optional environment variables available. Have a look at
|
||||
their [docs](https://dev.maxmind.com/geoip/updating-databases/?lang=en)!
|
||||
|
||||
Save and close the file, but don't restart the stack yet!
|
||||
|
||||
## 5. Modification of Pangolin's config.yml
|
||||
|
||||
Navigate to `/config` within the same folder and open it with a text editor.
|
||||
|
||||
```bash theme={null}
|
||||
cd config
|
||||
```
|
||||
|
||||
Add these lines to the `server` object
|
||||
|
||||
```yaml theme={null}
|
||||
server:
|
||||
maxmind_db_path: "./config/GeoLite2/GeoLite2-Country.mmdb"
|
||||
maxmind_asn_path: "./config/GeoLite2/GeoLite2-ASN.mmdb"
|
||||
```
|
||||
|
||||
These entries tell the Pangolin application where to find the databases.
|
||||
|
||||
Save and close the file then navigate to the `pangolin` folder one level higher.
|
||||
|
||||
Restart your Pangolin stack with:
|
||||
|
||||
```bash theme={null}
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Et voilà, you are now able to define country rules and ASN rules for your ressources! 🏁
|
||||
|
||||
btw: you can use these exact databases for your Traefik dashboard
|
||||
too -> [Community Guide](/self-host/community-guides/traefiklogsdashboard)
|
||||
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Home Assistant Add-on
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Note>
|
||||
This is a community add-on and is not officially supported. If you have any issues, please reach out to the [author](https://github.com/Ferdinand99/home-assistant-newt-addon).
|
||||
</Note>
|
||||
|
||||
This Home Assistant add-on allows you to easily run **Newt** directly in Home Assistant. The add-on lets you configure *
|
||||
*PANGOLIN\_ENDPOINT**, **NEWT\_ID**, and **NEWT\_SECRET** via the Home Assistant interface.
|
||||
|
||||
## Features
|
||||
|
||||
* Easy installation via Home Assistant Add-on Store
|
||||
* Automated setup and execution of the Newt container
|
||||
* Supports `amd64`, `armv7`, `armhf`, and `aarch64` architectures
|
||||
* Automatic restart on crash
|
||||
|
||||
## Installation
|
||||
|
||||
### **1. Add the GitHub Repository as an Add-on Source**
|
||||
|
||||
* Go to **Settings → Add-ons → Add-on Store**.
|
||||
* Click the menu (three dots in the top right) and select **Repositories**.
|
||||
* Add the following URL:
|
||||
```
|
||||
https://github.com/Ferdinand99/home-assistant-newt-addon
|
||||
```
|
||||
or
|
||||
```
|
||||
https://git.opland.net/Ferdinand99/home-assistant-newt-addon/
|
||||
```
|
||||
|
||||
1. Click **Add** and wait for the repository to load.
|
||||
|
||||
### **2. Install and Start the Add-on**
|
||||
|
||||
1. Find **Newt Add-on** in the list and click **Install**.
|
||||
2. Go to the **Configuration** tab and enter your values for:
|
||||
* **PANGOLIN\_ENDPOINT** (e.g., `https://example.com`)
|
||||
* **NEWT\_ID**
|
||||
* **NEWT\_SECRET**
|
||||
3. Click **Save** and then **Start**.
|
||||
4. Check the **Logs** tab to verify that everything is running correctly.
|
||||
|
||||
## **Configuration**
|
||||
|
||||
After installation, you can configure the add-on via the Home Assistant UI:
|
||||
|
||||
```yaml theme={null}
|
||||
PANGOLIN_ENDPOINT: "https://example.com"
|
||||
NEWT_ID: "your_newt_id"
|
||||
NEWT_SECRET: "your_newt_secret"
|
||||
```
|
||||
|
||||
### **Docker Environment Variables**
|
||||
|
||||
The following environment variables are passed to the `Newt` container:
|
||||
|
||||
* `PANGOLIN_ENDPOINT`
|
||||
* `NEWT_ID`
|
||||
* `NEWT_SECRET`
|
||||
|
||||
## Exposing Home Assistant through addon
|
||||
|
||||
1. Connect addon to your Pangolin by completing environment variables and starting the addon
|
||||
2. In Pangolin create new HTTP resource for your new Tunnel with subdomain
|
||||
3. Within the created Resource add new Target Configuration
|
||||
|
||||
| Method | IP / Hostname | Port |
|
||||
|--------|---------------|------|
|
||||
| HTTP | 127.0.0.1 | 8123 |
|
||||
|
||||
4. In Home Assistant's `configuration.yaml` add these two sections:
|
||||
|
||||
```yaml theme={null}
|
||||
http:
|
||||
use_x_forwarded_for: true
|
||||
trusted_proxies:
|
||||
- 127.0.0.1
|
||||
homeassistant:
|
||||
allowlist_external_urls:
|
||||
- "https://<subdomain>.example.com" # <-- Replace with URL of created resource in Pangolin
|
||||
```
|
||||
|
||||
4.5: If you want to use SSO Authentication in Pangolin you need to set up the `configuration.yaml` like this:
|
||||
|
||||
```
|
||||
http:
|
||||
cors_allowed_origins:
|
||||
- https://google.com
|
||||
- https://www.home-assistant.io
|
||||
ip_ban_enabled: true
|
||||
login_attempts_threshold: 2
|
||||
use_x_forwarded_for: true
|
||||
trusted_proxies:
|
||||
- 127.0.0.1
|
||||
- Local IP of your NEWT instance
|
||||
- VPS IP
|
||||
```
|
||||
|
||||
You also need to set up `Resource rules` in the pangolin
|
||||
dashboard. [See rule overview here](/manage/access-control/rules).
|
||||
|
||||
Many thanks to steuerlexi for finding this out!
|
||||
|
||||
[https://github.com/fosrl/pangolin/issues/757#issuecomment-2903774897](https://github.com/fosrl/pangolin/issues/757#issuecomment-2903774897)
|
||||
|
||||
<Note>
|
||||
Please see [http](https://www.home-assistant.io/integrations/http/) documentation and [allowlist\_external\_urls](https://www.home-assistant.io/integrations/homeassistant/#external_url) on Home Assistant site.
|
||||
</Note>
|
||||
|
||||
5. Restart Home Assistant and your new Pangolin Proxy should be alive
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
#### **Add-on does not start?**
|
||||
|
||||
* Check the logs in Home Assistant (`Settings → Add-ons → Newt → Logs`).
|
||||
* Ensure that `PANGOLIN_ENDPOINT`, `NEWT_ID`, and `NEWT_SECRET` are set correctly.
|
||||
|
||||
#### **Changes in configuration do not take effect?**
|
||||
|
||||
* Restart the add-on after making changes.
|
||||
|
||||
* Try removing the container manually:
|
||||
|
||||
```shell theme={null}
|
||||
docker stop newt
|
||||
docker rm newt
|
||||
```
|
||||
|
||||
* Then start the add-on again.
|
||||
|
||||
#### **Docker not available?**
|
||||
|
||||
* Home Assistant OS manages Docker automatically, but check if the system has access to Docker by running:
|
||||
```shell theme={null}
|
||||
docker info
|
||||
```
|
||||
|
||||
If this fails, there may be a restriction in Home Assistant OS.
|
||||
|
||||
## Useful Links
|
||||
|
||||
* [HA addon repo](https://github.com/Ferdinand99/home-assistant-newt-addon)
|
||||
* [Home Assistant](https://www.home-assistant.io/)
|
||||
* [Docker Docs](https://docs.docker.com/)
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Metrics
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Note>
|
||||
This is a community guide and is not officially supported. If you have any issues, please reach out to the [author](https://github.com/Lokowitz).
|
||||
</Note>
|
||||
|
||||
This is a basic example of collecting metrics from Traefik and CrowdSec using Prometheus and visualizing them with
|
||||
Grafana dashboards.
|
||||
|
||||
<Warning>
|
||||
Important for users with low-powered server (1GB RAM):
|
||||
This setup will increase the use of your server RAM.
|
||||
</Warning>
|
||||
|
||||
## Configuration
|
||||
|
||||
### Traefik
|
||||
|
||||
For claiming metrics from Traefik we have to adjust some configuration files.
|
||||
|
||||
1. Update the `docker-compose.yml` file of the Pangolin stack to expose metrics port `8082` for the Prometheus
|
||||
connection:
|
||||
|
||||
```yaml theme={null}
|
||||
service:
|
||||
gerbil:
|
||||
ports:
|
||||
- 8082:8082
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Docker’s NAT-based port publishing feature automatically exposes all `ports:` defined in `docker-compose` file. This behavior can bypass your host firewall settings, potentially exposing services that you did not intend to make public.
|
||||
Please see [complete warning about exposing ports](/self-host/dns-and-networking).
|
||||
</Warning>
|
||||
|
||||
2. Update the `/config/traefik/traefik_config.yml` file to include the following:
|
||||
|
||||
```yaml theme={null}
|
||||
entryPoints:
|
||||
metrics:
|
||||
address: ":8082"
|
||||
|
||||
metrics:
|
||||
prometheus:
|
||||
buckets:
|
||||
- 0.1
|
||||
- 0.3
|
||||
- 1.2
|
||||
- 5.0
|
||||
entryPoint: metrics
|
||||
addEntryPointsLabels: true
|
||||
addRoutersLabels: true
|
||||
addServicesLabels: true
|
||||
```
|
||||
|
||||
3. Restart the Gerbil and Traefik container to apply the changes:
|
||||
|
||||
```bash theme={null}
|
||||
sudo docker restart traefik gerbil
|
||||
```
|
||||
|
||||
### Crowdsec
|
||||
|
||||
For claiming metrics from Crowdsec we have to adjust the docker compose files.
|
||||
|
||||
1. Update the `docker-compose.yml` file of the Pangolin stack to expose metrics port `6060` for the Prometheus
|
||||
connection:
|
||||
|
||||
```yaml theme={null}
|
||||
service:
|
||||
crowdsec:
|
||||
ports:
|
||||
- 6060:6060
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Docker’s NAT-based port publishing feature automatically exposes all `ports:` defined in the `docker-compose` file on all network interfaces. This behavior can bypass your host firewall settings, potentially exposing services that you did not intend to make public.
|
||||
Please see [complete warning about exposing ports](/self-host/dns-and-networking).
|
||||
</Warning>
|
||||
|
||||
2. Restart the Crowdsec container to apply the changes:
|
||||
|
||||
```bash theme={null}
|
||||
sudo docker restart crowdsec
|
||||
```
|
||||
|
||||
## Prometheus
|
||||
|
||||
1. Create a new Prometheus container or add it to `docker-compose.yml` of Pangolin stack:
|
||||
|
||||
```yaml theme={null}
|
||||
services:
|
||||
prometheus:
|
||||
container_name: prometheus
|
||||
image: prom/prometheus:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 9090:9090
|
||||
volumes:
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./config/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- ./config/prometheus/data:/prometheus
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Docker’s NAT-based port publishing feature automatically exposes all `ports:` defined in the `docker-compose` file on all network interfaces. This behavior can bypass your host firewall settings, potentially exposing services that you did not intend to make public.
|
||||
Please see [complete warning about exposing ports](/self-host/dns-and-networking).
|
||||
</Warning>
|
||||
|
||||
2. Create a `prometheus.yml` file in the `/config/prometheus` directory with the following content:
|
||||
|
||||
```yaml theme={null}
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: "prometheus"
|
||||
static_configs:
|
||||
- targets: ["localhost:9090"]
|
||||
|
||||
- job_name: traefik
|
||||
static_configs:
|
||||
- targets: ["172.17.0.1:8082"]
|
||||
|
||||
- job_name: crowdsec
|
||||
static_configs:
|
||||
- targets: ["172.17.0.1:6060"]
|
||||
```
|
||||
|
||||
3. Create a folder `data` in `/config/prometheus` and change the owner and owning group:
|
||||
|
||||
```bash theme={null}
|
||||
chown nobody:nogroup data
|
||||
```
|
||||
|
||||
4. Start the Prometheus container:
|
||||
|
||||
```bash theme={null}
|
||||
sudo docker compose up -d
|
||||
```
|
||||
|
||||
## Grafana
|
||||
|
||||
1. Create a new Grafana container or add it to `docker-compose.yml` of Pangolin stack:
|
||||
|
||||
```yaml theme={null}
|
||||
services:
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: grafana
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./config/grafana/data:/var/lib/grafana
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Docker’s NAT-based port publishing feature automatically exposes all `ports:` defined in the `docker-compose` file on all network interfaces. This behavior can bypass your host firewall settings, potentially exposing services that you did not intend to make public.
|
||||
Please see [complete warning about exposing ports](/self-host/dns-and-networking).
|
||||
</Warning>
|
||||
|
||||
2. Start the Grafana container:
|
||||
|
||||
```bash theme={null}
|
||||
sudo docker compose up -d
|
||||
```
|
||||
|
||||
<Note>
|
||||
Default login credentials for Grafana admin user is admin:admin.
|
||||
</Note>
|
||||
|
||||
### Add Prometheus Connection
|
||||
|
||||
Add the Prometheus connection under Connections -> Add new connection.
|
||||
|
||||
Set `http://172.17.0.1:9090` as `Prometheus Server URL` and click `Save & test`.
|
||||
|
||||
### Add Dashboard
|
||||
|
||||
Add a Dashboard under Dashboard -> New -> Import and import a pre configured Dashboard or create your own.
|
||||
|
||||
#### Traefik
|
||||
|
||||
<Frame caption="Traefik Dashboard">
|
||||
<img src="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_dashboard.png?fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=6afb4e81847fffc7aaf6c45686826528" alt="Traefik Dashboard" data-og-width="1842" width="1842" data-og-height="770" height="770" data-path="images/traefik_dashboard.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_dashboard.png?w=280&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=bb9b62a17b2b7e7889158bd2795a01e2 280w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_dashboard.png?w=560&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=7454585b3478a194163804fdbf29e7eb 560w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_dashboard.png?w=840&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=e8f3caea9bb396b433a4c1ae60dddcc1 840w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_dashboard.png?w=1100&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=69121558ea6b5627a12148b50ba2c261 1100w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_dashboard.png?w=1650&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=bf2d1d60bd3d2dcc90b55438c6b668ac 1650w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_dashboard.png?w=2500&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=7c14e820503c65dfcd6ebdc754d3aa82 2500w" />
|
||||
</Frame>
|
||||
|
||||
Template Import ID = 17346
|
||||
|
||||
[https://grafana.com/grafana/dashboards/17346-traefik-official-standalone-dashboard/](https://grafana.com/grafana/dashboards/17346-traefik-official-standalone-dashboard/)
|
||||
|
||||
#### Crowdsec
|
||||
|
||||
[https://github.com/crowdsecurity/grafana-dashboards/tree/master](https://github.com/crowdsecurity/grafana-dashboards/tree/master)
|
||||
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Middleware Manager
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Note>
|
||||
This is a community guide and not officially supported. For issues, contributions, or bug reports, please use the [official GitHub repository](https://github.com/hhftechnology/middleware-manager).
|
||||
</Note>
|
||||
|
||||
## What is Middleware Manager?
|
||||
|
||||
The **Middleware Manager** is a microservice that extends your existing traefik deployments.\
|
||||
It provides a **web UI** to attach Traefik middlewares to resources without editing Pangolin itself.
|
||||
|
||||
#### Security Warning
|
||||
|
||||
Middlewares can strengthen security but also create vulnerabilities if misconfigured.
|
||||
|
||||
* Test in staging before production.
|
||||
* Misusing forward authentication can leak credentials.
|
||||
* Bad rate limiter configs may be bypassed.
|
||||
* Header misconfigurations can expose apps to XSS/CSRF.
|
||||
* Stacking too many middlewares impacts performance.
|
||||
* Always check provider references (`@http` vs `@file`).
|
||||
|
||||
***
|
||||
|
||||
### Key Use Cases
|
||||
|
||||
* External authentication (Authelia, Authentik, JWT)
|
||||
* Security headers and CSP policies
|
||||
* Geographic IP blocking
|
||||
* Rate limiting / DDoS protection
|
||||
* Redirects & path rewrites
|
||||
* CrowdSec and other security tool integrations
|
||||
|
||||
***
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* A running **Pangolin v1.0.0+**
|
||||
* Docker + Docker Compose
|
||||
* Basic Traefik knowledge
|
||||
* Admin access to your Pangolin host
|
||||
|
||||
***
|
||||
|
||||
## Step 1: Add Middleware Manager Service
|
||||
|
||||
Update your `docker-compose.yml`:
|
||||
|
||||
```yaml theme={null}
|
||||
middleware-manager:
|
||||
image: hhftechnology/middleware-manager:latest
|
||||
container_name: middleware-manager
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./config/traefik/rules:/conf
|
||||
- ./config/middleware-manager/templates.yaml:/app/config/templates.yaml # Optional custom templates
|
||||
environment:
|
||||
- PANGOLIN_API_URL=http://pangolin:3001/api/v1
|
||||
- TRAEFIK_CONF_DIR=/conf
|
||||
- DB_PATH=/data/middleware.db
|
||||
- PORT=3456
|
||||
ports:
|
||||
- "3456:3456"
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Step 2: Create Required Directories
|
||||
|
||||
```bash theme={null}
|
||||
mkdir -p ./config/traefik/rules
|
||||
mkdir -p ./config/middleware-manager
|
||||
```
|
||||
|
||||
Move any dynamic configs into `./config/traefik/rules`.
|
||||
|
||||
***
|
||||
|
||||
## Step 3: Update Traefik Volumes & Providers
|
||||
|
||||
In your `traefik` service:
|
||||
|
||||
```yaml theme={null}
|
||||
volumes:
|
||||
- ./config/traefik:/etc/traefik:ro
|
||||
- ./config/letsencrypt:/letsencrypt
|
||||
- ./config/traefik/logs:/var/log/traefik
|
||||
- ./config/traefik/rules:/rules # required
|
||||
```
|
||||
|
||||
In `traefik_config.yml`:
|
||||
|
||||
```yaml theme={null}
|
||||
providers:
|
||||
file:
|
||||
directory: "/rules"
|
||||
watch: true
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Step 4: Start Services
|
||||
|
||||
```bash theme={null}
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Step 5: Access the UI
|
||||
|
||||
Middleware Manager runs at:
|
||||
👉 [http://localhost:3456](http://localhost:3456)
|
||||
|
||||
***
|
||||
|
||||
## Common Middleware Examples
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
```yaml theme={null}
|
||||
middlewares:
|
||||
- id: "rate-limit"
|
||||
type: "rateLimit"
|
||||
config:
|
||||
average: 100
|
||||
burst: 50
|
||||
```
|
||||
|
||||
### Security Headers
|
||||
|
||||
```yaml theme={null}
|
||||
middlewares:
|
||||
- id: "security-headers"
|
||||
type: "headers"
|
||||
config:
|
||||
customResponseHeaders:
|
||||
Server: ""
|
||||
X-Powered-By: ""
|
||||
browserXSSFilter: true
|
||||
contentTypeNosniff: true
|
||||
forceSTSHeader: true
|
||||
stsSeconds: 63072000
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* **Service does not exist** → Check `@http` or `@file` suffix in references
|
||||
* **Middleware does not exist** → Verify config and required plugins
|
||||
* **No changes applied** → Check Traefik logs, middleware priority, restart services
|
||||
* **UI not showing resources** → Confirm `PANGOLIN_API_URL` and network connectivity
|
||||
* **Database errors** → Check `./data` permissions, or reset `middleware.db`
|
||||
* \*\*CrowdSec errors → Ensure the crowdsec container is running; middlewares fail if the service is down.
|
||||
* **Protecting Pangolin itself** → Apply middlewares (e.g. geoblock, headers) directly on the websecure entryPoint to
|
||||
cover all traffic.
|
||||
* **Applying to many services** → Attach middleware to entryPoints instead of individual resources to cover all
|
||||
subdomains at once.
|
||||
* **TCP / SMTP with STARTTLS** → Not supported. Traefik cannot handle STARTTLS negotiation (only implicit TLS like SMTPS
|
||||
on 465).
|
||||
|
||||
***
|
||||
|
||||
## Final Notes
|
||||
|
||||
The Middleware Manager gives you a UI to work with Traefik’s powerful middleware ecosystem.
|
||||
|
||||
* Start with simple configs → test thoroughly → expand gradually.
|
||||
* Use templates where possible.
|
||||
* Always validate in staging before production.
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Overview
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Note>
|
||||
These are community written guides and are not officially supported. If you have any issues, please reach out to the authors or the community on [Discord](https://pangolin.net/discord) or [Github discussions](https://github.com/orgs/fosrl/discussions).
|
||||
</Note>
|
||||
|
||||
The modular design of this system enables the extension of its functionality through the integration of existing Traefik
|
||||
plugins, such as Crowdsec and Geoblock.
|
||||
Additionally, Prometheus can collect metrics from both CrowdSec and Traefik, which can then be visualized in Grafana to
|
||||
monitor security events, request statistics, and traffic patterns in real time.
|
||||
|
||||
## Traefik plugins
|
||||
|
||||
For a complete list of available plugins, please refer to the [Plugin Catalog](https://plugins.traefik.io/plugins).
|
||||
|
||||
### Crowdsec Bouncer
|
||||
|
||||
When installing Crowdsec via the Pangolin installer, the Crowdsec Traefik Bouncer will be automatically installed and
|
||||
configured by default. The configuration can be customized to meet your specific requirements.
|
||||
|
||||
The CrowdSec Bouncer plugin for Traefik integrates CrowdSec’s security engine to block malicious traffic in real time.
|
||||
It runs as middleware within a Traefik container and enforces decisions based on CrowdSec’s threat intelligence. This
|
||||
helps protect services from bots, attackers, and abusive IPs dynamically.
|
||||
|
||||
For additional information, consult the following resources:
|
||||
|
||||
* [Traefik Plugin Catalog](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin)
|
||||
* [Github Repository](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin)
|
||||
|
||||
### Geoblock
|
||||
|
||||
The GeoBlock plugin for Traefik is a middleware that restricts access based on the client’s geographic location. It runs
|
||||
within a Traefik container and uses IP-based geolocation to allow or block traffic from specific countries. This is
|
||||
useful for security, compliance, or access control in Traefik-managed services.
|
||||
|
||||
<Note>
|
||||
Pangolin now supports native geoblocking. The GeoBlock plugin is considered legacy in Pangolin setups. If you previously installed it, follow [Remove GeoBlock Plugin](/self-host/community-guides/remove-geoblock-plugin) before enabling native geoblocking.
|
||||
</Note>
|
||||
|
||||
For more details, please refer to the following resources:
|
||||
|
||||
* [Github Repository](https://github.com/PascalMinder/geoblock)
|
||||
|
||||
### Middleware Manager
|
||||
|
||||
The Middlware manager is a microservice that allows you to add custom middleware to Pangolin / Traefik resources.
|
||||
|
||||
For more details, please refer to the following resources:
|
||||
|
||||
* [Github Repository](https://github.com/hhftechnology/middleware-manager)
|
||||
|
||||
## Metrics
|
||||
|
||||
Currently you can claim metric data from Traefik and Crowdsec with Prometheus and visualize it within a Grafana
|
||||
Dashboard.
|
||||
|
||||
### Prometheus
|
||||
|
||||
Prometheus is an open-source monitoring and alerting toolkit designed for collecting and querying time-series metrics.
|
||||
It runs as a Docker container and uses a pull-based model to scrape data from configured endpoints. Prometheus
|
||||
integrates well with Grafana for visualization and Alertmanager for alert handling.
|
||||
|
||||
For more details, please refer to the following resources:
|
||||
|
||||
* [Homepage](https://prometheus.io/)
|
||||
* [Github Repository](https://github.com/prometheus/prometheus)
|
||||
|
||||
### Grafana
|
||||
|
||||
Grafana is an open-source analytics and visualization platform used to monitor and display time-series data. It runs as
|
||||
a Docker container and supports multiple data sources, including Prometheus, InfluxDB, and MySQL. Grafana provides
|
||||
interactive dashboards, alerting, and extensive customization options for data visualization.
|
||||
|
||||
For more details, please refer to the following resources:
|
||||
|
||||
* [Homepage](https://grafana.com/)
|
||||
* [Github Repository](https://github.com/grafana/grafana)
|
||||
|
||||
### Traefik Logs Dashboard
|
||||
|
||||
The Traefik Logs Dashboard is a real-time dashboard for analyzing Traefik logs with IP geolocation, status code
|
||||
analysis, and service metrics.
|
||||
|
||||
For more details, please refer to the following resources:
|
||||
|
||||
* [Github Repository](https://github.com/hhftechnology/traefik-log-dashboard)
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Remove GeoBlock Plugin
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Note>
|
||||
This is a community guide and is not officially supported. If you have any issues, please reach out to the community on [Discord](https://pangolin.net/discord) or [Github discussions](https://github.com/orgs/fosrl/discussions).
|
||||
</Note>
|
||||
|
||||
Pangolin now supports native geoblocking. If you previously installed the Traefik GeoBlock plugin, remove it before
|
||||
enabling native geoblocking to avoid duplicate blocking or startup errors.
|
||||
|
||||
<Note>
|
||||
After cleanup, follow [Enable Geo-blocking](/self-host/advanced/enable-geoblocking) to configure native geoblocking in Pangolin.
|
||||
</Note>
|
||||
|
||||
## Remove the GeoBlock plugin
|
||||
|
||||
<Steps>
|
||||
<Step title="Remove GeoBlock middleware references">
|
||||
Remove any references to `geoblock@file` from your Traefik entry points, routers, or labels.
|
||||
|
||||
Example removal in `/config/traefik/traefik_config.yml`:
|
||||
|
||||
```yaml theme={null}
|
||||
entryPoints:
|
||||
websecure:
|
||||
http:
|
||||
middlewares:
|
||||
# Remove this line
|
||||
- geoblock@file
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Remove the plugin definition from Traefik static config">
|
||||
Delete the GeoBlock plugin block from `/config/traefik/traefik_config.yml`:
|
||||
|
||||
```yaml theme={null}
|
||||
experimental:
|
||||
plugins:
|
||||
geoblock:
|
||||
moduleName: github.com/PascalMinder/geoblock
|
||||
version: v0.3.2
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Remove the middleware configuration from dynamic config">
|
||||
Delete the GeoBlock middleware section from `/config/traefik/dynamic_config.yml`:
|
||||
|
||||
```yaml theme={null}
|
||||
http:
|
||||
middlewares:
|
||||
geoblock:
|
||||
plugin:
|
||||
geoblock:
|
||||
...
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Restart Traefik">
|
||||
Restart Traefik to apply the changes:
|
||||
|
||||
```bash theme={null}
|
||||
docker restart traefik
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Next steps
|
||||
|
||||
Follow [Enable Geo-blocking](/self-host/advanced/enable-geoblocking) to configure native geoblocking in Pangolin.
|
||||
|
||||
+302
@@ -0,0 +1,302 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Traefik Log Dashboard (v2 – Agent Architecture)
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Note>
|
||||
This is a community guide and is not officially supported. For issues or advanced configuration, please visit the [official repository](https://github.com/hhftechnology/traefik-log-dashboard).
|
||||
</Note>
|
||||
|
||||
If you’re already using the **Pangolin stack with Traefik as your reverse proxy**, you already have robust routing in
|
||||
place.\
|
||||
However, raw logs can be hard to interpret — making it difficult to visualize request patterns, latency, and geographic
|
||||
origins.
|
||||
|
||||
The **new Traefik Log Dashboard (v2)** introduces a **lightweight agent-based architecture** with **multi-instance
|
||||
scalability, enhanced GeoIP analytics, and a modern Next.js frontend** for real-time insights into your Traefik traffic.
|
||||
|
||||
***
|
||||
|
||||
## Highlights (New in v2)
|
||||
|
||||
* **Agent-based architecture**: The Go-powered agent parses logs, exposes metrics, and supports multiple Traefik
|
||||
instances.
|
||||
* **Multi-agent support**: Monitor multiple Traefik setups (e.g., production, staging) from one dashboard.
|
||||
* **Next.js 14 frontend**: Real-time charts, filters, and system stats in a responsive UI.
|
||||
* **Enhanced GeoIP**: Supports both **City** and **Country** MaxMind databases.
|
||||
* **System monitoring**: Built-in CPU, memory, and disk tracking.
|
||||
* **Bearer token authentication**: Secure access between dashboard and agents.
|
||||
* **Backward compatible** with existing Traefik log setups.
|
||||
|
||||
***
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* Docker + Docker Compose
|
||||
* Traefik v2.x or v3.x (logs in JSON format)
|
||||
* A working **Pangolin stack**
|
||||
* (Optional) MaxMind GeoLite2 databases (City + Country)
|
||||
|
||||
***
|
||||
|
||||
## Step 1: Configure Traefik Logs
|
||||
|
||||
Ensure Traefik is outputting **JSON logs** and **access logs** are written to a file.
|
||||
|
||||
Update your `./config/traefik/traefik_config.yml`:
|
||||
|
||||
```yaml theme={null}
|
||||
log:
|
||||
level: INFO
|
||||
filePath: "/var/log/traefik/traefik.log"
|
||||
format: json
|
||||
|
||||
accessLog:
|
||||
filePath: "/var/log/traefik/access.log"
|
||||
format: json
|
||||
fields:
|
||||
defaultMode: keep
|
||||
headers:
|
||||
defaultMode: keep
|
||||
```
|
||||
|
||||
> Tip: JSON format is required for accurate parsing by the new agent.
|
||||
|
||||
***
|
||||
|
||||
## Step 2: Add Dashboard and Agent Services
|
||||
|
||||
Extend your existing `docker-compose.yml` with the new services.
|
||||
|
||||
```yaml theme={null}
|
||||
# Traefik Log Dashboard Agent
|
||||
traefik-agent:
|
||||
image: hhftechnology/traefik-log-dashboard-agent:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "5000:5000"
|
||||
volumes:
|
||||
- ./data/positions:/data
|
||||
- ./config/traefik/logs:/logs:ro
|
||||
- ./config/maxmind:/geoip:ro
|
||||
environment:
|
||||
# Log Paths
|
||||
- TRAEFIK_LOG_DASHBOARD_ACCESS_PATH=/logs/access.log
|
||||
- TRAEFIK_LOG_DASHBOARD_ERROR_PATH=/logs/traefik.log
|
||||
|
||||
# Authentication
|
||||
- TRAEFIK_LOG_DASHBOARD_AUTH_TOKEN=YOUR_API_TOKEN
|
||||
|
||||
# System Monitoring
|
||||
- TRAEFIK_LOG_DASHBOARD_SYSTEM_MONITORING=true
|
||||
|
||||
# GeoIP Configuration
|
||||
- TRAEFIK_LOG_DASHBOARD_GEOIP_ENABLED=true
|
||||
- TRAEFIK_LOG_DASHBOARD_GEOIP_CITY_DB=/geoip/GeoLite2-City.mmdb
|
||||
- TRAEFIK_LOG_DASHBOARD_GEOIP_COUNTRY_DB=/geoip/GeoLite2-Country.mmdb
|
||||
|
||||
# Log Format
|
||||
- TRAEFIK_LOG_DASHBOARD_LOG_FORMAT=json
|
||||
|
||||
# Server Port
|
||||
- PORT=5000
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5000/api/logs/status"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
# Traefik Log Dashboard - Web UI
|
||||
traefik-dashboard:
|
||||
image: hhftechnology/traefik-log-dashboard:latest
|
||||
container_name: traefik-log-dashboard
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
# Agent Configuration
|
||||
- AGENT_API_URL=http://traefik-agent:5000
|
||||
- AGENT_API_TOKEN=YOUR_API_TOKEN
|
||||
- NODE_ENV=production
|
||||
- PORT=3000
|
||||
depends_on:
|
||||
traefik-agent:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
```
|
||||
|
||||
Please replace the YOUR\_API\_TOKEN with a secure token of your choice.
|
||||
|
||||
> Note: The new agent replaces both `log-dashboard-backend` and `log-dashboard-frontend` from the previous guide.
|
||||
|
||||
***
|
||||
|
||||
## Step 3: Setup MaxMind GeoIP (City + Country)
|
||||
|
||||
GeoIP is optional but highly recommended for geographic analytics and maps.
|
||||
|
||||
### 1. Create a free MaxMind account
|
||||
|
||||
[GeoLite2 Signup](https://www.maxmind.com/en/geolite2/signup)
|
||||
Generate a license key and export it for Docker use:
|
||||
|
||||
```bash theme={null}
|
||||
export MAXMIND_LICENSE_KEY=your_license_key_here
|
||||
mkdir -p ./config/maxmind
|
||||
```
|
||||
|
||||
### 2. Add the GeoIP Database Updater
|
||||
|
||||
Append this to your `docker-compose.yml`:
|
||||
|
||||
```yaml theme={null}
|
||||
# Optional: MaxMind GeoIP Database Updater
|
||||
maxmind-updater:
|
||||
image: alpine:latest
|
||||
restart: "no"
|
||||
volumes:
|
||||
- ./config/maxmind:/data
|
||||
environment:
|
||||
- MAXMIND_LICENSE_KEY=${MAXMIND_LICENSE_KEY:-your-license-key-here}
|
||||
command: >
|
||||
sh -c "
|
||||
apk add --no-cache wget tar &&
|
||||
cd /data &&
|
||||
if [ ! -f GeoLite2-City.mmdb ] || [ \"$(find . -name 'GeoLite2-City.mmdb' -mtime +7)\" ]; then
|
||||
echo 'Updating GeoLite2-City database...'
|
||||
wget -O GeoLite2-City.tar.gz 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=${MAXMIND_LICENSE_KEY}&suffix=tar.gz' &&
|
||||
tar --wildcards -xzf GeoLite2-City.tar.gz --strip-components=1 '*/GeoLite2-City.mmdb' &&
|
||||
rm -f GeoLite2-City.tar.gz
|
||||
fi &&
|
||||
if [ ! -f GeoLite2-Country.mmdb ] || [ \"$(find . -name 'GeoLite2-Country.mmdb' -mtime +7)\" ]; then
|
||||
echo 'Updating GeoLite2-Country database...'
|
||||
wget -O GeoLite2-Country.tar.gz 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=${MAXMIND_LICENSE_KEY}&suffix=tar.gz' &&
|
||||
tar --wildcards -xzf GeoLite2-Country.tar.gz --strip-components=1 '*/GeoLite2-Country.mmdb' &&
|
||||
rm -f GeoLite2-Country.tar.gz
|
||||
fi &&
|
||||
echo 'GeoIP databases updated successfully.'
|
||||
"
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Step 4: Launch the Stack
|
||||
|
||||
```bash theme={null}
|
||||
docker compose up -d
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Step 5: Access the Dashboard
|
||||
|
||||
* **Web UI** → [http://localhost:3000](http://localhost:3000)
|
||||
* Default data source: `traefik-agent:5000`
|
||||
|
||||
You should see real-time traffic metrics, GeoIP maps, error tracking, and system performance indicators.
|
||||
|
||||
***
|
||||
|
||||
## Key Features
|
||||
|
||||
**Real-time analytics** for request rates, response times, and errors
|
||||
**GeoIP maps** with both City and Country-level resolution
|
||||
**System health** (CPU, memory, disk)
|
||||
**Multi-agent support** (monitor multiple Traefik instances)
|
||||
**Secure API authentication** via token
|
||||
**Responsive modern UI**
|
||||
|
||||
***
|
||||
|
||||
## Advanced: Multi-Agent Setup
|
||||
|
||||
You can deploy multiple `traefik-agent` instances across environments and connect them all to a single dashboard.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml theme={null}
|
||||
traefik-agent-prod:
|
||||
image: hhftechnology/traefik-log-dashboard-agent:latest
|
||||
ports: ["5000:5000"]
|
||||
environment:
|
||||
- TRAEFIK_LOG_DASHBOARD_AUTH_TOKEN=prod_token
|
||||
- TRAEFIK_LOG_DASHBOARD_ACCESS_PATH=/logs/access.log
|
||||
- TRAEFIK_LOG_DASHBOARD_GEOIP_ENABLED=true
|
||||
volumes:
|
||||
- /var/log/traefik/prod:/logs:ro
|
||||
- ./config/maxmind:/geoip:ro
|
||||
- ./data/positions-prod:/data
|
||||
|
||||
traefik-agent-staging:
|
||||
image: hhftechnology/traefik-log-dashboard-agent:latest
|
||||
ports: ["5001:5000"]
|
||||
environment:
|
||||
- TRAEFIK_LOG_DASHBOARD_AUTH_TOKEN=staging_token
|
||||
- TRAEFIK_LOG_DASHBOARD_ACCESS_PATH=/logs/access.log
|
||||
volumes:
|
||||
- /var/log/traefik/staging:/logs:ro
|
||||
- ./config/maxmind:/geoip:ro
|
||||
|
||||
traefik-dashboard:
|
||||
image: hhftechnology/traefik-log-dashboard:latest
|
||||
ports: ["3000:3000"]
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
```
|
||||
|
||||
Then, in the **Dashboard → Settings → Agents**, add each agent URL and token.
|
||||
|
||||
***
|
||||
|
||||
## Performance Tuning
|
||||
|
||||
| Setting | Description | Recommended |
|
||||
|-------------------------------------------|----------------------|-------------|
|
||||
| `TRAEFIK_LOG_DASHBOARD_SYSTEM_MONITORING` | Enables system stats | `true` |
|
||||
| `TRAEFIK_LOG_DASHBOARD_LOG_FORMAT` | Log parsing format | `json` |
|
||||
|
||||
***
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Cause | Fix |
|
||||
|-----------------------|--------------------------|---------------------------------------------------------------------|
|
||||
| Dashboard not loading | Container not healthy | `docker compose ps` → check `health` |
|
||||
| No logs appearing | Wrong log path or format | Ensure `access.log` is JSON and volume mounted |
|
||||
| GeoIP missing | Missing databases | Run `maxmind-updater` or mount both `.mmdb` files |
|
||||
| Auth errors | Token mismatch | Verify `AGENT_API_TOKEN` matches `TRAEFIK_LOG_DASHBOARD_AUTH_TOKEN` |
|
||||
| Slow UI | Large logs | Use JSON logs + incremental read; prune logs periodically |
|
||||
|
||||
***
|
||||
|
||||
## Summary
|
||||
|
||||
* Replaces the old `log-dashboard-backend` + `log-dashboard-frontend` with the new **agent-based architecture**
|
||||
* Supports **multiple Traefik instances**
|
||||
* Adds **GeoLite2 Country + City databases**
|
||||
* Integrates **real-time analytics + system monitoring**
|
||||
* Uses **MaxMind license key** for GeoIP updates
|
||||
* More stable with less memory
|
||||
|
||||
***
|
||||
|
||||
**Project Repository
|
||||
** → [https://github.com/hhftechnology/traefik-log-dashboard](https://github.com/hhftechnology/traefik-log-dashboard)
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# DNS & Networking
|
||||
|
||||
> Configure your domain, DNS records, and network settings for Pangolin deployment
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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={2}>
|
||||
<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">
|
||||
**Site Tunnels**
|
||||
|
||||
This is the default port for sites (Newt) to establish tunnels to the proxy (Gerbil).
|
||||
|
||||
</Card>
|
||||
|
||||
<Card title="UDP Port 21820">
|
||||
**Client Tunnels**
|
||||
|
||||
This is the default port for clients relaying through Gerbil to newt. This port is only required for clients.
|
||||
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Warning>
|
||||
Always verify your exposed ports (e.g., with [nmap](https://nmap.org/) or [RustScan](https://github.com/bee-san/RustScan)) and ensure you expose **only** the ports that are absolutely necessary. By tunneling out to the VPS, you are effectively including the VPS in your security boundary, so you must secure it as part of your overall network strategy. For more details, see [Docker’s port publishing documentation](https://docs.docker.com/engine/network/packet-filtering-firewalls/#port-publishing-and-mapping).
|
||||
</Warning>
|
||||
|
||||
### Docker Port Exposure
|
||||
|
||||
By default, Pangolin exposes these ports on all interfaces:
|
||||
|
||||
```yaml theme={null}
|
||||
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 connections
|
||||
- "21820:21820" # WireGuard for 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 ports 51820 and 21820
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="UFW (Ubuntu)">
|
||||
```bash theme={null}
|
||||
sudo ufw allow 80/tcp
|
||||
sudo ufw allow 443/tcp
|
||||
sudo ufw allow 51820/udp
|
||||
sudo ufw allow 21820/udp
|
||||
sudo ufw enable
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="firewalld (CentOS/RHEL)">
|
||||
```bash theme={null}
|
||||
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 --permanent --add-port=21820/udp
|
||||
sudo firewall-cmd --reload
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Internal Network Configuration
|
||||
|
||||
### Default Subnet Settings
|
||||
|
||||
Pangolin uses these default network settings:
|
||||
|
||||
```yaml theme={null}
|
||||
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 theme={null}
|
||||
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>
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Enterprise Edition
|
||||
|
||||
> Learn about Enterprise Edition features, licensing, and how to get started
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
When self-hosting Pangolin, you can choose to run the **Community Edition** or the **Enterprise Edition**. Both editions
|
||||
provide the same core functionality, but the Enterprise Edition unlocks additional features for qualifying users.
|
||||
|
||||
## Edition Comparison
|
||||
|
||||
### Community Edition
|
||||
|
||||
* Fully compliant with AGPL-3 license
|
||||
* All core Pangolin features included
|
||||
|
||||
### Enterprise Edition
|
||||
|
||||
* Distributed under Fossorial Commercial License
|
||||
* Includes all Community Edition features
|
||||
* Unlocks "Paid Features" for qualifying users (see below)
|
||||
* Requires valid license key for activation
|
||||
|
||||
## Licensing Overview
|
||||
|
||||
The Enterprise Edition is distributed under the **Fossorial Commercial License**, which provides different terms based
|
||||
on your organization's revenue:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Personal Use">
|
||||
**Free for individuals and small businesses**
|
||||
|
||||
* **Revenue threshold**: Less than \$100,000 USD gross annual revenue
|
||||
* **License cost**: Free
|
||||
* **Features**: Full access to all "Paid Features"
|
||||
* **Usage**: Personal and small business use allowed
|
||||
|
||||
<Check>
|
||||
You still need to acquire a valid license key to unlock Enterprise features, even with free licensing.
|
||||
</Check>
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="Business Use">
|
||||
**Larger businesses require a paid license**
|
||||
|
||||
* **Revenue threshold**: \$100,000+ USD gross annual revenue
|
||||
* **License cost**: Paid license required
|
||||
* **Features**: Full access to all "Paid Features"
|
||||
* **Usage**: Business use with commercial terms
|
||||
|
||||
<Warning>
|
||||
Businesses exceeding the revenue threshold must purchase a commercial license to use Enterprise Edition features.
|
||||
</Warning>
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
To see pricing tiers for the self-hosted Enterprise Edition for
|
||||
businesses, [click here](https://pangolin.net/pricing?hosting=self-host). For more on how to purchase a key,
|
||||
see [Purchase a license key](/self-host/purchase-license-key).
|
||||
|
||||
## Getting Your License Key
|
||||
|
||||
<Steps>
|
||||
<Step title="Create an account">
|
||||
Visit [app.pangolin.net](https://app.pangolin.net) and create your account.
|
||||
</Step>
|
||||
|
||||
<Step title="Navigate to licenses">
|
||||
After logging in, go to the **Licenses** section in your account dashboard.
|
||||
</Step>
|
||||
|
||||
<Step title="Fill out the application">
|
||||
Complete the license application form.
|
||||
|
||||
<Tip>
|
||||
Inaccurate representation is a violation of the license and will result in the license being revoked.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Receive your key">
|
||||
Once approved, you'll receive your license key immediately. You can then activate it in your Pangolin instance in the Server Admin panel.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## License Requirements
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="How many license keys do I need?">
|
||||
**One key per Pangolin server instance**
|
||||
|
||||
Each host (server) running Pangolin requires its own license key. You cannot share a single key across multiple servers.
|
||||
|
||||
<Info>
|
||||
If you're running multiple Pangolin instances for high availability, each database needs its own license key.
|
||||
</Info>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Can I get a trial license?">
|
||||
Businesses that don't qualify for free personal licensing can reach out to [support@pangolin.net](mailto:support@pangolin.net) for a trial license key to test Enterprise features before purchasing.
|
||||
|
||||
<Warning>
|
||||
Trial keys are only available for organizations that exceed the personal license revenue threshold.
|
||||
</Warning>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What if I'm unsure about my license type?">
|
||||
**Contact us for guidance**
|
||||
|
||||
If you're uncertain whether you qualify for free licensing or need a commercial license, reach out to [sales@pangolin.net](mailto:sales@pangolin.net) with your organization details.
|
||||
|
||||
We'll help determine the appropriate license type and pricing for your use case.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Activating Enterprise Edition
|
||||
|
||||
<Steps>
|
||||
<Step title="Use Enterprise Edition image">
|
||||
Update your Docker Compose configuration to use the Enterprise Edition image:
|
||||
|
||||
```yaml theme={null}
|
||||
services:
|
||||
pangolin:
|
||||
image: fosrl/pangolin:ee-latest # Enterprise Edition
|
||||
# ... rest of configuration
|
||||
```
|
||||
|
||||
<Warning>
|
||||
The Enterprise Edition image is tagged with `ee` (e.g., `fosrl/pangolin:ee-latest`) and is different from the Community Edition (`fosrl/pangolin:latest`). Make sure to use the correct image.
|
||||
</Warning>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Restart Pangolin">
|
||||
Restart your Pangolin services to activate the license:
|
||||
|
||||
```bash theme={null}
|
||||
sudo docker compose restart pangolin
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Add license key to instance">
|
||||
Log in to the Pangolin instance via the server admin credentials. Visit the Server Admin panel and naviage to the License section (`/admin/license`). Enter and activate the license key.
|
||||
|
||||
<Info>
|
||||
The license key should be provided exactly as received in your email confirmation.
|
||||
</Info>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Verify activation">
|
||||
Check your Pangolin dashboard to confirm Enterprise Edition features are unlocked.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Support and Contact
|
||||
|
||||
For licensing questions and quotes, email: [sales@pangolin.net](mailto:sales@pangolin.net)
|
||||
|
||||
Include your organization details and use case for faster assistance.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Can I switch between editions?">
|
||||
You can switch from Community to Enterprise Edition by:
|
||||
|
||||
1. Updating your Docker image to `fosrl/ee-<version>`
|
||||
2. Adding your license key to the configuration
|
||||
3. Restarting the services
|
||||
|
||||
<Warning>
|
||||
Switching back to Community Edition will disable Enterprise features and may require data migration.
|
||||
</Warning>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Is Enterprise Edition opt-in?">
|
||||
Enterprise Edition is fully opt-in. You can continue using the Community Edition.
|
||||
|
||||
<Check>
|
||||
The Community Edition will always remain free and open source with full AGPL-3 compliance.
|
||||
</Check>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What happens if my license expires?">
|
||||
If your license expires or becomes invalid:
|
||||
|
||||
* Enterprise features will be disabled
|
||||
* You can renew your license to restore Enterprise features
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Can I use Enterprise Edition for personal projects?">
|
||||
Individuals and small businesses under the revenue threshold can use Enterprise Edition for personal projects at no cost.
|
||||
|
||||
<Info>
|
||||
Personal use is explicitly allowed under the free license terms.
|
||||
</Info>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Are there special license terms for educational institutions, non-profits, or government organizations?">
|
||||
**No exceptions - same license terms apply**
|
||||
|
||||
Educational institutions, non-profit organizations, and government entities are subject to the same license terms as all other organizations. There are no special exceptions or discounts for these groups.
|
||||
|
||||
<Info>
|
||||
If you have questions about how your organization's revenue is calculated for licensing purposes, contact [sales@pangolin.net](mailto:sales@pangolin.net).
|
||||
</Info>
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# How to Update
|
||||
|
||||
> Keep your Pangolin deployment up to date with the latest features and security patches
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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 theme={null}
|
||||
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)
|
||||
* **Badger**: [GitHub Releases](https://github.com/fosrl/badger/releases)
|
||||
|
||||
<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" theme={null}
|
||||
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
|
||||
```
|
||||
|
||||
Increase the Badger version number in `config/traefik/traefik_config.yml`:
|
||||
|
||||
```yaml title="traefik_config.yml" theme={null}
|
||||
experimental:
|
||||
plugins:
|
||||
badger:
|
||||
moduleName: github.com/fosrl/badger
|
||||
version: v1.3.0 # Update to latest version
|
||||
```
|
||||
|
||||
<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 theme={null}
|
||||
sudo docker compose pull
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Start the stack">
|
||||
Start the updated containers:
|
||||
|
||||
```bash theme={null}
|
||||
sudo docker compose up -d
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Monitor the update">
|
||||
Watch the logs to ensure everything starts correctly:
|
||||
|
||||
```bash theme={null}
|
||||
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>
|
||||
|
||||
+372
@@ -0,0 +1,372 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Docker Compose
|
||||
|
||||
> Deploy Pangolin manually using Docker Compose without the automated installer
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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](/self-host/advanced/config-file) 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 theme={null}
|
||||
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 theme={null}
|
||||
sudo docker compose up -d
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Monitor startup">
|
||||
```bash theme={null}
|
||||
sudo docker compose logs -f
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Verify services">
|
||||
```bash theme={null}
|
||||
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" theme={null}
|
||||
name: pangolin
|
||||
services:
|
||||
pangolin:
|
||||
image: docker.io/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: "10s"
|
||||
timeout: "10s"
|
||||
retries: 15
|
||||
|
||||
gerbil:
|
||||
image: docker.io/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:3004
|
||||
- --generateAndSaveKeyTo=/var/config/key
|
||||
- --remoteConfig=http://pangolin:3001/api/v1/
|
||||
volumes:
|
||||
- ./config/:/var/config
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_MODULE
|
||||
ports:
|
||||
- 51820:51820/udp
|
||||
- 21820:21820/udp
|
||||
- 443:443
|
||||
- 80:80
|
||||
|
||||
traefik:
|
||||
image: docker.io/traefik:v3.6
|
||||
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
|
||||
- ./config/traefik/logs:/var/log/traefik # Volume to store Traefik logs
|
||||
|
||||
networks:
|
||||
default:
|
||||
driver: bridge
|
||||
name: pangolin
|
||||
#enable_ipv6: true # activate if your system supports IPv6
|
||||
```
|
||||
|
||||
## Traefik Static Configuration
|
||||
|
||||
Create `config/traefik/traefik_config.yml`:
|
||||
|
||||
```yaml title="config/traefik/traefik_config.yml" theme={null}
|
||||
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: "v1.3.1"
|
||||
|
||||
log:
|
||||
level: "INFO"
|
||||
format: "common"
|
||||
maxSize: 100
|
||||
maxBackups: 3
|
||||
maxAge: 3
|
||||
compress: true
|
||||
|
||||
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"
|
||||
encodedCharacters:
|
||||
allowEncodedSlash: true
|
||||
allowEncodedQuestionMark: true
|
||||
|
||||
serversTransport:
|
||||
insecureSkipVerify: true
|
||||
|
||||
ping:
|
||||
entryPoint: "web"
|
||||
```
|
||||
|
||||
## Traefik Dynamic Configuration
|
||||
|
||||
Create `config/traefik/dynamic_config.yml`:
|
||||
|
||||
```yaml title="config/traefik/dynamic_config.yml" theme={null}
|
||||
http:
|
||||
middlewares:
|
||||
badger:
|
||||
plugin:
|
||||
badger:
|
||||
disableForwardAuth: true
|
||||
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
|
||||
- badger
|
||||
|
||||
# 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
|
||||
middlewares:
|
||||
- badger
|
||||
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
|
||||
middlewares:
|
||||
- badger
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
|
||||
# WebSocket router
|
||||
ws-router:
|
||||
rule: "Host(`pangolin.example.com`)" # REPLACE WITH YOUR DOMAIN
|
||||
service: api-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
middlewares:
|
||||
- badger
|
||||
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
|
||||
|
||||
tcp:
|
||||
serversTransports:
|
||||
pp-transport-v1:
|
||||
proxyProtocol:
|
||||
version: 1
|
||||
pp-transport-v2:
|
||||
proxyProtocol:
|
||||
version: 2
|
||||
```
|
||||
|
||||
## Pangolin Configuration
|
||||
|
||||
Create `config/config.yml` with your Pangolin settings. See the [configuration guide](/self-host/advanced/config-file)
|
||||
for detailed options and examples.
|
||||
|
||||
+421
@@ -0,0 +1,421 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Unraid Deployment
|
||||
|
||||
> Deploy Pangolin on Unraid for local reverse proxy and tunneling
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
## 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 theme={null}
|
||||
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](/self-host/advanced/config-file) 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.
|
||||
|
||||
<Frame caption="Pangolin configuration settings in Unraid">
|
||||
<img src="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/pangolin_config.png?fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=82c2ed95ef94b607605cca6863d5bbcd" alt="Pangolin configuration settings in Unraid" data-og-width="2660" width="2660" data-og-height="1318" height="1318" data-path="images/pangolin_config.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/pangolin_config.png?w=280&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=35fd7218d017780ca8db9979e709edca 280w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/pangolin_config.png?w=560&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=72d221df2af89585529fcd1439b7e830 560w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/pangolin_config.png?w=840&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=21d11e383cb9c0cb2f90aa523912210d 840w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/pangolin_config.png?w=1100&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=589e32bcb38347dd37ef461859218e21 1100w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/pangolin_config.png?w=1650&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=6efe30c3135a93871f2c9ad59ff5750a 1650w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/pangolin_config.png?w=2500&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=55eec73364fc83cbcccc8ab8184b2f65 2500w" />
|
||||
</Frame>
|
||||
|
||||
**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 theme={null}
|
||||
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: "v1.3.0"
|
||||
|
||||
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" theme={null}
|
||||
http:
|
||||
middlewares:
|
||||
badger:
|
||||
plugin:
|
||||
badger:
|
||||
disableForwardAuth: true
|
||||
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
|
||||
- badger
|
||||
|
||||
# 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
|
||||
middlewares:
|
||||
- badger
|
||||
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
|
||||
middlewares:
|
||||
- badger
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
|
||||
# WebSocket router
|
||||
ws-router:
|
||||
rule: "Host(`pangolin.example.com`)" # REPLACE THIS WITH YOUR DOMAIN
|
||||
service: api-service
|
||||
entryPoints:
|
||||
- websecure
|
||||
middlewares:
|
||||
- badger
|
||||
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.
|
||||
|
||||
<Frame caption="Traefik repository selection in Community Apps">
|
||||
<img src="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_repo.png?fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=4cf656c02b423be2793fe2c1d744ef08" width="400" alt="Traefik repository selection in Community Apps" data-og-width="836" data-og-height="600" data-path="images/traefik_repo.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_repo.png?w=280&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=5fad4a6d55cf78260027ba03c0578343 280w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_repo.png?w=560&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=08c19916403b2e4eac80d6bd097b2d26 560w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_repo.png?w=840&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=f84482b7a84601de8e415244f663e3eb 840w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_repo.png?w=1100&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=88d8f8c01b829cdb05c9881d73e13cff 1100w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_repo.png?w=1650&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=921cd181659de37dcf26cf103c8c7392 1650w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_repo.png?w=2500&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=7f81d7c4c888f16ea49afbfc181b69f3 2500w" />
|
||||
</Frame>
|
||||
|
||||
#### 3. Configure Traefik
|
||||
|
||||
<Frame caption="Traefik configuration settings in Unraid">
|
||||
<img src="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_config.png?fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=17d9c3ce28f805cb4969fe30e1a972a4" alt="Traefik configuration settings in Unraid" data-og-width="2560" width="2560" data-og-height="2400" height="2400" data-path="images/traefik_config.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_config.png?w=280&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=721083ebeeb0b3070ae28b7a2c762138 280w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_config.png?w=560&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=bfa0d45b6b2f5d59a8c305c302184d4b 560w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_config.png?w=840&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=cb53166c942cfb21a60519967afeba78 840w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_config.png?w=1100&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=101e742b4056ff8cba5530250fb4d173 1100w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_config.png?w=1650&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=7b00179786fe15ca73b011bd07c87bb5 1650w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_config.png?w=2500&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=184cfd96dc9c0ae6106598861be3bfa8 2500w" />
|
||||
</Frame>
|
||||
|
||||
<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 theme={null}
|
||||
--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.
|
||||
|
||||
<Frame caption="Gerbil configuration settings in Unraid">
|
||||
<img src="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_config.png?fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=aa621c43a60288ca8af10fc2df3acc68" alt="Gerbil configuration settings in Unraid" data-og-width="2428" width="2428" data-og-height="1400" height="1400" data-path="images/gerbil_config.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_config.png?w=280&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=d6cdc205135d248a2e7c9b3fd53289c0 280w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_config.png?w=560&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=472e756ededa6cc1c7b47b8d16f44caa 560w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_config.png?w=840&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=7520f4b8a3cfd9991a85fbf75b7580c8 840w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_config.png?w=1100&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=a86fc01b7abb45e72c2747d7b090ddf1 1100w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_config.png?w=1650&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=10d282b22314729afd7e2fd380c40b62 1650w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_config.png?w=2500&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=3b662c5cb21fcb65d76b20560a999b91 2500w" />
|
||||
</Frame>
|
||||
|
||||
**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:**
|
||||
|
||||
<Warning>
|
||||
You **must** use the default port of `51822` for WireGuard in the Gerbil container. Using any other port may cause connection issues that are difficult to debug.
|
||||
|
||||
Make sure this is also reflected in your Pangolin `config.yml`:
|
||||
|
||||
```yml theme={null}
|
||||
gerbil:
|
||||
start_port: 51822
|
||||
```
|
||||
|
||||
See [this GitHub issue comment](https://github.com/fosrl/pangolin/issues/227#issuecomment-2781608815) for more details.
|
||||
</Warning>
|
||||
|
||||
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 theme={null}
|
||||
--net=container:Gerbil
|
||||
```
|
||||
|
||||
Then, set "Network Type" to "None".
|
||||
|
||||
<Frame caption="Traefik networking configuration through Gerbil">
|
||||
<img src="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_networking.png?fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=789d989c26d6996eed6a573ac88a415d" alt="Traefik networking configuration through Gerbil" data-og-width="1840" width="1840" data-og-height="380" height="380" data-path="images/traefik_networking.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_networking.png?w=280&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=c41160a0a7bd3da0b0d5287cffd8ecaf 280w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_networking.png?w=560&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=6d67ef4a3501693616b83c33a6c9a50d 560w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_networking.png?w=840&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=7745b9983bc54245dc269ea73b8333c2 840w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_networking.png?w=1100&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=7de530b5b9ad061f385d673fb2e85349 1100w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_networking.png?w=1650&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=9bfe596ac027d7539d33ce511885e8d1 1650w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/traefik_networking.png?w=2500&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=8a0b3661cb97b152766ad15e8b8c555e 2500w" />
|
||||
</Frame>
|
||||
|
||||
#### 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>
|
||||
|
||||
<Frame caption="Gerbil logs showing WireGuard interface startup">
|
||||
<img src="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_logs.png?fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=51b8f7e56caee9e986dfa8557acb4cd9" alt="Gerbil logs showing WireGuard interface startup" data-og-width="1085" width="1085" data-og-height="212" height="212" data-path="images/gerbil_logs.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_logs.png?w=280&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=94a0ef8103c4c87081ad1280fe62e419 280w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_logs.png?w=560&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=62ba262d2bd3d54177461a17490956e8 560w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_logs.png?w=840&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=ba0418c4c54a25e16cd6b72a7cc49fb5 840w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_logs.png?w=1100&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=b4f6adb01f84f7adb153fa5aaa0997af 1100w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_logs.png?w=1650&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=1240163eaf35b46aebb7f70b3e197052 1650w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/gerbil_logs.png?w=2500&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=4298b8ccd8b21edaa9ef801b47073d2f 2500w" />
|
||||
</Frame>
|
||||
|
||||
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.
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Quick Install Guide
|
||||
|
||||
> Deploy your own fully self-hosted instance of Pangolin Community Edition
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<iframe className="w-full aspect-video rounded-xl" src="https://www.youtube.com/embed/0upWrqkJPy8?si=q0D-uR1IHuddaqeT" title="Pangolin Quick Install Guide" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />
|
||||
|
||||
## 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), 51820 (UDP), and 21820 (UDP for clients)
|
||||
|
||||
<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 theme={null}
|
||||
curl -fsSL https://static.pangolin.net/get-installer.sh | bash
|
||||
```
|
||||
|
||||
The installer supports both AMD64 (x86\_64) and ARM64 architectures.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Run the installer">
|
||||
Execute the installer with root privileges:
|
||||
|
||||
```bash theme={null}
|
||||
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:
|
||||
|
||||
* **Edition**: Choose Community Edition or [Enterprise Edition](/self-host/enterprise-edition). Review the edition differences before continuing.
|
||||
* **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 browser 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. Enter organization name and description
|
||||
2. Click "Create Organization"
|
||||
|
||||
<Check>
|
||||
You're now ready to start adding applications and configuring your reverse proxy!
|
||||
</Check>
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
@@ -0,0 +1,155 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Supporter Program
|
||||
|
||||
> Support Pangolin development and remove UI elements with a supporter key
|
||||
|
||||
<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
|
||||
<Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
|
||||
Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
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.
|
||||
|
||||
<Note>
|
||||
**Business & Enterprise Users:** For larger organizations or teams requiring advanced features, consider our self-serve enterprise license and [Enterprise Edition](/self-host/enterprise-edition). [Learn more](https://pangolin.net/pricing?hosting=self-host)
|
||||
</Note>
|
||||
|
||||
## 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>
|
||||
|
||||
<Frame caption="Supporter tier comparison showing Limited vs Full Supporter benefits">
|
||||
<img src="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/supporter-tiers.png?fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=9189003609b69821e87194670136f72f" alt="Supporter tier comparison showing Limited vs Full Supporter benefits" data-og-width="5110" width="5110" data-og-height="2650" height="2650" data-path="images/supporter-tiers.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/supporter-tiers.png?w=280&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=c3e5099a5e2e89ddf1ba18b5744d29be 280w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/supporter-tiers.png?w=560&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=4b7e9f9607b6293b74a60a67b602da0f 560w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/supporter-tiers.png?w=840&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=20e087bee3d236a0f0f3c4200a4b8c79 840w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/supporter-tiers.png?w=1100&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=d81755a386b1878d21b8d103f26af400 1100w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/supporter-tiers.png?w=1650&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=3aea36045d8be256b628dbc88ce91347 1650w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/supporter-tiers.png?w=2500&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=189f52cfcad91390a188419c27ad239d 2500w" />
|
||||
</Frame>
|
||||
|
||||
## 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>
|
||||
|
||||
<Frame caption="Pangolin supporter key redemption interface">
|
||||
<img src="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/redeem-key.png?fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=09685b9c96df9c51afdecbaa4826bd6e" alt="Pangolin supporter key redemption interface" data-og-width="1644" width="1644" data-og-height="1550" height="1550" data-path="images/redeem-key.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/redeem-key.png?w=280&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=d38a565c2c1c4208faf1abe17f0e9f70 280w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/redeem-key.png?w=560&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=2fb9a7c10febb10f006170bcdc8a607b 560w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/redeem-key.png?w=840&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=553787d00bc2325d70b48a08d6153aac 840w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/redeem-key.png?w=1100&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=0fd602e797b9758191d42e8538c39f32 1100w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/redeem-key.png?w=1650&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=9a56af8d967f396ade2e23fc8801880c 1650w, https://mintcdn.com/fossorial/u-2SUNWyK_LJL3sU/images/redeem-key.png?w=2500&fit=max&auto=format&n=u-2SUNWyK_LJL3sU&q=85&s=311ac06fa047941bfbb0d662642947ee 2500w" />
|
||||
</Frame>
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Can we use Paypal or other payment methods?">
|
||||
Github sponsors does not currently support other payment methods. We hope to add more options in the future.
|
||||
</Accordion>
|
||||
|
||||
<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>
|
||||
Reference in New Issue
Block a user