Hexo 使用 Gitea 和 Drone 托管和部署

介绍

通常我们会使用 Hexo 来搭建博客, 博客内容托管于 GitHub,使用 GitHub Pages 来部署博客。这样子部署博客较为方便,但是有几点不足。首先,国内访问 github.io 的速度较慢。另外,Hexo 在部署的时候只会将生成好的网页内容上传到 GitHub 仓库,并不会将博客原始的代码上传上去。当我们想在另外一台电脑上编辑博客时,就会遇到很多麻烦。

为了解决这个问题,我们就需要改变一下博客托管和部署的流程。将博客的原始代码托管于 Git 仓库,并使用 CI/CD 来自动部署博客。需要有一到两台最为基础的服务器,当然树莓派也是可以的。下面介绍一下我在 Ubuntu 服务器上使用自己搭建的 Gitea 和 Drone 托管并部署 Hexo 博客的流程。关于 Gitea 和 Drone 的安装,参考这篇 在 Ubuntu 上部署 Gitea 和 Drone,这里不做赘述。

创建 Hexo 博客

执行这步之前请先确保安装 node.js 和 npm,这里默认已经安装完成。

首先,在 Git 平台上创建一个 blog 仓库,并将其 clone 到本地。进入到 blog 仓库目录,执行以下命令安装 Hexo 并初始化 Hexo 博客:

1
2
npm install hexo-cli -g
hexo init

初始化完成后可以使用以下命令生成并运行博客,来验证安装是否成功:

1
2
hexo g
hexo s --debug

此时,命令行应当会提示如下信息,代表博客已经成功生成,并可以通过地址 http://localhost:4000/ 来访问博客:

1
2
INFO  Start processing
INFO Hexo is running at http://localhost:4000/ . Press Ctrl+C to stop.

可以注意到,我们生成的博客页面存储于 Hexo 目录下的 public 目录中,这个目录是 Hexo 默认的输出目录。而 Hexo 默认的 .gitignore 如下:

1
2
3
4
5
6
7
8
.DS_Store
Thumbs.db
db.json
*.log
node_modules/
public/
.deploy*/
_multiconfig.yml

可以看到,public 目录是存在于 .gitignore 文件中的。说明 Hexo 也考虑到使用 Git 管理博客源码的情况,并且可能是鼓励这样的做法的。

此时我们可以打开 Hexo 目录下的 _config.yml 文件,查看并修改 Hexo 初始化的默认配置。也可以安装一些主题,比如此博客使用的 NexT 主题:

1
npm install hexo-theme-next

在 Hexo 目录下创建 _config.next.yml 文件,并将 ./node_modules/hexo-theme-next/_config.yml 文件的内容复制过来,然后修改其中的内容为自己的配置。将图片资源放置到 ./source/images 目录下。将 _config.yml 中的 theme 字段修改为 hexo,并使用以下命令重新生成博客来验证主题是否配置成功:

1
2
3
hexo clean
hexo g
hexo s --debug

配置 Drone 任务

首先,要登录 Drone 平台,点击进入当前博客仓库,在 Settings 页面点击 Activate Repository 来激活当前仓库的自动任务管道。接着,在 Settings 中点击 Secrets,并点击 New secret 创建保密字段。主要创建的字段有:

  • ssh_host:部署博客的服务器地址
  • ssh_port:部署博客的服务器端口
  • ssh_username:部署博客的服务器用户名
  • ssh_password:部署博客的服务器密码

接着,我们需要编辑 Drone 配置文件来设定 Drone CI 的步骤。主要步骤有:Hexo 博客生成、复制页面文件到服务器、更新服务器静态文件。

我在 Hexo 中使用的主题是 NexT,NexT 从文章开始的 date 字段中获取发布时间,将当前文章的 md 文件最后一次修改时间做为更新时间。由于这里使用 Drone 部署,每次文章源码在 Drone 中都是重新 clone 下来的,所以更新时间总是会显示为最后一次部署的时间。所以我们需要通过以下指令,在 Drone 生成 Hexo 博客前,将博客源文件的修改时间修改为该文件最后一次 commit 的时间。这样就能保证页面显示的修改时间是正确的。可以用以下指令做到这一点:

1
git ls-files -z | while read -d '' path; do touch -d "$(git log -1 --format="@%ct" "$path")" "$path"; done

则完整的 drone.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
kind: pipeline
type: docker
name: default

steps:
- name: Set update time
image: alpine/git
commands:
- "git ls-files -z | while read -d '' path; do touch -d \"$(git log -1 --format=\"@%ct\" \"$path\")\" \"$path\"; done"

- name: Hexo Build
image: node:12-alpine
commands:
- npm install
- npm run clean
- npm run build

- name: SCP File Transfer
image: appleboy/drone-scp
settings:
target: /data/www/
source: ./public
host:
from_secret: ssh_host
port:
from_secret: ssh_port
username:
from_secret: ssh_username
password:
from_secret: ssh_password
rm: true
when:
branch:
- master
event:
exclude:
- pull_request

- name: Web Deploy
image: appleboy/drone-ssh
settings:
host:
from_secret: ssh_host
port:
from_secret: ssh_port
username:
from_secret: ssh_username
password:
from_secret: ssh_password
script:
- mv /data/www/public/* /data/www/
- rm -rf /data/www/public/

trigger:
event:
- push

此处博客文件存放于 /data/www/ 目录下,在部署前已将文件权限授予当前用户,否则可能会遇到文件读写权限问题。

将博客仓库 push 到 Git,Drone 会自动开始执行部署任务。部署可能会有各种问题,需要根据情况进行一些调试。任务执行成功后,我们可以在 /data/www/ 目录下看到生成的博客文件。

使用 Nginx 配置域名解析

在服务器成功安装 Nginx 后,我们可以将域名解析到博客所在的目录,这样就可以通过域名来访问博客了。在 /etc/nginx/sites-enabled/ 目录下创建一个文件,文件名为 hexo,内容如下:

1
2
3
4
5
6
7
server {
listen 80;
root /data/www/;
server_name hexo.example.com;
location / {
}
}

在云平台上设置域名解析到改服务器,并使用以下指令重启 Nginx 服务,访问该域名。若博客显示成功,则说明部署完成。

1
sudo systemctl restart nginx

后续使用和部署事项

部署完成后还需进行 ICP 备案等操作,之后,博客就正常运行了。每次 push 到该博客仓库都会自动进行内容更新。

需要注意的是,千万不要在此仓库中直接运行 hexo d 或者 hexo deploy 命令。若是使用该命令,有可能 Hexo 会直接生成最终的静态站点文件并强行覆盖本地和远程的 Git 仓库,仓库内容和过去的 commit 记录会全部被抹去。会导致站点源码的丢失,损失惨重。所以除了不要运行 deploy 命令以外,最好定期将此仓库做个备份,以防止各种错误的出现。