用GitHubGitLab CICD部署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. “网站”→”添加站点”,填入你的域名,如 xwdblog.top(会自动创建站点目录 /www/wwwroot/xwdblog.top
  3. 稍后 CI/CD 会将构建产物部署到此目录

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

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

1
2
3
4
5
# Ubuntu/Debian
sudo adduser deploy

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

deploy用户配置SSH:

1
2
3
4
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部署的语义。

授予站点目录权限:

1
sudo chown -R deploy:deploy /www/wwwroot/xwdblog.top

[!NOTE]

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


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

1. 生成部署密钥

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

[!NOTE]

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

1
2
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. 测试连接

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

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


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

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

🚀 六、配置 GitHub Actions 自动部署

1. 推送源码到 GitHub

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

[!WARNING]

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

1
2
3
4
5
6
7
# 在 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运行以下代码:

1
2
3
4
5
6
7
# 在仓库根目录执行
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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/xwdblog.top/*

- 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/xwdblog.top/"
strip_components: 1

4. 推送并触发部署

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

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


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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/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/xwdblog.top/
only:
- main
dependencies:
- build/
only:
- main
dependencies:
- build

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

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

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

  • 仅用于部署的deploy用户,禁止密码登录(仅允许密钥)
  • 站带目录属主设为deploy:deploy,避免权限错乱
  • 定期备份站点目录:/www/wwwroot/xwdblog.top
  • 建议将服务器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/xwdblog.top
    • 确认deploy用户对目录有些权限:sudo chown -R deploy:deploy /www/wwwroot/xWdblog.top
  4. 域名能访问但样式404

    • 检查Nginx站点根是否正确
    • 确认静态资源是否已正确上传到站点目录
    • 检查主题配置是否有绝对路径问题
  5. 想回滚到上一个版本

    在GitHub仓库中:

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

或手动回滚:

1
2
3
4
# 在服务器上
cd /www/wwwroot/xwdblog.top
git log --oneline # 查看提交历史
git checkout <commit-hash> # 回滚到指定提交

📌 十、进阶优化

  1. 多环境部署

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # .github/workflows/deploy.yml
    on:
    push:
    branches: [ main, develop ]

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

    在GitHub Actions中添加备份步骤:

    1
    2
    3
    4
    5
    6
    7
    8
    - 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/xwdblog.top
  3. 通知集成

    部署完成后发送通知:

    1
    2
    3
    4
    5
    6
    - 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. 有没有其他自动化部署的最佳实践?