使用 GitHub Actions + rsync/SSH 实现 Hugo 自动部署
由于本博客之前还是手动部署,忍受一段时间后实在受不了了,还是开启了 CI/CD 日子~
目标
实现:
本地写文章 → git push 到 GitHub → GitHub Actions 自动构建 Hugo → rsync 部署到服务器推荐结构:
GitHub 仓库:保存 Hugo 源码
GitHub Actions:负责构建 public/
deploy 用户:负责 SSH 登录和部署
www / www-data 用户:负责运行网站服务,例如 Nginx一、服务器准备
以 Debian / Ubuntu 为例,本文默认你已经安装了 nginx。
1. 安装依赖
sudo apt update
sudo apt install -y rsyncHugo 可以在 GitHub Actions 里构建,所以服务器不需要安装 Hugo。
二、创建 deploy 用户
不要使用 root 部署,也不建议让 www 用户登录 SSH。
sudo useradd -m -s /bin/bash deploy如果已经有 deploy 用户,可以检查:
getent passwd deploy最后一列应该类似:
/bin/bash如果是:
/usr/sbin/nologin可以改成:
sudo usermod -s /bin/bash deploy三、网站目录权限配置
假设网站目录是:
/var/www/blog创建目录:
sudo mkdir -p /var/www/blog如果 Nginx 使用 www 用户:
sudo usermod -aG www deploy
sudo chown -R www:www /var/www/blog
sudo chmod -R 775 /var/www/blog
sudo find /var/www/blog -type d -exec chmod g+s {} \;deploy 用户:可以写入 /var/www/blog
www 用户:可以读取网站文件四、配置 SSH 密钥登录
1. 本地生成部署密钥
在本地电脑执行:
ssh-keygen -t ed25519 -C "github-actions-hugo" -f github-actions-hugo会生成:
github-actions-hugo
github-actions-hugo.pub其中:
github-actions-hugo 私钥,放到 GitHub Secrets
github-actions-hugo.pub 公钥,放到服务器 deploy 用户2. 把公钥注册到 deploy 用户
在服务器上执行:
sudo mkdir -p /home/deploy/.ssh
sudo cat github-actions-hugo.pub >> /home/deploy/.ssh/authorized_keys把 github-actions-hugo.pub 的内容粘进去。
然后修复权限:
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys3. 本地测试 SSH
ssh -i ./github-actions-hugo deploy@你的服务器IP如果可以登录,说明密钥配置成功。
如果报错类似:
Permission denied
未注册用户密钥通常是:
公钥没有放到 /home/deploy/.ssh/authorized_keys
authorized_keys 权限不对
.ssh 目录权限不对
文件归属不是 deploy:deploy
登录用户写错五、配置 GitHub Secrets
进入 GitHub 仓库:
Settings → Secrets and variables → Actions → New repository secret添加:
SERVER_HOST=你的服务器IP或域名
SERVER_USER=deploy
SERVER_SSH_KEY=私钥内容
SERVER_PATH=/var/www/blog六、添加 GitHub Actions 配置
在 Hugo 仓库中新建文件:
.github/workflows/deploy.yml内容如下:
name: Deploy Hugo Blog
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: latest
extended: true
- name: Build
run: hugo --minify --cleanDestinationDir
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SERVER_SSH_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H "${{ secrets.SERVER_HOST }}" >> ~/.ssh/known_hosts
- name: Test SSH connection
run: |
ssh -o ConnectTimeout=20 -i ~/.ssh/deploy_key \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} \
"echo connected"
- name: Deploy with rsync
run: |
rsync -rlvz --delete \
-e "ssh -i ~/.ssh/deploy_key" \
public/ \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ secrets.SERVER_PATH }}/ps: 如果是宝塔,记得在最后一栏
rsync -rlvz --delete内添加排查.user.ini,否则会提示运行失败。
- name: Deploy with rsync
run: |
rsync -rlvz --delete \
--exclude='.user.ini' \
.......如果服务器 SSH 非 22 端口
假设 SSH 端口是 2222,修改 rsync:
rsync -avz --delete \
-e "ssh -i ~/.ssh/deploy_key -p 2222" \
public/ \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ secrets.SERVER_PATH }}/七、可选:限制 deploy 用户只能 rsync 到指定目录
如果不想让 deploy 用户正常登录 shell,可以使用 rrsync 限制它只能访问 /var/www/blog。
安装:
sudo apt install -y rrsync查看路径:
which rrsync通常是:
/usr/bin/rrsync编辑 deploy 的 authorized_keys:
sudo nano /home/deploy/.ssh/authorized_keys把原来的公钥:
ssh-ed25519 AAAA... github-actions-hugo改成:
command="/usr/bin/rrsync /var/www/blog",no-agent-forwarding,no-port-forwarding,no-pty,no-X11-forwarding ssh-ed25519 AAAA... github-actions-hugo这样这个密钥只能用于 rsync 部署,不能打开交互式 SSH 终端。
八、发布文章流程
以后只需要:
git add .
git commit -m "new post"
git push origin mainGitHub Actions 会自动:
1. 拉取 Hugo 源码
2. 安装 Hugo
3. 构建 public/
4. 通过 SSH 连接服务器
5. 用 rsync 同步 public/ 到 /var/www/blog
6. 网站自动更新九、常见错误排查
1. SSH 超时
错误:
ssh: connect to host xxx port 22: Connection timed out
rsync error: unexplained error (code 255)原因通常是:
服务器防火墙没开放 22
云服务器安全组没开放 22
SSH 端口不是 22
SERVER_HOST 填错
服务器只允许特定 IP 登录检查服务器防火墙:
sudo ufw status
sudo ufw allow 22/tcp
sudo ufw reload云服务器还要检查控制台安全组,开放:
TCP 22
来源 0.0.0.0/02. 密钥未注册 / Permission denied
原因通常是 deploy 用户没有配置公钥。
修复:
sudo mkdir -p /home/deploy/.ssh
sudo nano /home/deploy/.ssh/authorized_keys
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys3. deploy 无法写入网站目录
检查权限:
ls -ld /var/www/blog如果 Nginx 用户是 www-data:
sudo usermod -aG www-data deploy
sudo chown -R www-data:www-data /var/www/blog
sudo chmod -R 775 /var/www/blog
sudo find /var/www/blog -type d -exec chmod g+s {} \;4. Hugo 主题没有被拉下来
如果主题使用 Git submodule,确保 workflow 里有:
with:
submodules: recursive5. Hugo 主题需要 extended 版本
很多主题需要 Hugo Extended,确保:
with:
extended: true