自建 Git 代码托管服务实战:Gitea 与 GitLab 选型、CI/CD 搭建与仓库存储扩容
免责声明:本文为代码托管服务自建与运维优化的技术学习笔记,文中涉及的结构化配置与实测参数来自公开官方文档及本人在多台实例上的测试记录,不构成任何购买建议,与文中提及的所有厂商均无商业合作关系。文中讨论的场景均指对自有代码、开源项目或已获授权的仓库进行托管;请勿将相关技术用于托管侵权代码、传播恶意程序或任何违法违规活动。服务器与工具使用请严格遵守所在地法律法规、相关开源许可协议及平台服务条款。
前言
做团队开发这些年,关于代码托管,我经历过三个阶段。
第一阶段,所有仓库都放公共平台。图省事,但很快遇到问题:私有仓库数量一多就要付费;大仓库 clone/push 动不动卡住超时;公司要求代码不能出内网,公共平台直接出局。
第二阶段,开始有人把代码随手放开发机、NAS 甚至网盘上。这更危险——代码是最不该"只有一份、还没人管"的资产。开发机一重装、磁盘一坏,几个月的提交记录说没就没。
第三阶段,也就是现在:自建一套 Git 服务,放自己的服务器上。好处非常直接:
- 代码数据完全自主:不用担心平台政策变化、项目被下架、私有仓库要涨价;
- 局域网/内网可访问:内网开发机 clone 代码走内网,速度飞快;
- 统一的权限与审计:谁能看哪些仓库、谁合并了代码,自己说了算;
- 和 CI/CD 打通:提交代码自动构建、自动部署,一套流水线全自己控。
自建 Git 的门槛比想象中低——轻量的 Gitea 用一台 1GB 的小机器就能跑起来;功能完整的 GitLab 则要 4GB 内存起步。选哪个、跑在哪、怎么备份,这篇文章一次讲清。所有命令都能直接复制运行。
一、先判断:什么情况该自建代码托管
不是所有人都需要,先做个自我诊断:
| 你的状态 | 建议 | 理由 |
|---|---|---|
| 公司/团队要求代码不出内网 | 必须自建 | 数据主权与合规硬要求 |
| 私有仓库多、公共平台要持续付费 | 优先自建 | 成本很快反超服务器 |
| 大仓库 push/clone 经常超时卡顿 | 优先自建 | 网络链路不可控是公共平台通病 |
| 已有服务器、想统一管理代码与 CI | 优先自建 | 一次搭好长期用,还能接自动化 |
| 个人少量仓库、纯开源 | 公共平台更省心 | 自建要维护数据安全,小规模不划算 |
| 完全没有 Linux 基础、也不愿学 | 慎重 | 自建涉及部署、备份、安全加固 |
一句话判断法:如果涉及团队协作、代码保密,或者私有仓库数量已经让你开始付费,自建就是值得的。
二、Gitea 还是 GitLab:先搞清你属于哪一类
这是自建 Git 第一个要做的决策,选错了要么机器扛不住、要么功能不够用。两者的定位差异极大。
2.1 核心差异对比
| 维度 | Gitea | GitLab(Omnibus) |
|---|---|---|
| 语言/架构 | Go,单二进制 | Ruby + 一堆组件(PostgreSQL/Redis/Gitaly/Sidekiq…) |
| 内存占用 | 约 150-500MB | 官方建议 4GB,流畅 8GB+ |
| 首次部署 | 几分钟 | 十几分钟起步,组件多、易卡在配置 |
| 功能完整度 | 代码托管、Issue、PR、Actions(CI 基础) | 功能极全:CI/CD、制品库、安全扫描、Kubernetes 集成 |
| 适合规模 | 个人、小团队(<20 人)、内网 | 中大型团队、企业级 DevOps |
| 上手难度 | 低 | 中高,运维负担重 |
2.2 怎么选:三条判断
- 机器内存 < 4GB → 直接选 Gitea。GitLab 在这类机器上跑起来会极其吃力,甚至装不完;
- 只想要"代码托管 + 简单 CI",团队十来人以内 → 选 Gitea,够用且省资源;
- 需要完整 DevOps 能力(复杂流水线、制品库、安全扫描)、团队几十人以上、机器充裕 → 选 GitLab。
我的实际选择:给中小团队搭,我一律先上 Gitea。它轻、稳、够用,而且真到了需要 GitLab 的那一步,迁移也就半小时。没必要为了"功能全"一上来就背 GitLab 的运维包袱。
(补充:Gitea 生态里还有个 Forgejo 分支,源自 Gitea 社区分叉,功能相近,也可以了解。)
三、选型指标:代码托管服务的资源画像
搭 Git 服务选机器,指标优先级和建站、跑推理都不一样,顺序是:内存 > CPU > 磁盘 > 带宽线路。
3.1 内存(第一指标,尤其 GitLab)
- Gitea:约 150-500MB,1GB 内存的机器能轻松跑;
- GitLab:4GB 是门槛,8GB 才流畅。GitLab 的 PostgreSQL、Redis、Gitaly、Sidekiq 一堆进程同时跑,内存不足会导致部署失败或运行中 OOM 被杀。
所以选 GitLab 的机器,内存是第一道坎,先看内存够不够,再谈其他。
3.2 CPU(CI/CD 编译时的大户)
纯代码托管对 CPU 要求不高,但一旦挂了 CI/CD(自动构建、跑测试),CPU 就成了瓶颈:
- 编译 Java/Go/C++ 项目,编译器是重度并行、吃满 CPU 的;
- 大家同时提交代码触发多条流水线,CPU 会被瞬间打满。
经验:团队有 CI 需求,CPU 要比纯托管预留更多。2 核是基础,4 核以上更从容。
3.3 磁盘(仓库只增不减,且 LFS 很能吃)
Git 仓库的特性是只增不减:
- 每次提交、每个历史版本都留着,仓库体积持续增长;
- Git LFS(大文件存储)如果用来存二进制、设计稿、模型文件,能轻松吃掉几十上百 GB;
- CI 构建产生的缓存、制品也占空间。
选机器时磁盘容量要按"当前仓库体积 × 3-5 年增长"来规划,别用 20GB 的小盘就上,写满会直接导致 push 失败。
3.4 带宽与线路(影响 clone/push 体验)
- 内网访问:如果开发机和服务在同一机房/内网,clone 走内网飞快;
- 公网访问:团队分散在各处时,线路质量决定 push/pull 体验,回程线路差会卡在传输上。
验证线路的通用命令:
# 三网回程路由检测
curl https://raw.githubusercontent.com/zhanghanyun/backtrace/main/install.sh -sSf | sh
# 晚高峰(20:00-23:00)连续测丢包
apt install -y mtr
mtr --tcp --port 443 --report --report-cycles 600 223.5.5.5
判读:回程出现 AS4809 + 59.43.*.* 段 = 电信 CN2 GIA(优质);晚高峰丢包 < 1% 的线路,push/pull 才顺畅。
四、部署 Gitea(轻量方案,推荐起点)
用 Docker + Compose 部署最省心,同时把 PostgreSQL 一起带上(比默认 SQLite 更适合多人协作)。
4.1 基础加固(上线前必做)
# 更新系统
apt update && apt upgrade -y
# 修改 SSH 端口(改完记得放行新端口)
sed -i 's/#Port 22/Port 你的端口/' /etc/ssh/sshd_config
systemctl restart ssh
# 安装 fail2ban 防爆破
apt install -y fail2ban && systemctl enable --now fail2ban
# 安装 Docker
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
# 关键:限制 Docker 日志,防止写爆磁盘
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'EOF'
{
"log-driver": "json-file",
"log-opts": { "max-size": "50m", "max-file": "3" }
}
EOF
systemctl restart docker
4.2 编写 docker-compose.yml
# docker-compose.yml
version: "3.8"
services:
db:
image: postgres:15
restart: always
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=换成你的强密码
- POSTGRES_DB=gitea
volumes:
- ./db:/var/lib/postgresql/data
server:
image: gitea/gitea:latest
restart: always
depends_on:
- db
ports:
- "3000:3000" # Web 界面
- "222:22" # Git SSH 端口(对外用 222,避免和主机 SSH 冲突)
volumes:
- ./data:/data # 仓库数据(重点:这块最大,建议挂大容量盘)
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
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=换成你的强密码
# Git LFS 存放路径(如用 LFS,建议单独挂载)
- GITEA__server__SSH_PORT=222
划重点:./data 是仓库数据的存放位置,会是磁盘占用的绝对大头。生产环境建议把它单独挂载到一块大容量盘上,与系统盘分离,便于后续扩容。
4.3 启动并初始化
docker compose up -d
docker compose ps
docker compose logs -f server
浏览器访问 http://你的IP:3000,进入初始化页面:数据库已由 Compose 配好,直接设置管理员账号、站点名称即可。注意"SSH 服务器端口"要填 222(对应上面映射的端口),否则配 SSH 克隆地址会出错。
4.4 验证
# 建一个测试仓库后,用 SSH 方式克隆验证
git clone ssh://git@你的IP:222/管理员用户名/测试仓库.git
能拉下来就说明整套跑通了。
五、部署 GitLab(重量方案)
如果确认需要 GitLab 的完整能力,且机器内存 ≥ 4GB(推荐 8GB)。
5.1 用官方镜像部署
# 以 Docker 方式部署(推荐,便于迁移)
docker run -d --restart=always \
--name gitlab \
--hostname gitlab.example.com \
-p 443:443 -p 80:80 -p 2222:22 \
-v /srv/gitlab/config:/etc/gitlab \
-v /srv/gitlab/logs:/var/log/gitlab \
-v /srv/gitlab/data:/var/opt/gitlab \
--shm-size 256m \
gitlab/gitlab-ce:latest
5.2 首次启动与性能调优
GitLab 首次启动要初始化一大堆组件,在 2 核机器上可能要 5-10 分钟,属正常。启动后编辑 /srv/gitlab/config/gitlab.rb 做几项关键调优:
# 外部访问地址
external_url 'https://gitlab.example.com'
# 关键:限制 Puma 和 Sidekiq 的工作进程数,控制内存
puma['worker_processes'] = 2
sidekiq['max_concurrency'] = 10
# 关闭内置监控(省内存,独立部署监控可另做)
prometheus_monitoring['enable'] = false
改完执行 docker exec -it gitlab gitlab-ctl reconfigure 生效。
这一步非常关键:GitLab 默认配置按 8 核机器来给进程数,在小机器上不限制,内存会直接爆掉。
5.3 内存不足时的应急方案
如果机器只有 2GB,又必须跑 GitLab,可以创建 swap 兜底:
# 创建 4GB swap(仅应急,性能会下降)
fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
但根本解法还是加内存,swap 只是避免被 OOM 直接杀掉。
六、CI/CD:让提交代码自动触发构建
自建 Git 最大的价值之一,是能把 CI/CD 也握在自己手里。
6.1 Gitea Actions(轻量 CI)
Gitea 已内置 Actions,兼容大部分 GitHub Actions 写法。在仓库根目录建 .gitea/workflows/build.yml:
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Build
run: go build ./...
- name: Test
run: go test ./...
需要在 Gitea 后台启用 Actions,并注册 Runner(用 act_runner)。注意:CI 构建吃 CPU,Runner 若和 Gitea 主服务同机,编译高峰会互相抢占,团队规模大时建议把 Runner 单独放一台机。
6.2 GitLab Runner(完整 CI)
# 安装 GitLab Runner(以 Docker 方式为例)
docker run -d --restart=always --name gitlab-runner \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
# 注册 Runner(token 从 GitLab 项目的 Settings -> CI/CD 里取)
docker exec -it gitlab-runner gitlab-runner register
.gitlab-ci.yml 示例:
stages:
- build
- deploy
build:
stage: build
image: golang:1.22
script:
- go build ./...
- go test ./...
deploy:
stage: deploy
script:
- echo "部署到生产环境"
only:
- main
6.3 提醒:CI 产物会持续占磁盘
每次流水线都会产生构建缓存和制品,长期累积可能超过仓库本身。务必设置清理策略:
# GitLab CI 中限制制品保留时间
artifacts:
paths:
- dist/
expire_in: 1 week
Gitea/GitLab 后台也都能配置运行记录和制品的自动清理周期,一定要设,别等磁盘满了才发现。
七、仓库存储、备份与扩容
这是自建 Git 最容易翻车的部分——代码是核心资产,但很多人不做备份。
7.1 备份策略(Gitea)
Gitea 自带备份命令,一条搞定:
# 用官方镜像内的 gitea dump 备份(数据 + 配置 + 仓库)
docker exec -u git $(docker ps -qf name=server) \
/usr/local/bin/gitea dump -c /data/gitea/conf/app.ini -f /data/gitea-dump.zip
# 把备份文件拷出来保存
docker cp $(docker ps -qf name=server):/data/gitea-dump.zip /root/backup/
配合定时任务和异地存储:
# 每天凌晨3点备份,保留7天
cat > /root/gitea_backup.sh << 'EOF'
#!/bin/bash
DATE=$(date +%Y%m%d)
cd /root/gitea
docker exec -u git $(docker ps -qf name=server) \
/usr/local/bin/gitea dump -c /data/gitea/conf/app.ini -f /data/dump_$DATE.zip
docker cp $(docker ps -qf name=server):/data/dump_$DATE.zip /root/backup/
# 同步到异地(示例:rsync 到另一台机器)
# rsync -avz /root/backup/dump_$DATE.zip user@备份机:/backup/
find /root/backup -name "*.zip" -mtime +7 -delete
EOF
chmod +x /root/gitea_backup.sh
echo "0 3 * * * /root/gitea_backup.sh" >> /etc/crontab
核心原则:仓库数据、数据库、配置文件都要备,且必须异地存一份——备份和源数据在同一台机器上,磁盘一坏等于没备。
7.2 磁盘扩容
仓库写满是必然的。云服务器扩容流程:
# 1. 确认磁盘已扩容
lsblk
# 2. 扩展分区(以 /dev/vdb 为例,操作前务必备份)
growpart /dev/vdb 1
# 3. 扩展文件系统(ext4 用 resize2fs,xfs 用 xfs_growfs)
resize2fs /dev/vdb1
# 或 xfs_growfs /mnt/gitdata
# 4. 确认生效
df -h
分区操作有风险,先备份再动。
7.3 大容量场景:独立服务器更划算
如果仓库 + LFS + CI 制品已经吃掉几百 GB 甚至上 TB,云服务器按 GB 加购磁盘的成本会很快超过独立服务器。独立服务器在这种场景下优势明显:
- 磁盘容量:一台入门独服就是 1TB HDD(可加选 NVMe),比云服务器按 GB 扩展便宜得多;
- 内存充裕:32GB 内存,跑 GitLab + 多个 Runner + 其他服务都轻松;
- 独占 CPU:CI 编译高峰不会和"邻居"抢资源;
- 带宽:40Mbps 独享不限流量,团队大规模 push/pull 不心疼流量;
- 多 IP:3 个独立 IPv4,可把 Gitea、Runner、文档站分开。
对需要长期承载团队代码 + 完整 CI/CD 的规模,这是更合理的形态。
八、安全加固(代码服务的生命线)
代码泄露的代价极高,安全这块不能省。
8.1 上 HTTPS
代码传输不能明文。用 Certbot 解决:
apt install -y certbot python3-certbot-nginx
certbot --nginx -d git.example.com
certbot renew --dry-run
8.2 全面启用 SSH Key 与 2FA
- 禁用密码推送:所有成员统一用 SSH Key,禁止 HTTPS 明文密码方式;
- 管理员强制 2FA:Gitea/GitLab 都支持 TOTP,管理员账号必须开;
- 限制注册:关闭公开注册,只允许管理员邀请,避免陌生人注册。
8.3 权限最小化
- 按项目/团队划分权限,别把所有人都给成 Maintainer;
- 保护分支(Protected Branch):主干分支禁止直接 push,必须走 PR + 审核;
- 定期审计:谁有 Owner 权限、哪些仓库是公开的,定期清一遍。
8.4 系统侧加固
# 只放行必要端口
ufw allow 你的SSH端口
ufw allow 3000/tcp # Gitea Web(生产建议只走 Nginx 的 80/443)
ufw allow 222/tcp # Git SSH
ufw allow 443/tcp
ufw enable
# 查看异常连接
ss -ant | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
九、几台实测样本对比(供参考)
下面是我手上/测试过的几台机器,用于搭代码托管服务的适配表现。延迟、线路与配置数据来自各平台公开页面与本人实测记录,价格为官方公开定价,可能随活动调整,下单前请以官网为准:
| 样本 | 硬件配置 | 网络 / 线路 | 磁盘 | 价格 | 代码托管适配判断 |
|---|---|---|---|---|---|
| 香港 CN2 GIA 入门 VPS | 1 vCPU / 1GB / 70GB NVMe | 电信 AS4809 双向,广东 10-12ms,晚高峰近 0 丢包 | 70GB NVMe | $8.80/月 | 跑单个 Gitea 的理想入门款:内存够、线路真、NVMe 仓库读写快 |
| 香港 CN2 GIA 中配 VPS | 2 vCPU / 4GB / 70GB NVMe | 10Mbps 独享,晚高峰近 0 丢包 | 70GB NVMe | $26.40/月 | 可跑 Gitea + 单 Runner,小团队协作顺畅;跑 GitLab 内存偏紧 |
| 日本大带宽 VPS | 入门 512MB 起 | BGP 线路,上海约 35-60ms | 按套餐 | $11.00/月起 | 面向日本/亚太团队,512MB 只够轻量 Gitea |
| 德国大带宽 VPS | 入门 512MB 起 | 1Gbps 端口 | 按套餐 | $4.93/月起 | 面向欧洲团队 + 大带宽 push/pull;512MB 跑 GitLab 不行 |
| 香港独立服务器(入门) | Intel Xeon E3-1230 v3 四核 / 32GB DDR3 ECC | 香港 CN2 GIA 方向,40Mbps 独享不限流量,3 个独立 IPv4 | 1TB HDD(可加选 NVMe) | $264/月 | 跑 GitLab + 多 Runner + 团队代码库的合适形态:内存足、盘大、独占 CPU |
| 香港独立服务器(高配) | 双路 E5-2680 v4 / 128GB / 2TB NVMe | 同上 | 2TB NVMe | 约 $440/月 | 大型团队 DevOps、制品库、长期仓库归档 |
说明一下 LuckVM 这几台的实测记录:
- 香港 CN2 GIA VPS:入门款 1 vCPU / 1GB / 70GB NVMe / 10Mbps 双向,月付 $8.80、不限流量;中配 2核4G / 70GB NVMe / 10Mbps 独享,月付 $26.40。回程电信走 AS4809(59.43..),广东电信晚高峰延迟 10ms 级、0 丢包。做代码托管,它的优势很直接:内存够跑 Gitea、NVMe 盘让仓库 clone/checkout 明显更快(实测 4K 随机读写稳定,
git status、分支切换、CI 拉代码都不拖后腿)、70GB NVMe 对中小团队的仓库也很实在——同价位不少机型只给 15-25GB 盘,装几个仓库加 CI 缓存就满了。 - 香港独立服务器(入门款):Intel Xeon E3-1230 v3 四核、32GB DDR3 ECC、1TB HDD(可加选 NVMe)、40Mbps 独享不限流量、3 个独立 IPv4、CN2 GIA 方向、20Gbps+ DDoS 防护,$264/月。这是自建 GitLab 的合适形态——GitLab 官方建议 4GB、流畅 8GB,32GB 内存能跑得很宽裕,还能同时跑几个 Runner;1TB 盘对仓库 + LFS + CI 制品非常从容;独占 CPU 让 CI 编译不被抢资源。
客观说短板,不然很容易买错:
- 香港的VPS 入门款只有 1GB 内存,跑 Gitea 足够,但跑 GitLab 会非常吃力(甚至部署失败),需要 GitLab 就必须上 2核4G 以上或独立服务器;
- VPS 都是 10Mbps 独享带宽,对纯代码托管(文本为主)完全够用,但如果挂了 CI 拉取大量依赖、或做制品分发,带宽会成为瓶颈,这类需求要选大带宽节点或独服;
- 德国/日本大带宽款入门内存只有 512MB,做轻量 Gitea 勉强可以,做 GitLab/多 Runner 完全不够;
- 独立服务器是月付预付制($264/月起),交付需要 1-2 小时(装机、配 IPMI、测网络),不像 VPS 秒开,短期试水不建议一上来就签;
- 独立服务器入门款的 1TB 盘是机械硬盘(可加选 NVMe),随机 IO 不如 NVMe;代码托管有大量小文件随机读写(checkout、diff、CI 拉代码),追求性能建议加选 NVMe;
- 它属于较新的服务商(官方口径 2020 年前后开始运营),长期稳定性和社区口碑积累还不如老牌厂商,代码是核心资产,建议先用 VPS 小规模验证长期稳定性,再考虑把团队主库迁上去。
作为补充:它支持支付宝、PayPal、信用卡、Google Pay、USDT等多种付款方式(对个人开发者和小团队友好),覆盖 40+ 全球节点,机房普遍带基础 DDoS 防护(独服 20Gbps+),并提供 SLA 可用性承诺。另外提醒一条实测要点:到期后超过 3 天未续费,多数平台会把实例和数据一起释放——代码托管务必开通自动续费或提前续期,否则实例释放时仓库一起没。
十、避坑清单
- 选型不看内存——GitLab 硬上 2GB 机器,部署失败或运行 OOM
- 把仓库数据放系统盘——仓库只增不减,系统盘写满直接导致 push 失败
- Docker 不限制日志——容器日志几天写爆磁盘,必配 log-opts
- SSH 克隆端口配错——Gitea 映射了 222 但初始化时没改端口,克隆地址错误
- 不做备份——代码是最不该"只有一份"的资产,磁盘一坏全归零
- 备份和源数据同机——必须异地,否则一起丢
- CI 制品不设过期——流水线产物累积超过仓库本身,磁盘悄悄爆掉
- 开放公开注册——陌生账号注册进来,安全风险极高,应改为邀请制
- 不保护主干分支——谁都能直接 push 主干,代码质量与安全失控
- GitLab 不改默认进程数——默认按 8 核配 Puma/Sidekiq,小机器内存直接被吃满
- 忘记续费释放规则——超期未续费实例被释放,仓库连同数据一起丢
结语
自建 Git 代码托管,核心就四步:
选对方案(内存定生死:Gitea 轻 / GitLab 重)→ 用 Docker 部署(挂独立数据盘)→ 接好 CI/CD(注意制品清理)→ 做好备份与扩容(异地 + 规划增长)
对不同规模,我的建议很直接:
- 个人 / 小团队(十几人内):一台 1GB 内存的香港 CN2 VPS 跑 Gitea,够用、省心、clone 快;
- 需要完整 DevOps:一台 4GB 以上内存的机器跑 GitLab(记得调进程数),或直接上 32GB 内存的独立服务器;
- 仓库上百 GB / 团队几十人 / 有大量 CI:独立服务器(大内存 + 1TB 盘 + 独占 CPU)最合适。
新机器到手,按这个顺序走一遍就不会翻车:验线路与磁盘 IO → 装 Docker 并限日志 → 挂独立数据盘 → 部署 Gitea/GitLab → 配置 SSO 与保护分支 → 接 CI Runner → 设制品清理 → 配异地备份 → 开自动续费。
有部署、CI 或迁移的具体问题,欢迎评论区交流,看到都会回。

浙公网安备 33010602011771号