自建 Git 仓库:裸仓库与 Gitea 两条路
GitHub 已经很好用了,但私有仓库、不想依赖第三方、或者就是想折腾的时候,一台小服务器就能搞定。
一、先问要不要自建
| 情况 | 建议 |
|---|---|
| 只是要私有仓库 | GitHub/GitLab 免费私有仓库够用 |
| 不信任第三方、数据要自控 | 自建 |
| 要 CI/CD 全套 | 自建 Gitea + Actions,或直接托管 |
| 只是自己两台机器同步 | 裸仓库就够,别装 Gitea |
我的判断:个人用裸仓库,小团队用 Gitea。别一上来就装全套。
二、方案 A:裸仓库(零依赖)
不需要装任何软件,有 SSH 就行。
服务端
sudo apt install -y git
# 建一个 git 用户(可选,隔离用)
sudo adduser --disabled-password git
sudo su - git
mkdir -p ~/.ssh && chmod 700 ~/.ssh
# 建仓库(注意 --bare)
mkdir -p ~/repos/baize-site.git
cd ~/repos/baize-site.git
git init --bare裸仓库没有工作区,只有 .git 里的内容,专供推送。
客户端
# 已有仓库就加个 remote
git remote add origin git@example.com:repos/baize-site.git
git push -u origin main
# 或者克隆
git clone git@example.com:repos/baize-site.git自动部署(post-receive 钩子)
这是裸仓库最有价值的用法:push 上去自动更新网站目录。
# ~/repos/baize-site.git/hooks/post-receive
#!/usr/bin/env bash
set -e
TARGET="/var/www/baize"
GIT_DIR="/home/git/repos/baize-site.git"
BRANCH="main"
while read -r oldrev newrev ref; do
if [[ "$ref" = "refs/heads/$BRANCH" ]]; then
echo "==> 部署 $BRANCH 到 $TARGET"
git --work-tree="$TARGET" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
# 部署后要做的事
cd "$TARGET" && npm run build 2>/dev/null || true
sudo systemctl reload nginx
echo "==> 完成"
fi
donechmod +x hooks/post-receive
# 目标目录要能让 git 用户写
sudo chown -R git:www-data /var/www/baize
sudo chmod -R g+w /var/www/baize三、方案 B:Gitea(有界面)
Gitea 是轻量的自托管 Git 服务,Go 写的,资源占用很低(几十 MB 内存)。
# 1. 建用户和目录
sudo adduser --disabled-password --home /var/lib/gitea git
# 2. 下载二进制(一行命令,无需编译)
sudo mkdir -p /usr/local/bin
sudo wget -O /usr/local/bin/gitea https://dl.gitea.com/gitea/1.22.0/gitea-1.22.0-linux-amd64
sudo chmod +x /usr/local/bin/gitea
# 3. 目录权限
sudo mkdir -p /var/lib/gitea/{custom,data,log}
sudo chown -R git:git /var/lib/gitea
sudo chmod -R 750 /var/lib/giteasystemd 服务:
# /etc/systemd/system/gitea.service
[Unit]
Description=Gitea
After=network.target
[Service]
Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/gitea
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
Environment=USER=git HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea
[Install]
WantedBy=multi-user.targetsudo systemctl enable --now gitea
curl -I http://127.0.0.1:3000四、Nginx 反代
server {
listen 443 ssl http2;
server_name git.bzii.cn;
ssl_certificate /etc/letsencrypt/live/git.bzii.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.bzii.cn/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;
# Git 大推送需要长超时
proxy_read_timeout 720s;
proxy_send_timeout 720s;
}
}首次访问 Web 界面完成安装向导,数据库选 SQLite(小团队足够)。
关键配置项 /etc/gitea/app.ini:
[server]
DOMAIN = git.bzii.cn
ROOT_URL = https://git.bzii.cn/
SSH_DOMAIN = git.bzii.cn
SSH_PORT = 2222
DISABLE_SSH = false
[service]
DISABLE_REGISTRATION = true # 关闭公开注册
REQUIRE_SIGNIN_VIEW = true # 必须登录才能看
[security]
INSTALL_LOCK = true
[repository]
DEFAULT_BRANCH = main五、备份
Gitea 自带 dump 命令,一条搞定:
sudo -u git /usr/local/bin/gitea dump -c /etc/gitea/app.ini -w /var/lib/gitea -f /backup/gitea-$(date +%F).zip加到定时任务:
0 4 * * * sudo -u git /usr/local/bin/gitea dump -c /etc/gitea/app.ini -w /var/lib/gitea -f /backup/gitea-$(date +\%F).zip
# 清理 30 天前的
0 5 * * * find /backup -name "gitea-*.zip" -mtime +30 -delete裸仓库的备份更简单,直接打包:
tar czf repos-$(date +%F).tar.gz /home/git/repos六、迁移
从别处搬到自建:
# 镜像克隆(包含所有分支、标签)
git clone --mirror https://github.com/you/repo.git
cd repo.git
git push --mirror git@example.com:repos/repo.git反向(自建 → 别处)同理。
七、SSH 端口冲突
服务器 22 端口已被系统 SSH 占用,Gitea 用 2222:
git remote add origin ssh://git@git.bzii.cn:2222/you/repo.git嫌难看可以在 ~/.ssh/config 里配:
Host gitea
HostName git.bzii.cn
Port 2222
User git
IdentityFile ~/.ssh/id_ed25519git clone gitea:you/repo.git八、安全
- 关闭公开注册(除非你想要公开服务)
- 只用 SSH 密钥或强密码
- 定期更新 Gitea(
wget换新版二进制即可) - 仓库目录权限正确
- 有备份并验证过能恢复
- 后台管理页面不要暴露到公网(或加 IP 白名单)
# 升级 Gitea:停服务 → 换二进制 → 启服务
sudo systemctl stop gitea
sudo wget -O /usr/local/bin/gitea.new <新版URL>
sudo mv /usr/local/bin/gitea.new /usr/local/bin/gitea
sudo chmod +x /usr/local/bin/gitea
sudo systemctl start gitea九、成本对比
| 方案 | 成本 | 运维 | 适用 |
|---|---|---|---|
| 裸仓库 | 0 | 极低 | 个人、自动化部署 |
| Gitea | 一台小服务器 | 低(定期备份 + 升级) | 小团队 |
| GitLab CE | 4GB 内存起步 | 中 | 需要完整 DevOps |
| 托管平台 | 0 | 0 | 绝大多数情况 |
如果只是想在自己服务器上放代码,一个裸仓库 + post-receive 钩子就够了,两分钟配完,还能顺带实现自动部署。
