自建Git私有仓库与异地团队协作完整方案

内容分享4小时前发布
0 0 0

前言

公司用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里设置的

服务器和第三方服务设置:

域名:
git.yourcompany.com
(如果没域名就用IP)SSH端口:222HTTP端口:3000应用URL:
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:
http://jenkins.yourcompany.com/gitea-webhook/post
触发事件:Push

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)网络优化:星空组网企业版

© 版权声明

相关文章

暂无评论

none
暂无评论...