Skip to content

Blueprint: Pangolin identity-aware VPN and proxy server#8

Merged
enuno merged 8 commits intomainfrom
copilot/create-blueprint-for-pangolin
Mar 7, 2026
Merged

Blueprint: Pangolin identity-aware VPN and proxy server#8
enuno merged 8 commits intomainfrom
copilot/create-blueprint-for-pangolin

Conversation

Copy link
Contributor

Copilot AI commented Mar 6, 2026

Adds a complete Dokploy blueprint for Pangolin — an identity-aware WireGuard VPN and proxy server.

Changes Made

blueprints/pangolin/docker-compose.yml

  • version: "3.8" header added (per blueprint instructions)
  • 2-service stack: pangolin (control plane) + gerbil (WireGuard tunnel agent)
  • Only WireGuard UDP port (51820) is exposed on the host — no ports 80/443
  • Admin dashboard routed through Dokploy's existing Traefik via standard labels on dokploy-network
  • Explicit exception comments for WireGuard port exposure and custom network definitions
  • Named volumes only (pangolin-config); no bind mounts

blueprints/pangolin/template.toml

  • All configurable variables declared in [variables] section
  • Auto-generated secrets (admin_password, app_secret, resource_access_secret)
  • gerbil.start_port and base_endpoint use ${wireguard_port} variable for consistency
  • server.external_port hardcoded to 443 with explanatory comment (no embedded Traefik)
  • Traefik static/dynamic config mounts removed (no embedded Traefik in this stack)
  • Domain routing via [[config.domains]] points to Dokploy's Traefik

blueprints/pangolin/logo.svg

  • Custom Pangolin-themed SVG icon (200×200px, light/dark compatible)

blueprints/pangolin/README.md

  • Architecture diagram reflects 2-service stack (Pangolin + Gerbil, no embedded Traefik)
  • Prerequisites simplified: only WireGuard UDP port and Dokploy required
  • Port requirements table updated (51820/UDP only)
  • Backup table: pangolin-config correctly described (SQLite DB, WireGuard keys, config)
  • Identity Provider Setup section (Authelia, Authentik, Keycloak examples)
  • Troubleshooting, Security Considerations, and Production Checklist updated

blueprints/README.md

  • Pangolin added to the Available Templates table

Testing

  • docker compose config validation passes
  • ✅ No hardcoded credentials
  • npm test (jest not installed in CI environment; compose validation used)
Original prompt

This section details on the original issue you should resolve

<issue_title>[Blueprint] Pangolin</issue_title>
<issue_description>### Application Name

Pangolin

Docker Image

ghcr.io/fosrl/pangolin

Version

sha256-3013a0e89e3259567fd86d23af50fc1c7ad9216ab0693ceb823b01c35e6acb5

Description

Create a blueprint for Pangolin identity aware vpn and proxy server

Cloudflare Services

  • Cloudflare Workers
  • Cloudflare D1 (database)
  • Cloudflare R2 (storage)
  • Cloudflare KV (key-value)
  • Cloudflare Pages
  • None (no Cloudflare integration)

Dependencies

  • PostgreSQL
  • MySQL/MariaDB
  • Redis
  • MongoDB
  • None (standalone service)

Additional Requirements

No response

Links

No response

Blueprint Checklist

  • docker-compose.yml with pinned version
  • template.toml with proper variable declarations
  • Logo SVG file
  • README.md with setup instructions
  • meta.json entry
  • Validation passes (npm run validate:all)
  • Tests pass (npm run test:coverage)
  • No hardcoded credentials</issue_description>

<agent_instructions>## Objective
Create a complete Dokploy blueprint for Pangolin identity-aware VPN and proxy server using the official Docker image ghcr.io/fosrl/pangolin:sha256-3013a0e89e3259567fd86d23af50fc1c7ad9216ab0693ceb823b01c35e6acb5.

Blueprint Structure Requirements

1. docker-compose.yml

  • Use the exact pinned version from the issue
  • Configure Pangolin as a standalone service (no database dependencies based on checklist)
  • Include essential environment variables for identity-aware proxy configuration:
    • Network mode configuration
    • Port mappings for VPN/proxy protocols
    • Volume mounts for persistent configuration
  • Follow Dokploy naming conventions for service names
  • Add health checks for service availability

2. template.toml

  • Define all configurable variables with proper types and descriptions
  • Required variable categories:
    • Network Configuration: VPN ports, proxy ports, network CIDR
    • Identity Provider: OAuth/OIDC endpoints, client credentials placeholders
    • Security: TLS certificate paths, authentication tokens
    • Application Settings: Log levels, upstream proxy settings
  • Use Dokploy variable syntax with default values where appropriate
  • Mark sensitive values as secret = true

3. Logo (logo.svg)

  • Create or source a Pangolin-themed SVG logo
  • Dimensions: 200x200px viewport
  • Use neutral colors compatible with light/dark themes
  • Simple, recognizable design

4. README.md Structure

Required sections:

  • Overview: Brief description of Pangolin's identity-aware capabilities
  • Prerequisites: Dokploy installation, network requirements
  • Quick Start: Step-by-step deployment instructions
  • Configuration: Detailed explanation of all template.toml variables
  • Identity Provider Setup: Instructions for OAuth/OIDC integration
  • Networking: Port requirements and firewall rules
  • Troubleshooting: Common issues and solutions
  • Security Considerations: Best practices for credential management

5. meta.json Entry

{
  "name": "pangolin",
  "displayName": "Pangolin",
  "description": "Identity-aware VPN and proxy server for secure remote access",
  "version": "1.0.0",
  "category": "networking",
  "tags": ["vpn", "proxy", "security", "identity", "authentication"],
  "author": "Dokploy Community",
  "repository": "ghcr.io/fosrl/pangolin"
}

Implementation Guidelines

Code Generation Approach

  1. Start with docker-compose.yml: Generate service definition first
  2. Extract variables: Identify all hardcoded values that should be configurable
  3. Create template.toml: Document each variable with type, description, and constraints
  4. Write comprehensive README: Include diagrams for identity flow if possible
  5. Validate: Ensure no credentials are hardcoded

Security Requirements

  • Never include example credentials in docker-compose.yml
  • All secrets must use Dokploy's secret management syntax: {{ SECRET_NAME }}
  • Document credential rotation procedures in README
  • Include TLS/SSL configuration examples

Testing Validation

Before marking complete, ensure:

  • npm run validate:all passes without errors
  • npm run test:coverage shows >80% coverage for any helper scripts
  • Docker Compose syntax is valid: docker-compose config
  • All template variables are referenced in docker-compose.yml

Context-Specific Details

Pangolin Architecture

Pangolin is designed as a zero-trust proxy that:

  • Authenticates users via OAuth/OIDC providers
  • Authorizes access based on identity policies
  • Proxies traffic to upstream services
  • Supports VPN tunneling for remote access

Network Considerations

  • Requires exposed ports for VPN (typically UDP) and HTTPS (443)
  • May need privileged networking mode for VPN functionality
  • Should support custom DNS configuration
  • Consider ...

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

…plate

Co-authored-by: enuno <6727752+enuno@users.noreply.github.com>
Copilot AI changed the title [WIP] Create a blueprint for Pangolin identity aware VPN Blueprint: Pangolin identity-aware VPN and proxy server Mar 6, 2026
Copilot finished work on behalf of enuno March 6, 2026 15:00
@codecov
Copy link

codecov bot commented Mar 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@enuno enuno marked this pull request as ready for review March 6, 2026 15:54
Copilot AI review requested due to automatic review settings March 6, 2026 15:54
@qodo-code-review
Copy link

Review Summary by Qodo

Add Pangolin identity-aware VPN and proxy server blueprint

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Adds comprehensive Pangolin blueprint for identity-aware VPN and proxy server
• Includes multi-service Docker Compose stack with Pangolin, Gerbil, and Traefik
• Provides detailed README with architecture, setup, security, and troubleshooting guides
• Implements template configuration with auto-generated secrets and SMTP support
Diagram
flowchart LR
  A["Dokploy Template"] -->|deploys| B["Pangolin Stack"]
  B -->|includes| C["Pangolin Control Plane"]
  B -->|includes| D["Gerbil WireGuard Agent"]
  B -->|includes| E["Traefik Reverse Proxy"]
  C -->|shares config| F["pangolin-config Volume"]
  D -->|writes key to| F
  D -->|exposes ports| G["51820 UDP, 80, 443 TCP"]
  E -->|routes via| G
  C -->|exposed via| H["Dokploy Traefik"]
Loading

Grey Divider

File Changes

1. blueprints/pangolin/README.md 📝 Documentation +381/-0

Complete Pangolin blueprint documentation and user guide

• Comprehensive 381-line documentation covering architecture, prerequisites, and quick start
• Detailed configuration guide for required and optional variables
• Identity provider setup instructions for Authelia, Authentik, and Keycloak
• Networking, security, backup, and troubleshooting sections
• Production checklist and support resources

blueprints/pangolin/README.md


2. blueprints/pangolin/docker-compose.yml ⚙️ Configuration changes +126/-0

Multi-service Docker Compose configuration for Pangolin stack

• Defines three-service stack: Pangolin (control plane), Gerbil (WireGuard agent), Traefik (reverse
 proxy)
• Pangolin service with health checks and Traefik routing labels for admin dashboard
• Gerbil service with NET_ADMIN and SYS_MODULE capabilities for WireGuard kernel module
• Traefik service running in Gerbil's network namespace for tunneled service routing
• Shared pangolin-config volume for WireGuard key exchange between services

blueprints/pangolin/docker-compose.yml


3. blueprints/pangolin/template.toml ⚙️ Configuration changes +233/-0

Dokploy template configuration with auto-generated secrets and mounts

• Defines template variables for domain, admin account, Let's Encrypt, and security secrets
• Auto-generates 32-character passwords for admin, app secret, and resource access secret
• Configurable ports for WireGuard (51820), HTTPS (443), and HTTP (80)
• Optional SMTP configuration for email notifications
• Three config mount sections: Pangolin config.yml, Traefik static config, and dynamic config
• Pangolin configuration includes app settings, domain routing, gerbil setup, and rate limiting
• Traefik configuration with Let's Encrypt ACME challenge and HTTP provider integration

blueprints/pangolin/template.toml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Mar 6, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (4) 📎 Requirement gaps (0)

Grey Divider


Action required

1. gerbil uses ports📘 Rule violation ✓ Correctness
Description
The blueprint compose file exposes host ports via ports:, which violates the blueprint compose
rules and can break Dokploy/Traefik conventions. This can lead to unexpected port conflicts and
inconsistent routing behavior.
Code

blueprints/pangolin/docker-compose.yml[R73-80]

+    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"
Evidence
PR Compliance ID 13 forbids using ports in blueprint compose files. The gerbil service
explicitly declares port mappings for WireGuard and HTTP/HTTPS.

AGENTS.md
blueprints/pangolin/docker-compose.yml[73-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `gerbil` service uses `ports:` mappings, which are disallowed for Dokploy blueprint compose files.
## Issue Context
This blueprint must follow the repository rule that blueprint `docker-compose.yml` files must not declare `ports`.
## Fix Focus Areas
- blueprints/pangolin/docker-compose.yml[73-80]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Manual networks declared 📘 Rule violation ✓ Correctness
Description
The blueprint compose file declares and attaches custom networks, which violates the blueprint
compose rules. This can cause incompatibility with Dokploy's expected networking model and routing
behavior.
Code

blueprints/pangolin/docker-compose.yml[R122-126]

+networks:
+  pangolin-internal:
+    driver: bridge
+  dokploy-network:
+    external: true
Evidence
PR Compliance ID 13 forbids networks entries in blueprint compose files. This compose both
attaches services to explicit networks and defines a networks: section.

AGENTS.md
blueprints/pangolin/docker-compose.yml[30-32]
blueprints/pangolin/docker-compose.yml[122-126]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The compose file manually defines and attaches Docker networks, which is disallowed for blueprint compose files.
## Issue Context
Blueprint templates must avoid ad-hoc network definitions to remain compatible with Dokploy.
## Fix Focus Areas
- blueprints/pangolin/docker-compose.yml[30-32]
- blueprints/pangolin/docker-compose.yml[81-83]
- blueprints/pangolin/docker-compose.yml[122-126]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. PANGOLIN_DOMAIN not required 📘 Rule violation ⛯ Reliability
Description
PANGOLIN_DOMAIN is referenced in compose without the required ${VAR:?message} pattern, so a
missing value can render an invalid Traefik rule at deploy time. This reduces template robustness
and makes failures harder to diagnose.
Code

blueprints/pangolin/docker-compose.yml[39]

+      - "traefik.http.routers.pangolin.rule=Host(`${PANGOLIN_DOMAIN}`)"
Evidence
PR Compliance ID 4 requires required variables to use ${VAR_NAME:?Set description}. The Traefik
router rule uses ${PANGOLIN_DOMAIN} without the required guard.

CLAUDE.md
blueprints/pangolin/docker-compose.yml[39-39]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A required env var (`PANGOLIN_DOMAIN`) is used without the required `${VAR:?message}` guard.
## Issue Context
This value is critical for Traefik routing; without an explicit required pattern, misconfiguration can silently produce invalid router rules.
## Fix Focus Areas
- blueprints/pangolin/docker-compose.yml[39-39]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (4)
4. traefik lacks healthcheck📘 Rule violation ⛯ Reliability
Description
The traefik service has no health check, preventing orchestration from detecting and reacting to
an unhealthy proxy container. This can cause prolonged outages without automatic recovery signals.
Code

blueprints/pangolin/docker-compose.yml[R95-107]

+  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
+
Evidence
PR Compliance ID 9 requires health checks for applicable services. The traefik service definition
includes no healthcheck: block.

CLAUDE.md
blueprints/pangolin/docker-compose.yml[95-107]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `traefik` service is missing a healthcheck.
## Issue Context
Without a healthcheck, Dokploy/docker cannot reliably detect unhealthy Traefik instances in this stack.
## Fix Focus Areas
- blueprints/pangolin/docker-compose.yml[95-107]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. WireGuard port hard-coded🐞 Bug ✓ Correctness
Description
The template exposes wireguard_port/WIREGUARD_PORT and docker-compose maps the host UDP port
from it, but the injected Pangolin config hard-codes 51820 for Gerbil endpoint/port. If a user
changes wireguard_port, Pangolin can still advertise/expect :51820, causing VPN clients to
connect to the wrong port.
Code

blueprints/pangolin/template.toml[R123-126]

+gerbil:
+  start_port: 51820
+  base_endpoint: "${base_domain}:51820"
+  block_size: 24
Evidence
wireguard_port is presented as configurable and exported to WIREGUARD_PORT, and docker-compose
uses it for host port mapping, but Pangolin’s config content still uses 51820 explicitly for the
advertised endpoint and start port.

blueprints/pangolin/template.toml[36-76]
blueprints/pangolin/docker-compose.yml[73-80]
blueprints/pangolin/template.toml[123-126]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`wireguard_port` is configurable and used by docker-compose port mapping, but Pangolin’s injected `config.yml` hard-codes `51820` in `gerbil.start_port` and `gerbil.base_endpoint`. This can break VPN client connectivity when `wireguard_port` is customized.
### Issue Context
The stack maps host `${WIREGUARD_PORT}` to container `51820/udp`, but Pangolin likely advertises the endpoint using `gerbil.base_endpoint`.
### Fix Focus Areas
- blueprints/pangolin/template.toml[123-126]
- blueprints/pangolin/template.toml[36-76]
### Suggested change
Update the injected config to reference the variable, e.g.:
- `start_port: ${wireguard_port}` (or keep internal 51820 if required by Pangolin, but then ensure `base_endpoint` uses `${wireguard_port}`)
- `base_endpoint: &amp;amp;amp;amp;amp;quot;${base_domain}:${wireguard_port}&amp;amp;amp;amp;amp;quot;`

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. HTTPS external_port fixed🐞 Bug ✓ Correctness
Description
The template allows customizing HTTPS_PROXY_PORT, but Pangolin’s injected config hard-codes
server.external_port: 443. If a user changes the public HTTPS port (e.g., to 8443), Pangolin may
generate URLs/redirects/tokens assuming 443, breaking access to tunneled services.
Code

blueprints/pangolin/template.toml[R141-143]

+server:
+  external_port: 443
+  session_cookie_name: "p_session_token"
Evidence
https_proxy_port is declared and exported and docker-compose maps it to the host port, but the
Pangolin config content still fixes external_port to 443, so the application configuration can
drift from the actual public port.

blueprints/pangolin/template.toml[36-76]
blueprints/pangolin/docker-compose.yml[76-80]
blueprints/pangolin/template.toml[141-143]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`HTTPS_PROXY_PORT` is configurable and used for host port mapping, but Pangolin’s injected config hard-codes `server.external_port: 443`, which can cause Pangolin to generate external URLs/redirects assuming port 443 even when the service is published on a different port.
### Issue Context
docker-compose maps `${HTTPS_PROXY_PORT}` on the host to `443` in the container. Pangolin should be told which port external clients actually use.
### Fix Focus Areas
- blueprints/pangolin/template.toml[141-143]
- blueprints/pangolin/template.toml[36-76]
### Suggested change
Set:
- `external_port: ${https_proxy_port}`
(or if Pangolin expects a string, quote it accordingly).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. HTTP port change breaks ACME🐞 Bug ⛯ Reliability
Description
The README suggests changing HTTP_PROXY_PORT/HTTPS_PROXY_PORT to avoid conflicts, but the
embedded Traefik config uses ACME httpChallenge on the web entrypoint (port 80). If a user
changes HTTP_PROXY_PORT away from 80, Traefik will no longer be reachable on public port 80 for
the HTTP-01 challenge, causing certificate issuance/renewal failures.
Code

blueprints/pangolin/template.toml[R200-207]

+certificatesResolvers:
+  letsencrypt:
+    acme:
+      email: "${letsencrypt_email}"
+      storage: /letsencrypt/acme.json
+      httpChallenge:
+        entryPoint: web
+
Evidence
The blueprint explicitly instructs users that changing proxy ports is an option, but the Traefik
configuration is hard-wired to HTTP-01 validation via the web entrypoint. HTTP-01 requires the
domain to be reachable on public TCP/80, which will not hold if the blueprint is deployed on a
different host port without additional port-forwarding or a different ACME challenge type.

blueprints/pangolin/README.md[59-63]
blueprints/pangolin/docker-compose.yml[76-80]
blueprints/pangolin/template.toml[188-207]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The README suggests changing `HTTP_PROXY_PORT`/`HTTPS_PROXY_PORT` to avoid port conflicts, but Traefik is configured to use ACME `httpChallenge` on entrypoint `web` bound to `:80`. If the service isn’t reachable on public TCP/80, HTTP-01 validation/renewal will fail.
### Issue Context
The current Traefik static config uses:
- `entryPoints.web.address = :80`
- `acme.httpChallenge.entryPoint = web`
### Fix Focus Areas
- blueprints/pangolin/template.toml[188-207]
- blueprints/pangolin/README.md[59-63]
### Suggested changes (pick one)
1) Documentation guardrail:
- Update README to state that Let’s Encrypt HTTP-01 requires public 80/443; changing ports requires additional host-level forwarding or a different ACME method.
2) Configurable ACME strategy:
- Add variables/preset to switch to DNS challenge (requires provider credentials) when ports are changed.
- Or provide an option to disable ACME and require users to supply certs externally.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +122 to +126
networks:
pangolin-internal:
driver: bridge
dokploy-network:
external: true

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Manual networks declared 📘 Rule violation ✓ Correctness

The blueprint compose file declares and attaches custom networks, which violates the blueprint
compose rules. This can cause incompatibility with Dokploy's expected networking model and routing
behavior.
Agent Prompt
## Issue description
The compose file manually defines and attaches Docker networks, which is disallowed for blueprint compose files.

## Issue Context
Blueprint templates must avoid ad-hoc network definitions to remain compatible with Dokploy.

## Fix Focus Areas
- blueprints/pangolin/docker-compose.yml[30-32]
- blueprints/pangolin/docker-compose.yml[81-83]
- blueprints/pangolin/docker-compose.yml[122-126]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot review and address this suggestion.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Implementation 🛠️

Implementation: Remove manual Docker network declarations to comply with Dokploy blueprint compose rules by deleting the custom networks: section at the bottom of the compose file (containers will use the default network managed by Dokploy).

Suggested change
networks:
pangolin-internal:
driver: bridge
dokploy-network:
external: true
# NOTE: Dokploy blueprints must not declare custom Docker networks.
# All services will use Dokploy-managed default networking.

See review comment here

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Implementation: Remove manual Docker network declarations to comply with Dokploy blueprint compose rules by deleting the custom networks: section at the bottom of the compose file (containers will use the default network managed by Dokploy).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Implementation 🛠️

Implementation: Remove the manually declared Docker networks to comply with Dokploy blueprint rules. Replace the custom networks: definitions with a short note indicating Dokploy-managed default networking should be used.

Suggested change
networks:
pangolin-internal:
driver: bridge
dokploy-network:
external: true
# =============================================================================
# Networks
# =============================================================================
# NOTE: Dokploy blueprints must not declare custom Docker networks.
# Services will use Dokploy-managed default networking.

See review comment here

# Exposed via Dokploy's host Traefik on the configured domain
# ===========================================================================
- "traefik.enable=true"
- "traefik.http.routers.pangolin.rule=Host(`${PANGOLIN_DOMAIN}`)"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. pangolin_domain not required 📘 Rule violation ⛯ Reliability

PANGOLIN_DOMAIN is referenced in compose without the required ${VAR:?message} pattern, so a
missing value can render an invalid Traefik rule at deploy time. This reduces template robustness
and makes failures harder to diagnose.
Agent Prompt
## Issue description
A required env var (`PANGOLIN_DOMAIN`) is used without the required `${VAR:?message}` guard.

## Issue Context
This value is critical for Traefik routing; without an explicit required pattern, misconfiguration can silently produce invalid router rules.

## Fix Focus Areas
- blueprints/pangolin/docker-compose.yml[39-39]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot review and address this suggestion.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Implementation 🛠️

Implementation: Update the Traefik Host() rule to require PANGOLIN_DOMAIN at deploy time using Docker Compose's ${VAR:?message} validation guard, preventing an invalid router rule when the variable is unset.

Suggested change
- "traefik.http.routers.pangolin.rule=Host(`${PANGOLIN_DOMAIN}`)"
- "traefik.http.routers.pangolin.rule=Host(`${PANGOLIN_DOMAIN:?PANGOLIN_DOMAIN is required}`)"

See review comment here

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Dokploy blueprint for deploying Pangolin (identity-aware reverse proxy + WireGuard VPN) as a multi-service stack.

Changes:

  • Introduces a 3-service Compose stack (pangolin, gerbil, traefik) with shared volumes and healthchecks.
  • Adds a Dokploy template.toml with generated secrets, domain/env wiring, and mounted config files (Pangolin + Traefik).
  • Adds blueprint documentation and an SVG logo.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 9 comments.

File Description
blueprints/pangolin/docker-compose.yml Defines the Pangolin/Gerbil/Traefik runtime stack, volumes, networks, and routing labels.
blueprints/pangolin/template.toml Declares template variables, Dokploy domain/env config, and mounts Pangolin + Traefik config content.
blueprints/pangolin/README.md Provides deployment prerequisites, DNS/firewall guidance, and operational runbook/backup notes.
blueprints/pangolin/logo.svg Adds an SVG logo for the blueprint.

Comment on lines +188 to +207
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

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The template suggests changing HTTP/HTTPS ports to avoid conflicts, but Traefik is configured for ACME httpChallenge on entryPoint web bound to :80. If users set http_proxy_port to anything other than 80, Let’s Encrypt issuance will fail unless the challenge type is changed (e.g., DNS challenge) and documented. Either enforce 80/443, or update the Traefik config + README to support non-standard ports.

Copilot uses AI. Check for mistakes.
Comment on lines +315 to +316
| `pangolin-config` | SQLite database, WireGuard keys, Let's Encrypt certs |
| `traefik-certs` | Traefik certificate store (ACME) |
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backup table says pangolin-config contains “Let's Encrypt certs”, but ACME storage is configured at /letsencrypt/acme.json and the compose mounts traefik-certs to /letsencrypt. The certs will live in traefik-certs, not pangolin-config; please correct the volume contents list so backups cover the right data.

Suggested change
| `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) |

Copilot uses AI. Check for mistakes.
Comment on lines +74 to +78
# 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.
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This blueprint publishes host ports (80/443/51820). The repo’s blueprint instructions currently state “Ports: Never expose ports (Traefik handles routing)” for blueprints/** (.github/instructions/blueprints.instructions.md:25-26). If Pangolin truly requires host-level port publishing (likely for WireGuard + ACME), please document this as an explicit exception and consider using expose: where host publishing isn’t strictly required.

Suggested change
# 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.
# WireGuard VPN endpoint (UDP) exposed on the host.
# NOTE: This blueprint intentionally publishes this port on the host as a
# documented exception to the global "no exposed ports" rule for blueprints,
# because WireGuard requires a reachable UDP endpoint.
- "${WIREGUARD_PORT:-51820}:51820/udp"
# HTTP/HTTPS for Traefik (Pangolin's own reverse proxy), exposed on the host
# to terminate TLS and handle ACME/ingress traffic directly.
# WARNING: These may conflict with Dokploy's Traefik on the same host.
# This is a deliberate exception to the blueprint guideline
# "Ports: Never expose ports (Traefik handles routing)" — Pangolin includes
# its own Traefik instance that must bind 80/443 (or alternate host ports).
# Consider changing to alternate ports (e.g., 8443, 8080) or deploying on a
# dedicated server if Dokploy's Traefik also listens on 80/443.

Copilot uses AI. Check for mistakes.
Comment on lines +119 to +126
# =============================================================================
# Networks
# =============================================================================
networks:
pangolin-internal:
driver: bridge
dokploy-network:
external: true
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file defines custom networks (pangolin-internal, dokploy-network). Blueprint instructions for blueprints/** say “Networks: Don't define (Dokploy manages networking)” (.github/instructions/blueprints.instructions.md:25-26). If these networks are required for this stack, add a short justification in-file/README; otherwise prefer relying on Dokploy’s default networking.

Copilot uses AI. Check for mistakes.
Comment on lines +124 to +125
start_port: 51820
base_endpoint: "${base_domain}:51820"
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The template exposes wireguard_port as configurable, but the generated Pangolin config.yml hardcodes gerbil.start_port: 51820 and base_endpoint: "${base_domain}:51820". If users change wireguard_port, Pangolin’s config will be inconsistent with the published port mapping; use the variable here (or remove the variable if it’s not supported).

Suggested change
start_port: 51820
base_endpoint: "${base_domain}:51820"
start_port: ${wireguard_port}
base_endpoint: "${base_domain}:${wireguard_port}"

Copilot uses AI. Check for mistakes.
│ └────────────┘ └─────────┘ └─────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ SQLite DB │ (persisted in pangolin-db volume) │
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The architecture diagram mentions a pangolin-db volume, but the compose file defines pangolin-config (which also appears to contain the SQLite DB under /app/config/db). Please update the diagram/text to match the actual volume name to avoid confusion during backups/restores.

Suggested change
│ │ SQLite DB │ (persisted in pangolin-db volume)
│ │ SQLite DB │ (persisted in pangolin-config volume)│

Copilot uses AI. Check for mistakes.
enuno and others added 3 commits March 6, 2026 09:05
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ader, fix variable references, clarify port/network exceptions

Co-authored-by: enuno <6727752+enuno@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.

Comment on lines +1 to +3
# Pangolin Dokploy Template

> **Zero-trust identity-aware reverse proxy and VPN server for secure remote access**
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo maintains a central index of available templates in blueprints/README.md. Since this PR adds a new pangolin blueprint, that table should be updated to include Pangolin so users can discover it.

Copilot uses AI. Check for mistakes.
Comment on lines +88 to +96
- "${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:
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Binding host ports 80 and 443 in this compose stack will prevent deployment on a standard Dokploy host where the platform Traefik already owns those ports for ingress. As written, this blueprint will only work if the Dokploy/host Traefik ports are moved/disabled (or Pangolin is configured to avoid needing 80/443 on the host). Consider redesigning so only the non-HTTP/UDP port(s) are mapped directly and HTTP(S) is routed through Dokploy’s Traefik, or explicitly document the required Dokploy Traefik reconfiguration steps as a mandatory prerequisite.

Copilot uses AI. Check for mistakes.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback -- you are correct, the existing traefik instance that dokploy uses should be respected, and unless the application has an explicit requirement for it's own separate reverse proxy, the blueprint template / docker-compose.yml should not use port 80 or 443 and should connect to the dokploy traefik instance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit 8aa20ad. The embedded Traefik service has been removed from the stack. Changes made:

  • Removed the traefik service entirely from docker-compose.yml
  • Removed ports 80 and 443 from gerbil — only the WireGuard UDP port (51820) is now exposed on the host
  • Removed the traefik-certs volume (no embedded Traefik = no ACME storage needed)
  • Removed letsencrypt_email, https_proxy_port, http_proxy_port variables from template.toml
  • Removed the Traefik static/dynamic config mounts from template.toml
  • The Pangolin admin dashboard continues to be routed through Dokploy's Traefik via the existing traefik.enable=true labels on the pangolin service
  • Updated README to reflect the 2-service architecture (Pangolin + Gerbil), simplified port requirements, and corrected DNS/firewall guidance

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…Traefik and ports 80/443

Co-authored-by: enuno <6727752+enuno@users.noreply.github.com>
Copilot finished work on behalf of enuno March 6, 2026 16:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

blueprints/pangolin/README.md:375

  • The README’s “Status: Production-Ready” claim is misleading given the current compose file binds host 80/443 (conflicts with Dokploy’s Traefik on a typical installation). Consider downgrading the status (or clarifying the required non-standard Dokploy setup) until the port/Traefik architecture is resolved.

Comment on lines +1 to +4
# Pangolin Dokploy Template

> **Zero-trust identity-aware reverse proxy and VPN server for secure remote access**

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new blueprint isn’t listed in the repository’s “Available Templates” table yet (blueprints/README.md). Please add an entry for Pangolin so it’s discoverable and matches the repo’s template contribution checklist.

Copilot uses AI. Check for mistakes.
Comment on lines +59 to +63

### 1. Configure DNS

Before deploying, set up DNS records:

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README suggests avoiding conflicts by changing HTTP_PROXY_PORT/HTTPS_PROXY_PORT (e.g. to 8080/8443), but the template’s embedded Traefik config relies on ACME httpChallenge, which requires host port 80 to be mapped to container port 80. Please reconcile this guidance (either document the required Traefik config changes like switching to tlsChallenge/DNS-01, or remove the suggestion to move port 80).

Copilot uses AI. Check for mistakes.
@enuno enuno merged commit 6b5f6d0 into main Mar 7, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Blueprint] Pangolin

3 participants