前言
公司用GitHub Enterprise太贵(每人21美元/月),GitLab.com免费版限制多(CI分钟数不够),最后决定自己搭一套Git私有仓库。
折腾了一周,现在团队10个人用得挺顺,北京和上海的同事协作也没问题。这篇文章记录下完整的搭建和优化过程。
一、为什么要自建Git仓库
很多人觉得GitHub/GitLab不好吗?其实各有痛点:
1.1 成本问题
GitHub Enterprise:
21美元/用户/月10人团队一年就是2520美元(约18000元)
GitLab SaaS:
免费版:CI每月400分钟(不够用)付费版:19美元/用户/月
自建成本:
云服务器:500元/月一年6000元,省下12000元
1.2 数据安全
代码在别人服务器上,总觉得不踏实。尤其是核心业务代码,万一泄露了呢?
1.3 网络问题
GitHub/GitLab在国外,有时候clone/push很慢。我之前遇到过clone一个2GB的仓库要半小时。
1.4 定制需求
比如我们想和钉钉打通(push代码自动通知),想自定义CI流程,用第三方服务都不太方便。
二、方案选型
自建Git仓库主要有三个选择:
2.1 GitLab CE(社区版)
优点:
功能全(代码托管、CI/CD、Wiki、Issue)界面友好,接近GitHub文档齐全,社区活跃
缺点:
资源占用大(最少4GB内存)启动慢(要1-2分钟)更新麻烦(升级要按版本来,不能跳跃)
2.2 Gitea
优点:
轻量(Go写的,内存占用200MB)启动快(秒级)配置简单(5分钟搞定)
缺点:
功能相对简单(CI/CD是外挂的)插件生态不如GitLab
2.3 Gogs
优点:
比Gitea更轻量单机部署很简单
缺点:
功能简陋(连CI都没有)开发不活跃(Gitea是Gogs的fork,更新更快)
我的选择:Gitea
选Gitea主要考虑:
够用:代码托管、权限管理、PR/Issue都有省资源:2核4GB的服务器跑得很舒服稳定:社区活跃,Bug修得快
CI/CD后面可以单独搭Jenkins或者用Gitea Actions(类似GitHub Actions)。
三、快速搭建Gitea
3.1 使用Docker部署(推荐)
最简单的方式是用Docker Compose:
# docker-compose.yml
version: "3"
services:
gitea:
image: gitea/gitea:1.21
container_name: gitea
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=gitea_password
restart: always
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000" # Web界面
- "222:22" # SSH端口
depends_on:
- db
db:
image: postgres:14
restart: always
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=gitea_password
- POSTGRES_DB=gitea
volumes:
- ./postgres:/var/lib/postgresql/data
启动:
# 创建目录
mkdir -p ~/gitea-deploy && cd ~/gitea-deploy
# 保存上面的配置到docker-compose.yml
# 启动
docker-compose up -d
# 查看日志
docker-compose logs -f gitea
访问 ,按照向导完成初始化。
http://服务器IP:3000
3.2 基础配置
初始化时需要填几个关键配置:
数据库设置:
数据库类型:PostgreSQL主机:db:5432数据库名:gitea用户名/密码:上面docker-compose里设置的
服务器和第三方服务设置:
域名:(如果没域名就用IP)SSH端口:222HTTP端口:3000应用URL:
git.yourcompany.com
http://git.yourcompany.com:3000
管理员账号:
用户名:admin密码:设置一个强密码邮箱:admin@yourcompany.com
点击”安装Gitea”,几秒钟就好了。
四、进阶配置
4.1 配置邮件通知
团队协作必须有邮件通知(PR、Issue、@提醒)。
编辑 (在宿主机的
gitea/gitea/conf/app.ini 下):
./gitea/gitea/conf/
[mailer]
ENABLED = true
FROM = noreply@yourcompany.com
PROTOCOL = smtp
SMTP_ADDR = smtp.exmail.qq.com # 用的腾讯企业邮箱
SMTP_PORT = 465
USER = noreply@yourcompany.com
PASSWD = your_smtp_password
重启Gitea:
docker-compose restart gitea
测试邮件:
登录管理员账号访问 在”邮件配置”部分点击”发送测试邮件”
/admin/config
4.2 配置HTTPS
用Nginx反向代理:
# /etc/nginx/sites-available/gitea
server {
listen 80;
server_name git.yourcompany.com;
# 强制跳转HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name git.yourcompany.com;
# SSL证书(用Let's Encrypt申请)
ssl_certificate /etc/letsencrypt/live/git.yourcompany.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.yourcompany.com/privkey.pem;
# 安全配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost: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;
# WebSocket支持(Gitea的实时通知)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 上传大文件支持
client_max_body_size 512M;
}
}
启用配置:
# 申请SSL证书
certbot certonly --nginx -d git.yourcompany.com
# 启用Nginx配置
ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
修改Gitea配置 :
app.ini
[server]
DOMAIN = git.yourcompany.com
ROOT_URL = https://git.yourcompany.com/
重启Gitea,现在访问 就行了。
https://git.yourcompany.com
4.3 配置SSH访问
开发常用SSH clone/push(比HTTPS快)。
暴露SSH端口:
# 服务器防火墙开放222端口
ufw allow 222/tcp
# 测试
ssh -T git@git.yourcompany.com -p 222
添加SSH密钥:
生成密钥(如果没有):
ssh-keygen -t ed25519 -C "your_email@example.com"
查看公钥:
cat ~/.ssh/id_ed25519.pub
在Gitea界面添加:
右上角头像 → Settings → SSH/GPG Keys → Add Key粘贴公钥内容
测试:
ssh -T git@git.yourcompany.com -p 222
# 输出:Hi there, You've successfully authenticated...
4.4 配置LFS(大文件支持)
如果仓库有大文件(设计稿、视频、模型文件),需要开启Git LFS。
编辑 :
app.ini
[server]
LFS_START_SERVER = true
LFS_CONTENT_PATH = /data/gitea/lfs
LFS_JWT_SECRET = <生成一个随机字符串>
重启Gitea,客户端使用:
# 安装LFS
git lfs install
# 追踪大文件
git lfs track "*.psd"
git lfs track "*.mp4"
# 提交
git add .gitattributes
git add design.psd
git commit -m "Add design file"
git push
五、异地团队协作优化
我们团队分布在北京和上海,服务器在北京。上海同事clone/push很慢,怎么办?
5.1 问题分析
测试北京到上海的网速:
# 上海同事clone一个500MB的仓库
time git clone git@git.yourcompany.com:project/backend.git
# 结果:
real 8m32s # 太慢了!
问题原因:
跨地域网络延迟高(40-50ms)丢包率高(1-2%)Git是顺序传输,延迟影响大
5.2 解决方案1:浅克隆
适合场景: 开发时不需要完整历史。
# 只clone最近1次提交
git clone --depth 1 git@git.yourcompany.com:project/backend.git
# 结果:
real 1m15s # 快了7倍!
如果后面需要完整历史:
git fetch --unshallow
5.3 解决方案2:多地仓库镜像
架构:
北京:主仓库 (git.yourcompany.com)
上海:镜像仓库 (git-sh.yourcompany.com)
搭建上海镜像:
在上海服务器部署Gitea(同样的方法)
配置仓库镜像(在北京的主仓库):
进入仓库设置点击”镜像设置”添加推送镜像:输入认证信息
https://git-sh.yourcompany.com/project/backend.git
测试:北京推送代码后,上海镜像会在30秒内同步。
上海同事使用:
# clone时用上海镜像
git clone git@git-sh.yourcompany.com:project/backend.git
# 但push要push到北京主仓库(权限控制)
git remote set-url --push origin git@git.yourcompany.com:project/backend.git
# 这样clone/pull用上海镜像(快),push到北京主仓库(保证数据一致)
效果:
clone时间从8分钟降到1分钟pull代码也快很多
5.4 解决方案3:SD-WAN优化
后来发现一个更简单的方案:用SD-WAN给服务器之间建个专线。
我们用的是星空组网(企业版有7天试用)。
配置步骤:
北京服务器装客户端:
curl -O https://download.xk-group.com/xkmesh-client-linux.sh
bash xkmesh-client-linux.sh
登录Web管理界面,添加两台服务器到同一个组网
测试延迟:
# 从上海服务器ping北京
ping <北京服务器内网IP>
# 优化前:50ms
# 优化后:35ms(选了更优路径)
上海同事clone:
time git clone git@git.yourcompany.com:project/backend.git
# 结果:
real 3m20s # 比之前快了2.5倍
虽然没有镜像方案快,但优点是不需要额外维护镜像,数据一致性也有保证。
而且SD-WAN还能优化其他服务(Jenkins、文档站、内部系统),一举多得。
成本:
企业版:300元/月(10个节点)如果只用Git,可以用免费版(3个节点)
六、权限管理
6.1 组织和团队
Gitea的权限模型:
组织(Organization)
└── 团队(Team)
├── 仓库权限:读/写/管理
└── 成员
创建组织:
右上角 “+” → 新建组织组织名:yourcompany
创建团队:
进入组织页面 → Teams → New Team创建几个团队:
Backend Team:后端仓库的写权限Frontend Team:前端仓库的写权限DevOps Team:所有仓库的管理权限Guest:只读权限(外包、实习生)
分配权限:
进入仓库设置 → Collaborators添加团队并设置权限:
Backend Team:WriteFrontend Team:ReadDevOps Team:Admin
6.2 保护分支
场景: main分支不能直接push,必须通过PR。
配置:
仓库设置 → Branches → Add RuleBranch Name Pattern:勾选:
main
✅ Require pull request reviews before merging✅ Require status checks to pass before merging✅ Include administrators(管理员也遵守规则)
效果:
# 直接push到main会失败
git push origin main
# error: refusing to update checked out branch: refs/heads/main
# 必须创建PR
git checkout -b feature/new-api
git push origin feature/new-api
# 然后在Web界面创建PR
6.3 Webhooks集成
场景: push代码后自动通知钉钉。
仓库设置 → Webhooks → Add Webhook → Dingtalk填入钉钉机器人URL(在钉钉群设置里创建)选择触发事件:Push、Pull Request、Issue
测试:
git commit -m "Test webhook"
git push
钉钉群会收到通知:
[backend] Someone pushed to main
Commit: Test webhook
Author: zhangsan
七、备份和容灾
代码是公司核心资产,必须做好备份。
7.1 数据库备份
自动备份脚本:
#!/bin/bash
# backup-gitea.sh
BACKUP_DIR="/data/backups/gitea"
DATE=$(date +%Y%m%d_%H%M%S)
# 备份PostgreSQL
docker exec gitea-db pg_dump -U gitea gitea | gzip > $BACKUP_DIR/db_$DATE.sql.gz
# 备份Git仓库数据
tar -czf $BACKUP_DIR/repos_$DATE.tar.gz /root/gitea-deploy/gitea/git/repositories/
# 删除7天前的备份
find $BACKUP_DIR -mtime +7 -delete
echo "Backup completed: $DATE"
定时任务:
# 每天凌晨2点备份
crontab -e
0 2 * * * /root/backup-gitea.sh >> /var/log/gitea-backup.log 2>&1
7.2 异地备份
场景: 北京服务器挂了,数据全丢。
方案: 把备份同步到上海服务器。
#!/bin/bash
# backup-sync.sh
BACKUP_DIR="/data/backups/gitea"
REMOTE_HOST="git-sh.yourcompany.com"
REMOTE_DIR="/data/backups/gitea-bj"
# 同步到上海服务器
rsync -avz --delete $BACKUP_DIR/ $REMOTE_HOST:$REMOTE_DIR/
echo "Backup synced to remote"
定时任务:
# 每天凌晨3点同步
30 2 * * * /root/backup-sync.sh >> /var/log/gitea-backup.log 2>&1
7.3 容灾演练
模拟北京服务器挂掉:
停止北京Gitea:
docker-compose down
在上海服务器恢复:
# 解压备份
cd /data/backups/gitea-bj
gunzip -c db_20250101_020000.sql.gz | docker exec -i gitea-db psql -U gitea gitea
tar -xzf repos_20250101_020000.tar.gz -C /root/gitea-deploy/gitea/
# 启动Gitea
docker-compose up -d
修改DNS:把 指向上海服务器
git.yourcompany.com
恢复时间目标(RTO): 15分钟
八、性能优化
8.1 Git仓库瘦身
问题: 某个前端仓库有2GB,clone太慢。
原因: 历史提交里包含了node_modules(被删掉了,但历史还在)。
清理:
# 安装BFG(比git-filter-branch快)
brew install bfg # macOS
# apt-get install bfg # Ubuntu
# 备份仓库
git clone --mirror git@git.yourcompany.com:project/frontend.git
# 删除历史中的node_modules
bfg --delete-folders node_modules frontend.git
# 清理和推送
cd frontend.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push
# 效果:2GB -> 200MB
让同事重新clone:
# 旧的clone需要重置
cd frontend
git fetch origin
git reset --hard origin/main
8.2 启用Git协议缓存
Gitea支持Git协议缓存,提升clone/pull速度。
编辑 :
app.ini
[git]
GC_ARGS = --aggressive --auto
MAX_GIT_DIFF_LINES = 1000
MAX_GIT_DIFF_LINE_CHARACTERS = 5000
MAX_GIT_DIFF_FILES = 100
[cache]
ENABLED = true
ADAPTER = memory
INTERVAL = 60
HOST =
重启Gitea。
效果:
第一次访问仓库:生成缓存(稍慢)后续访问:直接读缓存(快很多)
8.3 使用SSD存储
如果Git仓库多,机械硬盘会成为瓶颈。
迁移到SSD:
# 停止Gitea
docker-compose down
# 挂载SSD到/mnt/ssd
# 迁移数据
rsync -av /root/gitea-deploy/gitea/ /mnt/ssd/gitea/
# 修改docker-compose.yml
# 把 ./gitea 改为 /mnt/ssd/gitea
# 启动
docker-compose up -d
效果:
clone速度提升30%Web界面打开仓库快50%
九、CI/CD集成
Gitea本身不带CI(GitLab CE有内置),但可以外挂。
9.1 Gitea Actions(推荐)
类似GitHub Actions,配置简单。
启用Actions:
编辑 :
app.ini
[actions]
ENABLED = true
重启Gitea。
创建Runner:
# 下载Runner
wget https://dl.gitea.com/act_runner/0.2.6/act_runner-0.2.6-linux-amd64
# 注册Runner
./act_runner-0.2.6-linux-amd64 register
--instance https://git.yourcompany.com
--token <从Gitea管理界面获取>
# 启动Runner
./act_runner-0.2.6-linux-amd64 daemon
编写工作流:
:
.gitea/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
- name: Build
run: npm run build
push代码后,自动触发CI。
9.2 Jenkins集成
如果已经有Jenkins,可以用Webhook触发。
Jenkins配置:
安装插件:Gitea Plugin创建任务:New Item → Pipeline配置:
Build Triggers → Build when a change is pushed to GiteaPipeline → Pipeline script from SCMSCM → Git → 仓库URL
Gitea配置:
仓库设置 → Webhooks → Add Webhook → GiteaURL:触发事件:Push
http://jenkins.yourcompany.com/gitea-webhook/post
push代码后,自动触发Jenkins构建。
十、实际案例
我们用Gitea半年,团队从5人扩到10人。
数据:
仓库:25个总代码量:15GB日均push:50次日均PR:8个
稳定性:
在线率:99.5%(只有一次因为磁盘满了挂了2小时)响应时间:< 200ms
成本:
服务器:500元/月(阿里云2核4GB)异地优化(星空组网):300元/月总计:800元/月
如果用GitHub Enterprise:21美元 × 10人 × 7(汇率)= 1470元/月
节省:670元/月,一年省8000元
而且自建的好处是:
代码完全掌控可以定制(和公司内部系统打通)网络访问快
十一、总结
自建Git仓库没那么难,关键是:
技术选型
小团队(< 20人):Gitea够用大团队或需要完整DevOps:GitLab CE追求极简:Gogs
网络优化
单地域:不需要特别优化多地域:镜像仓库或SD-WAN
安全
必须HTTPS必须SSH密钥认证(禁用密码)必须定期备份
成本
服务器:500-1000元/月如果有异地团队,再加300-500元/月(网络优化)总计:< 1500元/月
比用GitHub/GitLab省很多,而且更可控。
最后
代码托管是基础设施,稳定性比功能重要。不要盲目追求新特性,能满足团队需求就行。
如果有异地协作需求,可以试试星空组网这类SD-WAN工具,比自己搭镜像简单。
我的配置文件都放GitHub了(不是自建的Gitea,哈哈),有问题可以留言。
环境信息:
Gitea版本:1.21.3PostgreSQL版本:14服务器:阿里云ECS(2核4GB,Ubuntu 22.04)网络优化:星空组网企业版
