来源:intranet-tunnel/deploy/cloud/README.md(整篇)(原文 5604 字符)

内网穿透系统 —— 云服务器部署包

本目录是一套可直接部署到云服务器的完整配置,与本机测试版(仓库根的 docker-compose.yml)相比做了 4 处针对云环境的调整。

在已运行宝塔面板的服务器上部署? 先读 BAOTA-DEPLOY.md(源码路径 ./BAOTA-DEPLOY.md)。 那篇记录了 2026-09-12 的实测:80/443 被宝塔占用时的共存方案、 * 泛解析与 _acme-challenge 被占用时的域名规划、以及本项目自带的 DNS-01 证书链路为何在阿里云上不可用(附根因与绕行方案)。


一、包内文件

文件说明
docker-compose.yml云版编排:4 个服务(tunnel-server / postgres / nginx / db-backup)
.env完整生产配置,192 项(由代码自动提取,含已生成的强随机凭据)
.env.example脱敏模板,所有敏感项为 change_me_*
nginx/nginx-compose.confnginx 主配置(含 upstream 定义)
nginx/conf.d/00-http.conf80 端口:ACME 挑战透传 + 301 跳转 HTTPS
nginx/conf.d/10-panel.conf443:管理面板入口(需替换域名
nginx/conf.d/20-tunnel.conf443:隧道域名入口(需替换域名

云版与本地版的差异:

  1. postgres 不再映射端口到宿主机 —— 服务端容器通过 compose 网络用服务名 postgres 访问即可,减少暴露面
  2. tunnel-server 放开 nofile 到 65535 —— 隧道服务持有大量并发连接,默认 1024 在高并发下会 too many open files
  3. 各服务加 no-new-privileges —— 容器内进程无法再提权
  4. **资源上限走 .env*_LIMIT 变量** —— 按服务器规格调整

二、部署前必须做的三件事

1. 确认服务器架构

现有镜像 tar 是 amd64 的,如果服务器是 arm64 则无法使用。在服务器上执行:

uname -m
  • 输出 x86_64 → 可直接用现有镜像 tar
  • 输出 aarch64arm64需要重新导出 arm64 镜像(告诉我,我在本地用 buildx 交叉构建)

2. 配置云安全组

只需放行这些端口(其余一律不要开):

端口用途是否必需
80ACME HTTP-01 验证 + 跳转 HTTPS必需(证书自动签发依赖它)
443HTTPS 入口(面板 + 隧道)必需
47800控制连接,客户端接入必需
48081-48100TCP 隧道端口池需要 TCP 隧道时
49000-49100TCP/UDP 端口转发需要端口转发时
48443反向代理 HTTPS用内置反代直出 HTTPS 时
47801管理 API不要开放(只给 nginx 用,已在 compose 里绑 127.0.0.1)
5432PostgreSQL绝对不要开放

3. 修改 .env 与 nginx 配置

.env 里只有 2 处需要填(其余已自动生成,含强随机密钥):

EXTERNAL_IP=<服务器公网IP>      # NAT/云环境必填,影响隧道入口地址拼接
CERT_EMAIL=<你的邮箱>           # 证书申请的联系邮箱

nginx 配置里需要替换域名(两个文件):

# nginx/conf.d/10-panel.conf   把 <PANEL_DOMAIN> 全部替换为面板域名
# nginx/conf.d/20-tunnel.conf  把 <TUNNEL_DOMAIN> 全部替换为隧道域名

例如:

sed -i 's/<PANEL_DOMAIN>/panel.example.com/g'  nginx/conf.d/10-panel.conf
sed -i 's/<TUNNEL_DOMAIN>/example.com/g'       nginx/conf.d/20-tunnel.conf

提示:隧道域名建议用泛域名(如 *.example.com),这样以后新增隧道都不用再动 nginx。 但泛域名证书只能用 DNS-01 验证(HTTP-01 签不了通配符)。


三、部署步骤

1. 上传

# 本地执行
scp -r deploy/cloud/* user@<服务器IP>:/home/docker/intranet-tunnel/
scp release/intranet-tunnel-server-images-<版本>.tar user@<服务器IP>:/home/docker/intranet-tunnel/

2. 导入镜像(不需要联网)

cd /home/docker/intranet-tunnel
docker load -i intranet-tunnel-server-images-<版本>.tar
docker images | grep -E 'intranet-tunnel|postgres|nginx'
# 应看到:intranet-tunnel/server:1.0.0、postgres:16-alpine、nginx:alpine

3. 建运行时目录

mkdir -p logs/nginx cores certs backups/db

4. 启动

docker compose up -d
docker compose ps          # 三个容器应为 healthy
curl -s localhost:47801/healthz
# 期望:{"status":"ok","database":"ok",...}

5. 首次登录

浏览器打开 https://<面板域名>/

  • 用户名:admin
  • 口令:见第四节(已自动生成的强随机口令)

首次登录需要输入图形验证码(默认开启)。


四、已自动生成的凭据

这些是随机生成的,请立即保存到密码管理器。 部署后可在 .env 里查看:

项目变量
管理后台口令ADMIN_PASSWORD
数据库口令DB_PASSWORD / POSTGRES_PASSWORD
JWT 签名密钥JWT_SECRET(64 hex)
客户端令牌盐TOKEN_SALT(48 hex)
配置加密密钥CONFIG_ENCRYPT_KEY(恰好 32 字节)

⚠️ CONFIG_ENCRYPT_KEY 一旦开始使用就不能再改。 它加密着数据库里的敏感设置项(SMTP 口令、DNS 服务商凭据等)。 改了密钥,这些已保存的值将无法解密,需要重新填写。 请把它和数据库备份一起妥善保管。


五、证书申请

部署完成后,在面板里为域名申请证书:

  1. 进入「SSL 证书」→「申请证书」
  2. 填域名(面板域名 + 隧道域名各申请一张,或申请一张泛域名)
  3. 验证方式选 HTTP-01(需 80 端口可从公网访问,安全组已放行)
  4. 邮箱填 CERT_EMAIL 的值

证书签发后落在宿主机 ./certs/<域名>/,含 cert.pemkey.pem,nginx 已挂载该目录。

申请完成后执行一次 docker compose restart nginx 让 nginx 加载新证书。

已知限制:证书自动续期后 nginx 不会自动重载,需要手动执行上面的 restart。 如需自动化,可以给 nginx 容器挂载 docker socket 并加 inotify 脚本 —— 但那会扩大容器的权限面,本项目默认不做。


六、安全加固建议

按你的选择「nginx 转 HTTPS + 安全入口」,建议再做这几步:

  1. 设置安全入口:面板「系统设置」→「安全入口」填一段自定义路径(如 /tunnel-console)。

之后只有该路径能打开后台首页,其它路径返回 404,可挡掉绝大多数扫描器。

  1. 限制面板来源(可选):在 nginx/conf.d/10-panel.conf 里取消 allow/deny 注释,只放行你的常用出口 IP。
  2. 面板不要直接暴露 47801:compose 里已绑定 127.0.0.1,确认安全组也没放行它。
  3. 开启告警邮件:填好 SMTP 后,登录爆破、服务异常会发邮件通知。
  4. 定期检查审计日志:面板「日志审计」可查所有管理操作。

七、日常运维

# 查看状态 / 日志
docker compose ps
docker compose logs -f tunnel-server
docker compose logs -f postgres     # 时间戳应为 CST

# 重启 / 停止(保留数据卷)
docker compose restart tunnel-server
docker compose stop
docker compose down

# 更新服务端(导入新镜像后)
docker load -i intranet-tunnel-server-images-<新版本>.tar
docker compose up -d

# 数据库备份产物
ls -lh backups/db/                  # db-backup 每 24 小时一次,保留 30 天

恢复数据库

docker compose exec -T postgres pg_restore -U tunnel_user -d tunnel --clean < backups/db/tunnel-<时间戳>.dump

八、排障

现象原因与处理
lookup postgres: no such hostDB_HOST 被改成了非 compose 服务名。容器内应为 postgres
password authentication failedDB_PASSWORDPOSTGRES_PASSWORD 不一致,或数据库卷是用旧口令初始化的
address already in use端口被占用,检查是否有其它 nginx/postgres 在跑
nginx 启动报 host not found in upstreamtunnel-server 未启动或未 healthy。depends_on 已配健康检查,查 docker compose logs tunnel-server
面板打开是 502后端没起来,或 tunnel_api upstream 指向不对(应为 tunnel-server:47801
证书申请失败80 端口未从公网可达(安全组/防火墙),或域名未解析到本机
HTTPS 打开证书报错证书目录名与 server_name 不匹配。ls certs/ 看实际目录名
隧道 502客户端离线,或隧道上游地址不通。面板「客户端」看在线状态

九、需要我提供什么

如果还有以下信息,我可以把配置改成最终版,你直接上传即可:

  1. 公网 IP
  2. 面板域名隧道域名(隧道是否用泛域名?)
  3. 服务器规格(决定 *_LIMIT 资源上限取值)
  4. uname -m 的输出(确认架构,arm64 需要重新构建镜像)

来源:intranet-tunnel/release/README.md## 一、包内文件(原文 589 字符)

一、包内文件

文件说明
intranet-tunnel-server-images-1.1.1.tar服务端镜像归档:server:1.1.1 + postgres:16-alpine + nginx:alpine服务器无需联网拉取
intranet-tunnel-server-upgrade-1.1.1.tarserver:1.1.1 镜像(约 13 MB)。升级时导它就行,不必传 148 MB
intranet-tunnel-server-deploy-1.1.1.zip服务端自包含部署包(上面两项 + compose + .env 模板 + 本说明)
intranet-tunnel-client-images-1.2.1.tar客户端镜像归档:client:1.2.1(含 Web 配置界面与 SQLite 持久化)
intranet-tunnel-client-deploy-1.2.1.zip客户端自包含部署包(客户端镜像 + compose + init.sh + 配置模板 + 说明)
README.md本文件(服务端部署说明)

技术文档库 / 云服务器端部署 0 0 sushike
2026-09-13T12:41:54.115606939Z 2026-09-13T13:37:17.560354277Z