自建 Git 服务器:本地与生产环境部署
搭建自建 Git 时,常会遇到本地能推送、生产环境却无法拉取,或因目录不为空、私钥未绑定导致部署失败的问题。本文适合使用多台服务器部署项目的开发者,整理 Git 服务器创建仓库、本地初始化、生产环境免密拉取,以及新项目复用旧私钥的完整步骤。看完可快速完成项目代码的首次部署和后续更新。

适用:Git 服务器、开发电脑、生产服务器是不同机器;通过 SSH 私钥推送和拉取,不需要重复输入密码。
约定:
GIT_HOST=<Git服务器IP或域名>
PROJECT=<项目名>
REPO="git@${GIT_HOST}:/home/git/repos/${PROJECT}.git"
例如项目名为 demo-api,仓库地址就是:
git@<Git服务器IP>:/home/git/repos/demo-api.git
---
1. Git 服务器首次部署
以下命令在 Git 服务器 执行。
apt update
apt install -y git
id git >/dev/null 2>&1 || adduser --disabled-password --gecos "" git
install -d -o git -g git -m 755 /home/git/repos
install -d -o git -g git -m 700 /home/git/.ssh
touch /home/git/.ssh/authorized_keys
chown git:git /home/git/.ssh/authorized_keys
chmod 600 /home/git/.ssh/authorized_keys
---
2. 配置 SSH 私钥,免密码访问 Git
开发电脑与生产服务器各自生成一把私钥。私钥不要复制、不要发给别人。
2.1 本地开发电脑生成私钥
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_git -N "" -C "local-git"
cat ~/.ssh/id_ed25519_git.pub
复制输出的整行公钥。
2.2 生产服务器生成部署私钥
ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519_git_deploy -N "" -C "production-git"
cat /root/.ssh/id_ed25519_git_deploy.pub
复制输出的整行公钥。
2.3 将公钥加入 Git 服务器
在 Git 服务器 执行:
nano /home/git/.ssh/authorized_keys
把本地公钥、生产服务器公钥各粘贴一行后保存,再执行:
chown git:git /home/git/.ssh/authorized_keys
chmod 600 /home/git/.ssh/authorized_keys
---
3. Git 服务器创建新项目仓库
以下命令在 Git 服务器 执行:
PROJECT=<项目名>
sudo -u git git init --bare /home/git/repos/${PROJECT}.git
例如:
sudo -u git git init --bare /home/git/repos/demo-api.git
---
4. 本地项目初始化并首次推送
以下命令在 本地项目目录 执行:
cd <本地项目目录>
git init
git branch -M main
git config --local core.sshCommand "ssh -i ~/.ssh/id_ed25519_git -o IdentitiesOnly=yes"
git remote add origin git@<Git服务器IP>:/home/git/repos/<项目名>.git
git add -A
git commit -m "初始化项目"
git push -u origin main
以后本地提交:
git add -A
git commit -m "本次修改说明"
git push origin main
---
5. 生产环境首次拉取项目
以下命令在 生产服务器 执行。
目标目录必须为空。先进入目标目录,再执行最后带 . 的克隆命令:
APP_DIR=/home/www/web/<项目目录名>
mkdir -p "$APP_DIR"
cd "$APP_DIR"
GIT_SSH_COMMAND='ssh -i /root/.ssh/id_ed25519_git_deploy -o IdentitiesOnly=yes' \
git clone -b main git@<Git服务器IP>:/home/git/repos/<项目名>.git .
让当前项目以后永久使用这把私钥:
git config --local core.sshCommand "ssh -i /root/.ssh/id_ed25519_git_deploy -o IdentitiesOnly=yes"
git status
git remote -v
以后生产环境更新:
cd /home/www/web/<项目目录名>
git pull --ff-only origin main
生产服务器和 Git 服务器不是同一台时,不能使用/home/git/repos/xxx.git作为拉取地址;必须使用git@<Git服务器IP>:/home/git/repos/xxx.git。
---
6. 新项目复用以前项目的私钥配置
不需要重新生成私钥,只需创建新裸仓库,然后读取旧项目的 core.sshCommand。
6.1 Git 服务器创建新裸仓库
PROJECT=<新项目名>
sudo -u git git init --bare /home/git/repos/${PROJECT}.git
6.2 本地新项目复用旧项目配置
OLD_PROJECT=<旧项目本地目录>
NEW_PROJECT=<新项目本地目录>
SSH_COMMAND="$(git -C "$OLD_PROJECT" config --get core.sshCommand)"
cd "$NEW_PROJECT"
git init
git branch -M main
git config --local core.sshCommand "$SSH_COMMAND"
git remote add origin git@<Git服务器IP>:/home/git/repos/<新项目名>.git
git add -A
git commit -m "初始化项目"
git push -u origin main
查看旧项目具体使用的私钥:
git -C <旧项目本地目录> config --show-origin --get core.sshCommand
6.3 生产服务器新项目复用旧项目配置
SSH_COMMAND="$(git -C /home/www/web/<旧项目目录> config --get core.sshCommand)"
APP_DIR=/home/www/web/<新项目目录>
mkdir -p "$APP_DIR"
cd "$APP_DIR"
GIT_SSH_COMMAND="$SSH_COMMAND" \
git clone -b main git@<Git服务器IP>:/home/git/repos/<新项目名>.git .
git config --local core.sshCommand "$SSH_COMMAND"
git status
---
7. 两个常见问题
7.1 destination path '.' already exists and is not an empty directory
当前目录不是空的,先确认:
pwd
ls -la
不要在 /home/www/web 目录执行:
git clone ... .
7.2 Permission denied (publickey)
检查当前项目使用的私钥:
git config --get core.sshCommand
并确认对应的公钥已经加入 Git 服务器:
/home/git/.ssh/authorized_keys
8. 生产环境与 Git 服务器同一台:本地路径免密拉取
此场景不需要 SSH 私钥、不需要 authorized_keys、不需要 core.sshCommand。生产目录直接从本机裸仓库拉取代码。
8.1 已有裸仓库,首次部署项目
假设裸仓库已存在:
/home/git/repos/<项目名>.git
以下命令在同一台服务器执行:
mkdir -p /home/www/web/<项目目录名>
cd /home/www/web/<项目目录名>
# 当前目录必须为空;最后的 . 表示代码直接拉到当前目录
git clone -b main /home/git/repos/<项目名>.git .
git status
git remote -v
以后更新:
cd /home/www/web/<项目目录名>
git pull --ff-only origin main
8.2 新项目同机部署流程
# 1. 在 Git 服务器创建裸仓库
sudo -u git git init --bare /home/git/repos/<新项目名>.git
# 2. 本地开发电脑初始化、提交并推送代码(按第 4 节)
# 3. 同机生产目录首次拉取
mkdir -p /home/www/web/<新项目目录>
cd /home/www/web/<新项目目录>
git clone -b main /home/git/repos/<新项目名>.git .
8.3 同机项目权限建议
代码仓库由 root 管理,执行 git pull 也使用 root:
chown -R root:www-data /home/www/web/<项目目录名>
CI4 项目只有 writable/ 需要给 PHP 写入:
mkdir -p /home/www/web/<项目目录名>/writable
chown -R www-data:www-data /home/www/web/<项目目录名>/writable
chmod -R 775 /home/www/web/<项目目录名>/writable
若出现detected dubious ownership,通常是项目目录属于www-data,但当前用root执行 Git。先按上面的所有者规则修正,再执行git status或git pull。
完整内容为付费内容
购买后可查看完整排查步骤、关键配置和补充说明。