我的博客最初是部署在GitHub Pages上,由于万里长城的原因有时候打开极慢,而且使用自定义域名的时候无法启用https。我手上还有一台鹅厂的1C1G1M小水管云服务器,使用Nginx HTTP server,配合Let’s Encrypt的免费服务器证书、GitHub的webhooks服务,最终实现博客源文件的版本控制、服务端网站的自动更新部署。
简介
Hexo是一个基于Node.js的博客框架,每撰写一篇日志,Hexo会生成出静态的博客页面,不依赖任何动态文件,这使得我们可以使用GitHub Pages发布个人博客。这种情况下,每次对博客的修改都需要进行博客构建、发布的步骤,整个过程稍显麻烦。并且更换电脑撰写博客时需要重新搭建Hexo环境以及拷贝博客的Hexo源文件。如果需要使用个人域名解析到github.io的ip地址,也不能够开启https。
如果在GitHub仓库托管一份Hexo的源文件,在我更新博客后push到仓库里,云服务器自动从GitHub下载Hexo的源文件,然后进行构建步骤,通过Nginx对外提供访问。这样,在我们写完日志之后,就只需进行push操作,在其它的机器,也可以clone一份GitHub仓库的Hexo源文件,然后开始更新博客。
基本思路
- GitHub创建私有仓库yangyilts/hexo,用于托管Hexo源文件
- 开启GitHub的webhooks服务,当仓库yangyilts/hexo收到新的push时通知云服务器
- 云服务器收到webhooks通知的时候,pull新的Hexo源文件,在服务器中完成静态页面的构建
- 云服务器配置Nginx和SSL证书进行静态页面的发布,页面文件在hexo目录的public/目录下
我的Hexo源文件存放在一个私有仓库里,博客的源文件一般不涉及重要的隐私,但是如果托管于公开仓库,会暴露博客的配置文件,整个博客暴露在别人眼下也感觉有点不舒服。因为我还有一段时间的GitHub私有仓库优惠,所以暂时托管于GitHub。替代方案有国内的Coding,他家提供有限的私有仓库,托管一个博客已经足够了。
配置环境
本地机器环境
node.js、hexo、git以及配置git ssh密钥是基本环境,搜索一下有很多。
环境配置参考博文:零基础免费搭建个人博客-hexo+github
针对“国内拉npm比拉屎还难”的情况,是真的,可以切换到淘宝镜像,输入命令:
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
之后就使用cnpm 代替npm
云服务器环境
Hexo
同样也需要node.js、hexo、git以及配置git ssh密钥的基本环境。
clone源文件仓库到服务器
$ mkdir /usr/share/hexo
$ cd /usr/share/hexo
$ git clone git@github.com:yangyiLTS/hexo.git
然后需要重新安装hexo的依赖插件,之后不需要hexo init
,直接
$ hexo clean && hexo g
Nginx
我用的服务器镜像是Centos 7,首先安装Nginx
$ yum install -y nginx
修改/etc/nginx/nginx.conf文件中的server配置,举个例子
server {
listen 80;
server_name your domain name;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
# your hexo/public dir
root /hexo/public;
index index.html index.htm;
}
...
}
其实只要在默认文件内容下修改域名和网站根目录就可以了(网站根目录是hexo博客目录的public/目录),然后重启nginx
$ nginx -s reload
这个时候,如果域名解析、服务器访问控制都设置正确,hexo已经成功进行过$ hexo g
操作的情况下,就可以通过域名访问到博客了。
为博客开启https
其实开启https的作用并不大,但是基于小绿锁的强迫症,不免得要折腾一番。好在申请Let’s Encrypt的免费证书也不是特别麻烦,有了小绿锁之后感觉整个博客都不一样了。
Let’s Encrypt 简介
Let’s Encrypt是一个免费并且开源的CA,且已经获得Mozilla、微软等主要浏览器厂商的根授信。它极大低降低DV证书的入门门槛,进而推进全网的HTTPS化。
Let’s Encrypt 安装
以官方推荐的 letsencrypt-auto 脚本进行安装:
$ git clone https://github.com/letsencrypt/letsencrypt
$ cd letsencrypt
$ ./letsencrypt-auto --help
申请SSL证书
由于nginx已在运行中,故使用webroot模式来获取证书,命令:
$ ./letsencrypt-auto certonly --webroot --webroot-path /usr/share/hexo/public -d www.yangyilts.com --agree-tos --email youremail@mail.com
证书申请成功后会显示证书的路径,以及到期时间。
配置Nginx
生成2048位 DH parameters:
$ openssl dhparam -out /etc/ssl/certs/dhparams.pem 2048
修改nginx.conf
server {
listen 80;
server_name www.yangyilts.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name www.yangyilts.com;
ssl_certificate /etc/letsencrypt/live/www.yangyilts.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.yangyilts.com/privkey.pem;
ssl_dhparam /etc/ssl/certs/dhparams.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
location / {
root /usr/share/hexo/public;
index index.html index.htm;
}
...
}
其中配置了使http请求强制跳转至https的域名重定向。
然后访问https://www.yangyilts.com/
测试
博客的自动构建与发布
http server布置好之后,需要搭建自动构建博客静态页面的服务,这里用到一个Go语言编写的Webhook工具,以及GitHub的Webhooks服务。区分一下两个Webhook:
Webhook工具是一个Go语言实现、运行在服务端的,用于处理来自GitHub的Webhooks消息的工具。它能在服务器上打开一个端口,监听来自GitHub的Webhooks消息,如果收到消息,就可以执行一个制定的脚本。
Webhooks是Github仓库(Coding也有)提供的一种服务。它的功能是当GitHub仓库发生某种事件(例如push)时,向指定的URL发送一个HTTP POST请求。
Webhook工具配置
在releases中下载编译完成的文件,然后解压得到一个可执行文件webhook
$ wget https://github.com/adnanh/webhook/releases/download/2.6.8/webhook-linux-amd64.tar.gz
新建一个 hooks.json,需要指定一个"id"
,以及"secert"
,"execute-command"
处填入收到通知后,需要执行的build.sh
脚本的地址,"command-working-directory"
填入执行脚本的目录,也就是hexo目录。下面是示例
// hooks.json
[
{
"id": "webhook_id",
"execute-command": "/path/build.sh",
"command-working-directory": "/path",
"trigger-rule":
{
"match":
{
"type": "payload-hash-sha1",
"secret": "yoursecret",
"parameter":
{
"source": "header",
"name": "X-Hub-Signature"
}
}
}
}
]
其中"secert"
的作用是使用hash验证收到的Post请求是否来源于合法的Git服务器。
新建一个脚本/usr/share/hexo/build.sh
:
#!/bin/bash
rm -rf update.log
git pull | tee build.log
hexo clean && hexo g | tee build.log
然后,使用命令
$ ./webhook -hooks hooks.json -verbose
就可以运行Webhook了
GitHub Webhooks配置
这里,我要使用的是当仓库收到push时,向我云服务器的域名发送一个post请求。
webhooks的设置在仓库的setting里面:
添加一个webhook
Secret填入上面设置的"secert"
,PayloadURL填入http://yourdomain.com:9000/hooks/webhook_id
,然后post请求会被发到服务器的9000端口。
运行
在GitHub新建一个Webhook的时候,GitHub会自动发送一个ping事件的POST
如果POST请求被服务器上的Webhook成功响应,就会返回200 OK状态。如果返回值不是200,则需要检查配置的问题,然后Redeliver重新发送POST请求。
之前启动的Webhook会在退出服务器终端后终止,使用nohup使它长驻后台
$ nohup ./webhook -hooks /path/hooks.json -verbose > webhook.log 2>&1 &
收尾
最后,在本地Hexo目录下写一个Windows批处理public.bat
git add -A
git commit -m "updated %date:~0,10% %time%"
git push
hexo clean && hexo g && hexo d
pause
批处理的最后我还是用hexo d
把博客发布到GitHub Pages,做一个备份。这个步骤当然也可以在远程服务器执行。
这样,当我们写完Mrakdown保存之后,只需要运行一次public.bat
,就可以完成博客的所有发布工作了。