
Gitea 是轻量的自托管 Git 服务,提供仓库管理、issue、合并请求、组织权限和 CI 触发能力,资源占用远低于同类完整方案,适合个人和中小团队自建代码托管。本文完成 Gitea 的部署,涵盖资源规划、Docker 部署、SSH 与 HTTPS 双通道配置、关闭开放注册、组织与权限设置,以及仓库备份与迁移。
常见的理由有几个:代码属于核心资产,希望完全掌握存放位置;需要在内网环境使用,不依赖外部网络;团队人数增长后托管服务的费用上升;需要与内部系统做深度集成。
Gitea 相比其他自建方案的特点是轻量。它用单个二进制文件运行,默认配置下内存占用很低,1 GB 内存的机器就能稳定跑起来。功能上覆盖了日常开发需要的仓库管理、代码审查、问题跟踪和权限控制。
需要说明适用边界:Gitea 适合个人项目和中小团队。如果团队规模很大、需要复杂的合规审计、或者需要开箱的大规模 CI 算力,完整的一体化平台或托管服务会更合适。
项目 | 最低配置 | 建议配置 |
|---|---|---|
CPU | 1 核 | 2 核 |
内存 | 1 GB | 2 GB 及以上 |
磁盘 | 20 GB | 按仓库规模规划 |
磁盘是需要重点估算的项。仓库体积由代码历史决定,纯文本代码的仓库通常不大,但包含二进制文件、依赖包或大量图片的仓库会快速膨胀。如果团队会提交构建产物或素材文件,建议预留更多空间,或从一开始就规范提交内容。
数据库方面,Gitea 默认支持 SQLite,个人使用和小团队完全够用。用户数和仓库数较多时建议改用 PostgreSQL 或 MySQL。本文按 PostgreSQL 部署,便于长期使用。
需要放通的端口:
端口 | 协议 | 用途 |
|---|---|---|
22 或自定义 | TCP | SSH 方式访问仓库 |
80 | TCP | HTTP,用于证书验证与跳转 |
443 | TCP | HTTPS 访问与 Git over HTTPS |
关于 SSH 端口有个需要提前决定的事:容器内的 Gitea 需要提供 SSH 服务,而宿主机的 22 端口已被系统 SSH 占用。两种解决方式:把 Gitea 的 SSH 映射到宿主机的另一个端口(例如 2222),或者把系统 SSH 改到其他端口让 Gitea 用 22。本文采用前者,改动更小。
mkdir -p ~/apps/gitea && cd ~/apps/gitea编写 compose.yaml:
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: gitea
POSTGRES_PASSWORD: 替换为强密码
POSTGRES_DB: gitea
volumes:
- pg-data:/var/lib/postgresql/data
restart: unless-stopped
gitea:
image: gitea/gitea:1.22.6
environment:
USER_UID: 1000
USER_GID: 1000
GITEA__database__DB_TYPE: postgres
GITEA__database__HOST: postgres:5432
GITEA__database__NAME: gitea
GITEA__database__USER: gitea
GITEA__database__PASSWD: 与上面保持一致
GITEA__server__DOMAIN: git.example.com
GITEA__server__ROOT_URL: https://git.example.com/
GITEA__server__SSH_DOMAIN: git.example.com
GITEA__server__SSH_PORT: "2222"
GITEA__service__DISABLE_REGISTRATION: "false"
GITEA__service__REQUIRE_SIGNIN_VIEW: "true"
TZ: Asia/Shanghai
volumes:
- gitea-data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "127.0.0.1:3000:3000"
- "2222:22"
depends_on:
- postgres
restart: unless-stopped
volumes:
pg-data:
gitea-data:几处配置的说明:
ROOT_URL 决定界面上显示的仓库克隆地址。配置错误会导致复制出来的地址无法使用,这是最常见的配置问题。
SSH_PORT: "2222" 让 Gitea 在生成 SSH 克隆地址时带上正确的端口号。这个值要与端口映射中宿主机侧的端口一致。
REQUIRE_SIGNIN_VIEW: "true" 要求登录后才能查看仓库内容。私有代码托管应当开启,否则未登录用户也能浏览公开仓库。
DISABLE_REGISTRATION 先设为 false 以便注册管理员账号,注册完成后必须改为 true,后面会讲。
HTTP 端口绑定到 127.0.0.1,必须经过反向代理访问。SSH 端口需要对外,因为 Git 客户端要直连。
启动服务:
docker compose up -d
docker compose ps
docker compose logs gitea --tail 50在域名服务商处添加 A 记录,解析生效后验证:
dig +short git.example.com配置反向代理,以 Caddy 为例:
git.example.com {
reverse_proxy 127.0.0.1:3000
request_body {
max_size 2GB
}
}request_body max_size 要足够大。Git 推送大仓库或包含大文件的提交时,请求体可能很大,默认限制会导致推送失败并返回 413,而 Git 客户端报的错误往往看不出真正原因。
服务器位于中国内地且使用域名对外提供服务时,需要先完成 ICP 备案。
访问域名完成安装向导。数据库信息通常已通过环境变量填好,确认无误即可。
注册管理员账号:第一个注册的账号自动成为管理员。用户名避免使用常见默认值,密码 12 位以上。
立即关闭开放注册:账号创建后,编辑 compose.yaml:
GITEA__service__DISABLE_REGISTRATION: "true"重启服务:
docker compose up -d这一步不能省。代码托管服务的域名容易被识别,保持开放注册意味着任何人都能在你的服务器上注册账号。需要给同事使用时,通过管理后台创建账号或发送邀请。
其他建议开启的设置:
Gitea 支持两种克隆方式,建议都配好。
HTTPS 方式
直接用账号密码或访问令牌:
git clone https://git.example.com/用户名/仓库名.git日常使用建议生成访问令牌代替密码。在个人设置中创建令牌,按需勾选权限范围,然后用令牌代替密码。令牌可以随时吊销,比直接用密码更安全。
SSH 方式
先在本地生成密钥(如已有可跳过):
ssh-keygen -t ed25519 -C "gitea"
cat ~/.ssh/id_ed25519.pub把公钥内容添加到 Gitea 的个人设置中。然后测试连接:
ssh -T -p 2222 git@git.example.com返回欢迎信息说明密钥配置成功。
克隆地址会带上端口号:
git clone ssh://git@git.example.com:2222/用户名/仓库名.git如果觉得每次带端口麻烦,可以在本地 ~/.ssh/config 中配置:
Host git.example.com
Port 2222
User git配置后可以用简短形式:
git clone git@git.example.com:用户名/仓库名.git完整验证清单
网页端可通过 HTTPS 访问:
curl -I https://git.example.com创建一个测试仓库,然后逐项验证:
HTTPS 方式可克隆和推送:
git clone https://git.example.com/用户名/test.git
cd test
echo "test" > README.md
git add . && git commit -m "test"
git pushSSH 方式可克隆和推送:用 SSH 地址重复上面的流程。
两种方式都要实测。只测其中一种,另一种在实际使用时才发现不通会很被动。
推送的内容在网页端可见:刷新仓库页面,确认文件和提交记录都显示正常。
大文件推送通过:提交一个较大的文件测试。小文件完全不会暴露请求体大小限制的问题。
个人使用可以跳过这一节。团队协作时权限设计很重要。
组织用于管理团队共享的仓库。创建组织后,仓库归属于组织而非个人,成员变动不影响仓库归属。这一点很关键——仓库建在个人名下,该成员离职时会很麻烦。
团队在组织内划分权限组。可以按项目或职能创建团队,分别授予不同仓库的不同权限级别。
权限级别的实际含义:
级别 | 可执行的操作 |
|---|---|
读取 | 克隆、查看代码和问题 |
写入 | 推送代码、管理问题 |
管理员 | 修改仓库设置、管理协作者 |
分支保护建议对主分支开启。可以要求合并请求必须经过审查、必须通过检查才能合并、禁止强制推送。这能防止误操作直接覆盖主分支历史。
克隆地址不对或无法访问
检查 ROOT_URL 和 SSH_DOMAIN、SSH_PORT 配置。修改后重启容器生效。
SSH 连接被拒绝
按顺序检查:2222 端口是否在控制台放通;公钥是否正确添加到账号;连接时是否指定了端口。注意添加公钥时不要把私钥内容贴上去,这是常见失误。
推送大文件失败
检查反向代理的请求体大小限制。Git 仓库中确实需要存放大文件时,建议使用 Git 的大文件扩展,而不是直接提交,否则仓库体积会随历史不断膨胀。
页面样式错乱或链接指向 http
ROOT_URL 未使用 https 前缀。修正后重启。
数据库连接失败
容器化部署时数据库主机应填容器服务名。确认密码与配置一致,数据库容器处于运行状态。
磁盘空间增长快
docker compose exec gitea du -sh /data/git/repositories
df -h仓库和上传的附件是主要占用。可以在管理后台查看各仓库体积,对异常膨胀的仓库做垃圾回收。如果确实是正常增长,云硬盘支持在控制台扩容。
忘记管理员密码
可以通过容器内的命令行工具重置:
docker compose exec -u git gitea gitea admin user change-password \
--username 用户名 --password 新密码备份要覆盖三部分
内容 | 说明 |
|---|---|
数据库 | 用户、仓库元数据、问题、合并请求 |
仓库文件 | 实际的 Git 数据 |
配置与附件 | 应用配置、头像、上传的附件 |
Gitea 提供了打包备份命令:
docker compose exec -u git gitea gitea dump -c /data/gitea/conf/app.ini生成的压缩包包含上述内容。把它移到宿主机并同步到对象存储:
docker compose cp gitea:/tmp/gitea-dump-xxx.zip ~/数据库也可以单独备份:
docker compose exec -T postgres \
pg_dump -U gitea gitea | gzip > ~/gitea-db-$(date +%Y%m%d).sql.gzGit 的分布式特性是一层天然保护
这里有个值得说明的点:每个开发者克隆的仓库都包含完整的提交历史。即使服务端完全损坏,任何一份克隆都能作为恢复来源。这是 Git 相比集中式版本控制的重要优势。
但要注意,问题、合并请求、评论、CI 配置这些元数据只存在服务端,克隆里没有。所以数据库备份仍然必要。
恢复演练
用备份在另一个环境还原,确认仓库可克隆、问题记录完整。备份能生成不代表能恢复。
变更前创建快照:升级版本前给实例创建快照。回滚会把整块系统盘恢复到快照时间点,之后写入的数据会被清除,运行中的实例会自动关机。使用存储型套餐的实例不支持创建快照。
日常检查
安全与合规要点
部署完成后,如果需要建立从代码提交到自动构建发布的流水线,或为多个自建服务配置统一的域名入口,可以作为下一步方向。
代码托管这类轻量但重要的服务,轻量应用服务器配合快照能快速恢复环境;仓库规模增长后需要更大磁盘时可使用云硬盘扩容,备份归档建议使用对象存储 COS。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。