Git 远程自建服务器完整指南

在自有 Linux 服务器上搭建 Git 远程仓库,用法与 GitHub SSH 一致:git push / git pull 同步代码,主机换成你的 VPS,仓库路径自行创建。

适用场景:私有仓库、内网部署、推送后自动发布静态站(如 Hexo)。


一、整体架构

flowchart LR
  subgraph local["本地"]
    A["工作区 .git"]
  end
  subgraph server["服务器"]
    B["git 用户 + SSH"]
    C["裸仓库 xxx.git"]
    D["post-receive"]
    E["网站目录"]
  end
  A -->|git push| B --> C --> D --> E
概念 说明
裸仓库 仅含 .git 数据,无工作区,专用于接收 push
git 用户 独立系统账号 + SSH 鉴权,避免用 root 推代码
远程地址 git@IP:/home/git/项目.git,与 GitHub SSH 格式相同

二、原理速览

传输协议

Git 远程 = 传输通道 + pack 交换git-upload-pack / git-receive-pack)。URL 前缀决定鉴权与传输方式,对象协商逻辑不变。

协议 示例 说明
SSH git@host:/path/repo.git 本文推荐,密钥认证
HTTPS https://host/repo.git 走 443,适合 Gitea/GitLab
本地/file /path/repo.git 同机脚本或备份
git:// git://host/path 无加密,公网不推荐

自建场景即 Smart over SSH:远端运行 receive-pack,双方协商差异后传输 packfile,而非拷贝整个目录。

push 做了什么

  1. 客户端声明要更新的 ref(如 refs/heads/master
  2. 计算远程缺失的对象,打成 pack 发送
  3. 对象落盘后原子更新 ref
  4. 触发服务器钩子(若配置)

git push 传的是 对象与引用,不是工作区文件夹;裸仓库无检出目录,不会自动更新网站——需 post-receive 钩子完成部署。

SSH push 流程

sequenceDiagram
  participant Dev as 本地 git
  participant SSH as SSH
  participant Recv as receive-pack
  participant Repo as 裸仓库
  participant Hook as post-receive
  Dev->>SSH: ssh git@host git-receive-pack 'repo.git'
  SSH->>Recv: 鉴权并启动
  Recv->>Dev: 协商 want/have
  Dev->>Recv: 上传 pack
  Recv->>Repo: 写入 objects,更新 refs
  Recv->>Hook: 调用钩子

鉴权在 SSH 层(authorized_keys);git-shell 可限制用户仅执行 Git 命令。

钩子与自动部署

钩子 时机 用途
pre-receive ref 更新前 拒绝不合规 push
post-receive 全部 ref 更新后 部署:checkout、构建
post-update 之后 通知、清缓存

post-receive 从 stdin 读取 旧SHA 新SHA 引用名。裸仓库检出需指定环境变量:

1
2
3
4
export GIT_DIR=/home/git/my-blog.git
export GIT_WORK_TREE=/www/wwwroot/example/my-blog
git checkout -f master
# 可继续:hexo generate、rsync 等

钩子以 git 用户运行,需 chmod +x 且去掉 .sample 后缀才生效。


三、服务器配置

以下在服务器执行(Ubuntu/Debian 示例)。

3.1 基础环境

1
2
3
4
sudo apt update && sudo apt install -y git
sudo adduser --system --group --shell /usr/bin/git-shell git
sudo mkdir -p /home/git/.ssh && sudo chmod 700 /home/git/.ssh
sudo chown -R git:git /home/git/.ssh

3.2 添加公钥

本地生成密钥:

1
ssh-keygen -t ed25519 -C "备注" -f ~/.ssh/id_ed25519_git

服务器追加公钥:

1
2
3
sudo bash -c 'echo "公钥内容" >> /home/git/.ssh/authorized_keys'
sudo chmod 600 /home/git/.ssh/authorized_keys
sudo chown git:git /home/git/.ssh/authorized_keys

本地验证:ssh -i ~/.ssh/id_ed25519_git git@服务器IP。若提示 Interactive git shell is not enabled,说明 SSH 已通。

3.3 创建裸仓库

1
2
3
4
sudo mkdir -p /home/git/my-blog.git
cd /home/git/my-blog.git
sudo git init --bare
sudo chown -R git:git /home/git

远程地址:git@服务器IP:/home/git/my-blog.git

3.4 自动部署(可选)

1
sudo nano /home/git/my-blog.git/hooks/post-receive
1
2
3
4
5
6
#!/bin/bash
set -e
export GIT_DIR=/home/git/my-blog.git
export GIT_WORK_TREE=/www/wwwroot/www.example.com/my-blog
git checkout -f master
echo "Deploy done"
1
2
3
4
sudo chmod +x /home/git/my-blog.git/hooks/post-receive
sudo chown git:git /home/git/my-blog.git/hooks/post-receive
sudo mkdir -p /www/wwwroot/www.example.com/my-blog
sudo chown -R git:git /www/wwwroot/www.example.com/my-blog

3.5 安全建议

  • sshd_configPasswordAuthentication noPermitRootLogin no
  • 防火墙仅开放 SSH:sudo ufw allow OpenSSH && sudo ufw enable

四、本地关联与推送

多密钥时指定私钥:

1
2
3
4
5
# Linux / macOS / Git Bash
git config core.sshCommand "ssh -i ~/.ssh/id_ed25519_git -o StrictHostKeyChecking=accept-new"

# Windows PowerShell
git config core.sshCommand "ssh -i C:/Users/用户名/.ssh/id_ed25519_git -o StrictHostKeyChecking=accept-new"

添加远程并推送:

1
2
3
git remote add origin git@服务器IP:/home/git/my-blog.git
git branch -M master # 主分支为 main 则改 main
git push -u origin master

日常:git pull / git push / git clone,与 GitHub 无异。

可与 GitHub 并存:

1
2
git remote add github git@github.com:用户/仓库.git
git push github master && git push origin master

五、扩展与排错

多项目:在 /home/git/ 下为每个项目建 xxx.git 裸仓库。

多人协作:将各人公钥追加到 authorized_keys;需细粒度权限可上 Gitolite / Gitea。

现象 处理
Permission denied (publickey) 检查公钥、core.sshCommand、私钥路径
not a git repository 确认路径存在且已 init --bare
push 成功但站点未更新 钩子权限、分支名、hexo generate 是否执行
钩子写文件失败 chown git:git 部署目录

查看服务器最近提交:

1
sudo -u git git --git-dir=/home/git/my-blog.git log -1

六、检查清单

服务器

  • git 用户与 authorized_keys 就绪
  • /home/git/项目.gitinit --bare
  • (可选)post-receive 可执行、部署目录可写

本地

  • ssh -i 私钥 git@IP 认证通过
  • git remote -v 指向正确地址
  • git push -u origin master 成功

备份裸仓库:直接打包 /home/git/*.git 目录即可。


参考


Git 远程自建服务器完整指南
http://www.iroot.tech/2026/05/29/git自建远程服务器/运维/
作者
Wizard
发布于
2026年5月29日
许可协议