Blog

搭建私有 Git:Gitea 部署全记录

不是每个仓库都该放公开 GitHub。家庭实验室的 compose、画了内网地址的拓扑图、带一点环境细节的脚本——放云上要么付 private 的钱,要么接受「内容在别人磁盘」的心理摩擦。Gitea 轻、界面够用、资源占用小,是我为「主权仓库」选的落点。本文先把为什么要私有 Git 说清楚,再写部署与日常如何配得上这个动机;没有动机的自托管,停服三个月也不会有人想念。

公共托管解决不了的三种别扭

第一是边界。开源项目放 GitHub 理所当然;homelab 仓库里却经常混进主机名、网段、备份路径。即便开 private repo,账号体系、审计与二次分享仍受平台约束。第二是依赖。平台宕机、账号风控、地区访问波动时,你连 push 内网配置的能力都不应一并失去。第三是备份主权。SaaS 的「我们会备份」不能代替你自己持有可恢复的对象;真要迁出时,完整 issue、wiki、附件的导出体验参差不齐。

Gitea 不是要替代 GitHub 的社交与 Actions 生态。PR 协作、公开社区、复杂 CI 市场仍是 GitHub 更强。我的分工很明确:私有配置与敏感周边在 Gitea;需要公开协作的在 GitHub;密钥进环境变量与专用密钥库,不进任何远端的明文历史。

主权仓库里实际放什么

  • Homelab 的 compose、脚本、Ansible 清单
  • 私人文档与以 git 管理的笔记
  • 不想单点依赖某一 SaaS 的代码镜像

刻意不放:巨大的二进制制品(走制品库或对象存储)、唯一一份不可再生成的密钥(走 Vaultwarden 一类)、需要对外协作审查的开源主仓库。仓库粒度按项目拆,建组织 homelab,避免一个 mono 塞进全世界,权限和 mirror 策略都难做。

落地:容器、数据库与入口

官方容器加 Postgres(SQLite 只适合试玩)。反向代理终结 HTTPS,禁用公开注册,账号管理员手开。SSH 克隆映射到 2222 或独立域名,和宿主 22 错开,避免和系统 sshd 抢语义。外网若必须暴露,优先挂在已有隧道或 VPN 之后,而不是给 Gitea 单独开一个「全世界可扫」的 443——动机是主权,不是把自己变成公网 git 蜜罐。

services:
  gitea:
    image: gitea/gitea:1.22
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=postgres
    volumes:
      - /data/gitea:/data
    ports:
      - "2222:22"

装完先登录改站点名、关注册、开强制 HTTPS 相关选项,再导入自己的 SSH 公钥。密码登录可以关。Web 与 SSH 都走密钥习惯后,攻击面立刻清爽一圈。

备份必须对齐「你为何自建」

既然动机包含主权,备份就不能只 rsync 一下 git 目录。至少三样一起走:

  1. data 卷(仓库对象、附件、LFS 若有)
  2. 数据库(issue、PR、用户、webhook 配置)
  3. app.ini 与关键配置

只保裸仓库会丢掉协作元数据;只保库没有对象则网页能开、clone 是空的。恢复演练:空实例导入,看 commit 与 Web 界面是否一致。重要仓库再 mirror 到 GitHub 私有或另一台 Gitea——单向保险,防单站点灾难,不要求把协作主场搬走。

权限与习惯比界面主题重要

哪怕一个人用,也为 main 开分支保护,禁止直推,防手滑 force。webhook 谨慎,不要指到无鉴权的内网 URL,避免 SSRF 式误伤。Gitea Actions / Act Runner 按需启用,不是装完就自动拥有的义务。权限模型保持简单:自己读写、家人只读、CI 用部署密钥最小权限。

升级 Gitea 时同样对齐动机:先备份 data 与数据库,再读版本说明里的破坏性变更,最后拉镜像。界面换肤可以冲动,存储格式迁移不行。跑了一年后若发现自己从不开 issue、只用纯 git,也可以把部分仓库降级为裸仓库加镜像,但家庭场景里 Web 审 diff 与简单权限仍值得保留。

私有 Git 的价值是掌控与备份策略自主。部署不难,难的是真的定期备份并演练,以及克制——不要把 Gitea 暴露成公网可注册的垃圾场,也不要因为「既然有了」就把所有人生仓库搬进去却从不 mirror、从不恢复测试。动机写在前面,落地才有检验标准:出事时,你是否仍持有可 clone、可还原讨论区的那一份。

← Back to Blog