Pangolin 1.25.1 Docker Compose 部署指南
从零在一台 Ubuntu 24.04 服务器上以 Docker Compose 编排部署 Pangolin 1.25.1,覆盖 pangolin/gerbil/traefik 三服务编排、config.yml 与 Traefik 配置准备、首个管理员初始化、Newt 站点接入实测与数据持久化说明。
Pangolin 1.25.1 Docker Compose 部署指南
目标:在一台 Ubuntu 24.04 服务器上用 Docker Compose 从零部署 Pangolin 1.25.1(fosrl/pangolin,自托管身份感知反向代理与隧道网关),覆盖官方三服务编排(pangolin 控制面 + gerbil WireGuard 路由 + traefik 边缘反代)、config.yml 与 Traefik 配置准备、首个管理员初始化、Newt 站点接入实测与数据持久化说明。文中全部命令与回显均在真实部署环境(Ubuntu 24.04、Docker 29.8.1、Docker Compose v5.5.1、Pangolin 1.25.1 / Gerbil 1.5.2 / Traefik v3.7,管理台域名
pangolin.example.com)实测通过。组件定位、架构与选型对比见 《Pangolin 1.24.0 介绍与选型指南》。
一、环境信息
本篇部署目标与实测环境的关键信息如下,读者按本文操作时请将域名换成自己服务器对应的域名:
- 操作系统:Ubuntu 24.04(x86_64),具备 root 权限
- Docker:Docker version 29.8.1, build 4a63305
- Docker Compose:Docker Compose version v5.5.1
- Pangolin:
fosrl/pangolin:1.25.1(2026-10-22 实查 GitHub Releases 为最新稳定版,2026-10-21 发布;官方安装器对 1.25.1 配套注入的组件版本为 Gerbil 1.5.2、Badger v1.8.0) - 配套组件:
fosrl/gerbil:1.5.2(WireGuard 隧道服务端)、traefik:v3.7(边缘反代)、fosrl/newt:1.19.0(站点连接器,远端内网侧使用) - 监听端口:
80/tcp(HTTP 入口)、443/tcp+udp(HTTPS/HTTP3 入口)、51820/udp(WireGuard 隧道)、21820/udp(Newt 客户端隧道) - 部署目录:
/opt/pangolin/(编排文件所在),持久化目录/opt/pangolin/config/ - 示例域名:管理台
pangolin.example.com,根域example.com,被发布资源示例app.example.com
💡 说明:Pangolin 官方发行形态即「Docker Compose 编排的完整栈」(pangolin + gerbil + traefik 三服务,可选 postgres/redis 企业扩展),官方 Quick Install 脚本在服务器上落地的也是同一套编排。因此本文直接手写编排文件部署,便于逐项理解每个配置;官方脚本方式见 《Pangolin 1.24.0 介绍与选型指南》第五章。三服务里 pangolin 与 traefik 是普通服务,gerbil 需要
NET_ADMIN/SYS_MODULE特权以维护 WireGuard 接口。
二、版本与组件 tag 选型说明
Pangolin 控制面、Gerbil、Traefik 三个服务的版本需要配套选型,2026-10-22 实查的可用 tag 与选择建议如下:
| 服务 | 组件 tag | 说明 |
|---|---|---|
| pangolin | fosrl/pangolin:1.25.1 | 最新稳定版(2026-10-21 发布)。另有 postgresql-1.25.1(PG 存储版)与 ee- 前缀(企业版)tag |
| pangolin | fosrl/pangolin:latest | 跟随上游滚动,生产不建议(升级不可控) |
| gerbil | fosrl/gerbil:1.5.2 | 2026-10-22 实查最新稳定版(2026-09-18 发布),1.25.1 安装器配套注入版本 |
| traefik | traefik:v3.7 | 官方编排锁定的大版本 tag(当前解析为 v3.7.x 最新修订) |
| badger 插件 | github.com/fosrl/badger v1.7.0 | Traefik 插件,负责 Forward Auth。⚠️ 默认取最新 v1.8.0 在 traefik v3.7 实测报插件完整性校验失败,用 v1.7.0 正常(见十、常见问题 Q1 排障实录) |
| newt | fosrl/newt:1.19.0 | 2026-10-22 实查最新稳定版(2026-10 发布),部署在资源所在内网 |
如何选:生产环境锁定精确版本 tag(pangolin 锁 1.25.1、gerbil 锁 1.5.2、traefik 锁 v3.7),升级由运维显式改 tag 触发;latest 只用于临时测试。版本升级操作见九、常用运维命令中的 9.3 节。
三、前置条件
- 已安装 Docker 24 及以上与 Docker Compose v2 插件(本文实测 29.8.1 / v5.5.1),
docker compose version可正常输出版本号:
docker compose version
实测回显:
Docker Compose version v5.5.1
- 一台具有 root 权限的服务器,且
80/tcp、443/tcp、51820/udp、21820/udp四组端口未被占用。执行前先用ss确认:
ss -ltn | grep -E ':(80|443)\b'; ss -lun | grep -E ':(51820|21820)\b' || echo "80/443/51820/21820 均空闲"
实测回显(端口空闲时):
80/443/51820/21820 均空闲
⚠️ 注意:80/443 与同机既有 Web 服务(Nginx、其他反代)冲突是 Pangolin 最常见的部署障碍;官方要求四个端口独占。确需同机共存时需自行做边缘分流,不在本文展开。
-
一个指向服务器公网 IP 的域名,并规划管理台子域名(本文用
pangolin.example.com);如需 Let's Encrypt 自动签发证书,域名必须公网可达(内网/保留域名签发会失败,见十、常见问题 Q2)。 -
防火墙放行
80/tcp、443/tcp+udp、51820/udp、21820/udp(云服务器还需在安全组同步放行)。 -
建好部署目录:
mkdir -p /opt/pangolin/config/traefik /opt/pangolin/config/db /opt/pangolin/config/logs /opt/pangolin/config/letsencrypt
命令无回显即为成功;ls /opt/pangolin/config/ 应看到 traefik db logs letsencrypt 四个子目录。
四、部署步骤
官方编排由 pangolin(控制面:Web 管理台 + API + 身份认证)、gerbil(WireGuard 隧道服务端,80/443/51820/21820 全部经它对外)、traefik(TLS 终结与路由,与 gerbil 共享网络栈)三个服务组成。下面按「配置文件 → Traefik 配置 → 编排文件 → 启动 → 初始化 → 验证」的顺序从零完成。
4.1 生成 config.yml
生成服务器密钥并写控制面配置文件 /opt/pangolin/config/config.yml:
SECRET=$(openssl rand -base64 32 | tr -d '/+=' | head -c 40)
echo "生成的密钥: $SECRET"
实测回显(每次生成值不同,取你自己的值填入下一步):
生成的密钥: ckrLbFxQVDUV5lBC9cVGxWGGMR6tUxmiiDopESP1
将以下内容保存为 /opt/pangolin/config/config.yml(secret 换成上一步生成的值):
# To see all available options, please visit the docs:
# https://docs.pangolin.net/
gerbil:
start_port: 51820
base_endpoint: "https://pangolin.example.com"
app:
dashboard_url: "https://pangolin.example.com"
log_level: "info"
telemetry:
anonymous_usage: false
domains:
domain1:
base_domain: "example.com"
server:
secret: "ckrLbFxQVDUV5lBC9cVGxWGGMR6tUxmiiDopESP1"
cors:
origins: ["https://pangolin.example.com"]
methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]
allowed_headers: ["X-CSRF-Token", "Content-Type"]
credentials: false
flags:
require_email_verification: false
disable_signup_without_invite: true
disable_user_create_org: false
allow_raw_resources: true
配置项逐项说明:
| 配置项 | 本例取值 | 含义 |
|---|---|---|
gerbil.start_port | 51820 | WireGuard 隧道起始端口(与编排文件映射的 51820/udp 对应) |
gerbil.base_endpoint | https://pangolin.example.com | 告知远端 Newt 管理台地址,用于建立隧道 |
app.dashboard_url | https://pangolin.example.com | 管理台完整 URL(登录页、邮件链接都基于它) |
app.log_level | info | 控制面日志级别,可选 debug/info/warn/error |
app.telemetry.anonymous_usage | false | 匿名使用统计上报开关(官方默认 true,内网部署可关) |
domains.domain1.base_domain | example.com | 资源域名根域,发布的资源自动生成为 <子域>.example.com |
server.secret | (随机 40 位) | 会话签名密钥,至少 8 字符,必须随机生成且不外泄 |
server.cors.* | 见上 | 管理 API 的跨域白名单,指向管理台域名 |
flags.disable_signup_without_invite | true | 禁止无邀请注册(默认即 true,防止陌生人注册) |
flags.require_email_verification | false | 是否强制邮箱验证(未配 SMTP 时保持 false) |
全部字段的默认值与逐项详解见 《Pangolin 1.25.1 配置参数详解》。
4.2 编写 Traefik 静态配置
将以下内容保存为 /opt/pangolin/config/traefik/traefik_config.yml(email 换成你的证书通知邮箱):
api:
insecure: true
dashboard: true
providers:
http:
endpoint: "http://pangolin:3001/api/v1/traefik-config"
pollInterval: "5s"
file:
filename: "/etc/traefik/dynamic_config.yml"
experimental:
plugins:
badger:
moduleName: "github.com/fosrl/badger"
version: "v1.7.0"
log:
level: "INFO"
format: "common"
maxSize: 100
maxBackups: 3
maxAge: 3
compress: true
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: "pangolin-admin@163.com"
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: "30m"
http3:
advertisedPort: 443
http:
tls:
certResolver: "letsencrypt"
encodedCharacters:
allowEncodedSlash: true
allowEncodedQuestionMark: true
serversTransport:
insecureSkipVerify: true
ping:
entryPoint: "web"
要点说明:
providers.http.endpoint指向 pangolin 控制面的/api/v1/traefik-config,Traefik 每 5 秒拉取一次动态路由——你在管理台创建资源后无需重启 Traefik 即自动生效;experimental.plugins.badger是官方 Forward Auth 插件,所有未认证请求由它重定向到管理台登录页;版本用v1.7.0(v1.8.0完整性校验失败见十、Q1);certificatesResolvers.letsencrypt走 HTTP-01 挑战,证书落盘到/letsencrypt/acme.json(由编排挂载持久化);entryPoints.websecure.transport.respondingTimeouts.readTimeout: 30m是长连接场景(远桌面、SSH 资源)的官方取值。
4.3 编写 Traefik 动态配置
将以下内容保存为 /opt/pangolin/config/traefik/dynamic_config.yml(两处 pangolin.example.com 换成你的管理台域名):
http:
middlewares:
badger:
plugin:
badger:
disableForwardAuth: true
redirect-to-https:
redirectScheme:
scheme: https
routers:
# HTTP to HTTPS redirect router
main-app-router-redirect:
rule: "Host(`pangolin.example.com`)"
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
- badger
# Next.js router (handles everything except API and WebSocket paths)
next-router:
rule: "Host(`pangolin.example.com`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
# API router (handles /api/v1 paths)
api-router:
rule: "Host(`pangolin.example.com`) && PathPrefix(`/api/v1`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
# WebSocket router
ws-router:
rule: "Host(`pangolin.example.com`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Next.js server
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API/WebSocket server
tcp:
serversTransports:
pp-transport-v1:
proxyProtocol:
version: 1
pp-transport-v2:
proxyProtocol:
version: 2
要点说明:四个路由把管理台流量按「HTTP 跳转 / Next.js 页面 / /api/v1 接口 / WebSocket」分发到控制面的 3002(页面)与 3000(API/WS)两个内部端口;tcp.serversTransports 两条 ProxyProtocol 传输配置供 TCP 资源透传真实客户端 IP 使用。
4.4 编写部署编排文件
将以下内容保存为 /opt/pangolin/docker-compose.yml:
name: pangolin-1.25.1-stack
services:
pangolin:
image: docker.io/fosrl/pangolin:1.25.1
container_name: pangolin
restart: unless-stopped
deploy:
resources:
limits:
memory: 2g
reservations:
memory: 512m
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "10s"
timeout: "10s"
retries: 15
gerbil:
image: docker.io/fosrl/gerbil:1.5.2
container_name: gerbil
restart: unless-stopped
depends_on:
pangolin:
condition: service_healthy
command:
- --reachableAt=http://gerbil:3004
- --generateAndSaveKeyTo=/var/config/key
- --remoteConfig=http://pangolin:3001/api/v1/
volumes:
- ./config/:/var/config
cap_add:
- NET_ADMIN
- SYS_MODULE
ports:
- 51820:51820/udp
- 21820:21820/udp
- 443:443
- 443:443/udp # For http3 QUIC if desired
- 80:80
traefik:
image: docker.io/traefik:v3.7
container_name: traefik
restart: unless-stopped
network_mode: service:gerbil # Ports appear on the gerbil service
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
volumes:
- ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration
- ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
- ./config/traefik/logs:/var/log/traefik # Volume to store Traefik logs
networks:
default:
driver: bridge
name: pangolin_frontend
编排要点逐项说明:
name: pangolin-1.25.1-stack:显式项目名,docker compose ps等命令输出与版本对应,多套环境不混淆;- 端口全部挂在 gerbil 服务上:traefik 用
network_mode: service:gerbil与 gerbil 共享网络栈(官方设计,便于对 TCP/UDP 资源做 ProxyProtocol 透传),所以 80/443/51820/21820 都由 gerbil 发布; gerbil.cap_add:维护 WireGuard 接口需要NET_ADMIN;SYS_MODULE用于加载内核模块;pangolin.healthcheck:用控制面内部健康检查接口http://localhost:3001/api/v1/判定就绪,traefik/gerbil 依赖service_healthy后启动;- 内存限制沿用官方编排(pangolin 上限 2g/预留 512m);
- 三处挂载覆盖「配置 + 证书 + 日志」,全部落在
./config/(见五、数据持久化说明)。
💡 说明:官方编排模板中还提供 postgres(
postgres:18)与 redis(redis:8-trixie)可选服务,用于多节点/企业版场景;社区版单机默认用内置 SQLite,无需引入。需要 PostgreSQL 时 pangolin 应换postgresql-1.25.1tag 并在 config.yml 增加postgres.connection_string。
4.5 启动编排
cd /opt/pangolin && docker compose up -d
实测回显(首次启动,服务按健康检查依赖顺序拉起):
Container gerbil Created
Container traefik Created
Container pangolin Started
Container gerbil Starting
Container pangolin Healthy
Container gerbil Started
Container traefik Starting
Container traefik Started
查看运行状态:
cd /opt/pangolin && docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
gerbil docker.io/fosrl/gerbil:1.5.2 "/entrypoint.sh --re…" gerbil 17 minutes ago Up 17 minutes 0.0.0.0:80->80/tcp, [::]:80->80/tcp, 0.0.0.0:443->443/udp, [::]:443->443/udp, 0.0.0.0:21820->21820/udp, [::]:21820->21820/udp, 0.0.0.0:443->443/tcp, [::]:443->443/tcp, 0.0.0.0:51820->51820/udp, [::]:51820->51820/udp
pangolin docker.io/fosrl/pangolin:1.25.1 "docker-entrypoint.s…" pangolin 18 minutes ago Up About a minute (healthy)
traefik docker.io/traefik:v3.7 "/entrypoint.sh --co…" traefik 17 minutes ago Up 9 minutes
pangolin 状态为 Up (healthy)(健康检查通过)、gerbil 发布了全部四个对外端口即为启动正常。
4.6 获取初始 Setup Token 并完成管理员初始化
首次启动时控制面会生成一次性 Setup Token(初始化管理员用):
cd /opt/pangolin && docker compose logs pangolin | grep -A 3 "SETUP TOKEN"
实测回显:
=== SETUP TOKEN GENERATED ===
Token: lr6k2k3og0jyb14ivxvjjvxq2nrqr0ab
Use this token on the initial setup page
================================
⚠️ 注意:管理员密码有平台策略——至少 8 位,且必须同时包含大写字母、小写字母、数字和特殊字符(正则校验)。纯数字小写组合(如
q1w2e3r4)会被拒绝,请使用形如Q1w2e3r4!的组合。本文示例管理员:邮箱admin@example.com、密码Q1w2e3r4!。
浏览器访问 https://pangolin.example.com/auth/initial-setup 完成注册。也可用 API 直接初始化(setupToken 换成上一步日志里的值):
curl -sk -X PUT https://127.0.0.1/api/v1/auth/set-server-admin \
-H "Host: pangolin.example.com" -H "Content-Type: application/json" \
-H "x-csrf-token: x-csrf-protection" \
-d '{"email":"admin@example.com","password":"Q1w2e3r4!","setupToken":"lr6k2k3og0jyb14ivxvjjvxq2nrqr0ab"}'
实测回显:
{"data":null,"success":true,"error":false,"message":"Server admin set successfully","status":200}
再验证登录(会话 Cookie 名为 p_session_token):
curl -sk -c /tmp/pg-cookies.txt -X POST https://127.0.0.1/api/v1/auth/login \
-H "Host: pangolin.example.com" -H "Content-Type: application/json" \
-H "x-csrf-token: x-csrf-protection" \
-d '{"email":"admin@example.com","password":"Q1w2e3r4!"}'
实测回显:
{"data":null,"success":true,"error":false,"message":"Logged in successfully","status":200}
4.7 验证部署
验证 1:管理台入口与 HTTP 跳转。 服务器本机用 Host 头模拟域名访问(DNS 尚未切到位时同样适用):
curl -sk https://127.0.0.1/auth/initial-setup -H "Host: pangolin.example.com" -o /dev/null -w "initial-setup: %{http_code}\n"
curl -sk http://127.0.0.1/ -H "Host: pangolin.example.com" -o /dev/null -w "http: %{http_code} -> %{redirect_url}\n"
实测回显:
initial-setup: 200
http: 302 -> https://pangolin.example.com/
验证 2:API 健康检查。
curl -sk https://127.0.0.1/api/v1/ -H "Host: pangolin.example.com"
实测回显:
{"message":"Healthy"}
验证 3:服务端口监听。
ss -ltn | grep -E ':(80|443)\b'; ss -lun | grep -E ':(51820|21820)\b'
实测回显:
LISTEN 0 4096 0.0.0.0:443 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:80 0.0.0.0:*
LISTEN 0 4096 [::]:443 [::]:*
LISTEN 0 4096 [::]:80 [::]:*
UNCONN 0 0 0.0.0.0:21820 0.0.0.0:*
UNCONN 0 0 0.0.0.0:51820 0.0.0.0:*
UNCONN 0 0 [::]:21820 [::]:*
UNCONN 0 0 [::]:51820 [::]:*
验证 4:控制面版本。
curl -sk https://127.0.0.1/api/v1/server-info -H "Host: pangolin.example.com"
实测回显:
{"data":{"version":"1.25.1","supporterStatusValid":true,"build":"oss","enterpriseLicenseValid":false,"enterpriseLicenseType":null},"success":true,"error":false,"message":"Server info retrieved","status":200}
验证 5:零信任基线。 未认证请求访问任何资源都会被 badger 插件拦截(此处资源尚未创建,直接访问根域即被拦):
curl -sk https://127.0.0.1/ -H "Host: app.example.com" -o /dev/null -w "resource: %{http_code}\n"
实测回显:
resource: 401
四项全过即部署完成:管理台可登录、API 健康、四端口就绪、未授权访问被默认拒绝。
4.8 站点接入实测(Newt 连接)
在资源所在内网部署 Newt 连接器后,站点即上线。先在管理台(或 API)创建 Newt 类型站点,创建接口返回 newtId 与 secret:
curl -sk -b /tmp/pg-cookies.txt -X PUT https://127.0.0.1/api/v1/org/demo-org/site \
-H "Host: pangolin.example.com" -H "Content-Type: application/json" \
-H "x-csrf-token: x-csrf-protection" \
-d '{"name":"Lab Site","type":"newt","niceId":"lab-site"}'
实测回显(节选):
{"data":{"siteId":1,"orgId":"demo-org","niceId":"lab-site","name":"Lab Site","type":"newt","online":false,"newtId":"bg30ja3zzszynk1","secret":"5l0r9lo0dvl35cnbgxssdpe15owej1zm79w4zqlmok3l8mmc"},"success":true,"error":false,"message":"Site created successfully","status":201}
在资源所在内网用下面的服务片段部署 Newt(--id/--secret 换成上一步返回值,--endpoint 指向管理台域名;加入 compose 编排或独立单服务编排均可):
services:
newt:
image: docker.io/fosrl/newt:1.19.0
restart: unless-stopped
network_mode: host
command:
- --id=bg30ja3zzszynk1
- --secret=5l0r9lo0dvl35cnbgxssdpe15owej1zm79w4zqlmok3l8mmc
- --endpoint=https://pangolin.example.com
Newt 连接成功后,服务端日志可见:
INFO: 2026/10/22 11:19:56 Server version: 1.25.1
INFO: 2026/10/22 11:19:56 Websocket connected
查询站点状态,online 已变为 true:
curl -sk -b /tmp/pg-cookies.txt https://127.0.0.1/api/v1/site/1 -H "Host: pangolin.example.com"
实测回显(节选):
{"data":{"niceId":"lab-site","type":"newt","online":true,"newtVersion":"1.19.0","address":"100.90.128.0/20",...},"success":true,"error":false,"message":"Site retrieved successfully","status":200}
💡 说明:Newt 与服务端之间先经
POST /api/v1/auth/newt/get-token换取令牌再建 WebSocket 控制通道,WireGuard 数据面由 gerbil 动态下发 peer(服务端日志可见Adding peer ... to exit node)。内网/自签名证书环境 Newt 会报 TLS 校验失败,处理方式见十、Q3。
五、数据持久化说明
整套栈的状态全部落在 /opt/pangolin/config/ 单一目录树中,升级或重建编排(docker compose down 后再 up)不丢数据。实测目录布局与职责:
/opt/pangolin/config/
├── config.yml # 控制面主配置(手工维护)
├── db/
│ └── db.sqlite # 全部业务数据(SQLite,单文件,实测 1.1MB 起步)
├── key # gerbil 首次启动自动生成的 WireGuard 服务端私钥(44 字节)
├── letsencrypt/ # Traefik 证书存储(acme.json)
├── logs/ # 控制面应用日志(app.log_level/save_logs 开启时写入)
├── openapi.yaml # 控制面自动生成的完整 OpenAPI 规范(实测 540KB)
└── traefik/
├── traefik_config.yml # Traefik 静态配置(手工维护)
├── dynamic_config.yml # Traefik 动态配置(手工维护)
├── logs/ # Traefik 访问日志
└── certs/ # (可选)自定义证书
要点:
config/db/db.sqlite是唯一业务数据源:组织、站点、资源、用户、角色、会话全在里面,备份见 《Pangolin 1.25.1 常用命令与运维操作详解》第九章;config/key首次启动生成后不可删除:删除会导致全部站点隧道失效(peer 密钥重新生成,远端 Newt 需重新接入);- Traefik 的证书(
acme.json)与动态路由数据同在 config 树下,整机迁移时整目录打包即可。
六、服务组件与环境变量表
编排三服务的内部端口与职责(排障时用):
| 服务 | 内部端口 | 职责 |
|---|---|---|
| pangolin | 3000 | 管理 API 与 WebSocket 服务(api-service 反代目标) |
| pangolin | 3001 | 内部 API(健康检查、Traefik 动态配置下发、Gerbil 远程配置) |
| pangolin | 3002 | Next.js 管理台页面(next-service 反代目标) |
| pangolin | 3003 | Integration API(机器对机器,需 flags.enable_integration_api: true 开启,默认关闭) |
| pangolin | 3005 | AI 网关服务 |
| gerbil | 3004 | --reachableAt 上报地址;51820/udp WireGuard;21820/udp Newt 客户端 |
| traefik | 80/443 | 公网入口(与 gerbil 共享网络栈) |
Pangolin 支持用环境变量覆盖部分敏感配置(优先级高于 config.yml),常用项:
| 环境变量 | 对应配置 | 用途 |
|---|---|---|
SERVER_SECRET | server.secret | 从密钥管理注入会话密钥,不在 config.yml 落明文 |
EMAIL_SMTP_USER | email.smtp_user | SMTP 账号注入 |
EMAIL_SMTP_PASS | email.smtp_pass | SMTP 密码注入 |
POSTGRES_LOGS_CONNECTION_STRING | postgres_logs.connection_string | 日志库连接串注入 |
ENABLE_AI_GATEWAY_CLIENT_IP_HEADER | server.enable_ai_gateway_client_ip_header | AI 网关客户端 IP 头开关 |
注入方式:在编排文件的 pangolin.services 下加 environment: 段,如 - SERVER_SECRET=${SERVER_SECRET:?},配合 shell 的 export 使用。
七、配置参数说明
部署即用的核心参数集中在三个文件,均已在前文部署步骤中给出完整内容与逐项说明:
config/config.yml:控制面全部行为(域名、日志、限流、flags 开关、邮件、Gerbil 端口等)。每个字段的默认值、取值范围与生效方式见 《Pangolin 1.25.1 配置参数详解》;config/traefik/traefik_config.yml:入口端口、证书签发器、badger 插件版本、Traefik 日志轮转;config/traefik/dynamic_config.yml:管理台四条路由与中间件。
常用调整举例(改完 cd /opt/pangolin && docker compose restart pangolin 生效):
# config.yml
app:
log_level: "debug" # 排障时临时开 debug,回显含 [debug] 前缀行
rate_limits:
auth:
window_minutes: 1 # 登录限流窗口(分钟)
max_requests: 500 # 窗口内最大请求数
八、配置文件挂载对照
| 编排挂载 | 服务内路径 | 读写 | 内容 |
|---|---|---|---|
./config:/app/config | /app/config | 读写 | 控制面配置 + SQLite 库 + 日志 + 自动生成物 |
./config/:/var/config | /var/config | 读写 | gerbil 密钥 key 与远程配置缓存 |
./config/traefik:/etc/traefik | /etc/traefik | 只读 | Traefik 静态/动态配置 |
./config/letsencrypt:/letsencrypt | /letsencrypt | 读写 | ACME 证书存储 |
./config/traefik/logs:/var/log/traefik | /var/log/traefik | 读写 | Traefik 日志落盘 |
⚠️ 注意:
./config/traefik以只读(:ro)挂入 Traefik,修改配置文件后需docker compose restart traefik重读;控制面配置同理restart pangolin。
九、常用运维命令
以下命令均在 /opt/pangolin 目录下执行(每条都有实测回显,逐条可独立执行)。
9.1 状态与日志
cd /opt/pangolin && docker compose ps
cd /opt/pangolin && docker compose logs --tail 20 pangolin
实测回显(ps 见 4.5;日志节选):
pangolin | 2026-10-22T11:23:00+00:00 [info]: WebSocket connection established - NEWT ID: bg30ja3zzszynk1
pangolin | 2026-10-22T11:23:00+00:00 [info]: Adding peer with public key hH2I3YMHKdWtr8uKVn67dcDg4DTCqdWTj5ApTsK7WQ4= to exit node 1
pangolin | 2026-10-22T11:23:00+00:00 [info]: Exit node request successful: {"method":"POST","url":"http://gerbil:3004/peer","status":"Peer added successfully"}
9.2 重启与停止
cd /opt/pangolin && docker compose restart pangolin # 改 config.yml 后重启控制面
cd /opt/pangolin && docker compose restart traefik # 改 Traefik 配置后重启反代
cd /opt/pangolin && docker compose down # 停止整套栈(数据保留在 ./config/)
cd /opt/pangolin && docker compose up -d # 再启动
down 实测回显:
Container pangolin Stopping
Container pangolin Stopped
Container traefik Stopping
Container traefik Stopped
Container gerbil Stopping
Container gerbil Stopped
Container pangolin Removing
Container traefik Removing
Container gerbil Removing
9.3 版本升级
改编排文件中三个 image: tag(如 1.25.1 → 1.26.0、1.5.2 → 新版)后:
cd /opt/pangolin && docker compose pull && docker compose up -d
⚠️ 注意:官方在 Release Notes 中反复强调升级前先备份
config/(尤其db.sqlite),跨大版本回滚困难;升级后用server-info接口确认版本生效(回显见 4.7 验证 4)。
9.4 资源占用观测
cd /opt/pangolin && docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}"
实测回显(空闲态,pangolin 内存上限即编排中的 2g):
NAME MEM USAGE / LIMIT CPU %
newt-lab 13.27MiB / 31.3GiB 0.03%
traefik 27.49MiB / 31.3GiB 0.05%
gerbil 6.75MiB / 31.3GiB 0.00%
pangolin 270.2MiB / 2GiB 0.06%
三服务合计常驻内存约 300MB,1C2G 及以上的服务器即可承载。
十、常见问题
以下 Q1–Q3 为部署实测中真实踩到并定位解决的问题,Q4/Q5 为高频咨询。
Q1:Traefik 日志报 plugin integrity check failed,管理台访问全部 404。
现象:启动后 docker compose logs traefik 出现:
traefik | ERR Plugins are disabled because an error has occurred. error="unable to set up plugins environment: unable to install plugin badger: unable to check archive integrity of the plugin github.com/fosrl/badger: plugin integrity check failed"
traefik | ERR error="invalid middleware \"badger@file\" configuration: invalid middleware type or middleware does not exist" entryPointName=websecure routerName=next-router@file
定位:badger 是挂在每条路由上的中间件,插件加载失败 → 中间件不存在 → 四条路由全部失效 → 所有请求 404。根因是 v1.8.0(当时最新 tag)的发布包与 Traefik 插件完整性校验不匹配。
解决:把 traefik_config.yml 中 badger version 从 v1.8.0 降到 v1.7.0,重启 traefik 后插件正常加载、路由恢复(本篇 4.2 配置即修复后版本)。若未来官方发布修复版,可再试新版本号。
Q2:Let's Encrypt 证书签发失败。
现象:docker compose logs traefik 出现 Unable to obtain ACME certificate for domains ... Cannot issue for "pangolin.example.com": The ACME server refuses to issue ... forbidden by policy 或 DNS 解析类错误。
定位:Let's Encrypt 对保留域名(example.com 等)与无法公网解析的域名拒绝签发;HTTP-01 挑战还要求 80 端口公网可达。
解决:生产环境使用真实公网域名并确保 DNS A 记录指向服务器、80/443 放行;内网/测试环境可用自签证书(在 dynamic_config.yml 追加 tls.certificates 段并挂载证书文件)或继续用 curl -k 验证功能,登录页与 API 均可正常工作。
Q3:远端 Newt 连接报 tls: failed to verify certificate。
现象:Newt 日志反复出现 Failed to connect: failed to get token: ... x509: certificate is valid for ... not pangolin.example.com。
定位:服务端 TLS 证书不是公共 CA 签发(自签/内网 CA),Newt 默认校验证书链。
解决:测试环境给 Newt 服务加环境变量 SKIP_TLS_VERIFY=true(官方客户端内置开关,仅限测试);生产环境换 Let's Encrypt 正式证书。
Q4:80/443 端口被占用启动失败。 gerbil 服务启动报端口绑定错误。先 ss -ltnp | grep -E ':(80|443)\b' 找到占用方;同机已有 Nginx 等反代时,要么迁移走,要么将既有反代作为 Pangolin 前置(官方不建议,需保留 51820/21820 独占)。
Q5:管理台能打开但一直转圈。 检查 docker compose logs pangolin 是否有 Internal API server is running(3001)与 Dashboard Web UI server is running(3002)两行;再确认 dynamic_config.yml 中 next-service/api-service 指向的 pangolin:3002/pangolin:3000 与编排服务名一致(服务改名后需同步改)。
十一、参考链接
- 官方仓库:https://github.com/fosrl/pangolin (编排模板
compose.example.yaml与安装器模板install/config/) - 官方文档站:https://docs.pangolin.net / https://docs.digpangolin.com
- 快速安装指南:https://docs.digpangolin.com/self-host/quick-install
- Gerbil 仓库:https://github.com/fosrl/gerbil
- Newt 仓库:https://github.com/fosrl/newt
- Badger 插件仓库:https://github.com/fosrl/badger
- 系列文档:《Pangolin 1.24.0 介绍与选型指南》、《Pangolin 1.25.1 配置参数详解》、《Pangolin 1.25.1 常用命令与运维操作详解》