「推送即部署」是很多个人站长和中小团队最想要的部署体验:本地 git push,线上自动更新,不需要登录服务器敲命令。Git 生态里实现这件事有三条常用路线——GitHub Actions、Git Hooks 和 Webhook——下面逐个拆解,最后给出选择建议。
方案一:GitHub Actions 自动部署
把「推送即部署」做成标准动作,最省事的方式是用 GitHub Actions。每次 push 到 main,自动在云端跑构建和 rsync 到服务器。整体工作流长这样:
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy via rsync
uses: easingthemes/ssh-deploy@main
with:
SSH_PRIVATE_KEY: \${{ secrets.SSH_PRIVATE_KEY }}
SOURCE: "dist/"
REMOTE_HOST: \${{ secrets.DEPLOY_HOST }}
REMOTE_USER: \${{ secrets.DEPLOY_USER }}
TARGET: /var/www/example.com/
GitHub Secrets 配置
上面用到的变量都来自仓库的 Secrets,不在代码里出现。在 GitHub 仓库 Settings → Secrets and variables → Actions 中添加:
| Secret 名称 | 说明 |
|---|---|
| SSH_PRIVATE_KEY | 服务器的 SSH 私钥 |
| DEPLOY_HOST | 服务器 IP 或域名 |
| DEPLOY_USER | SSH 登录用户名 |
思路是「构建和产物上传都交给云端,服务器只做接收」。私钥建议用专门的部署用户生成,别拿 root 的密钥到处用。
把三个 Secrets 配好之后,还需要在服务器上准备好两样东西:SSH 私钥对应的公钥要写进部署用户的 authorized_keys,服务器的 /var/www/example.com 目录要归部署用户所有。第一次跑之前,可以在本地先用 ssh -i ~/.ssh/deploy_key deploy@<host> 手动连一次,确认免密登录没问题,再让 Actions 去跑。
方案二:Git Hooks 自动部署
不想引入 CI 平台,也可以在服务器上配一个裸仓库,本地 push 时通过 post-receive hook 自动拉取并部署。先看服务器端的 hook 脚本:
#!/bin/bash
# /var/repo/site.git/hooks/post-receive
TARGET=/var/www/example.com
GIT_DIR=/var/repo/site.git
while read oldrev newrev ref
do
if [[ $ref =~ main$ ]]; then
echo "Deploying to production..."
git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f
cd $TARGET
npm ci --production
npm run build
sudo systemctl reload nginx
echo "Deployment complete!"
fi
done
git --work-tree=... --git-dir=... checkout -f 会把最新代码直接检出到目标目录,这是 Git Hooks 方案的骨干。
服务器端配置步骤
# 1. 在服务器上创建裸仓库
sudo mkdir -p /var/repo/site.git
cd /var/repo/site.git
sudo git init --bare
# 2. 创建 post-receive hook
sudo nano hooks/post-receive
# (粘贴上面的脚本内容)
sudo chmod +x hooks/post-receive
# 3. 设置目标目录权限
sudo mkdir -p /var/www/example.com
sudo chown -R $USER:$USER /var/www/example.com
本地配置
# 添加服务器为 remote
git remote add production ssh://user@your-server/var/repo/site.git
# 推送部署
git push production main
之后每次 git push production main,服务器就会自动执行部署脚本,全程不需要 SSH 上去敲命令。
本地配置这块有两点容易踩坑:一是服务器的目录必须是裸仓库(git init --bare),普通仓库收不到 push;二是 hook 文件必须有执行权限,否则 push 成功了脚本也不会跑。可以先用 git push production main 推一次,再在服务器上 ls -l hooks/post-receive 确认权限和内容都正确。
方案三:Webhook 触发部署
如果服务器没有开通 GitHub Actions,或想用别的平台(如 Gitee、GitLab)触发,可以在服务器上跑一个轻量 Webhook 监听:
#!/bin/bash
# deploy-webhook.sh - 在服务器上运行的 Webhook 监听脚本
API_PORT=9000
SECRET="your-webhook-secret"
while true; do
request=$(nc -l -p $API_PORT)
# 验证签名并拉取最新代码
cd /var/www/example.com
git pull origin main
npm ci --production
npm run build
sudo systemctl reload nginx
done
注意:真实环境里务必验证 Webhook 请求的签名(平台会带签名头),否则任何人都能触发你的部署脚本。生产环境更推荐用方案一或方案二,这类自写监听更适合内网或个人项目。如果确实需要自己写 Webhook,建议用现成的工具(如开源的 webhook 项目或 CI 平台自带的 Webhook 支持),把签名校验、并发保护这些脏活交给成熟实现,自己只写部署那一步。
三种方案怎么选
| 方案 | 适合场景 | 优点 | 缺点 |
|---|---|---|---|
| GitHub Actions | 代码托管在 GitHub | 云端构建、日志可查、生态成熟 | 需要公网可达或有 runner |
| Git Hooks | 自建 Git 服务器 | 简单直接、无额外依赖 | 脚本在服务器上维护,出问题难排查 |
| Webhook | 多平台触发、自定义流程 | 灵活、可对接任意平台 | 安全要自己把关,稳定性要自己保障 |
选择时先问自己三个问题:代码托管在哪里、服务器能不能公网访问、团队愿不愿意维护额外组件。大多数托管在 GitHub 的中小项目,方案一就是性价比最高的起点。
安全建议
- 使用专门的部署用户,最小权限原则——不要用 root 跑部署。
- SSH 密钥添加密码短语(passphrase),并限制用途。
- 部署后清理 .env 等敏感文件,确保不被公开。
- 保留上一版本作为回滚备份,出问题秒级回退。
- 添加部署通知(Slack/邮件),部署失败第一时间知道。
- 定期轮换部署密钥和密码,离职成员的权限及时回收。
- 用 .gitignore 把 .env、密钥文件等排除在仓库之外,防止误提交。
常见问题
- 推送后没有触发部署? 检查 hook 是否可执行、分支名是否匹配(main),以及服务器上是不是裸仓库。
- 部署脚本没有权限写目标目录? 确认运行部署的用户对 /var/www/example.com 有写权限,用 chown 或把用户加进对应组。
- 怎么回滚? 在目标目录保留上一版本(比如软链切换),或者给仓库打 tag,出问题 checkout 到上一个 tag 再跑一次部署。
- 部署很快但页面没变化? 检查部署目标目录和 Web 服务器根目录是否一致,以及是否配置了 CDN/缓存。
- push 超时? 大仓库用
git push --mirror拆分,或把产物构建挪到 CI 上,只传输成品。
参考:GitHub Actions 官方文档 https://docs.github.com/actions ;Git Hooks 文档 https://git-scm.com/docs/githooks