作为一名长期在代码仓库管理一线工作的开发者,我深刻体会到国内访问GitHub的不稳定性。2018年微软收购GitHub后,虽然服务稳定性有所提升,但跨国网络延迟和偶尔的访问中断仍然困扰着国内开发者。搭建私有镜像站成为许多技术团队的刚需。
镜像站的核心价值主要体现在三个方面:
以我们团队为例,在部署镜像站后:
根据镜像仓库的预期规模,推荐以下配置方案:
| 仓库数量 | CPU核心 | 内存 | 存储 | 带宽 | 适用场景 |
|---|---|---|---|---|---|
| <100 | 4核 | 8GB | 500GB | 10Mbps | 个人/小团队 |
| 100-500 | 8核 | 16GB | 2TB | 30Mbps | 中型企业 |
| >500 | 16核+ | 32GB+ | 5TB+ | 100Mbps | 大型组织 |
实测数据:同步100个平均大小50MB的仓库,8核CPU/16GB内存服务器完成全量同步约需2小时
推荐选择国内BGP网络服务器,并配置:
bash复制git.example.com A记录 → 服务器IP
*.git.example.com CNAME → git.example.com
bash复制sudo apt install certbot
sudo certbot certonly --nginx -d git.example.com
创建专用系统账户保障安全:
bash复制sudo adduser --system --shell /bin/bash --group gitmirror
sudo mkdir -p /mnt/gitmirror/repos
sudo chown -R gitmirror:gitmirror /mnt/gitmirror
使用git clone --mirror实现完整仓库克隆:
bash复制#!/bin/bash
REPO_URL="https://github.com/owner/repo.git"
MIRROR_DIR="/mnt/gitmirror/repos/owner/repo.git"
if [ -d "$MIRROR_DIR" ]; then
cd "$MIRROR_DIR" || exit
git fetch --prune
else
git clone --mirror "$REPO_URL" "$MIRROR_DIR"
fi
关键参数说明:
--mirror:创建裸仓库并同步所有引用--prune:删除远程已不存在的分支引用对于使用Git LFS的仓库,需额外配置:
bash复制git lfs install --skip-smudge # 初始化LFS
git lfs fetch --all # 获取所有LFS对象
存储优化技巧:
bash复制# 设置LFS本地缓存路径
git config --global lfs.storage /mnt/gitmirror/lfs-objects
推荐使用Webhook+API的实时同步方案:
python复制from flask import Flask, request
import subprocess
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def sync():
repo_name = request.json['repository']['full_name']
subprocess.run([f"/scripts/sync_{repo_name.replace('/', '_')}.sh"])
return "OK"
使用cgit提供友好的浏览界面:
nginx复制# /etc/nginx/conf.d/cgit.conf
server {
listen 443 ssl;
server_name git.example.com;
location / {
root /usr/share/cgit;
try_files $uri @cgit;
}
location @cgit {
include fastcgi_params;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME /usr/libexec/cgit/cgit.cgi;
}
}
nginx复制proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=gitcache:10m inactive=7d;
location ~* \.(git|png|jpg)$ {
proxy_cache gitcache;
proxy_cache_valid 200 302 7d;
}
.git$后缀文件缓存7天bash复制#!/bin/bash
# check_repo_sync.sh
REPO_DIR="$1"
LAST_SYNC=$(git -C "$REPO_DIR" log -1 --format=%ct)
CURRENT_TIME=$(date +%s)
DELTA=$((CURRENT_TIME - LAST_SYNC))
if [ $DELTA -gt 86400 ]; then
echo "警报:仓库 $REPO_DIR 超过24小时未同步" | mail -s "镜像同步异常" admin@example.com
fi
定期清理策略:
bash复制# 查找大于100MB的.git目录
find /mnt/gitmirror -name "*.git" -type d -size +100M -exec du -sh {} \;
# 清理90天未访问的仓库
find /mnt/gitmirror -atime +90 -exec rm -rf {} \;
mermaid复制graph TD
A[GitHub] -->|主同步| B[主镜像节点]
B -->|rsync| C[从节点1]
B -->|rsync| D[从节点2]
C --> E[华东用户]
D --> F[华南用户]
典型架构组合:
流量控制:
bash复制# 限制单个IP并发连接数
iptables -A INPUT -p tcp --dport 443 -m connlimit --connlimit-above 20 -j REJECT
敏感内容过滤:
python复制# 使用git hooks检测敏感关键词
def pre_receive():
banned_words = ["secret_key", "password="]
for commit in sys.stdin:
if any(word in commit for word in banned_words):
sys.exit(1)
性能优化实测数据:
git config --global pack.packSizeLimit 512m在实际运维中,我们团队总结出三个关键经验:
git fsck --full