GitHub Actions 自动部署到服务器:从配置到上线的完整流程
把代码推到 GitHub 后自动同步到服务器,是很多个人项目和团队希望实现的基础能力。
GitHub Actions 服务器部署的核心思路是:在仓库里配置一个工作流文件,让 GitHub 托管的运行器通过 SSH 连上你的服务器,执行拉取代码、安装依赖、重启服务等命令。
下面按实际操作顺序说明。
需要提前准备好的东西
开始之前,确认以下条件已经满足,否则后面的步骤会卡住:
- 一台可以通过 SSH 登录的 Linux 服务器,记下公网 IP、登录用户名和端口(默认 22)。
- 服务器上已经安装好 Git、运行环境(如 Node.js、Python、PHP)和 Web 服务(如 Nginx)。
- 一个 GitHub 仓库,并且你对它有推送权限。
- 本地能执行
ssh命令,用来生成和测试密钥。
如果服务器还没配置过 Git 拉取权限,建议先在服务器上手动 git clone 一次,确认能正常拉取,再交给 Actions 自动化。
生成并配置 SSH 密钥
自动化部署需要让 GitHub 的运行器免密登录服务器。
不要直接用你个人的私钥,而是单独生成一对专用于部署的密钥。
在本地终端执行:
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/deploy_key
执行后会生成两个文件:deploy_key(私钥)和 deploy_key.pub(公钥)。
把公钥内容追加到服务器的授权文件里。
可以先查看公钥内容:
cat ~/.ssh/deploy_key.pub
然后在服务器上执行(把下面的公钥内容替换成实际值):
echo "ssh-ed25519 AAAA... github-actions-deploy" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
接着在本地测试能否用这把密钥登录:
ssh -i ~/.ssh/deploy_key 用户名@服务器IP
能正常进入服务器,说明密钥配置成功。
如果提示 Permission denied,先检查 authorized_keys 权限和用户名是否正确。
在仓库中配置 Secrets
私钥不能直接写在 Workflow 文件里,要放到 GitHub 仓库的加密变量中。
进入 GitHub 仓库页面,
依次点击 Settings → Secrets and variables → Actions → New repository secret,
添加以下变量:
SERVER_HOST:服务器公网 IP。SERVER_USER:登录用户名。SERVER_PORT:SSH 端口,默认填22。SSH_PRIVATE_KEY:刚才生成的deploy_key私钥完整内容,包括开头和结尾行。
添加完成后,Workflow 里通过 secrets.SERVER_HOST 这种方式引用,不会明文暴露。
编写部署 Workflow
在仓库根目录创建 .github/workflows/deploy.yml,一个可用的最小示例如下:
name: Deploy to Server
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: ${{ secrets.SERVER_PORT }}
script: |
cd /var/www/myapp
git pull origin main
npm install --production
pm2 restart myapp
这个流程做了三件事:检出代码、通过 SSH 连接服务器、在服务器上拉取最新代码并重启应用。script 部分要改成你服务器上的真实路径和启动命令。
保存后推送到 main 分支,进入仓库的 Actions 标签页,可以看到工作流开始运行。
点进去能查看每一步的日志。
容易踩坑的几个地方
路径写错:cd /var/www/myapp 必须是服务器上真实存在的目录,并且该目录已经初始化为 Git 仓库、配置了远程地址。
权限不足:如果服务器上的项目目录属于 www-data 或其他用户,而登录用户没有写权限,git pull 会失败。
可以先用 ls -ld 目录 确认属主,再决定是否调整权限或使用 sudo(注意 sudo 在非交互环境下可能需要额外配置)。
密钥格式问题:粘贴到 SSH_PRIVATE_KEY 时,如果漏掉 -----BEGIN OPENSSH PRIVATE KEY----- 或结尾行,连接会直接失败。
建议用 cat 完整复制。
端口未放行:如果服务器防火墙或云厂商安全组没有放行 SSH 端口,GitHub 运行器无法连接。
先确认本地能连,再检查安全组规则。
首次连接提示确认指纹:appleboy/ssh-action 默认会处理,
但如果你用原生 ssh 命令,
可能需要在脚本里加 -o StrictHostKeyChecking=no,
不过更安全的做法是提前把服务器指纹加入 known_hosts。
怎么确认部署真的成功了
不要只看 Actions 显示绿色就认为完成。
可以按下面几步验证:
- 在服务器上进入项目目录,执行
git log -1,确认最新提交和 GitHub 上一致。 - 查看应用进程是否在运行,例如
pm2 status或systemctl status 服务名。 - 用浏览器或
curl访问站点,确认返回内容已更新。 - 回到 GitHub Actions 日志,确认没有隐藏的警告或非零退出码。
如果日志里某一步失败,先看该步骤的输出信息,再对照上面提到的路径、权限、密钥三类问题排查。
什么时候需要调整方案
上面的做法适合代码直接放在服务器上、通过 git pull 更新的场景。
如果项目需要构建产物、使用 Docker 镜像,或者服务器不允许直接访问 GitHub,可以改为在 Actions 里构建后通过 scp 上传文件,或者推送镜像到镜像仓库再由服务器拉取。
选择哪种方式,取决于你的部署频率、网络条件和回滚要求。
对于刚开始接触 GitHub Actions 服务器部署的读者,建议先用最小流程跑通一次,再逐步加入构建、测试和通知步骤。
每增加一个环节,都保留可验证的输出,这样出问题时能快速定位。