Pangolin 实操:从部署到接入 Web/SSH 全流程
这篇是可直接执行的自托管教程,按步骤操作即可完成从 0 到 1 的部署。
- 服务器与网络前置检查
- Pangolin 安装与初始化
- Site(Newt)接入
- Web 资源与 SSH 资源配置
- 权限分层、验收清单与常见故障排查
适合场景:已经有 Linux 服务器和域名,希望把“反向代理 + 内网访问 + 访问控制”统一到一套系统里。
最终效果
做完后你会得到:
- 一个可登录的 Pangolin 控制台
- 浏览器里能访问内网 Web 服务
- 客户端里能连通内网 SSH 机器
- 能按用户/组做资源授权
1. 环境准备(5 分钟)
准备下面这些:
- 一台 Linux 服务器(建议 Ubuntu 20.04+ 或 Debian 11+)
- 已安装 Docker 与 Docker Compose
- 一个域名,并且 A 记录已经解析到服务器公网 IP
- 一台内网测试机(例如 192.168.1.10)
防火墙先放行:
- 80/TCP
- 443/TCP
- 51820/UDP
- 21820/UDP
先确认 Docker 正常:
docker --version
docker compose version如果命令能返回版本号,就可以继续。
2. 部署 Pangolin
给三种官方体系下的部署方式:
- 方案 A:官方安装器(推荐,生产优先)
- 方案 B:Docker Compose 手动部署(可控)
- 方案 C:Docker Run 单容器实验(仅测试)
步骤 1:下载并运行
curl -fsSL https://static.pangolin.net/get-installer.sh | bash
sudo ./installer步骤 2:安装器交互项怎么填
安装器会依次问这些问题:
- 是否企业版:一般选社区版
- Base Domain:主域名(例
example.com) - Dashboard Domain:控制台域名(例
pangolin.example.com) - Let's Encrypt Email:证书邮箱
- 是否启用 Gerbil 隧道:建议
Yes - 是否启用 SMTP:初次可
No
步骤 3:安装完成后的检查
docker compose ps
docker compose logs -f --tail=100正常情况下会看到安装完成提示,并给出初始化地址:
https://你的控制台域名/auth/initial-setup步骤 4:这个方案的优点
- 官方主推路径,自动处理多服务组件编排
- 生产环境优先这个方案
- 安装过程会提示是否启用 Gerbil 隧道(默认开启)
适合:你需要完全掌控配置文件。
步骤 1:创建目录
mkdir -p ~/pangolin/config/traefik ~/pangolin/config/db ~/pangolin/config/letsencrypt ~/pangolin/config/logs
cd ~/pangolin
touch docker-compose.yml
touch config/config.yml
touch config/traefik/traefik_config.yml
touch config/traefik/dynamic_config.yml
touch config/letsencrypt/acme.json
chmod 600 config/letsencrypt/acme.json步骤 2:写入 docker-compose.yml
name: pangolin
services:
pangolin:
image: docker.io/fosrl/pangolin:latest
container_name: pangolin
restart: unless-stopped
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "10s"
timeout: "10s"
retries: 15
gerbil:
image: docker.io/fosrl/gerbil:latest
container_name: gerbil
restart: unless-stopped
depends_on:
pangolin:
condition: service_healthy
command:
- --reachableAt=http://gerbil:3004
- --generateAndSaveKeyTo=/var/config/key
- --remoteConfig=http://pangolin:3001/api/v1/
volumes:
- ./config/:/var/config
cap_add:
- NET_ADMIN
- SYS_MODULE
ports:
- 51820:51820/udp
- 21820:21820/udp
- 443:443
- 80:80
traefik:
image: docker.io/traefik:v3.6
container_name: traefik
restart: unless-stopped
network_mode: service:gerbil
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
volumes:
- ./config/traefik:/etc/traefik:ro
- ./config/letsencrypt:/letsencrypt
- ./config/traefik/logs:/var/log/traefik
networks:
default:
driver: bridge
name: pangolin步骤 3:写入 config/traefik/traefik_config.yml
api:
insecure: true
dashboard: true
providers:
http:
endpoint: "http://pangolin:3001/api/v1/traefik-config"
pollInterval: "5s"
file:
filename: "/etc/traefik/dynamic_config.yml"
experimental:
plugins:
badger:
moduleName: "github.com/fosrl/badger"
version: "v1.3.1"
log:
level: "INFO"
format: "common"
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: "[email protected]"
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: "30m"
http:
tls:
certResolver: "letsencrypt"
serversTransport:
insecureSkipVerify: true步骤 4:写入 config/traefik/dynamic_config.yml
http:
middlewares:
badger:
plugin:
badger:
disableForwardAuth: true
redirect-to-https:
redirectScheme:
scheme: https
routers:
main-app-router-redirect:
rule: "Host(`pangolin.example.com`)"
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
- badger
next-router:
rule: "Host(`pangolin.example.com`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
api-router:
rule: "Host(`pangolin.example.com`) && PathPrefix(`/api/v1`)"
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
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"
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000"步骤 5:写入 config/config.yml
gerbil:
start_port: 51820
base_endpoint: "pangolin.example.com"
app:
dashboard_url: "https://pangolin.example.com"
log_level: "info"
telemetry:
anonymous_usage: true
domains:
domain1:
base_domain: "example.com"
cert_resolver: "letsencrypt"
server:
secret: "replace-with-a-long-random-secret"
cors:
origins: ["https://pangolin.example.com"]步骤 6:启动
docker compose up -d
docker compose ps如果 config/config.yml 不存在或格式错误,pangolin 容器会退出。
适合:本地临时验证容器能否启动,不建议直接上生产。
按官方自托管体系,生产需要多服务协同,docker run 只用于实验。
如果只做单容器实验,可改用这条更完整的版本:
docker run -d \
--name pangolin \
--restart unless-stopped \
-p 3000:3000 \
-p 3001:3001 \
-p 3002:3002 \
-v $PWD/config:/app/config \
-v pangolin-certs:/var/certificates \
-v pangolin-dynamic:/var/dynamic \
--health-cmd='curl -f http://localhost:3001/api/v1/ || exit 1' \
--health-interval=10s \
--health-timeout=10s \
--health-retries=15 \
docker.io/fosrl/pangolin:latest注意:如果 config/config.yml 不存在或格式错误,容器会直接退出。
无论哪种方式,80/TCP、443/TCP、51820/UDP、21820/UDP 都要放行。
3. 首次初始化(3 分钟)
浏览器访问:
https://你的控制台域名/auth/initial-setup按页面完成初始化:
- 创建管理员账号(邮箱 + 强密码)
- 创建组织(Organization)
- 登录控制台
这里有两个建议:
- 管理员账号务必开启 MFA
- 初始化密钥单独保存,别只放在聊天记录里
4. 先接 Site(Newt)
不先接 Site,后面的资源都无法连通。
4.1 控制台创建 Site
创建后会拿到 3 个参数:
PANGOLIN_ENDPOINTNEWT_IDNEWT_SECRET
4.2 目标网络安装 Newt
Linux 二进制方式:
curl -fsSL https://static.pangolin.net/get-newt.sh | bash
newt --id <NEWT_ID> --secret <NEWT_SECRET> --endpoint <PANGOLIN_ENDPOINT>Docker 方式:
docker run -dit --network host fosrl/newt --id <NEWT_ID> --secret <NEWT_SECRET> --endpoint <PANGOLIN_ENDPOINT>等控制台里 Site 状态变成在线,再继续资源接入。
5. 接入 Web 服务(浏览器访问)
这一步建议用内网现成服务,比如:
- 192.168.1.10:80 的 nginx
- 192.168.1.20:3000 的开发面板
操作顺序:
- 新建 Web 资源
- Target 填目标地址与端口
- 给测试用户或测试组授权
- 浏览器访问该资源地址
验证通过标准:
- 未登录时访问会跳认证
- 登录后可正常打开页面
- 无权限账号看不到该资源或无法访问
6. 接入 SSH 资源(客户端访问)
Web 通了以后,再测非 Web 资源。
操作顺序:
- 安装 Pangolin 客户端或 CLI
- 登录你的自托管端点
- 添加 SSH 资源(目标例如 192.168.1.30:22)
- 给资源设置别名(例如
dev-ssh.internal) - 给测试账号授权
- 本机执行连接测试
示例:
如果你不习惯别名,也可以先按控制台给出的直连方式测试。
7. 最小可用权限模型(直接可用)
很多人第一次踩坑都在“先全开,后面再收”。 建议反过来做:先最小授权,再按需放开。
可用这套简单分层:
- admin 组:管理控制台 + 全资源管理权限
- ops 组:生产 SSH/数据库可访问
- dev 组:仅开发和测试资源可访问
- guest 组:仅少量 Web 入口可访问
执行规则:
- 默认拒绝(deny all)
- 只给组授权,不给个人长期直授
- 离职或项目结束只改组成员,不改资源规则
8. 验收清单(上线前必跑)
按这个清单过一遍,基本就能上生产前灰度:
- 管理员 MFA 已开启
- 普通账号无法看到未授权资源
- Web 与 SSH 访问链路都已实测
- 关键操作有审计日志
- 配置和数据已做备份
- 明确升级窗口和回滚方案
9. 常见问题与处理
问题 1:资源显示在线,但访问超时
优先排查:
- Site 到目标服务是否真可达
- 目标服务监听地址是否仅绑定 127.0.0.1
- 目标主机本地防火墙是否拦截
快速检查:
curl -I http://目标IP:目标端口
nc -zv 目标IP 目标端口问题 2:登录成功但看不到资源
通常是授权层问题:
- 用户不在对应组
- 资源策略未绑定该组
- OIDC 的组映射字段没对上
问题 3:移动网络下连通性不稳定
常见原因:
- NAT 环境复杂,直连成功率低
- 中继链路未就近
可先把重心放在“稳定可用”,再做性能优化。
10. 什么时候适合上 Pangolin
更适合用 Pangolin:
- 你想把 Web 入口和私有资源访问统一起来
- 你需要细粒度权限和审计
- 你希望可自托管
不建议硬上:
- 团队没人维护基础设施
- 只是临时几台设备互联
- 只需要单一能力(仅反代或仅组网)
11. 收尾建议
第一次上线,建议按这个顺序走:
- 先打通安装和初始化
- 只接一个 Site + 一个 Web 资源
- 再加 SSH 资源
- 最后再扩权限、扩资源、做高可用
参考来源
- GitHub: https://github.com/fosrl/pangolin
- 官方文档: https://docs.pangolin.net
- 官网: https://pangolin.net