11 KiB
Trojan、Nginx、Caddy 与 Gitea 迁移实施记录
实施日期:2026-07-26
1. 服务器与域名
| 服务器 | Trojan 与管理后台 | Gitea | 宿主机 SSH | Git SSH |
|---|---|---|---|---|
43.154.35.111 |
www.hk.chermack.top |
git.hk.chermack.top |
22 |
2222 |
43.159.139.193 |
www.us.chermack.top |
git.us.chermack.top |
22 |
2222 |
2. 最终架构
flowchart LR
U[客户端] -->|HTTP :80| N[Nginx]
U -->|HTTPS :443 / SNI| N
N -->|www.* HTTP| W[Trojan 管理后台 :8081]
N -->|www.* TLS 透传| T[Trojan :8443]
T -->|非 Trojan 流量回落| W
N -->|git.* HTTP| C1[Caddy :8080]
N -->|git.* TLS 透传| C2[Caddy :9443]
C1 --> G[Gitea :3000]
C2 --> G
U -->|Git SSH :2222| G
公网 80/443 只由宿主机 Nginx 监听。Trojan 客户端和 Trojan 管理后台继续共用 www.* 域名,不新增 panel 域名:Nginx 将 www.* 的 TLS 按 SNI 透传到 Trojan;Trojan 对非 Trojan TLS 流量回落到本机管理后台。
3. 迁移前备份与检查
在变更前检查原容器和配置:
docker ps
docker inspect trojan
docker exec trojan cat /usr/local/etc/trojan/config.json
docker exec trojan systemctl cat trojan-web.service
已创建的备份目录:
/root/trojan-gitea-migration-backup-20260726-004630 # 香港
/root/trojan-gitea-migration-backup-20260726-014435 # 美国
/root/gitea-pre-reset-20260726-012207 # 香港 Gitea 重置前
香港服务器另保留了迁移前 Trojan 镜像快照。
4. Trojan 端口调整
容器内 Trojan 配置调整为:
{
"local_port": 8443,
"remote_port": 8081
}
管理后台 systemd unit 调整为:
ExecStart=/usr/local/bin/trojan web --host 127.0.0.1 --port 8081
重载和启动命令:
docker exec trojan systemctl daemon-reload
docker exec trojan systemctl enable trojan-web
docker exec trojan systemctl restart trojan
docker exec trojan systemctl restart trojan-web
预期监听:Trojan 为 0.0.0.0:8443,管理后台为 127.0.0.1:8081。这两个端口不应对公网开放。
5. Nginx 统一入口
安装并启用:
apt-get update
apt-get install -y nginx libnginx-mod-stream
systemctl enable --now nginx
nginx -t
443 使用 stream 和 ssl_preread 按 SNI 分流。香港示例(美国替换为 www.us.chermack.top 与 git.us.chermack.top):
map $ssl_preread_server_name $tls_backend {
www.hk.chermack.top 127.0.0.1:8443;
git.hk.chermack.top 127.0.0.1:9443;
default 127.0.0.1:8443;
}
server {
listen 443;
proxy_pass $tls_backend;
ssl_preread on;
}
80 的 www.* 虚拟主机反向代理到 127.0.0.1:8081,并将 /.well-known/acme-challenge/ 转发到 127.0.0.1:8082;git.* 反向代理到 Caddy 127.0.0.1:8080。
每次配置改动后:
nginx -t && systemctl reload nginx
6. Gitea 与 Caddy
/opt/gitea 使用 Docker Compose 运行:
- Gitea
1.27.0:127.0.0.1:3000->3000,2222->22; - PostgreSQL
16:仅 Docker 内网; - Caddy:
127.0.0.1:8080->80、127.0.0.1:9443->443,反向代理到 Gitea。
cd /opt/gitea
docker compose up -d
docker compose ps
Caddy 管理 git.* 的 HTTPS 证书和自动续期;Nginx 对 Git 的 443 流量仅做 TLS 透传。Gitea 初始化时应填写:
ROOT_URL: https://git.<地区>.chermack.top/
SSH 域名: git.<地区>.chermack.top
SSH 端口: 2222
香港 Gitea 曾按授权清空数据并重新初始化;再次重置前必须先备份 /opt/gitea/gitea 和 /opt/gitea/postgres。
7. 美国服务器 SSH 端口处理
美国服务器原 OpenSSH 监听 22、2222、2223,与 Gitea Git SSH 的 2222 冲突。已保留宿主机 SSH 22,移除宿主机的 2222/2223 监听,并将 2222 留给 Gitea。
变更前备份:
/etc/ssh/sshd_config.pre-gitea-20260726-014417
安全操作:
sshd -t
systemctl reload ssh
ss -ltnp | grep sshd
修改 SSH 配置时必须保持一条现有的 22 端口会话,验证完成后再断开。
8. Trojan 证书续期
Trojan 的 www.* 证书仍由容器内 acme.sh 管理;Caddy 只管理 git.*。由于宿主机 80 已交给 Nginx,Trojan standalone 验证改用本地 8082:
docker exec trojan /root/.acme.sh/acme.sh --issue \
--server letsencrypt --standalone --httpport 8082 \
-d www.hk.chermack.top --ecc --force
docker exec trojan systemctl restart trojan
美国服务器替换为 www.us.chermack.top。本次两张 Trojan 证书均已成功签发,有效期为 2026-07-25 至 2026-10-23。后续应确认容器内自动续期任务也携带 --httpport 8082。
9. 重启后不可用:原因与永久修复
现象
香港服务器重启后,Nginx、Trojan 容器、Gitea、Caddy 都自动启动,但:
docker exec trojan systemctl is-active trojan # inactive
docker exec trojan systemctl is-active trojan-web # inactive
此时没有 8443 和 8081 监听,因此 www.hk.chermack.top 不可用。
临时恢复
docker exec trojan systemctl start trojan
docker exec trojan systemctl start trojan-web
ss -ltnp | grep -E ':(8443|8081)'
永久兜底
容器内 unit 虽为 enabled,但容器启动时没有拉起服务。因此在香港宿主机新增并启用:/etc/systemd/system/trojan-container-services.service。
[Unit]
Description=Start Trojan services inside the trojan container
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/docker exec trojan /bin/systemctl start trojan.service
ExecStartPost=/usr/bin/docker exec trojan /bin/systemctl start trojan-web.service
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
启用并验证:
systemctl daemon-reload
systemctl enable trojan-container-services.service
systemctl start trojan-container-services.service
systemctl is-enabled trojan-container-services.service
systemctl is-active trojan-container-services.service
docker exec trojan systemctl is-active trojan trojan-web
本次已验证该兜底服务为 enabled、active;Trojan 和 trojan-web 均为 active,且外部 HTTPS 访问 https://www.hk.chermack.top/ 成功。
美国服务器也已部署同名的宿主机兜底 unit,并完成验证:trojan-container-services.service 为 enabled、active;Trojan 监听 0.0.0.0:8443,管理后台监听 127.0.0.1:8081;https://www.us.chermack.top/ 与 https://git.us.chermack.top/ 外部访问均成功。
10. 日常检查与故障排查
# 统一入口、监听与容器
nginx -t
ss -ltnp | grep -E ':(80|443|8080|8081|8443|9443|2222)'
docker ps
# Trojan 及后台
docker exec trojan systemctl is-active trojan
docker exec trojan systemctl is-active trojan-web
# Web 链路
curl -kI https://www.hk.chermack.top/
curl -kI https://git.hk.chermack.top/
curl -kI https://www.us.chermack.top/
curl -kI https://git.us.chermack.top/
www.* 不可访问时,先检查 trojan-web 和 8081;Trojan 客户端也异常时,再检查 trojan 和 8443:
docker exec trojan systemctl restart trojan
docker exec trojan systemctl restart trojan-web
docker exec trojan journalctl -u trojan -u trojan-web --no-pager -n 200
docker logs --tail 200 trojan
11. 美国服务器 Gitea 初始化记录
初始化页面曾提示数据库密码无效。服务器内核验结果如下:
gitea容器的GITEA__database__*与gitea-db容器的POSTGRES_*用户、数据库和密码完全一致;- 使用 Gitea 容器实际注入的密码连接 PostgreSQL 成功;
/data/gitea/conf/app.ini中落盘的密码也与 PostgreSQL 一致;- 初始化页面已预填密码,错误由浏览器密码管理器覆盖表单密码或提交了其他密码造成,不是数据库密码失效。
为避免表单再次覆盖,已通过 Gitea CLI 使用明确配置文件完成初始化:
gitea --work-path /data/gitea \
--config /data/gitea/conf/app.ini migrate
随后创建临时管理员 admin,具备管理员权限并设置为首次登录必须修改密码;INSTALL_LOCK 已设为 true。随机初始密码只保存在美国服务器:
/root/gitea-initial-admin.txt
文件权限为 0600 root:root。登录并修改密码后应删除该凭据文件。
初始化前备份目录:
/root/gitea-us-pre-init-20260726-041434
最终验证结果:数据库中存在一个管理员且 must_change_password=true,Gitea 日志无初始化错误,https://git.us.chermack.top/user/login 从服务器内外访问均成功。
12. 美国管理后台周期性退出的根因(2026-07-26)
故障现象:https://www.us.chermack.top/ 失效,Nginx 80/443 和 Trojan 8443 正常,但 trojan-web 为 failed,127.0.0.1:8081 无监听。
现场排查排除了磁盘耗尽、内存 OOM、Docker 容器重启、Nginx/Caddy 和本次 ACME 定时任务。关键证据:
宿主机 cgroup:cgroup2fs
容器基础系统:CentOS 7 / systemd 219
容器 systemctl:systemctl.py 1.5.7113(Python 替代实现)
容器启动日志:Failed to allocate manager object, freezing
容器内状态:多个 trojan/web 僵尸进程,无 journal 日志
当前镜像的 PID 1 systemd 无法在宿主机 cgroup v2 环境中正常建立 manager;/usr/bin/systemctl 实际是一次性 Python 替代脚本,不是持续运行的服务管理器。因此 unit 中的 Restart=on-failure 不能可靠监督进程。宿主机现有 trojan-container-services.service 也是 Type=oneshot,只在开机时执行一次启动,运行中 Web 退出后不会再次拉起。
以前台方式直接运行以下命令持续 15 秒无异常,证明 Go Web 程序、数据库和 8081 端口本身健康:
docker exec trojan /usr/local/bin/trojan web \
--host 127.0.0.1 --port 8081
探针启动的进程随后继续运行,8081、本地 /auth/check 和公网 HTTPS 均恢复 200;但替代 systemctl 仍错误显示 failed,再次证明问题位于服务管理层。
临时永久化建议:由宿主机真实 systemd 使用前台 docker exec 直接监督 trojan-web(以及 Trojan core),设置 Restart=always 并将 stdout/stderr 写入宿主机 journal。最终解决方案是使用已规划的新镜像,移除 CentOS 7、冻结的容器 systemd 和运行时下载的 systemctl.py。
13. 后续维护事项
- 两台服务器的
trojan-mariadb仍将3306映射到公网;为避免额外中断,迁移中未改动。确认无外部依赖后,应限制为127.0.0.1:3306或移除映射。 www.*与git.*使用不同的证书管理者:前者为 Trojan 容器内 acme.sh,后者为 Caddy。- 两台服务器均已部署
trojan-container-services.service。重启服务器后,优先检查该服务及容器内两个 Trojan 服务状态。