用 GitHub/GitLab CI/CD 部署 Hexo 到宝塔服务器

📝 前言

相比直接部署到服务器,使用 GitHub/GitLab CI/CD 的方案更现代化、更安全:源码托管在云端,服务器只接收构建产物,支持团队协作、版本控制、自动化测试等。

[!TIP]
适合人群:希望源码云端托管、自动化构建部署、支持团队协作的 Hexo 用户。


🔧 一、准备与目标

1. 前置条件

  • 已有一台可外网访问的服务器(推荐 Ubuntu 22.04/24.04 或 CentOS 7/8 Stream)
  • 已有域名,并能在域名服务商处设置解析
  • GitHub 或 GitLab 账号
  • 本地已安装 Node.js、Git、Hexo 开发环境(若未搭好,可参考《Hexo博客搭建教程》

2. 部署目标与架构

  1. 源码托管:Hexo 源码推送到 GitHub/GitLab 仓库

  2. 自动构建:GitHub Actions 或 GitLab CI 自动构建 Hexo 静态文件

  3. 自动部署:构建完成后自动推送到宝塔服务器站点目录

  4. Web 服务:Nginx 提供 Web 访问,开启 HTTPS 并强制跳转

[!NOTE]
我们采用”源码云端托管 → CI/CD 自动构建 → 自动部署到服务器”的方案。更安全、更稳定、支持团队协作。


💡 二、安装宝塔与 Nginx

1. 安装宝塔面板

前往官网获取安装脚本:宝塔面板下载,免费全能的服务器运维软件

在服务器上以 root 执行对应系统脚本。安装完成后,按提示登录面板。

2. 在宝塔安装 Nginx 与创建站点

  1. 打开”软件商店”仅安装 Nginx(暂不装 PHP/MySQL)

  2. “网站”→”添加站点”,填入你的域名,如 xmdblog.com(会自动创建站点目录 /www/wwwroot/xmdblog.com

  3. 稍后 CI/CD 会将构建产物部署到此目录


🔐 三、创建部署用户与配置 SSH(服务器)

以下以 Ubuntu 为例,CentOS 在命令后附等价命令。

# Ubuntu/Debian
sudo adduser deploy

# CentOS/RHEL(等价创建)
# sudo adduser deploy

deploy 用户配置 SSH:

sudo -u deploy mkdir -p /home/deploy/.ssh
sudo -u deploy touch /home/deploy/.ssh/authorized_keys
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys

[!TIP]
我们使用 deploy 用户而不是 git,更符合 CI/CD 部署的语义。

授予站点目录权限:

sudo chown -R deploy:deploy /www/wwwroot/xmdblog.com

[!NOTE]
若宝塔在站点目录生成 .user.ini 导致权限操作受限,可先暂时删除此文件;或在”网站 → 设置 → 伪静态/配置文件”里关闭相关限制后,或删除这个文件再设置权限。


🔑 四、生成 SSH 密钥并配置到 CI/CD

1. 生成部署密钥

在本地生成专门用于 CI/CD 部署的密钥:

[!NOTE]

这一步在你的电脑上使用Git Bash运行,不是服务器。

ssh-keygen -t ed25519 -C "ci-deploy@xmdblog" -f ~/.ssh/ci_deploy_key
# 一路回车。会生成 ci_deploy_key(私钥)和 ci_deploy_key.pub(公钥)

2. 配置服务器公钥

将公钥内容添加到服务器:

打开你电脑的C:\Users\您的用户名\.ssh目录,用记事本打开ci_deploy_key.pub复制里面的全部内容。

登录你服务器的宝塔面板,打开”文件”找到/home/deploy/.ssh目录,双击authorized_keys这个文件名,将复制的内容粘贴进去,注意点击对话框左上角的保存!

3. 测试连接

ssh -i ~/.ssh/ci_deploy_key deploy@你的服务器IP
exit

若能登录/退出,说明密钥配置正常。


🧩 五、配置 Nginx 与 HTTPS(宝塔)

  1. 在宝塔”网站 → 你的域名 → SSL”,申请/安装 Let’s Encrypt,建议勾选”强制 HTTPS”
  2. Nginx 站点根目录保持为 /www/wwwroot/xmdblog.com

🚀 六、配置 GitHub Actions 自动部署

1. 推送源码到 GitHub

首先将你的 Hexo 源码推送到 GitHub 仓库(提前在GitHub创建好仓库,在你本地的博客目录运行以下命令):

[!WARNING]

一定要创建私人库!一定要创建私人库!一定要创建私人库!不要公开!

# 在 Hexo 根目录
git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/你的用户名/你的仓库名.git
git push -u origin main

[!NOTE]

如果你使用了第三方主题且运行过hexo generate,运行git add .时报错,那么请根据情况使用Git Bash运行以下代码:

# 在仓库根目录执行
git rm --cached .deploy_git
git rm --cached themes/anzhiyu
rm -rf .deploy_git
rm -rf .gitmodules
git commit -m "chore: remove invalid submodule config"
git push #重新上传

2. 配置 GitHub Secrets

在 GitHub 仓库页面,进入 SettingsSecrets and variablesActionsManage environment secretsNew environmentName*输入secretsConfigure environmentAdd environment secret添加以下 secrets:

  • SERVER_HOST: 你的服务器 IP 或域名
  • SERVER_USER: deploy
  • SSH_PRIVATE_KEY: 私钥内容(ci_deploy_key 文件的完整内容)

3. 创建 GitHub Actions 工作流

在 Hexo 根目录创建 .github/workflows/deploy.yml

name: Deploy Hexo to Server

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build-and-deploy:
runs-on: ubuntu-latest
environment: secrets

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Install Hexo
run: npm install hexo-cli -g

- name: Build Hexo
run: |
hexo clean
hexo generate

- name: Deploy to Server
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
# 清空站点目录
rm -rf /www/wwwroot/xmdblog.com/*

- name: Upload files
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "public/*"
target: "/www/wwwroot/xmdblog.com/"
strip_components: 1

4. 推送并触发部署

git add .github/workflows/deploy.yml
git commit -m "Add GitHub Actions workflow"
git push

此时访问 GitHub 仓库的 Actions 页面,应该能看到构建和部署过程。


🦊 七、配置 GitLab CI/CD(替代方案)

如果你更喜欢 GitLab,可以创建 .gitlab-ci.yml

stages:
- build
- deploy

variables:
NODE_VERSION: "18"

build:
stage: build
image: node:18-alpine
cache:
paths:
- node_modules/
before_script:
- npm ci
script:
- hexo clean
- hexo generate
artifacts:
paths:
- public/
expire_in: 1 hour

deploy:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan -H $SERVER_HOST >> ~/.ssh/known_hosts
script:
- rsync -avz --delete public/ $SERVER_USER@$SERVER_HOST:/www/wwwroot/xmdblog.com/
only:
- main
dependencies:
- build

在 GitLab 项目设置中添加以下变量:

  • SERVER_HOST: 服务器地址
  • SERVER_USER: deploy
  • SSH_PRIVATE_KEY: 私钥内容

🧱 八、安全与权限最佳实践

  • 仅用于部署的 deploy 用户,禁止密码登录(仅允许密钥)
  • 站点目录属主设为 deploy:deploy,避免权限错乱
  • 定期备份站点目录:/www/wwwroot/xmdblog.com
  • 建议将服务器 22 端口改为高位端口并在防火墙中放行;或使用宝塔安全组放行所需端口
  • GitHub Secrets 中的私钥要妥善保管,不要泄露

🛠️ 九、常见问题排查(精选)

1) GitHub Actions 构建失败

  • 检查 package.json 中是否有正确的依赖
  • 确认 Node.js 版本是否匹配(推荐 18.x)
  • 查看 Actions 日志中的具体错误信息

2) 部署失败:SSH 连接问题

  • 确认 GitHub Secrets 中的 SSH_PRIVATE_KEY 格式正确(包含完整的私钥内容)
  • 检查服务器 SSH 服务是否正常运行:systemctl status ssh
  • 确认防火墙是否放行了 SSH 端口

3) 文件上传失败:权限问题

  • 检查站点目录权限:ls -al /www/wwwroot/xmdblog.com
  • 确认 deploy 用户对目录有写权限:sudo chown -R deploy:deploy /www/wwwroot/xmdblog.com

4) 域名能访问但样式 404

  • 检查 Nginx 站点根是否正确
  • 确认静态资源是否已正确上传到站点目录
  • 检查主题配置是否有绝对路径问题

5) 想回滚到上一个版本

在 GitHub 仓库中:

  1. 进入 Actions 页面
  2. 找到想要回滚的提交
  3. 点击 “Re-run jobs” 重新部署

或手动回滚:

# 在服务器上
cd /www/wwwroot/xmdblog.com
git log --oneline # 查看提交历史
git checkout <commit-hash> # 回滚到指定提交

📌 十、进阶优化

1. 多环境部署

可以配置不同的分支部署到不同环境:

# .github/workflows/deploy.yml
on:
push:
branches: [ main, develop ]

jobs:
build-and-deploy:
if: github.ref == 'refs/heads/main'
# 生产环境部署逻辑

2. 自动备份

在 GitHub Actions 中添加备份步骤:

- name: Backup current site
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
tar -czf /tmp/backup-$(date +%Y%m%d-%H%M%S).tar.gz /www/wwwroot/xmdblog.com

3. 通知集成

部署完成后发送通知:

- name: Notify deployment
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
channel: '#deployments'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}

📚 总结

通过本教程,你获得了一套现代化的 Hexo 部署方案:

  • 源码云端托管:GitHub/GitLab 管理源码,支持版本控制和团队协作
  • 自动化构建:CI/CD 自动构建 Hexo 静态文件,无需本地环境
  • 安全部署:专用部署用户 + SSH 密钥,最小权限原则
  • 宝塔管理:Nginx/HTTPS 配置,简单易用的服务器管理
  • 可回滚:Git 历史记录支持快速回滚到任意版本

相比传统方案的优势

  1. 更安全:服务器只接收构建产物,不暴露源码
  2. 更稳定:云端构建环境一致,避免本地环境差异
  3. 更高效:支持并行构建,构建缓存加速
  4. 更灵活:支持多环境部署、自动备份、通知集成

💬 讨论

欢迎在评论区分享:

  1. 你使用哪种 CI/CD 平台?GitHub Actions 还是 GitLab CI?
  2. 在部署过程中遇到过哪些问题?如何解决的?
  3. 有没有其他自动化部署的最佳实践?