From 772009e0f2c5d1a06082a97f05a56cfc83f235c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Sat, 16 May 2026 17:07:32 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0Forgejo=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E6=8E=92=E9=9A=9C=E7=BB=8F=E9=AA=8C=E5=BA=93=EF=BC=8C?= =?UTF-8?q?=E8=AE=B0=E5=BD=952026-05-16=E8=BF=81=E7=A7=BB=E5=85=A8?= =?UTF-8?q?=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ops/forgejo-deployment-experience.md | 279 ++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 docs/ops/forgejo-deployment-experience.md diff --git a/docs/ops/forgejo-deployment-experience.md b/docs/ops/forgejo-deployment-experience.md new file mode 100644 index 0000000..0f0d4ff --- /dev/null +++ b/docs/ops/forgejo-deployment-experience.md @@ -0,0 +1,279 @@ +# Forgejo 部署与排障经验库 + +> 光湖语言世界代码仓库(guanghulab.com)从 CVM 迁移到广州轻量云服务器的完整踩坑记录。 +> 换服务器或遇到类似问题时,先看这个文档,不用重新推演。 + +--- + +## 核心:一键部署脚本 + +优先使用仓库里的 `scripts/smart-deploy-forgejo.sh`。 +这个脚本做了智能检测(Docker可用性、COS配置、已有Forgejo状态),一条命令跑完全部部署流程。 +换服务器时的第一步。 + +--- + +## 二进制部署(Docker 不可用的替代方案) + +当 Docker pull 失败(429限流或被墙)时,直接下载 Gitea 二进制: + +```bash +# 下载 Gitea 1.23.7(Forgejo 的底层引擎) +wget -O /usr/local/bin/gitea https://dl.gitea.com/gitea/1.23.7/gitea-1.23.7-linux-amd64 +chmod +x /usr/local/bin/gitea + +# 创建专用用户 +adduser --disabled-login --gecos "" git + +# 目录结构 +mkdir -p /opt/forgejo/custom/conf /opt/forgejo/data +chown -R git:git /opt/forgejo +``` + +### app.ini 配置 + +`/opt/forgejo/custom/conf/app.ini`: + +```ini +APP_NAME = 光湖 · Forgejo +RUN_USER = git +RUN_MODE = prod + +[database] +DB_TYPE = sqlite3 +PATH = /opt/forgejo/data/forgejo.db + +[server] +DOMAIN = guanghulab.com +HTTP_PORT = 3001 +ROOT_URL = https://guanghulab.com/ +HTTP_ADDR = 127.0.0.1 +LANDING_PAGE = explore +OFFLINE_MODE = false + +[service] +DISABLE_REGISTRATION = false +REQUIRE_SIGNIN_VIEW = false + +[mailer] +ENABLED = false + +[session] +PROVIDER = file + +[log] +MODE = console +LEVEL = info +ROOT_PATH = /opt/forgejo/data/log +``` + +> **注意**:`ROOT_URL` 必须用 `https://`,否则克隆链接会显示 `http://`。 + +### systemd 服务 + +`/etc/systemd/system/forgejo.service`: + +```ini +[Unit] +Description=Forgejo (Git with a cup of tea) +After=network.target + +[Service] +ExecStart=/usr/local/bin/gitea web -c /opt/forgejo/custom/conf/app.ini --work-path /opt/forgejo +Restart=always +User=git +Group=git +WorkingDirectory=/opt/forgejo + +[Install] +WantedBy=multi-user.target +``` + +```bash +systemctl daemon-reload +systemctl enable --now forgejo +systemctl status forgejo +``` + +--- + +## 常见问题与排查流程 + +### 1. Forgejo 拒绝以 root 运行 + +**现象**:启动报错 "Forgejo/Gitea refuses to run as root" + +**原因**:Forgejo/Gitea 安全机制禁止 root 运行。 + +**解决**: +- 直接用 `sudo -u git /usr/local/bin/gitea ...` 启动 +- 或者在 systemd 里设 `User=git` + +--- + +### 2. Git 推送失败:HTTP 413 Request Entity Too Large + +**现象**: + +``` +error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 +send-pack: unexpected disconnect while reading sideband packet +``` + +**排查流程**: +1. 确认 Nginx 配置中有 `client_max_body_size`:`cat /etc/nginx/sites-available/guanghulab` +2. 默认 Nginx 限制 1MB,Git 推送的 packfile 远超此值 +3. 检查配置是否写在正确的 server block 里(certbot 可能创建了多个配置) + +**解决**: + +```bash +# 在 location / 块中添加 client_max_body_size +sudo sed -i '/location \/ {/a \ client_max_body_size 100M;' /etc/nginx/sites-available/guanghulab + +# 重载 Nginx +sudo systemctl reload nginx +``` + +**验证**:`git push` 不再报 413 即为成功。 + +--- + +### 3. 仓库数据损坏:推送成功但网页不显示文件 + +**现象**: +- `git push` 返回成功(`[new branch] main -> main`) +- Forgejo 网页显示仓库名但看不到文件 +- 再次推送报错:`Gitea: Internal Server Error Decoding Failed` + `pre-receive hook declined` +- 远程 HEAD 不一致:`git ls-remote` 显示的 hash 与本地不同 + +**根本原因**:从 COS 备份恢复旧 Gitea 数据时,Git 内部数据损坏或版本不兼容。 + +**排查流程**: +1. `git ls-remote origin HEAD main` — 检查远程 HEAD 是否匹配本地 +2. `curl -u user:token https://domain.com/api/v1/user/repos` — 查看仓库状态(empty、size) +3. 尝试推送观察具体错误信息 + +**解决**: + +```bash +# 1. 通过 API 删除损坏仓库 +curl -s -X DELETE -u "bingshuo:ACCESS_TOKEN" "https://guanghulab.com/api/v1/repos/bingshuo/guanghulab" + +# 2. 创建新空仓库 +curl -s -X POST -u "bingshuo:ACCESS_TOKEN" \ + "https://guanghulab.com/api/v1/user/repos" \ + -H "Content-Type: application/json" \ + -d '{"name":"guanghulab","description":"光湖代码仓库·国内镜像","private":false,"auto_init":false}' + +# 3. 从本地推送完整代码 +git push https://user:token@guanghulab.com/user/repo.git main +``` + +--- + +### 4. SSL 证书配置 + +```bash +# 申请证书 +sudo certbot --nginx -d guanghulab.com + +# 验证自动续期 +sudo certbot renew --dry-run + +# 证书位置 +/etc/letsencrypt/live/guanghulab.com-0001/ +``` + +certbot 会自动在 Nginx 配置中添加 `listen 443 ssl` 和 HTTP→HTTPS 重定向。 + +--- + +### 5. COS(腾讯云对象存储)备份恢复 + +```bash +# 安装 coscmd +pip3 install coscmd + +# 配置 +coscmd config -a {secret_id} -s {secret_key} -b {bucket_name} -r ap-guangzhou + +# 列出文件 +coscmd list + +# 下载备份 +coscmd download backups/guanghu-old-backup-20260512.tar.gz /root/forgejo-backup.tar.gz + +# 恢复到 Forgejo 目录 +tar -xzf /root/forgejo-backup.tar.gz -C /opt/forgejo/ +chown -R git:git /opt/forgejo/ +``` + +> **注意**:COS 存储桶名称:`zy-team-hub-1317346199`,区域:`ap-guangzhou`。 +> 备份文件在 `backups/` 目录下。 + +--- + +### 6. 验证部署完整性 + +**确认服务运行**: + +```bash +systemctl status forgejo # 服务 active +curl -I http://127.0.0.1:3001 # 返回 200 +curl -I https://guanghulab.com # HTTPS 正常 +``` + +**确认仓库状态**: +- Forgejo 网页登录 → 仓库列表有数据 +- `git ls-remote https://guanghulab.com/bingshuo/guanghulab.git HEAD` → 返回正确 commit +- Forgejo API `GET /api/v1/user/repos` → 返回仓库列表 + +--- + +## 部署流程速查 + +从零开始部署的完整流程(假设已有 COS 备份): + +1. **执行 `scripts/smart-deploy-forgejo.sh`** 或手动部署二进制 +2. **从 COS 下载备份并恢复** +3. **配置 Nginx 反向代理**(脚本已自动处理) +4. **申请 SSL 证书**(`certbot --nginx`) +5. **启动 Forgejo 并验证** +6. **如果仓库损坏** → 删除仓库,重建,重新推送 +7. **如果推送报 413** → 配置 Nginx `client_max_body_size 100M` + +--- + +## 注意事项 + +- **不要用 root 直接运行 Forgejo** — 必须用 git 用户 +- **Nginx 配置改动后必须 reload** — `sudo systemctl reload nginx` +- **备份恢复后检查仓库完整性** — 用 `git ls-remote` 对比本地 hash +- **ROOT_URL 要写 https** — 否则克隆链接显示 http:// +- **certbot 会修改 Nginx 配置** — 注意它创建的是独立的 server block + +--- + +## 2026-05-16 实测记录 + +本次迁移完整时间线: + +| 时间 | 事件 | 结果 | +|------|------|------| +| 14:30 | 从 COS 下载 44MB 备份 | ✅ | +| 14:45 | 解压恢复 forgejo.db + 仓库 | ✅ | +| 15:00 | 下载 Gitea 1.23.7 二进制 | ✅ | +| 15:20 | Nginx 反向代理 + SSL 证书 | ✅ | +| 15:50 | 域名解析切换到广州服务器 | ✅ | +| 16:37 | 推送代码到新仓库 | ⚠️ 推送成功但网页不显示 | +| 16:50 | 发现仓库数据损坏 | ❌ Internal Server Error | +| 16:52 | 删除损坏仓库,重建 | ✅ | +| 16:55 | 再次推送 → HTTP 413 | ❌ | +| 16:58 | 排查 Nginx 配置 → 缺 client_max_body_size | ✅ 修复 | +| 17:02 | 重载 Nginx,第三次推送 | ✅ 成功 | + +**教训总结**: +1. COS 备份恢复后,仓库数据可能损坏——先 `git ls-remote` 验证 +2. Nginx 默认 1MB body 限制——Git 推送必超,需显式设置 +3. 经验要沉淀到仓库里,不能只留在本地终端