CentOS 服务器部署 Hexo 博客并利用 Webhook 自动更新

Hexo, A fast, simple & powerful blog framework.

本地部署 Hexo

安装

根据 Hexo 官网的介绍,首先要安装 Git 以及 Nodejs,CentOS 系统下直接 yum 安装即可:

1
2
yum install git
yum install nodejs

两个工具都装好之后,必要时设置 npm 的源:

1
2
npm config set proxy https://domain:port
npm config set registry http://registry.npm.taobao.org/

利用 npm 安装 hexo

1
npm install hexo-cli -g

注意 npm 安装的包在 ~/.npm 目录下(所以是用户级别的)。

配置

初始化 Hexo:

1
2
3
4
mkdir ~/Hexo
cd ~/Hexo
hexo init
npm install

Hexo 文件夹下的 _config.yml 为站点配置文件,比如

_config.yml
1
2
3
4
5
6
7
# Site
title:
subtitle:
description:
author:
language:
timezone:

服务器

这里摘自 Hexo 官网的介绍。安装 hexo-server 包:

1
npm install hexo-server --save

那么输入

1
hexo server

网站就会在 http://localhost:4000 下启动,并且 Hexo 会监视文件变动并更新,如需改变端口或遇到 EADDRINUSE 错误,加上 -p 参数并指定端口:

1
hexo server -p 5000

生成器

利用 hexo generate 或者 hexo g 即可生成静态文件,生成的文件目录为 ~/Hexo/public

同步到代码托管平台

安装 hexo-deployer-git

1
npm install hexo-deployer-git --save

在前述 _config.yml 文件中,找到 deploy 项,配置为:

_config.yml
1
2
3
4
5
6
deploy:
type: git
repo:
github: git@github.com:xxx/blog.git
coding: git@git.coding.net:xxx/blog.git
branch: master

这里将 Github 上的仓库命名为 blog,与后文中本地仓库名相同。

直接利用 hexo deployhexo d 直接 push 到 Github 上。生成静态文件与同步可以合为一步(两者作用相同):

1
2
hexo g -d
hexo d -g

详细配置过程见官方文档

配置 Nginx

添加 Nginx 的 repo 并安装:

1
2
3
rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
yum info nginx
yum install nginx

Nginx 二进制文件所在目录为 /usr/sbin/nginx,配置目录为 /etc/nginx/。由于 /etc/nginx/nginx.conf 文件中包含

1
include /etc/nginx/conf.d/*.conf;

所以仅需在 /etc/nginx/conf.d/ 下新建 hexo.conf 文件,配置网站信息即可:

hexo.conf
1
2
3
4
5
6
server {
listen 80;
server_name domain.com;
root /var/www/blog;
index index.html index.htm;
}
  • 启动Nginx服务:service nginx start
  • 重载Nginx服务:service nginx reload

这里的 root 即为网站所在目录,大量的教程中将 /var/www/ 设成网站所在目录,估计是约定俗成吧。那么这里就有权限问题了,刚入坑的我还并不是很了解 Linux 的权限机制,所以干脆决定在普通用户下生成静态文件,并同步至 Github,再利用系统用户利用 Webhook 从 Github 更新网站目录。

配置 Webhook

root 用户登录,创建两个文件: - sync.sh:用于从 Github 上 pull 数据,即更新本地网站目录,注意加上执行权限

sync.sh
1
2
3
4
5
6
7
8
#!/bin/bash
echo -e "\033[32m [AUTO SYNC] sync hexo start \033[0m"
cd /var/www/blog
echo -e "\033[32m [AUTO SYNC] git pull... \033[0m"
git fetch --all
git reset --hard origin/master
git pull
echo -e "\033[32m [AUTO SYNC] sync hexo finish \033[0m"
- hexo-server.js:接受 Github 的 post 信息后执行 sync.sh
hexo-server.js
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
var http = require('http')
var exec = require('child_process').exec
var createHandler = require('github-webhook-handler')
var handler = createHandler({ path: '/webhook', secret: '******' })

http.createServer(function (req, res) {
handler(req, res, function (err) {
res.statusCode = 404
res.end('no such location')
})
}).listen(7777)

handler.on('error', function (err) {
console.error('Error:', err.message)
})

handler.on('push', function (event) {
console.log('Received a push event for %s to %s',
event.payload.repository.name,
event.payload.ref)
exec('/root/Scripts/sync.sh', function(err, stdout, stderr){
if(err) {
console.log('sync server err: ' + stderr)
} else {
console.log(stdout)
}
})
})

handler.on('issues', function (event) {
console.log('Received an issue event for %s action=%s: #%d %s',
event.payload.repository.name,
event.payload.action,
event.payload.issue.number,
event.payload.issue.title)
})

注意 hexo-server.js 中的 sync.sh 填写的是绝对路径。
安装 github-webhook-handler 以及 forever

1
2
npm install github-webhook-handler
npm install forever -g

在 Github 的仓库设置的 Webhooks 选项中,Payload URL 填写为:

1
http://domain.com:7777/webhook

这里的端口7777与上面 hexo-server.js 中设定的端口是一致的,Content type 选择 application/json,秘钥 Secret 自行设置,与上述 js 文件中 ****** 相同。触发事件选择仅 push 的时候即可。之前生成静态文件并更新至 Github 时发现 Webhooks 设置页面最下方的记录中,总出现

1
We couldn’t deliver this payload: Service Timeout

的提示,当然外网访问的博客也没有更新,说明是 Github 与阿里云服务器的沟通出了问题。结合之前部署 RStudio 服务器的经历,想起阿里云服务器配备了安全组,所以在阿里云服务器安全组规则设置页面中开放 7777 端口,这样才能正常访问。这里不知道是否可用 Nginx 来做中转,以后再折腾。
利用之前安装的 forever 运行 js 脚本:

hexo-server.js
1
forever start hexo-server.js
当然如果要停止这个脚本: forever stop ***.js.

于是,写完博客,hexo g -d 同步到 Github 仓库,就万事大吉了:Github 接受到这样的一个 push 请求之后向服务器特定端口发送了一个 HTTP POST,服务器接受到这个POST后自动执行 sync.sh,也就是到定位本地仓库/网页目录,从 Github 上拉取最新的网页文件。

更新历史

  • 2017-07-17 修改了部分主题样式,添加部分插件,注意利用 npm 安装插件必须加上 --save 选项!
    • font-awesome 图标:hexo-tag-fontawesome
    • 字数统计插件 hexo-wordcount,不过最新版的NexT主题已经内置该功能
    • RSS插件 hexo-generator-feed
    • 本地搜索服务 hexo-generator-searchdb
    • SEO优化 hexo-generator-sitemaphexo-generator-baidu-sitemap
  • 2017-07-18 发现外网访问服务器速度实在过慢,老实投靠 Github,Coding 进行双线部署,并更新博客为二级域名,在解析上下了点功夫。加之 Coding 可以强制 https 访问,遂抛弃 Github 部署
  • 2017-12-03 增加 \(Mathjax\) 支持。参考: 搭建一个支持LaTEX的hexo博客。然而这里出现了一些意外状况,比如公式的分式的中横线显示偏低,这是不能接受的,首先将主题配置文件中 mathjax 设置为:
    1
    2
    3
    4
    mathjax:
    enable: true
    per_page: true
    cdn: //cdn.bootcss.com/mathjax/2.7.2/latest.js?config=TeX-MML-AM_CHTML
    这末尾的 config=... 极其重要,就是被这玩意儿折腾良久。关键在于公式的渲染方式,在这儿应选 Common HTML 而不是坑爹的 HTML-CSS。 再折腾下文件 themes/next/layout/_third-party/mathjax.swig
    mathjax.swig
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    MathJax.Hub.Config({
    showProcessingMessages: false,
    messageStyle: "none",
    tex2jax: {
    inlineMath: [ ['$','$'], ["\\(","\\)"] ],
    displayMath: [ ['$$', '$$'], ["\\[", "\\]"] ],
    processEscapes: true,
    skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
    },
    TeX: {
    equationNumbers: {
    autoNumber: 'AMS'
    },
    extensions: ["AMSmath.js", "AMSsymbols.js", "autobold.js"]
    }
    });
    最后,对于 IE 浏览器兼容方面出现问题的解决方案:
    mathjax.swig
    1
    2
    <script type="text/javascript" src="https://cdn.bootcss.com/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML"></script>
    <!-- <script type="text/javascript" src=""></script> -->
  • 2017-12-03 再再次更换阵地 – 把博客迁移至 码云 (感觉访问速度更快些)
  • 2017-12-03 再再再次更换阵地 – 又回到码市的怀抱,因为码云不支持自定义域名,做跳转又不清真,我只想好好写个博客 ToT
  • 2017-12-03 实现多端博客同步。这里采用比较暴力但高效的办法:在远程新建两个仓库, 一个私有仓库用户存储源文件(原始 Markdown 文件,各类魔改过的文件等, 将整个本地的 Hexo 目录作为本地仓库),一个公有仓库(用于展示网页)。那么这两个命令就可以手动同步了:
    1
    2
    alias hexopull='git fetch --all && git reset --hard origin/master && git pull'
    alias hexopush='hexo clean && hexo g -d && git add -A && git commit -m "update" && git push origin master'
  • 2017-12-31 更换 markdown 渲染引擎。
    1
    2
    npm uninstall hexo-renderer-marked --save
    npm install hexo-renderer-pandoc --save
  • 2018-07-17 添加脚注插件 hexo-footnotes
  • 2018-11-20 将博客回归至 Github,并以 Netlify 作为持续集成