319 lines
11 KiB
Markdown
319 lines
11 KiB
Markdown
# 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. 最终架构
|
||
|
||
```mermaid
|
||
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. 迁移前备份与检查
|
||
|
||
在变更前检查原容器和配置:
|
||
|
||
```bash
|
||
docker ps
|
||
docker inspect trojan
|
||
docker exec trojan cat /usr/local/etc/trojan/config.json
|
||
docker exec trojan systemctl cat trojan-web.service
|
||
```
|
||
|
||
已创建的备份目录:
|
||
|
||
```text
|
||
/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 配置调整为:
|
||
|
||
```json
|
||
{
|
||
"local_port": 8443,
|
||
"remote_port": 8081
|
||
}
|
||
```
|
||
|
||
管理后台 systemd unit 调整为:
|
||
|
||
```ini
|
||
ExecStart=/usr/local/bin/trojan web --host 127.0.0.1 --port 8081
|
||
```
|
||
|
||
重载和启动命令:
|
||
|
||
```bash
|
||
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 统一入口
|
||
|
||
安装并启用:
|
||
|
||
```bash
|
||
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`):
|
||
|
||
```nginx
|
||
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`。
|
||
|
||
每次配置改动后:
|
||
|
||
```bash
|
||
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。
|
||
|
||
```bash
|
||
cd /opt/gitea
|
||
docker compose up -d
|
||
docker compose ps
|
||
```
|
||
|
||
Caddy 管理 `git.*` 的 HTTPS 证书和自动续期;Nginx 对 Git 的 443 流量仅做 TLS 透传。Gitea 初始化时应填写:
|
||
|
||
```text
|
||
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。
|
||
|
||
变更前备份:
|
||
|
||
```text
|
||
/etc/ssh/sshd_config.pre-gitea-20260726-014417
|
||
```
|
||
|
||
安全操作:
|
||
|
||
```bash
|
||
sshd -t
|
||
systemctl reload ssh
|
||
ss -ltnp | grep sshd
|
||
```
|
||
|
||
修改 SSH 配置时必须保持一条现有的 22 端口会话,验证完成后再断开。
|
||
|
||
## 8. Trojan 证书续期
|
||
|
||
Trojan 的 `www.*` 证书仍由容器内 `acme.sh` 管理;Caddy 只管理 `git.*`。由于宿主机 80 已交给 Nginx,Trojan standalone 验证改用本地 8082:
|
||
|
||
```bash
|
||
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 都自动启动,但:
|
||
|
||
```bash
|
||
docker exec trojan systemctl is-active trojan # inactive
|
||
docker exec trojan systemctl is-active trojan-web # inactive
|
||
```
|
||
|
||
此时没有 `8443` 和 `8081` 监听,因此 `www.hk.chermack.top` 不可用。
|
||
|
||
### 临时恢复
|
||
|
||
```bash
|
||
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`。
|
||
|
||
```ini
|
||
[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
|
||
```
|
||
|
||
启用并验证:
|
||
|
||
```bash
|
||
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. 日常检查与故障排查
|
||
|
||
```bash
|
||
# 统一入口、监听与容器
|
||
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`:
|
||
|
||
```bash
|
||
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 使用明确配置文件完成初始化:
|
||
|
||
```bash
|
||
gitea --work-path /data/gitea \
|
||
--config /data/gitea/conf/app.ini migrate
|
||
```
|
||
|
||
随后创建临时管理员 `admin`,具备管理员权限并设置为首次登录必须修改密码;`INSTALL_LOCK` 已设为 `true`。随机初始密码只保存在美国服务器:
|
||
|
||
```text
|
||
/root/gitea-initial-admin.txt
|
||
```
|
||
|
||
文件权限为 `0600 root:root`。登录并修改密码后应删除该凭据文件。
|
||
|
||
初始化前备份目录:
|
||
|
||
```text
|
||
/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 定时任务。关键证据:
|
||
|
||
```text
|
||
宿主机 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 端口本身健康:
|
||
|
||
```bash
|
||
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. 后续维护事项
|
||
|
||
1. 两台服务器的 `trojan-mariadb` 仍将 `3306` 映射到公网;为避免额外中断,迁移中未改动。确认无外部依赖后,应限制为 `127.0.0.1:3306` 或移除映射。
|
||
2. `www.*` 与 `git.*` 使用不同的证书管理者:前者为 Trojan 容器内 acme.sh,后者为 Caddy。
|
||
3. 两台服务器均已部署 `trojan-container-services.service`。重启服务器后,优先检查该服务及容器内两个 Trojan 服务状态。
|