未来星球 未来星球
  • 首页
  • 新闻资讯
  • 技术教程
  • 软件工具
  • 知识百科
  • 生活实用
  • 个人随笔
  • 生命外星人
首页 › 技术教程 › 用 Gitea 搭自建 Git 服务:3 份配置,和 4 个必踩的坑
  • 0
  • 0

用 Gitea 搭自建 Git 服务:3 份配置,和 4 个必踩的坑

admin
2 小时前
2 views
用 Gitea 搭自建 Git 服务:3 份配置,和 4 个必踩的坑-未来星球

一台 2 核 4G 的云主机,装完系统剩下 38G 空间,跑一个自建 Git 服务绰绰有余。真正占时间的不是安装,是安装完之后那四个会静默失败的地方。

这篇写的是一套能直接复制运行的配置:Gitea 1.24 系列、PostgreSQL 16、Nginx 反代、SSH 走 2222 端口。所有版本号都写死,避免某天自动升级把数据目录顶掉。

1. 目录怎么摆

先建目录,再动手写配置。目录结构决定了以后备份和迁移的难度,一开始摆错,后面每次操作都要多记一条路径。把「程序」和「数据」分开,是这套部署里唯一不能妥协的原则。

/opt/gitea
├── docker-compose.yml
├── db/                 # PostgreSQL 数据,容器写入
└── data/               # Gitea 全部家当
    ├── gitea/conf/app.ini
    ├── git/repositories/   # 裸仓库
    ├── lfs/                # 大文件
    ├── avatars/
    └── backup/             # gitea dump 的输出

/etc/nginx/conf.d/gitea.conf

data 这一个目录就是全部资产。仓库、附件、头像、配置、密钥都在里面,迁机器时把它和数据库一起搬走就能复原。除它之外的东西都可以重建,包括容器。

2. 第一份配置:docker-compose.yml

数据库单独一个容器,不要用 Gitea 内置的 SQLite。这不是性能问题,是备份问题:SQLite 在写入过程中做文件级拷贝,拿到的是一个损坏的库。单人多仓库用 SQLite 也能跑,但只要涉及定时备份,Postgres 的 pg_dump 是唯一省心的选项。

services:
  db:
    image: postgres:16
    restart: always
    environment:
      POSTGRES_USER: gitea
      POSTGRES_PASSWORD: change-me-db
      POSTGRES_DB: gitea
    volumes:
      - ./db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U gitea -d gitea"]
      interval: 10s
      timeout: 5s
      retries: 5

  server:
    image: gitea/gitea:1.24.3
    restart: always
    depends_on:
      db:
        condition: service_healthy
    environment:
      USER_UID: 1000
      USER_GID: 1000
      GITEA__database__DB_TYPE: postgres
      GITEA__database__HOST: db:5432
      GITEA__database__NAME: gitea
      GITEA__database__USER: gitea
      GITEA__database__PASSWD: change-me-db
      GITEA__server__SSH_PORT: 2222
      GITEA__server__SSH_LISTEN_PORT: 22
      GITEA__server__ROOT_URL: https://git.example.com/
      GITEA__service__DISABLE_REGISTRATION: "true"
    ports:
      - "127.0.0.1:3000:3000"
      - "2222:22"
    volumes:
      - ./data:/data
      - /etc/localtime:/etc/localtime:ro

三个细节值得单独说明。3000 端口绑在 127.0.0.1 上,不对外,外网只走 Nginx 的 443;USER_UID 和 GITEA__server__SSH_PORT 必须同时出现,前者决定写文件的身份,后者决定页面上给出的克隆地址;DISABLE_REGISTRATION 要在第一次启动前就设好,否则公开的注册页会在你发现之前积下几十个垃圾账号。

启动之前先把数据目录的属主改掉。这一步现在做,能省掉后面一次莫名其妙的 push 失败。

mkdir -p /opt/gitea/db /opt/gitea/data
chown -R 1000:1000 /opt/gitea/data
cd /opt/gitea && docker compose up -d
docker compose logs -f server | head -40

3. 第二份配置:app.ini 里真正要改的五项

首次启动后,Gitea 会在 data/gitea/conf/app.ini 生成一份完整配置,你不需要从零写,只需要改五行。改环境变量也行,但环境变量和文件同时存在时,以文件为准,这是最容易互相打脸的地方。

[server]
DOMAIN           = git.example.com
ROOT_URL         = https://git.example.com/
SSH_DOMAIN       = git.example.com
SSH_PORT         = 2222
SSH_LISTEN_PORT  = 22
HTTP_PORT        = 3000

[service]
DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW  = false

[repository]
DEFAULT_BRANCH = main
ROOT           = /data/git/repositories

[lfs]
PATH = /data/lfs

[security]
INSTALL_LOCK = true

SSH_PORT 和 SSH_LISTEN_PORT 的区别必须记清楚。前者是对外公布的端口,会写进克隆地址;后者是容器内 sshd 实际监听的端口。写反了的后果是:网页上给的地址是 ssh://git@host:22/…,而宿主机的 22 端口被系统 sshd 占着,clone 会一直在那转圈直到超时。

INSTALL_LOCK = true 也建议手动加上。它锁掉网页安装向导,避免某次重启后配置被重置成初始状态。

改完重启,然后建第一个管理员。不要靠注册页建,那是最容易留下隐患的路径。

docker compose restart server
docker compose exec -u git server \
  gitea admin user create \
  --username guo --password 'Your-Strong-Pass' \
  --email guo@example.com --admin --must-change-password=false

4. 第三份配置:反代与证书

反代这一段只有三个必填项,漏掉任何一个,症状都会在几天后才出现。Host 决定生成链接的域名,X-Forwarded-Proto 决定链接是 http 还是 https,client_max_body_size 决定你能不能推大文件。

server {
    listen 443 ssl http2;
    server_name git.example.com;

    ssl_certificate     /etc/letsencrypt/live/git.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem;

    client_max_body_size 512m;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
    }
}

client_max_body_size 默认是 1m。不改这一行,push 一个带 20MB 素材的提交会直接被 Nginx 拦下,返回一个和 Git 毫无关系的 413。

如果反代和 Gitea 不在同一台机器,还要在 app.ini 里加 REVERSE_PROXY_TRUSTED_PROXIES,否则 Gitea 会把所有请求的来源 IP 记成反代的地址,登录失败次数限制会误伤所有人。一个所有用户共享的 IP,等于一个所有用户共享的风控额度。

这套配置在 2 核 4G 的机器上,空载内存大约占 600MB 到 800MB,其中 Postgres 和 Gitea 各一半。五十个仓库、日常三五个人的提交量,CPU 基本闲着。真正会把机器拖死的是两件事:一次性导入几百个仓库的历史,和有人在网页上打开一个两万行的 diff。

如果仓库数量会超过两三百个,内存建议给到 8G 以上,并把 Postgres 的 shared_buffers 显式设成 1GB 左右。默认值是 128MB,在大仓库的 gc 阶段会成为瓶颈。

5. 把已有的仓库搬过来

搬仓库有两种做法,选哪种取决于你要不要保留 issue、wiki 和 release。只要代码的用镜像推送,全套元数据都要的用网页端的迁移功能。

只要代码,用 --mirror 推一遍最干净。它会把所有分支、所有标签、所有远程引用原样搬过去,不经过工作区。速度取决于带宽,不取决于仓库里有多少文件,这是它比网页迁移可靠的地方。

git clone --mirror https://github.com/old/project.git
cd project.git
git push --mirror ssh://git@git.example.com:2222/guo/project.git
cd .. && rm -rf project.git

要保留 issue 和 wiki,用 Gitea 的「迁移仓库」页面,填旧仓库地址和访问令牌。迁移是异步任务,页面关掉它照样在跑,但失败时不会弹窗,只会在「管理后台 – 监控 – 队列」里留一条错误。

迁移完成后有一件事必须手工确认:默认分支。旧仓库如果默认分支是 master,而你在 app.ini 里设了 DEFAULT_BRANCH = main,迁移过来的仓库会显示一个空首页。它没坏,只是把不存在的 main 当成了首页。

网页迁移还有一个容易忽略的限制:单仓库大小和超时。超过一定体积的仓库会因为反向代理的 proxy_read_timeout 被切断,日志里只有一行 504。大仓库老老实实用镜像推送,别指望网页端。

6. 验收:四条命令

装完不要只看网页能不能打开。下面四条按顺序跑,每条都对应一个独立的链路,任何一条失败都指向不同的层。能打开首页只证明 Nginx 和 HTTP 通了,其余三条才证明这套东西能用。

  1. curl -sI https://git.example.com/api/healthz 应返回 200,证明反代与后端都在。
  2. ssh -T -p 2222 git@git.example.com 应返回一句欢迎语加你的用户名,证明 SSH 链路和公钥都认了。
  3. 新建一个空仓库,git clone ssh://git@git.example.com:2222/guo/test.git,能克隆说明仓库路径与权限正常。
  4. 提交一个 2MB 的二进制文件并 push,再 git lfs ls-files,确认 LFS 真的接管了它。

第二条命令最容易失败,而且报错信息通常只有一句 Permission denied (publickey)。它同时可能是密钥没上传、端口错、容器内 sshd 没起、或者宿主的 2222 被别的服务占了,四种原因一个提示。

7. 四个必然踩到的坑

下面四条不是假设,是按这套配置走一遍几乎一定会遇到的。提前知道症状,比事后看日志快得多。

坑一:push 时报 insufficient permission for adding an object。原因是 data/git/repositories 的属主不是 1000。容器内 git 用户的 UID 是 1000,宿主机上如果目录是 root 建的,写权限就没有。修法是 chown -R 1000:1000 /opt/gitea/data,不要用 chmod 777 绕过去,那只是把问题藏起来。

坑二:SSH 端口改对了,克隆地址还是 22。原因写在上一节:SSH_PORT 没改,或者改了没重启。Gitea 生成克隆地址时只读 SSH_PORT,它不知道你的 docker 端口映射表。

坑三:网页登录后跳回 http,或者邮件里的链接点不开。两个原因,ROOT_URL 写了 localhost:3000,或者反代没传 X-Forwarded-Proto。前者影响所有绝对链接,后者只影响需要拼协议的页面,所以症状时有时无,最难查。

坑四:直接改 compose 里的 postgres 标签做升级,容器起不来。Postgres 的大版本升级要重写数据目录格式,16 的数据文件用 17 的镜像打不开。正确顺序是 pg_dump 导出、换镜像、导回,中间不能省。

8. 备份与升级,这两件事不能等到出事

备份不要用 rsync 或 tar 直接打包 data 和 db。仓库在写入时打包,拿到的是一个能解开但没法用的快照,而且这种损坏不会在解压时报错。它只会在你真正需要恢复的那天报错。

docker compose exec -T -u git server   gitea dump -c /data/gitea/conf/app.ini   -f /data/backup/gitea-daily.zip

把它挂进 crontab,每天凌晨跑一次,输出文件名带上当天日期;保留 14 天,再按修改时间定期清理旧包。排程本身不是难点,难点是「跑成功但包是空的」这种情况——它不会报错,只会让恢复那天发现少了一个月的提交。

gitea dump 会把仓库、数据库、配置、附件打成一个包,但它不含 LFS 对象和 data/backup 自身。如果你启用了 LFS,要把 data/lfs 单独纳入备份,否则恢复后仓库能打开,大文件全是断链。

恢复的顺序也要记一下:先起一个空数据库,导入 dump 里的 SQL,再把 repositories 和 lfs 放回原位,最后启动。顺序错了不会报错,只会得到一个空站点。

写在最后

自建 Git 服务的门槛从来不在安装。docker compose up 之后十分钟内你就能看到登录页,这件事太顺,顺到让人以为已经完成。真正的成本在之后的每一次端口变更、每一次证书续期、每一次大版本升级里。

托管服务卖的不是服务器,是这些琐事有人替你处理。自建换来的不是省钱,是知道数据在哪、以及出事时能自己动手。这两件事对不同的人价值完全不同,选之前最好先想清楚自己要的是哪一个。

如果只是想给自己几个私人仓库找个落脚点,一台 2 核 4G 的机器加上这四份配置就够了。但它从此是你的系统,坏了没人替你修。


你自建的哪一项服务,最后因为升级或迁移太麻烦而放弃了?

0

当训练数据吃完了互联网:三代人的代价,和一个不太好接受的推论

上一篇

评论 (0)

登录后可发布~
立即登录
暂无评论

admin

当生活给你的全是不如意,那你一定要相信自己的兴趣!
161
文章
0
评论
-11
喜欢
2026 年 11 月
一 二 三 四 五 六 日
 1
2345678
9101112131415
16171819202122
23242526272829
30  
« 10 月    

近期评论

聚合文章

用 Gitea 搭自建 Git 服务:3 份配置,和 4 个必踩的坑
当训练数据吃完了互联网:三代人的代价,和一个不太好接受的推论
龙宫样本的 20 种氨基酸:5.4 克岩石,和一场污染之争
自助收银台前那十分钟:一次称重、两次呼叫,和三个人换了位置
AI 新闻日报 – 2026年11月2日:198亿与0.75美元
窗户漏风,暖气费在漏:一份按投入产出排序的封窗清单
抓一个 HTTP 请求:4 个工具的边界,和 3 种选错的信号
邮件地址里的 @ 从哪来:1971年的排除,和1536年的旧用法

猜你喜欢

2026 年必学的 5 个 AI 提示词技巧

2026 年必学的 5 个 AI 提示词技巧

admin
97 0 0
用 WireGuard 组建家庭内网:三台设备、一份可复现的配置

用 WireGuard 组建家庭内网:三台设备、一份可复现的配置

admin
23 0 0
深入理解 JavaScript 异步编程:从回调到 async/await

深入理解 JavaScript 异步编程:从回调到 async/await

admin
94 0 0
用Nginx做双向认证:3份配置,和4个必然踩到的坑

用Nginx做双向认证:3份配置,和4个必然踩到的坑

admin
8 0 0

关于我们

你是否对浩瀚的宇宙充满好奇?你是否渴望掌握未来科技的力量?现在,机会来了!“未来星球”将带你进入奇妙世界,开启你的科技探险之旅! 这是一个充满想象和创造力的博客!

分类导航

首页 新闻资讯 技术教程 软件工具 知识百科 生活实用 个人随笔 生命外星人

友情链接

未来星球AI工具【网络版】 未来星球 pycharm官方站【中国】
Copyright © 2026 未来星球. Designed by nicetheme. 蒙ICP备2026002569号-1
  • 请到 [后台->外观->菜单] 中设置菜单
  • AI未来
  • 生活百科
  • 档案
  • 外星人
  • 未来星球

admin

当生活给你的全是不如意,那你一定要相信自己的兴趣!
161
文章
0
评论
-11
喜欢