From 220c4c228db3d43db7ca6eb9e59549bebc41bee1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:49:14 +0000 Subject: [PATCH 1/8] Initial plan From f7092d3de042d542d125800ae381c3a8861bd4bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:59:01 +0000 Subject: [PATCH 2/8] blueprint: feat pangolin: add identity-aware VPN and proxy server template Co-authored-by: enuno <6727752+enuno@users.noreply.github.com> --- blueprints/pangolin/README.md | 381 +++++++++++++++++++++++++ blueprints/pangolin/docker-compose.yml | 126 ++++++++ blueprints/pangolin/logo.svg | 38 +++ blueprints/pangolin/template.toml | 233 +++++++++++++++ 4 files changed, 778 insertions(+) create mode 100644 blueprints/pangolin/README.md create mode 100644 blueprints/pangolin/docker-compose.yml create mode 100644 blueprints/pangolin/logo.svg create mode 100644 blueprints/pangolin/template.toml diff --git a/blueprints/pangolin/README.md b/blueprints/pangolin/README.md new file mode 100644 index 0000000..1c2dcca --- /dev/null +++ b/blueprints/pangolin/README.md @@ -0,0 +1,381 @@ +# Pangolin Dokploy Template + +> **Zero-trust identity-aware reverse proxy and VPN server for secure remote access** + +- 🔐 **Identity-Aware Access**: Enforce authentication before reaching any resource +- 🌐 **WireGuard VPN Tunnels**: Connect remote sites and clients with modern WireGuard +- 🔄 **Dynamic Reverse Proxy**: Built-in Traefik for automatic TLS and HTTP routing +- 👥 **Multi-Org Support**: Isolated organizations with role-based access control +- 🔑 **SSO / OIDC Integration**: Connect to Authelia, Authentik, Keycloak, and more +- 🛡️ **Zero-Trust Architecture**: No implicit trust — every request is authenticated +- 📊 **Audit Logging**: Track all access and connections + +**Official Documentation**: https://docs.pangolin.net/ + +--- + +## Architecture + +``` +Internet + │ + ├── 443 (HTTPS) ──► Gerbil + Traefik ──► Tunneled Services + ├── 51820 (UDP) ──► Gerbil (WireGuard) ──► VPN Clients + │ + └── Dokploy Traefik ──► Pangolin Dashboard (Admin UI) + +┌─────────────────────────────────────────────────────┐ +│ Pangolin Stack │ +│ │ +│ ┌────────────┐ ┌─────────┐ ┌─────────────┐ │ +│ │ Pangolin │◄───│ Gerbil │◄───│ Traefik │ │ +│ │ (Control) │ │ (VPN) │ │ (Proxy) │ │ +│ │ Port 3001 │ │UDP 51820│ │ Port 80/443 │ │ +│ │ Port 3000 │ │ │ │ │ │ +│ └────────────┘ └─────────┘ └─────────────┘ │ +│ │ │ +│ ┌──────▼──────┐ │ +│ │ SQLite DB │ (persisted in pangolin-db volume) │ +│ └─────────────┘ │ +└─────────────────────────────────────────────────────┘ +``` + +**Service Type**: Multi-service stack (Pangolin + Gerbil + Traefik) +**Database**: Self-contained SQLite (in `/app/config/db`) +**VPN**: WireGuard via Gerbil +**Proxy**: Embedded Traefik instance for tunneled services + +--- + +## Prerequisites + +1. **Dedicated server or VPS** (recommended — Pangolin uses ports 80, 443, 51820) +2. **DNS configuration**: + - `pangolin.example.com` → Server IP (admin dashboard) + - `*.example.com` → Server IP (wildcard for tunneled services) +3. **Firewall rules**: Open ports `443/tcp`, `80/tcp`, `51820/udp` +4. **Dokploy** installed and running + +> **⚠️ Port Conflict Warning**: Pangolin's embedded Traefik uses ports 80 and 443. +> If Dokploy's Traefik already uses these ports on the same host, you must either: +> - Deploy Pangolin on a **dedicated server** +> - Change `HTTP_PROXY_PORT` and `HTTPS_PROXY_PORT` to alternate values (e.g., 8080, 8443) + +--- + +## Quick Start + +### 1. Configure DNS + +Before deploying, set up DNS records: + +``` +# Admin dashboard +pangolin.example.com A + +# Wildcard for tunneled services +*.example.com A +``` + +### 2. Deploy Template + +In Dokploy: +1. Select **"Add New Template"** +2. Choose **"Pangolin"** +3. Fill in the required variables (see [Configuration](#configuration) below) +4. Deploy + +### 3. Complete Initial Setup + +Navigate to `https://pangolin.example.com/auth/initial-setup` and: +1. Confirm admin email and password +2. Configure your organization name +3. Verify DNS is working + +### 4. Create Your First Tunnel + +1. In Pangolin admin: **Sites** → **Add Site** +2. Choose **WireGuard** tunnel type +3. Follow the newt/WireGuard client setup instructions +4. Add resources behind the tunnel + +--- + +## Configuration + +### Required Variables + +| Variable | Description | Example | +|----------|-------------|---------| +| `pangolin_domain` | Admin dashboard domain | `pangolin.example.com` | +| `base_domain` | Base domain for tunneled services | `example.com` | +| `admin_email` | Initial admin email address | `admin@example.com` | +| `admin_password` | Initial admin password (auto-generated) | *(generated)* | +| `letsencrypt_email` | Email for Let's Encrypt certificates | `admin@example.com` | +| `app_secret` | Application secret key (auto-generated) | *(generated)* | +| `resource_access_secret` | Resource token secret (auto-generated) | *(generated)* | + +### Optional Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `wireguard_port` | `51820` | WireGuard VPN UDP port | +| `https_proxy_port` | `443` | HTTPS port for tunneled services | +| `http_proxy_port` | `80` | HTTP port (redirects to HTTPS) | +| `smtp_host` | *(empty)* | SMTP server for email notifications | +| `smtp_port` | `587` | SMTP port | +| `smtp_username` | *(empty)* | SMTP username | +| `smtp_password` | *(empty)* | SMTP password | +| `smtp_from_email` | *(empty)* | From address for outgoing emails | +| `log_level` | `info` | Log level: `debug`, `info`, `warn`, `error` | + +### Environment Variables (Advanced) + +These are set via Dokploy's environment variable injection: + +| Variable | Description | +|----------|-------------| +| `PANGOLIN_DOMAIN` | Admin dashboard domain | +| `WIREGUARD_PORT` | WireGuard listen port | +| `HTTPS_PROXY_PORT` | HTTPS proxy port | +| `HTTP_PROXY_PORT` | HTTP proxy port | + +--- + +## Identity Provider Setup + +Pangolin supports SSO via OpenID Connect (OIDC). Configure in the admin UI under: +**Settings** → **Identity Providers** + +### Authelia + +1. In Authelia, create a new OIDC client: + ```yaml + # authelia/configuration.yml + identity_providers: + oidc: + clients: + - id: pangolin + description: Pangolin + secret: your-client-secret + public: false + authorization_policy: two_factor + redirect_uris: + - https://pangolin.example.com/api/v1/auth/oidc/callback + scopes: + - openid + - profile + - email + grant_types: + - authorization_code + ``` +2. In Pangolin admin: **Settings** → **Identity Providers** → **Add OIDC** +3. Enter: + - **Issuer URL**: `https://auth.example.com` + - **Client ID**: `pangolin` + - **Client Secret**: `your-client-secret` + +### Authentik + +1. In Authentik, create an OAuth2/OIDC provider: + - **Redirect URIs**: `https://pangolin.example.com/api/v1/auth/oidc/callback` + - **Scopes**: `openid`, `profile`, `email` +2. Create an Application linked to this provider +3. In Pangolin admin: **Settings** → **Identity Providers** → **Add OIDC** +4. Use the Authentik OIDC metadata URL + +### Keycloak + +1. In Keycloak, create a new client: + - **Client ID**: `pangolin` + - **Client Protocol**: `openid-connect` + - **Valid Redirect URIs**: `https://pangolin.example.com/api/v1/auth/oidc/callback` +2. Note the client secret from the **Credentials** tab +3. In Pangolin admin: configure OIDC with Keycloak's realm OIDC endpoint + +--- + +## Networking + +### Port Requirements + +| Port | Protocol | Purpose | Required | +|------|----------|---------|----------| +| `443` | TCP | HTTPS for tunneled services + Let's Encrypt | Yes | +| `80` | TCP | HTTP → HTTPS redirect + Let's Encrypt challenge | Yes | +| `51820` | UDP | WireGuard VPN tunnels | Yes | + +### Firewall Rules + +```bash +# Open required ports +ufw allow 80/tcp +ufw allow 443/tcp +ufw allow 51820/udp + +# Restrict admin dashboard to trusted IPs (recommended) +ufw allow from to any port 443 +``` + +### DNS Wildcard Setup + +Pangolin creates subdomains for each exposed service: + +``` +# All tunneled services use subdomains of base_domain +api.example.com → service behind Pangolin tunnel +app.example.com → another service +db-admin.example.com → protected database UI +``` + +--- + +## Security Considerations + +### Credential Management + +- ✅ Admin password is auto-generated (32 characters) +- ✅ App secrets are auto-generated and stored in Dokploy +- ✅ Change admin password after first login +- ✅ Enable MFA for admin accounts + +### Network Security + +- ✅ All traffic encrypted via TLS (Let's Encrypt) +- ✅ WireGuard provides end-to-end encryption for VPN tunnels +- ✅ Deploy on a dedicated server to avoid port conflicts +- ✅ Use firewall to restrict access to management ports +- ✅ Enable identity provider authentication for zero-trust access + +### Secrets Rotation + +To rotate secrets: +1. Update `app_secret` and `resource_access_secret` in Dokploy +2. Redeploy the stack +3. Users will need to log in again (sessions invalidated) + +--- + +## Troubleshooting + +### Admin Dashboard Not Loading + +```bash +# Check Pangolin is healthy +docker compose ps +docker compose logs pangolin + +# Verify Traefik routing +curl -I https://pangolin.example.com +``` + +### WireGuard Connection Fails + +```bash +# Check Gerbil is running +docker compose logs gerbil + +# Verify UDP port is open +nc -u -zv your-server-ip 51820 + +# Check WireGuard key was generated +docker compose exec gerbil ls /var/config/key +``` + +### Let's Encrypt Certificate Issues + +```bash +# Check Traefik logs +docker compose logs traefik + +# Verify HTTP challenge is reachable +curl http://your-domain/.well-known/acme-challenge/test + +# Common cause: port 80 blocked by firewall +ufw status +``` + +### Services Not Accessible via Tunnel + +1. Verify site is connected: Pangolin admin → **Sites** → check status +2. Check resource configuration: correct target URL +3. Review access policies: user has permission to access resource +4. Check Traefik config: `docker compose logs traefik` + +--- + +## Backup + +### Critical Data + +Back up these named volumes regularly: + +| Volume | Contents | +|--------|----------| +| `pangolin-config` | SQLite database, WireGuard keys, Let's Encrypt certs | +| `traefik-certs` | Traefik certificate store (ACME) | + +```bash +# Example backup command for pangolin config volume +docker run --rm \ + -v pangolin-config:/source:ro \ + -v /backup:/backup \ + alpine tar czf /backup/pangolin-config-$(date +%Y%m%d).tar.gz -C /source . +``` + +--- + +## Updating + +To update Pangolin: +1. Check the [Pangolin releases page](https://github.com/fosrl/pangolin/releases) +2. Update the image reference in `docker-compose.yml` +3. Also update `gerbil` image to the compatible version +4. Redeploy in Dokploy + +> ⚠️ Always check the release notes for breaking changes before upgrading. + +--- + +## Production Checklist + +Before going live: + +- [ ] DNS configured: `pangolin.example.com` and `*.example.com` → server IP +- [ ] Firewall open: ports 80, 443 (TCP), 51820 (UDP) +- [ ] Admin password changed after first login +- [ ] MFA enabled on admin account +- [ ] Let's Encrypt certificates active (check Traefik logs) +- [ ] SMTP configured (for user invites) +- [ ] Identity provider configured (optional but recommended) +- [ ] Volume backup strategy in place +- [ ] First tunnel tested end-to-end + +--- + +## Support & Resources + +- **Official Docs**: https://docs.pangolin.net/ +- **GitHub**: https://github.com/fosrl/pangolin +- **GitHub Issues**: https://github.com/fosrl/pangolin/issues +- **Gerbil (tunnel agent)**: https://github.com/fosrl/gerbil + +--- + +## Template Metadata + +- **Application**: Pangolin +- **Image**: `ghcr.io/fosrl/pangolin:sha256-3013a0e89e3259567fd86d23af50fc1c7ad9216ab0693ceb823b01c35e6acb5` +- **Gerbil**: `ghcr.io/fosrl/gerbil:1.3.0` +- **Type**: Identity-aware VPN and Proxy Server +- **Architecture**: Multi-service (Pangolin + Gerbil + Traefik) +- **Storage**: SQLite in persistent volumes +- **Networking**: WireGuard VPN + HTTP/HTTPS reverse proxy +- **Status**: Production-Ready + +--- + +## License + +Pangolin is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) +See: https://github.com/fosrl/pangolin/blob/main/LICENSE diff --git a/blueprints/pangolin/docker-compose.yml b/blueprints/pangolin/docker-compose.yml new file mode 100644 index 0000000..f6f9c9d --- /dev/null +++ b/blueprints/pangolin/docker-compose.yml @@ -0,0 +1,126 @@ +# ============================================================================= +# Pangolin - Identity-Aware VPN and Proxy Server +# https://github.com/fosrl/pangolin +# ============================================================================= +# Architecture: +# - Pangolin: Central control plane / admin dashboard (port 3001 API, 3000 UI) +# - Gerbil: WireGuard-based tunnel agent (UDP 51820, HTTPS 443) +# - Traefik: Dynamic reverse proxy running in Gerbil's network namespace +# +# NOTE: This stack includes its own Traefik instance for proxying tunneled +# services. Pangolin's admin dashboard is exposed via Dokploy's host Traefik. +# Ports 443 and 80 (used by Gerbil/Traefik) may conflict with Dokploy's +# Traefik on the same host — deploy on a dedicated server for best results. +# ============================================================================= + +services: + # =========================================================================== + # Pangolin - Identity-Aware Proxy Control Plane + # Admin dashboard on port 3000, REST API on port 3001 + # =========================================================================== + pangolin: + # NOTE: The tag "sha256-..." is a valid GHCR image tag (not a digest reference). + # GitHub Actions publishes images with this tag format alongside semantic version tags. + image: ghcr.io/fosrl/pangolin:sha256-3013a0e89e3259567fd86d23af50fc1c7ad9216ab0693ceb823b01c35e6acb5 + restart: unless-stopped + volumes: + # Shared config directory — WireGuard key (written by gerbil) is read here + # Pangolin's config.yml is injected via Dokploy config mounts + - pangolin-config:/app/config + networks: + - pangolin-internal + - dokploy-network + labels: + # =========================================================================== + # Traefik Routing - Pangolin Admin Dashboard + # Exposed via Dokploy's host Traefik on the configured domain + # =========================================================================== + - "traefik.enable=true" + - "traefik.http.routers.pangolin.rule=Host(`${PANGOLIN_DOMAIN}`)" + - "traefik.http.routers.pangolin.entrypoints=websecure" + - "traefik.http.routers.pangolin.tls.certresolver=letsencrypt" + - "traefik.http.services.pangolin.loadbalancer.server.port=3000" + - "traefik.docker.network=dokploy-network" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"] + interval: 10s + timeout: 10s + retries: 15 + start_period: 30s + + # =========================================================================== + # Gerbil - WireGuard Tunnel Agent + # Manages WireGuard VPN peers and exposes HTTP/HTTPS for Traefik + # Requires NET_ADMIN and SYS_MODULE capabilities for WireGuard kernel module + # =========================================================================== + gerbil: + image: ghcr.io/fosrl/gerbil:1.3.0 + 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: + # Gerbil shares the same config volume to write the WireGuard key + # Key is written to /var/config/key → readable by pangolin at /app/config/key + - pangolin-config:/var/config + cap_add: + - NET_ADMIN + - SYS_MODULE + ports: + # WireGuard VPN endpoint (UDP) + - "${WIREGUARD_PORT:-51820}:51820/udp" + # HTTP/HTTPS for Traefik (Pangolin's own reverse proxy) + # WARNING: These may conflict with Dokploy's Traefik on the same host. + # Consider changing to alternate ports (e.g., 8443, 8080) if needed. + - "${HTTPS_PROXY_PORT:-443}:443" + - "${HTTP_PROXY_PORT:-80}:80" + networks: + - pangolin-internal + healthcheck: + test: ["CMD-SHELL", "nc -z localhost 3004 || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s + + # =========================================================================== + # Traefik - Dynamic Reverse Proxy for Pangolin-Tunneled Services + # Runs in Gerbil's network namespace to handle HTTP/HTTPS routing + # This is Pangolin's own Traefik — separate from Dokploy's Traefik + # =========================================================================== + traefik: + image: traefik:v3.3 + restart: unless-stopped + # Shares Gerbil's network namespace so it can use Gerbil's exposed ports + network_mode: "service:gerbil" + depends_on: + pangolin: + condition: service_healthy + command: + - --configFile=/etc/traefik/traefik_config.yml + volumes: + - traefik-certs:/letsencrypt + +# ============================================================================= +# Volumes +# ============================================================================= +volumes: + # Shared config: both pangolin (/app/config) and gerbil (/var/config) mount + # this same volume so the WireGuard key generated by gerbil is readable by pangolin + pangolin-config: + driver: local + traefik-certs: + driver: local + +# ============================================================================= +# Networks +# ============================================================================= +networks: + pangolin-internal: + driver: bridge + dokploy-network: + external: true diff --git a/blueprints/pangolin/logo.svg b/blueprints/pangolin/logo.svg new file mode 100644 index 0000000..f4546f5 --- /dev/null +++ b/blueprints/pangolin/logo.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PANGOLIN + diff --git a/blueprints/pangolin/template.toml b/blueprints/pangolin/template.toml new file mode 100644 index 0000000..2961fd4 --- /dev/null +++ b/blueprints/pangolin/template.toml @@ -0,0 +1,233 @@ +# Pangolin - Identity-Aware VPN and Proxy Server +# Secure remote access with zero-trust identity enforcement +# https://github.com/fosrl/pangolin + +[variables] +# ============================================================================= +# Domain Configuration +# ============================================================================= +# Admin dashboard domain (e.g., pangolin.example.com) — REQUIRED +pangolin_domain = "${domain}" + +# Base domain for tunneled services (e.g., example.com) — REQUIRED +# Wildcard DNS *.example.com should point to this server +# Example: "example.com" +base_domain = "" + +# ============================================================================= +# Admin Account — REQUIRED +# ============================================================================= +# Initial admin email address (e.g., admin@example.com) +admin_email = "" +admin_password = "${password:32}" + +# ============================================================================= +# Let's Encrypt — REQUIRED +# Email used for certificate notifications and recovery +# ============================================================================= +letsencrypt_email = "" + +# ============================================================================= +# Security Secrets (auto-generated) +# ============================================================================= +app_secret = "${password:32}" +resource_access_secret = "${password:32}" + +# ============================================================================= +# Port Configuration +# These can be changed to avoid conflicts with Dokploy's Traefik +# ============================================================================= +wireguard_port = "51820" +https_proxy_port = "443" +http_proxy_port = "80" + +# ============================================================================= +# Optional: SMTP Email Configuration +# Required for user invite emails, password resets, etc. +# ============================================================================= +smtp_host = "" +smtp_port = "587" +smtp_username = "" +smtp_password = "" +smtp_from_email = "" + +# ============================================================================= +# Application Settings +# ============================================================================= +log_level = "info" + +# ============================================================================= +# Domain Routing (Dokploy's Traefik) +# Points to Pangolin admin dashboard +# ============================================================================= +[[config.domains]] +serviceName = "pangolin" +port = 3000 +host = "${pangolin_domain}" + +# ============================================================================= +# Environment Variables +# ============================================================================= +[config.env] +PANGOLIN_DOMAIN = "${pangolin_domain}" +WIREGUARD_PORT = "${wireguard_port}" +HTTPS_PROXY_PORT = "${https_proxy_port}" +HTTP_PROXY_PORT = "${http_proxy_port}" + +# ============================================================================= +# Pangolin Configuration File +# Mounted into the container at /app/config/config.yml +# ============================================================================= +[[config.mounts]] +serviceName = "pangolin" +mountPath = "/app/config/config.yml" +content = """ +# Pangolin Configuration +# Auto-generated by Dokploy — edit via environment variables or redeploy +# https://docs.pangolin.net/self-host/manual/install + +# ============================================================================= +# Application +# ============================================================================= +app: + dashboard_url: "https://${pangolin_domain}" + log_level: "${log_level}" + save_logs: false + secret: "${app_secret}" + +# ============================================================================= +# Domain +# ============================================================================= +domains: + base_domain: "${base_domain}" + cert_resolver: "letsencrypt" + prefer_wildcard_cert: false + +# ============================================================================= +# Admin User (initial setup — change password after first login) +# ============================================================================= +users: + server_admin: + email: "${admin_email}" + password: "${admin_password}" + +# ============================================================================= +# Ingress +# ============================================================================= +ingress: + base_domain: "${base_domain}" + +# ============================================================================= +# Gerbil (WireGuard tunnel agent) +# ============================================================================= +gerbil: + start_port: 51820 + base_endpoint: "${base_domain}:51820" + block_size: 24 + site_block_size: 30 + subnet_group: "100.89.137.0/20" + +# ============================================================================= +# Traefik (Pangolin's embedded reverse proxy) +# ============================================================================= +traefik: + cert_resolver: "letsencrypt" + http_entrypoint: "web" + https_entrypoint: "websecure" + +# ============================================================================= +# HTTP Server +# ============================================================================= +server: + external_port: 443 + session_cookie_name: "p_session_token" + resource_access_token_param: "p_token" + resource_access_token_headers: "X-Pangolin-Token" + resource_access_secret: "${resource_access_secret}" + cors: + origins: + - "https://${pangolin_domain}" + +# ============================================================================= +# Rate Limiting +# ============================================================================= +rate_limit: + window_minutes: 1 + max_requests: 100 + +# ============================================================================= +# Email / SMTP (optional — required for user invites and password resets) +# ============================================================================= +email: + smtp_host: "${smtp_host}" + smtp_port: ${smtp_port} + smtp_username: "${smtp_username}" + smtp_password: "${smtp_password}" + no_reply_address: "${smtp_from_email}" + email_header: "Pangolin" +""" + +# ============================================================================= +# Traefik Static Configuration +# Mounted into the Traefik container at /etc/traefik/traefik_config.yml +# ============================================================================= +[[config.mounts]] +serviceName = "traefik" +mountPath = "/etc/traefik/traefik_config.yml" +content = """ +# Traefik Static Configuration for Pangolin +# https://doc.traefik.io/traefik/getting-started/configuration-overview/ + +api: + dashboard: false + insecure: false + +log: + level: "INFO" + +entryPoints: + web: + address: ":80" + http: + redirections: + entryPoint: + to: websecure + scheme: https + permanent: true + websecure: + address: ":443" + +certificatesResolvers: + letsencrypt: + acme: + email: "${letsencrypt_email}" + storage: /letsencrypt/acme.json + httpChallenge: + entryPoint: web + +providers: + http: + endpoint: "http://pangolin:3001/api/v1/traefik-config" + pollInterval: "5s" + file: + filename: /etc/traefik/dynamic_config.yml + watch: true +""" + +# ============================================================================= +# Traefik Dynamic Configuration +# ============================================================================= +[[config.mounts]] +serviceName = "traefik" +mountPath = "/etc/traefik/dynamic_config.yml" +content = """ +# Traefik Dynamic Configuration for Pangolin +# This file is managed by Pangolin — changes may be overwritten + +http: + middlewares: + redirect-to-https: + redirectScheme: + scheme: https + permanent: true +""" From 0fd74b0c457fab4f1021c9a3f72c2c5710a61808 Mon Sep 17 00:00:00 2001 From: Elvis Nuno <6727752+enuno@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:05:45 -0700 Subject: [PATCH 3/8] Update blueprints/pangolin/docker-compose.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- blueprints/pangolin/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blueprints/pangolin/docker-compose.yml b/blueprints/pangolin/docker-compose.yml index f6f9c9d..5164924 100644 --- a/blueprints/pangolin/docker-compose.yml +++ b/blueprints/pangolin/docker-compose.yml @@ -93,7 +93,7 @@ services: # This is Pangolin's own Traefik — separate from Dokploy's Traefik # =========================================================================== traefik: - image: traefik:v3.3 + image: traefik:v3.3.0 restart: unless-stopped # Shares Gerbil's network namespace so it can use Gerbil's exposed ports network_mode: "service:gerbil" From 48691c9ac4615b027c3a205c4ae7fc38ad082548 Mon Sep 17 00:00:00 2001 From: Elvis Nuno <6727752+enuno@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:06:33 -0700 Subject: [PATCH 4/8] Update blueprints/pangolin/template.toml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- blueprints/pangolin/template.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blueprints/pangolin/template.toml b/blueprints/pangolin/template.toml index 2961fd4..a2699fe 100644 --- a/blueprints/pangolin/template.toml +++ b/blueprints/pangolin/template.toml @@ -139,7 +139,7 @@ traefik: # HTTP Server # ============================================================================= server: - external_port: 443 + external_port: ${https_proxy_port} session_cookie_name: "p_session_token" resource_access_token_param: "p_token" resource_access_token_headers: "X-Pangolin-Token" From 70cb33289a8f0937d3f79457d5e0849f22481745 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 16:08:26 +0000 Subject: [PATCH 5/8] =?UTF-8?q?blueprint:=20fix=20pangolin=20review=20comm?= =?UTF-8?q?ents=20=E2=80=94=20pin=20traefik,=20add=20version=20header,=20f?= =?UTF-8?q?ix=20variable=20references,=20clarify=20port/network=20exceptio?= =?UTF-8?q?ns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: enuno <6727752+enuno@users.noreply.github.com> --- blueprints/pangolin/README.md | 6 ++--- blueprints/pangolin/docker-compose.yml | 31 ++++++++++++++++++++++---- blueprints/pangolin/template.toml | 11 +++++++-- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/blueprints/pangolin/README.md b/blueprints/pangolin/README.md index 1c2dcca..cc7ff44 100644 --- a/blueprints/pangolin/README.md +++ b/blueprints/pangolin/README.md @@ -35,7 +35,7 @@ Internet │ └────────────┘ └─────────┘ └─────────────┘ │ │ │ │ │ ┌──────▼──────┐ │ -│ │ SQLite DB │ (persisted in pangolin-db volume) │ +│ │ SQLite DB │ (persisted in pangolin-config volume)│ │ └─────────────┘ │ └─────────────────────────────────────────────────────┘ ``` @@ -312,8 +312,8 @@ Back up these named volumes regularly: | Volume | Contents | |--------|----------| -| `pangolin-config` | SQLite database, WireGuard keys, Let's Encrypt certs | -| `traefik-certs` | Traefik certificate store (ACME) | +| `pangolin-config` | SQLite database, WireGuard keys, Pangolin application configuration | +| `traefik-certs` | Traefik ACME storage (Let's Encrypt certificates) | ```bash # Example backup command for pangolin config volume diff --git a/blueprints/pangolin/docker-compose.yml b/blueprints/pangolin/docker-compose.yml index 5164924..ad32fb5 100644 --- a/blueprints/pangolin/docker-compose.yml +++ b/blueprints/pangolin/docker-compose.yml @@ -13,6 +13,8 @@ # Traefik on the same host — deploy on a dedicated server for best results. # ============================================================================= +version: "3.8" + services: # =========================================================================== # Pangolin - Identity-Aware Proxy Control Plane @@ -71,11 +73,23 @@ services: - NET_ADMIN - SYS_MODULE ports: - # WireGuard VPN endpoint (UDP) + # =========================================================================== + # EXCEPTION TO BLUEPRINT "NO EXPOSED PORTS" RULE: + # Pangolin is a self-contained networking stack that includes its own Traefik + # instance. It requires host-level port binding for: + # - WireGuard VPN (UDP 51820): must be reachable by remote tunnel clients + # - HTTPS (443): terminates TLS for all services proxied through Pangolin + # - HTTP (80): Let's Encrypt ACME httpChallenge; redirects to HTTPS + # These ports CANNOT be routed through Dokploy's Traefik because Gerbil and + # its Traefik must bind them directly on the host network stack. + # =========================================================================== + # WireGuard VPN endpoint (UDP) — must be reachable by tunnel clients - "${WIREGUARD_PORT:-51820}:51820/udp" - # HTTP/HTTPS for Traefik (Pangolin's own reverse proxy) - # WARNING: These may conflict with Dokploy's Traefik on the same host. - # Consider changing to alternate ports (e.g., 8443, 8080) if needed. + # HTTPS for Pangolin's embedded Traefik — terminates TLS for tunneled services + # WARNING: Conflicts with Dokploy's Traefik if deployed on the same host. + # Deploy on a dedicated server or change HTTPS_PROXY_PORT and HTTP_PROXY_PORT. + # NOTE: Changing HTTP_PROXY_PORT away from 80 will break Let's Encrypt + # ACME httpChallenge. Port 80 must remain accessible for certificate issuance. - "${HTTPS_PROXY_PORT:-443}:443" - "${HTTP_PROXY_PORT:-80}:80" networks: @@ -119,6 +133,15 @@ volumes: # ============================================================================= # Networks # ============================================================================= +# EXCEPTION TO BLUEPRINT "DON'T DEFINE NETWORKS" RULE: +# This multi-service stack requires explicit network definitions because: +# - pangolin-internal: isolates Pangolin/Gerbil/Traefik inter-service traffic +# from the public-facing Dokploy network (security isolation) +# - dokploy-network: required to attach the pangolin service to Dokploy's +# host Traefik so the admin dashboard can be routed and TLS-terminated +# Without these, service discovery between Pangolin and Gerbil breaks and the +# admin dashboard cannot be reached via Dokploy's Traefik. +# ============================================================================= networks: pangolin-internal: driver: bridge diff --git a/blueprints/pangolin/template.toml b/blueprints/pangolin/template.toml index a2699fe..e4af2fe 100644 --- a/blueprints/pangolin/template.toml +++ b/blueprints/pangolin/template.toml @@ -121,8 +121,8 @@ ingress: # Gerbil (WireGuard tunnel agent) # ============================================================================= gerbil: - start_port: 51820 - base_endpoint: "${base_domain}:51820" + start_port: ${wireguard_port} + base_endpoint: "${base_domain}:${wireguard_port}" block_size: 24 site_block_size: 30 subnet_group: "100.89.137.0/20" @@ -188,6 +188,11 @@ log: entryPoints: web: address: ":80" + # NOTE: Port 80 must remain mapped to the host for ACME httpChallenge to work. + # The HTTP_PROXY_PORT variable controls which host port maps to this container + # port 80. If you change HTTP_PROXY_PORT away from 80, Let's Encrypt certificate + # issuance will fail. In that case, switch to tlsChallenge below (requires port 443) + # by replacing httpChallenge with: tlsChallenge: {} http: redirections: entryPoint: @@ -202,6 +207,8 @@ certificatesResolvers: acme: email: "${letsencrypt_email}" storage: /letsencrypt/acme.json + # httpChallenge requires host port 80 → container port 80. + # If HTTP_PROXY_PORT is not 80, switch to: tlsChallenge: {} httpChallenge: entryPoint: web From 0e04bcb8c6e27b4c60c53a609d38c4f3fc9f94fe Mon Sep 17 00:00:00 2001 From: Elvis Nuno <6727752+enuno@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:09:24 -0700 Subject: [PATCH 6/8] Update blueprints/pangolin/docker-compose.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- blueprints/pangolin/docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/blueprints/pangolin/docker-compose.yml b/blueprints/pangolin/docker-compose.yml index ad32fb5..0c2b351 100644 --- a/blueprints/pangolin/docker-compose.yml +++ b/blueprints/pangolin/docker-compose.yml @@ -13,6 +13,7 @@ # Traefik on the same host — deploy on a dedicated server for best results. # ============================================================================= +version: "3.8" version: "3.8" services: From ae789f57a2d64678038b11f2508f528f3d88582a Mon Sep 17 00:00:00 2001 From: Elvis Nuno <6727752+enuno@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:29:01 -0700 Subject: [PATCH 7/8] Update blueprints/pangolin/docker-compose.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- blueprints/pangolin/docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/blueprints/pangolin/docker-compose.yml b/blueprints/pangolin/docker-compose.yml index 0c2b351..ad32fb5 100644 --- a/blueprints/pangolin/docker-compose.yml +++ b/blueprints/pangolin/docker-compose.yml @@ -13,7 +13,6 @@ # Traefik on the same host — deploy on a dedicated server for best results. # ============================================================================= -version: "3.8" version: "3.8" services: From 8aa20ad44ffc70cde8221d74c95c5721821404ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 16:41:09 +0000 Subject: [PATCH 8/8] blueprint: redesign pangolin to use Dokploy Traefik, remove embedded Traefik and ports 80/443 Co-authored-by: enuno <6727752+enuno@users.noreply.github.com> --- blueprints/README.md | 1 + blueprints/pangolin/README.md | 97 +++++++---------------- blueprints/pangolin/docker-compose.yml | 58 +++----------- blueprints/pangolin/template.toml | 103 ++----------------------- 4 files changed, 49 insertions(+), 210 deletions(-) diff --git a/blueprints/README.md b/blueprints/README.md index b5c6ce5..73ed862 100644 --- a/blueprints/README.md +++ b/blueprints/README.md @@ -70,6 +70,7 @@ This directory contains custom Dokploy templates for deploying applications in t | [open-notebook](/blueprints/open-notebook/) | Private multi-model AI knowledge management platform with 16+ AI provider support | 1 (all-in-one) | Ready | | [paaster](/blueprints/paaster/) | Secure end-to-end encrypted pastebin with zero-knowledge server | 5 (paaster, mongodb, + helpers) | Ready | | [padloc](/blueprints/padloc/) | Open-source password manager with end-to-end encryption and zero-knowledge architecture | 2 (server, pwa) | Ready | +| [pangolin](/blueprints/pangolin/) | Identity-aware VPN and proxy server with WireGuard tunnels and zero-trust access control | 2 (pangolin, gerbil) | Ready | | [personalized-deep-research](/blueprints/personalized-deep-research/) | Intelligent research agent with Nuxt frontend for complex AI-powered research tasks | 1 (deep-research-web) | Ready | | [signal-cli-rest-api](/blueprints/signal-cli-rest-api/) | REST API wrapper for Signal Messenger enabling programmatic messaging with QR code device linking | 1 (signal-cli-rest-api) | Ready | | [someguy](/blueprints/someguy/) | HTTP Delegated Routing V1 server for IPFS with Amino DHT proxy | 1 (someguy) | Ready | diff --git a/blueprints/pangolin/README.md b/blueprints/pangolin/README.md index cc7ff44..f735774 100644 --- a/blueprints/pangolin/README.md +++ b/blueprints/pangolin/README.md @@ -4,7 +4,6 @@ - 🔐 **Identity-Aware Access**: Enforce authentication before reaching any resource - 🌐 **WireGuard VPN Tunnels**: Connect remote sites and clients with modern WireGuard -- 🔄 **Dynamic Reverse Proxy**: Built-in Traefik for automatic TLS and HTTP routing - 👥 **Multi-Org Support**: Isolated organizations with role-based access control - 🔑 **SSO / OIDC Integration**: Connect to Authelia, Authentik, Keycloak, and more - 🛡️ **Zero-Trust Architecture**: No implicit trust — every request is authenticated @@ -19,20 +18,19 @@ ``` Internet │ - ├── 443 (HTTPS) ──► Gerbil + Traefik ──► Tunneled Services ├── 51820 (UDP) ──► Gerbil (WireGuard) ──► VPN Clients │ - └── Dokploy Traefik ──► Pangolin Dashboard (Admin UI) + └── Dokploy Traefik (443/HTTPS) ──► Pangolin Dashboard (Admin UI) ┌─────────────────────────────────────────────────────┐ │ Pangolin Stack │ │ │ -│ ┌────────────┐ ┌─────────┐ ┌─────────────┐ │ -│ │ Pangolin │◄───│ Gerbil │◄───│ Traefik │ │ -│ │ (Control) │ │ (VPN) │ │ (Proxy) │ │ -│ │ Port 3001 │ │UDP 51820│ │ Port 80/443 │ │ -│ │ Port 3000 │ │ │ │ │ │ -│ └────────────┘ └─────────┘ └─────────────┘ │ +│ ┌────────────┐ ┌─────────┐ │ +│ │ Pangolin │◄───│ Gerbil │ │ +│ │ (Control) │ │ (VPN) │ │ +│ │ Port 3001 │ │UDP 51820│ │ +│ │ Port 3000 │ │ │ │ +│ └────────────┘ └─────────┘ │ │ │ │ │ ┌──────▼──────┐ │ │ │ SQLite DB │ (persisted in pangolin-config volume)│ @@ -40,26 +38,20 @@ Internet └─────────────────────────────────────────────────────┘ ``` -**Service Type**: Multi-service stack (Pangolin + Gerbil + Traefik) +**Service Type**: Multi-service stack (Pangolin + Gerbil) **Database**: Self-contained SQLite (in `/app/config/db`) **VPN**: WireGuard via Gerbil -**Proxy**: Embedded Traefik instance for tunneled services +**Routing**: Dokploy's Traefik handles HTTPS for the admin dashboard --- ## Prerequisites -1. **Dedicated server or VPS** (recommended — Pangolin uses ports 80, 443, 51820) +1. **Dokploy** installed and running 2. **DNS configuration**: - - `pangolin.example.com` → Server IP (admin dashboard) - - `*.example.com` → Server IP (wildcard for tunneled services) -3. **Firewall rules**: Open ports `443/tcp`, `80/tcp`, `51820/udp` -4. **Dokploy** installed and running - -> **⚠️ Port Conflict Warning**: Pangolin's embedded Traefik uses ports 80 and 443. -> If Dokploy's Traefik already uses these ports on the same host, you must either: -> - Deploy Pangolin on a **dedicated server** -> - Change `HTTP_PROXY_PORT` and `HTTPS_PROXY_PORT` to alternate values (e.g., 8080, 8443) + - `pangolin.example.com` → Server IP (admin dashboard, routed via Dokploy Traefik) + - `*.example.com` → Server IP (optional wildcard for services accessed through WireGuard tunnels) +3. **Firewall rules**: Open port `51820/udp` --- @@ -72,9 +64,6 @@ Before deploying, set up DNS records: ``` # Admin dashboard pangolin.example.com A - -# Wildcard for tunneled services -*.example.com A ``` ### 2. Deploy Template @@ -108,10 +97,9 @@ Navigate to `https://pangolin.example.com/auth/initial-setup` and: | Variable | Description | Example | |----------|-------------|---------| | `pangolin_domain` | Admin dashboard domain | `pangolin.example.com` | -| `base_domain` | Base domain for tunneled services | `example.com` | +| `base_domain` | Base domain for WireGuard tunnel clients | `example.com` | | `admin_email` | Initial admin email address | `admin@example.com` | | `admin_password` | Initial admin password (auto-generated) | *(generated)* | -| `letsencrypt_email` | Email for Let's Encrypt certificates | `admin@example.com` | | `app_secret` | Application secret key (auto-generated) | *(generated)* | | `resource_access_secret` | Resource token secret (auto-generated) | *(generated)* | @@ -120,8 +108,6 @@ Navigate to `https://pangolin.example.com/auth/initial-setup` and: | Variable | Default | Description | |----------|---------|-------------| | `wireguard_port` | `51820` | WireGuard VPN UDP port | -| `https_proxy_port` | `443` | HTTPS port for tunneled services | -| `http_proxy_port` | `80` | HTTP port (redirects to HTTPS) | | `smtp_host` | *(empty)* | SMTP server for email notifications | | `smtp_port` | `587` | SMTP port | | `smtp_username` | *(empty)* | SMTP username | @@ -137,8 +123,6 @@ These are set via Dokploy's environment variable injection: |----------|-------------| | `PANGOLIN_DOMAIN` | Admin dashboard domain | | `WIREGUARD_PORT` | WireGuard listen port | -| `HTTPS_PROXY_PORT` | HTTPS proxy port | -| `HTTP_PROXY_PORT` | HTTP proxy port | --- @@ -201,31 +185,24 @@ Pangolin supports SSO via OpenID Connect (OIDC). Configure in the admin UI under | Port | Protocol | Purpose | Required | |------|----------|---------|----------| -| `443` | TCP | HTTPS for tunneled services + Let's Encrypt | Yes | -| `80` | TCP | HTTP → HTTPS redirect + Let's Encrypt challenge | Yes | | `51820` | UDP | WireGuard VPN tunnels | Yes | +> **Note**: The admin dashboard HTTPS traffic (port 443) is handled by Dokploy's Traefik instance. Only the WireGuard UDP port needs to be opened in the firewall. + ### Firewall Rules ```bash -# Open required ports -ufw allow 80/tcp -ufw allow 443/tcp +# Open WireGuard port ufw allow 51820/udp - -# Restrict admin dashboard to trusted IPs (recommended) -ufw allow from to any port 443 ``` -### DNS Wildcard Setup +### DNS Setup -Pangolin creates subdomains for each exposed service: +Pangolin needs a domain for the admin dashboard: ``` -# All tunneled services use subdomains of base_domain -api.example.com → service behind Pangolin tunnel -app.example.com → another service -db-admin.example.com → protected database UI +# Admin dashboard (routed via Dokploy Traefik) +pangolin.example.com A ``` --- @@ -241,10 +218,9 @@ db-admin.example.com → protected database UI ### Network Security -- ✅ All traffic encrypted via TLS (Let's Encrypt) +- ✅ Admin dashboard TLS handled by Dokploy's Traefik (Let's Encrypt) - ✅ WireGuard provides end-to-end encryption for VPN tunnels -- ✅ Deploy on a dedicated server to avoid port conflicts -- ✅ Use firewall to restrict access to management ports +- ✅ Use firewall to restrict WireGuard port access - ✅ Enable identity provider authentication for zero-trust access ### Secrets Rotation @@ -282,25 +258,11 @@ nc -u -zv your-server-ip 51820 docker compose exec gerbil ls /var/config/key ``` -### Let's Encrypt Certificate Issues - -```bash -# Check Traefik logs -docker compose logs traefik - -# Verify HTTP challenge is reachable -curl http://your-domain/.well-known/acme-challenge/test - -# Common cause: port 80 blocked by firewall -ufw status -``` - ### Services Not Accessible via Tunnel 1. Verify site is connected: Pangolin admin → **Sites** → check status 2. Check resource configuration: correct target URL 3. Review access policies: user has permission to access resource -4. Check Traefik config: `docker compose logs traefik` --- @@ -308,12 +270,11 @@ ufw status ### Critical Data -Back up these named volumes regularly: +Back up this named volume regularly: | Volume | Contents | |--------|----------| | `pangolin-config` | SQLite database, WireGuard keys, Pangolin application configuration | -| `traefik-certs` | Traefik ACME storage (Let's Encrypt certificates) | ```bash # Example backup command for pangolin config volume @@ -341,11 +302,11 @@ To update Pangolin: Before going live: -- [ ] DNS configured: `pangolin.example.com` and `*.example.com` → server IP -- [ ] Firewall open: ports 80, 443 (TCP), 51820 (UDP) +- [ ] DNS configured: `pangolin.example.com` → server IP +- [ ] Firewall open: port 51820 (UDP) - [ ] Admin password changed after first login - [ ] MFA enabled on admin account -- [ ] Let's Encrypt certificates active (check Traefik logs) +- [ ] TLS certificate active (check Dokploy Traefik for domain) - [ ] SMTP configured (for user invites) - [ ] Identity provider configured (optional but recommended) - [ ] Volume backup strategy in place @@ -368,9 +329,9 @@ Before going live: - **Image**: `ghcr.io/fosrl/pangolin:sha256-3013a0e89e3259567fd86d23af50fc1c7ad9216ab0693ceb823b01c35e6acb5` - **Gerbil**: `ghcr.io/fosrl/gerbil:1.3.0` - **Type**: Identity-aware VPN and Proxy Server -- **Architecture**: Multi-service (Pangolin + Gerbil + Traefik) +- **Architecture**: Multi-service (Pangolin + Gerbil) - **Storage**: SQLite in persistent volumes -- **Networking**: WireGuard VPN + HTTP/HTTPS reverse proxy +- **Networking**: WireGuard VPN, admin UI via Dokploy Traefik - **Status**: Production-Ready --- diff --git a/blueprints/pangolin/docker-compose.yml b/blueprints/pangolin/docker-compose.yml index ad32fb5..d556819 100644 --- a/blueprints/pangolin/docker-compose.yml +++ b/blueprints/pangolin/docker-compose.yml @@ -4,13 +4,11 @@ # ============================================================================= # Architecture: # - Pangolin: Central control plane / admin dashboard (port 3001 API, 3000 UI) -# - Gerbil: WireGuard-based tunnel agent (UDP 51820, HTTPS 443) -# - Traefik: Dynamic reverse proxy running in Gerbil's network namespace +# - Gerbil: WireGuard-based tunnel agent (UDP 51820) # -# NOTE: This stack includes its own Traefik instance for proxying tunneled -# services. Pangolin's admin dashboard is exposed via Dokploy's host Traefik. -# Ports 443 and 80 (used by Gerbil/Traefik) may conflict with Dokploy's -# Traefik on the same host — deploy on a dedicated server for best results. +# Admin dashboard is routed through Dokploy's Traefik (no separate Traefik +# instance in this stack). WireGuard UDP port is exposed directly on the host +# so remote tunnel clients can reach this server. # ============================================================================= version: "3.8" @@ -52,8 +50,13 @@ services: # =========================================================================== # Gerbil - WireGuard Tunnel Agent - # Manages WireGuard VPN peers and exposes HTTP/HTTPS for Traefik + # Manages WireGuard VPN peers and writes the WireGuard key to the shared volume # Requires NET_ADMIN and SYS_MODULE capabilities for WireGuard kernel module + # + # EXCEPTION TO BLUEPRINT "NO EXPOSED PORTS" RULE: + # WireGuard VPN (UDP 51820) must be directly reachable by remote tunnel + # clients — it cannot be routed through Dokploy's Traefik. This is the only + # port exposed on the host for this blueprint. # =========================================================================== gerbil: image: ghcr.io/fosrl/gerbil:1.3.0 @@ -73,25 +76,8 @@ services: - NET_ADMIN - SYS_MODULE ports: - # =========================================================================== - # EXCEPTION TO BLUEPRINT "NO EXPOSED PORTS" RULE: - # Pangolin is a self-contained networking stack that includes its own Traefik - # instance. It requires host-level port binding for: - # - WireGuard VPN (UDP 51820): must be reachable by remote tunnel clients - # - HTTPS (443): terminates TLS for all services proxied through Pangolin - # - HTTP (80): Let's Encrypt ACME httpChallenge; redirects to HTTPS - # These ports CANNOT be routed through Dokploy's Traefik because Gerbil and - # its Traefik must bind them directly on the host network stack. - # =========================================================================== # WireGuard VPN endpoint (UDP) — must be reachable by tunnel clients - "${WIREGUARD_PORT:-51820}:51820/udp" - # HTTPS for Pangolin's embedded Traefik — terminates TLS for tunneled services - # WARNING: Conflicts with Dokploy's Traefik if deployed on the same host. - # Deploy on a dedicated server or change HTTPS_PROXY_PORT and HTTP_PROXY_PORT. - # NOTE: Changing HTTP_PROXY_PORT away from 80 will break Let's Encrypt - # ACME httpChallenge. Port 80 must remain accessible for certificate issuance. - - "${HTTPS_PROXY_PORT:-443}:443" - - "${HTTP_PROXY_PORT:-80}:80" networks: - pangolin-internal healthcheck: @@ -101,24 +87,6 @@ services: retries: 3 start_period: 30s - # =========================================================================== - # Traefik - Dynamic Reverse Proxy for Pangolin-Tunneled Services - # Runs in Gerbil's network namespace to handle HTTP/HTTPS routing - # This is Pangolin's own Traefik — separate from Dokploy's Traefik - # =========================================================================== - traefik: - image: traefik:v3.3.0 - restart: unless-stopped - # Shares Gerbil's network namespace so it can use Gerbil's exposed ports - network_mode: "service:gerbil" - depends_on: - pangolin: - condition: service_healthy - command: - - --configFile=/etc/traefik/traefik_config.yml - volumes: - - traefik-certs:/letsencrypt - # ============================================================================= # Volumes # ============================================================================= @@ -127,16 +95,14 @@ volumes: # this same volume so the WireGuard key generated by gerbil is readable by pangolin pangolin-config: driver: local - traefik-certs: - driver: local # ============================================================================= # Networks # ============================================================================= # EXCEPTION TO BLUEPRINT "DON'T DEFINE NETWORKS" RULE: # This multi-service stack requires explicit network definitions because: -# - pangolin-internal: isolates Pangolin/Gerbil/Traefik inter-service traffic -# from the public-facing Dokploy network (security isolation) +# - pangolin-internal: isolates Pangolin/Gerbil inter-service traffic from +# the public-facing Dokploy network (security isolation) # - dokploy-network: required to attach the pangolin service to Dokploy's # host Traefik so the admin dashboard can be routed and TLS-terminated # Without these, service discovery between Pangolin and Gerbil breaks and the diff --git a/blueprints/pangolin/template.toml b/blueprints/pangolin/template.toml index e4af2fe..10d1739 100644 --- a/blueprints/pangolin/template.toml +++ b/blueprints/pangolin/template.toml @@ -9,8 +9,9 @@ # Admin dashboard domain (e.g., pangolin.example.com) — REQUIRED pangolin_domain = "${domain}" -# Base domain for tunneled services (e.g., example.com) — REQUIRED -# Wildcard DNS *.example.com should point to this server +# Base domain for WireGuard tunnel clients and service routing (e.g., example.com) — REQUIRED +# This domain is used both as the WireGuard endpoint base and to build URLs for +# services accessed through WireGuard tunnels. # Example: "example.com" base_domain = "" @@ -21,12 +22,6 @@ base_domain = "" admin_email = "" admin_password = "${password:32}" -# ============================================================================= -# Let's Encrypt — REQUIRED -# Email used for certificate notifications and recovery -# ============================================================================= -letsencrypt_email = "" - # ============================================================================= # Security Secrets (auto-generated) # ============================================================================= @@ -35,11 +30,9 @@ resource_access_secret = "${password:32}" # ============================================================================= # Port Configuration -# These can be changed to avoid conflicts with Dokploy's Traefik # ============================================================================= +# WireGuard VPN UDP port — exposed directly on the host wireguard_port = "51820" -https_proxy_port = "443" -http_proxy_port = "80" # ============================================================================= # Optional: SMTP Email Configuration @@ -71,8 +64,6 @@ host = "${pangolin_domain}" [config.env] PANGOLIN_DOMAIN = "${pangolin_domain}" WIREGUARD_PORT = "${wireguard_port}" -HTTPS_PROXY_PORT = "${https_proxy_port}" -HTTP_PROXY_PORT = "${http_proxy_port}" # ============================================================================= # Pangolin Configuration File @@ -100,8 +91,6 @@ app: # ============================================================================= domains: base_domain: "${base_domain}" - cert_resolver: "letsencrypt" - prefer_wildcard_cert: false # ============================================================================= # Admin User (initial setup — change password after first login) @@ -127,19 +116,13 @@ gerbil: site_block_size: 30 subnet_group: "100.89.137.0/20" -# ============================================================================= -# Traefik (Pangolin's embedded reverse proxy) -# ============================================================================= -traefik: - cert_resolver: "letsencrypt" - http_entrypoint: "web" - https_entrypoint: "websecure" - # ============================================================================= # HTTP Server # ============================================================================= server: - external_port: ${https_proxy_port} + # Port 443 is the standard HTTPS port used in Pangolin-generated resource URLs. + # The admin UI is routed through Dokploy's Traefik (no separate proxy in this stack). + external_port: 443 session_cookie_name: "p_session_token" resource_access_token_param: "p_token" resource_access_token_headers: "X-Pangolin-Token" @@ -166,75 +149,3 @@ email: no_reply_address: "${smtp_from_email}" email_header: "Pangolin" """ - -# ============================================================================= -# Traefik Static Configuration -# Mounted into the Traefik container at /etc/traefik/traefik_config.yml -# ============================================================================= -[[config.mounts]] -serviceName = "traefik" -mountPath = "/etc/traefik/traefik_config.yml" -content = """ -# Traefik Static Configuration for Pangolin -# https://doc.traefik.io/traefik/getting-started/configuration-overview/ - -api: - dashboard: false - insecure: false - -log: - level: "INFO" - -entryPoints: - web: - address: ":80" - # NOTE: Port 80 must remain mapped to the host for ACME httpChallenge to work. - # The HTTP_PROXY_PORT variable controls which host port maps to this container - # port 80. If you change HTTP_PROXY_PORT away from 80, Let's Encrypt certificate - # issuance will fail. In that case, switch to tlsChallenge below (requires port 443) - # by replacing httpChallenge with: tlsChallenge: {} - http: - redirections: - entryPoint: - to: websecure - scheme: https - permanent: true - websecure: - address: ":443" - -certificatesResolvers: - letsencrypt: - acme: - email: "${letsencrypt_email}" - storage: /letsencrypt/acme.json - # httpChallenge requires host port 80 → container port 80. - # If HTTP_PROXY_PORT is not 80, switch to: tlsChallenge: {} - httpChallenge: - entryPoint: web - -providers: - http: - endpoint: "http://pangolin:3001/api/v1/traefik-config" - pollInterval: "5s" - file: - filename: /etc/traefik/dynamic_config.yml - watch: true -""" - -# ============================================================================= -# Traefik Dynamic Configuration -# ============================================================================= -[[config.mounts]] -serviceName = "traefik" -mountPath = "/etc/traefik/dynamic_config.yml" -content = """ -# Traefik Dynamic Configuration for Pangolin -# This file is managed by Pangolin — changes may be overwritten - -http: - middlewares: - redirect-to-https: - redirectScheme: - scheme: https - permanent: true -"""