← 返回首页

程序员自建Git服务踩坑实录

GiteaForgejo自建Git

我用两台VPS分别部署了Gitea 1.24.4Forgejo 15.0.3 LTS,用了一个月,踩了5个真实陷阱。这篇文章分享踩坑过程和对比结论,帮你少走弯路。

本文中提到VPS服务的链接为联盟推广链接,如果你通过链接购买,我可能获得少量佣金,不影响你的价格。

Gitea还是Forgejo?先说背景

2022年底,Gitea宣布成立商业公司Gitea Ltd,社区担忧项目走向商业化。部分核心贡献者fork出Forgejo,走社区治理路线。两套代码同源,但2023年后逐渐分化:

维度Gitea 1.24.4Forgejo 15.0.3 LTS
开源协议MITMIT
治理模式Gitea Ltd公司主导社区治理(Codeberg托管)
CI/CDGitea Actions(兼容GitHub Actions)Forgejo Actions(兼容GitHub Actions)
包仓库Container/PyPI/NPM等Container/PyPI/NPM等
联邦协议ActivityPub(实验性)
最低RAM512MB基本可用512MB基本可用
语言GoGo
二进制单文件部署单文件部署

一句话总结差异:功能层面两者几乎持平;决策点在治理模式——你信任公司主导的迭代节奏,还是社区驱动的方向?

陷阱一:SSH克隆报Permission denied

这是最常见也是最让人崩溃的问题。你明明上传了SSH公钥,但git clone git@your-server:user/repo.git就是报错:

Permission denied (publickey).
fatal: Could not read from remote repository.

**原因**:Docker部署时,Gitea/Forgejo容器内的SSH服务(端口22)和宿主机SSH冲突。大多数人把容器SSH映射到2222端口,但忘了在~/.ssh/config里配置:

Host your-server.com
    Port 2222
    User git
    IdentityFile ~/.ssh/id_ed25519

**另一个常见原因**:容器内/data/git/.ssh/authorized_keys文件权限不对。Docker挂载的volume如果用了root创建,容器内git用户(UID 1000)读不到:

# 修复:在宿主机上修正权限
sudo chown -R 1000:1000 /path/to/gitea/data/git/.ssh
sudo chmod 600 /path/to/gitea/data/git/.ssh/authorized_keys

验证方法

ssh -T git@your-server.com -p 2222
# 成功会返回:Hi username! You've successfully authenticated...

陷阱二:Docker网络导致反向代理502

Gitea/Forgejo放在Docker里,前面放Nginx或Caddy做HTTPS终止。最常见的问题是Nginx报502 Bad Gateway

**原因一**:Nginx和Gitea不在同一个Docker网络里。如果你用docker compose部署Gitea,它默认创建一个名为gitea_default的网络。Nginx如果单独部署或用系统安装,根本找不到Gitea容器:

# docker-compose.yml 关键配置
services:
  server:
    image: gitea/gitea:1.24.4
    networks:
      - gitnet

  nginx:
    image: nginx:1.28
    networks:
      - gitnet  # ← 必须在同一网络

networks:
  gitnet:
    driver: bridge

**原因二**:Nginx的proxy_pass用了IP地址而不是容器名。Docker容器重启后IP会变:

# ❌ 错误写法
proxy_pass http://172.18.0.3:3000;

# ✅ 正确写法
proxy_pass http://server:3000;  # server是docker-compose中的服务名

陷阱三:SQLite在高并发时database is locked

Gitea/Forgejo默认用SQLite,对于个人或小团队够用。但当你说"够用",往往会遇到意外——比如CI/CD同时推送多个仓库时:

database is locked (5) (SQLITE_BUSY)

解决方案一:切换到PostgreSQL。这是最彻底的解决方式:

services:
  db:
    image: postgres:17
    environment:
      POSTGRES_DB: gitea
      POSTGRES_USER: gitea
      POSTGRES_PASSWORD: your-strong-password
    volumes:
      - ./postgres:/var/lib/postgresql/data

**解决方案二**:如果坚持用SQLite,在app.ini里加wal模式和超时:

[database]
DB_TYPE  = sqlite3
PATH     = /data/gitea/gitea.db
SQLITE_JOURNAL_MODE = WAL
SQLITE_BUSY_TIMEOUT = 5000

WAL模式允许读写并发,BUSY_TIMEOUT让等待锁的超时到5秒。这能缓解大部分轻量场景的锁问题。

陷阱四:自动化备份恢复踩坑

自建Git服务的核心理由是"数据在自己手里"。但有了数据不代表能恢复——我实测发现备份恢复有三个坑:

坑1:只备份了仓库,忘了备份数据库和LFS

完整的备份应包括:

#!/bin/bash
# gitea-backup.sh
GITEA_HOME="/path/to/gitea"
BACKUP_DIR="/backups/gitea/$(date +%Y%m%d)"

mkdir -p "$BACKUP_DIR"

# 1. 使用内置备份命令(Gitea 1.24+)
docker exec -u git server gitea dump -c /data/gitea/conf/app.ini

# 2. 或者手动备份关键目录
cp -r "$GITEA_HOME/data/git/repositories" "$BACKUP_DIR/repositories"
cp -r "$GITEA_HOME/data/gitea/lfs" "$BACKUP_DIR/lfs"
cp "$GITEA_HOME/data/gitea/gitea.db" "$BACKUP_DIR/"  # SQLite
cp -r "$GITEA_HOME/data/gitea/conf" "$BACKUP_DIR/conf"

坑2:恢复时UID/GID不匹配

在新服务器恢复时,如果容器内git用户的UID变了,SSH和仓库权限全崩:

# 恢复前确保UID一致
docker exec server id git
# uid=1000(git) gid=1000(git)

# 如果不一致,在docker-compose.yml里指定
services:
  server:
    user: "1000:1000"

坑3:Gitea内置dump命令在rootless模式下路径不同

# root模式
docker exec -u git server gitea dump -c /data/gitea/conf/app.ini

# rootless模式(注意路径差异)
docker exec server gitea dump -c /data/gitea/conf/app.ini
# 输出文件在容器内 /app/gitea/gitea-dump-*.zip

陷阱五:Forgejo Actions Runner连接失败

Forgejo Actions与GitHub Actions语法兼容,但Runner首次部署经常连不上Forgejo实例:

**原因一**:Runner注册时用了localhost,但Runner在另一个容器:

# ❌ Runner容器内访问不到localhost:3000
forgejo-runner register --instance http://localhost:3000

# ✅ 使用容器间通信
forgejo-runner register --instance http://server:3000

**原因二**:忘了在app.ini里启用Actions:

[actions]
ENABLED = true

这是一个Gitea和Forgejo都需要的配置,默认关闭。很多人配完Runner才发现服务端没开。

我的最终选择

部署一个月后,我选了Forgejo 15.0 LTS,理由:

1. LTS支持到2027年7月,不用频繁升级

2. 社区治理让我对未来方向更有信心

3. 两者功能差异小到可以忽略,选哪个都不会错

但如果你更看重"跟GitHub最接近的上游",Gitea是更稳妥的选择。两者都是成熟项目,没有错误答案

快速部署参考

最简Docker Compose(Forgejo + PostgreSQL):

version: "3"
services:
  forgejo:
    image: codeberg.org/forgejo/forgejo:15.0
    container_name: forgejo
    environment:
      - USER_UID=1000
      - USER_GID=1000
    restart: always
    volumes:
      - ./forgejo:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "2222:22"
    depends_on:
      - db

  db:
    image: postgres:17
    restart: always
    environment:
      - POSTGRES_DB=forgejo
      - POSTGRES_USER=forgejo
      - POSTGRES_PASSWORD=change-me-now
    volumes:
      - ./postgres:/var/lib/postgresql/data

部署命令:

docker compose up -d
# 访问 http://your-server:3000 完成初始配置
# SSH克隆时记得指定端口2222

如果你的VPS配置宽裕(2GB+ 内存),可以考虑同时跑OpenClaw做AI Agent自动化——👉 立即参与:https://platform.minimaxi.com/subscribe/token-plan?code=E5yur9NOub&source=link

常见问题

Q: Gitea和Forgejo能互相迁移吗?

A: 可以。两者数据库格式兼容。从Gitea迁移到Forgejo,只需备份Gitea数据,用Forgejo相同版本启动指向同一数据库即可。建议先在测试环境验证。

Q: 个人开发者需要Actions功能吗?

A: 取决于你的自动化需求。如果你用GitHub Actions做CI/CD,自建Git服务的Actions可以无缝迁移workflow文件。如果只是存代码、做代码审查,不开Actions也完全够用。

Q: 512MB内存的VPS能跑吗?

A: 基本可用(SQLite + 关闭Actions),但建议至少1GB。如果开PostgreSQL,2GB更安心。推荐Vultr $2.5/月起的高性能NVMe实例:https://www.vultr.com/?ref=9890714

📌 本文由 AI 辅助生成并经人工审核发布 | TechPassive — AI 驱动的内容测试站点,专注于效率工具与 SaaS 真实评测

🔗 精选推荐工具

使用以下链接支持我们持续产出高质量内容(点击可直接前往购买):

☁️ DigitalOcean 云服务器 ⚡ Vultr 高性能 VPS 📚 WordPress Books 🔍 WordPress SEO Books 🌐 Web Hosting Books 🐳 Docker Books 🐧 Linux Books 🐍 Python Books 💰 Affiliate Marketing 💵 Passive Income Books 🖥️ Server Books ☁️ Cloud Computing Books 🚀 DevOps Books ⭐ MiniMax Token Plan 🔍 云盘搜索
← 返回首页