Hugo + GitHub Webhook 博客搭建教程
![https://cdn.jsdelivr.net/gh/chency147/image-bed@main/img/blog-building-tutorial/cover.jpg https://cdn.jsdelivr.net/gh/chency147/image-bed@main/img/blog-building-tutorial/cover.jpg](https://cdn.jsdelivr.net/gh/chency147/image-bed@main/img/blog-building-tutorial/cover.jpg)
写在前面
搭建博客这个过程,我曾经操作过不下十遍,但是每次因为VPS到期或者重装忘记备份,内容亡佚。后来在 简书
上创建了账号,也更新了几篇文章,但是这个平台一点都不极客,没有什么技术韵味,再加之平时工作忙碌不堪,当初更新博客这样的热情也渐渐地退却。
后来工作越久越是发觉,身边厉害的同事以及行业内的技术大牛,总是有着非凡的总结能力,而这也是我自己所欠缺的。最近在工作、编码中遇到的坑,可能事发时做了一下总结,但是由于没有良好记录,过段时间便又被抛在脑后,于是反复踩坑,毕竟好记性不如烂笔头嘛;还有学习技术过程中的感想和感悟,也缺乏记录总结,学习效果不明显。看起来,搭建博客并且定时更新博客这件事情亟待提上日程~
所以搭建本博客的目的为:给自己创建一个可以日常做总结的平台,培养自己的总结能力,达到自我技术提升。
至于为什么不选择 CSDN
、cnblog
这样的平台?
第一点,CSDN
是我最不喜欢的博客平台,广告太多,而且给我的印象是上面的文章都特别水,各种转载,虽然SEO做得好,但是搜索引擎第一页结果往往千篇一律甚至连内容都一模一样,对其天然没有好感,甚至有时候谷歌搜索时直接排除掉它的结果,比如这样搜索 phpredis 安装 -site:csdn.net
;
第二点,我自己有域名和VPS,希望可以把它们利用起来,毕竟每年都在交钱呢,而且自己的域名很有个性嘛。
技术选型
博客引擎(hugo)
hugo 是我最近了解到的博客程序,它可以将书写的 markdown 格式内容转成 html 文件,以静态文件的形式组织博客文章,还可以支持自定义主题,性能好、美观、渲染速度快,特别适用于我这样小水管型的VPS;作为一枚PHP程序员,之前的博客都是用 WordPress
或者 Typecho
,使用它们就不得不在服务器上安装和启动 php-fpm
和 mysql
服务,对于小水管来说它们还是太重了;
Web容器(nginx)
这里我推荐直接安装使用 OpenResty®;
内容上传和发布(GitHub + WebHook)
文章的撰写其实和写代码差不多,我希望我写博客的中的任何修改都能够被记录到,作为程序员,第一个想到能应对这样的需求的就是用 Git 做版本控制了,而且有 GitHub 这样免费的代码托管平台任君使用,怎么闻都香。
还有一个非常重要的原因,hugo
是将 markdown 文件转成 html 资源来提供浏览的,这其实可以看作是一个编译过程,我不可能把编译的产物提交到仓库,因为这样做实在太挫了。
GitHub
提供了 WebHook
功能,可以通知我们的程序有新的提交,利用这个功能,我们可以很容易地实现博客的持续集成写作;
WebHook
的服务端可以直接使用 adanh/webhook 这个项目,它可以帮助我们很轻松地开启一个 webhook 的服务端,并且自己帮忙做好了安全校验;
部署结果通知(Server酱)
上面说到我们要利用 WebHook
功能实现持续集成,这里面的部署结果我们需要怎么知晓呢?总不可能我每次都上服务器来查看吧?
幸运的是,已经有大牛提供了 Server酱 通知服务,免费使用而且接入简单,可以利用微信消息推送给我们部署结果。
其他
本人 vim 党,markdown 使用 vim
进行书写,平时使用 hugo
自带的实时预览功能或者 Typora 进行页面效果查看;
博客搭建
Openresty 安装和启动
Openresty的安装教程可以在官方文档,这里只简单例举一下 centos 上的安装方法,推荐直接使用官方编译好的 Linux包进行安装(官方文档);
安装指令参考如下
# 添加 openresty yum 源
wget https://openresty.org/package/centos/openresty.repo
sudo mv openresty.repo /etc/yum.repos.d/
# 更新 yum 源
sudo yum check-update
# 安装 openresty
sudo yum install -y openresty
安装完毕之后,可直接使用指令 /usr/local/openresty/nginx/sbin/nginx
启动 nginx 服务;
记录两条常用的 nginx 指令如下
# 检查 nginx 配置是否正确
/usr/local/openresty/nginx/sbin/nginx -t
# 检查并重新载入 nginx 配置
/usr/local/openresty/nginx/sbin/nginx -s reload
HTTPS 支持
HTTPS 支持有两种,CDN方式 和 申请SSL证书方式。
CDN方式(推荐)
推荐直接使用 Cloudflare 管理的域名,它可以帮助我们非常方便地支持 HTTPS;
SSL证书方式
可使用免费的 Let’s Entrypt 进行申请,现在已经支持申请泛域名。相关指令收录如下:
# 下载证书申请工具
wget https://dl.eff.org/certbot-auto
chmod +x certbot-auto
# 移动程序到自己喜欢的位置
mkdir /var/opt/letsencrypt/
mv certbot-auto /var/opt/letsencrypt/letsencrypt-auto
# 执行申请,-d 参数内容应该替换为你自己的域名,这里使用DNS的方式进行校验
/var/opt/letsencrypt/letsencrypt-auto certonly --preferred-challenges dns --manual -d "*.rickchen.info" --server "https://acme-v02.api.letsencrypt.org/directory"
# Are you OK with your IP being logged? 这个问题直接填入Yes
# 随后程序会提示要求在自己域名下面添加一条TXT类型的解析记录,按照提示在自己的域名运营商后台操作即可
# 稍等片刻(我等了5分钟左右让域名解析生效)之后按下回车即可完成申请
完成申请之后提示如下
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/rickchen.info/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/rickchen.info/privkey.pem
Your cert will expire on 2020-12-10. To obtain a new or tweaked
version of this certificate in the future, simply run
letsencrypt-auto again. To non-interactively renew *all* of your
certificates, run "letsencrypt-auto renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
上面提示中说明了证书所在位置,直接在nginx的443端口server中添加如下配置再reload即可
server {
listen 443 ssl;
server_name blog.rickchen.info;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/rickchen.info/fullchain.pem;
ssl_certificate /etc/letsencrypt/live/rickchen.info/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/rickchen.info/privkey.pem;
# 后续配置省略...
}
Let's Encrypt
的证书只有3个月的有效期,所以我们必需要定时地为其续期,这里可以用linux系统的crond进行定时执行。
- 定义
post_hook
,这一步是为了让更新程序支持在续期完证书之后自动reload nginx。上述域名申请之后,更新相关的配置存放在/etc/letsencrypt/renewal/rickchen.info.conf
,打开在最后添加如下配置行即可;
post_hook = /usr/local/nginx/sbin/nginx -s reload
- 添加定时任务,
vim /etc/crontab
添加下面配置即可,注意系统的crond服务需要开启;
# 每天凌晨2点检查并续期HTTPS证书
0 2 * * * root /var/opt/letsencrypt/letsencrypt-auto renew -q > /dev/null 2>&1 &
Hugo 安装
直接在 Hugo Release 页面中下载最新的、适用于自己操作系统的二进制包即可。服务器和自己的电脑上都应该安装一下。
以 centos 为例,执行以下指令即可完成安装:
# 注意替换成最新的版本链接,编写本文时最新的版本为0.74.3
wget "https://github.com/gohugoio/hugo/releases/download/v0.74.3/hugo_0.74.3_Linux-64bit.tar.gz"
# 解压
tar -zxvf hugo_0.74.3_Linux-64bit.tar.gz -C .
mv hugo /usr/local/bin/
hugo 安装完毕之后,可以先确定好自己博客文件的存放路径,把 nginx 配置设置好,以我的博客为例,执行如下指令创建目录;
mkdir /var/www/blog
这里推荐大家修改一下这个文件夹的用户所属,因为后面的 webhook 功能需要执行博客更新指令,用 root 用户会有风险;
groupadd blog
usradd blog -g blog
chown -R blog:blog /var/www/blog/
然后修改 nginx 配置的 root 为 /var/www/blog/public/
,并 reload;
GitHub 项目创建
本博客的内容维护在 chency147/blog。大家可以在自己的 GitHub 上创建自己的一个博客工程,拉取到本地之后就可以开始创作了。
# 仓库克隆
git clone git@github.com:chency147/blog.git
# 初始化博客
hugo new site blog
# 进入目录
cd blog
执行到此,即可进行创作以及主题的修改,本文目前使用的主题为 LoveIt,大家可按照其 文档 进行配置;
- 注意
上面的仓库拉取方式为 SSH 方式,需要将在自己电脑上生成SSH钥匙对,并将公钥上传到 GitHub 的 个人配置。
没有钥匙生成过对的同学的同学可以在
Git Bash
中执行如下指令生成并查看
ssh-keygen
# 一路回车到底
cat ~/.ssh/id_rsa.pub
# cat 指令输出即为公钥内容
将上述输出的公钥内容拷贝并添加到 GitHub SSH Key 管理页面中:
由于服务器端也需要拉取工程内容,所以服务器端 blog 用户的公钥也需要添加到GitHub配置中。
下面完成博客的首次提交
hugo new post/hello-world.md
git add -A
git commit -m "Hello World"
git push -u origin master
博客首次亮相
登录到服务器,执行指令 su blog
切换到 blog 用户,执行如下指令拉取工程并使用hugo生成页面文件:
cd /var/www/blog
git clone git@github.com:chency147/blog.git .
git submodule init
git submodule update
hugo -D
这个时候访问我们自己的博客域名,是不是有内容呈现出来了呢?
GitHub WebHook 使用
服务端
推荐直接使用 adnanh/webhook 项目搭建webhook服务。
webhook服务安装
wget "https://github.com/adnanh/webhook/releases/download/2.7.0/webhook-linux-amd64.tar.gz"
tar -zxvf webhook-linux-amd64.tar.gz -C .
mv webhook-linux-amd64/webhook /usr/local/bin/
部署脚本编写
以我的博客为例,我的部署脚本存放在 /var/www/blog_deploy.sh
,其作用为 从git仓库中拉取最新的博客内容,并使用 hugo 进行编译,其内容如下:
#!/bin/bash
cd /var/www/blog
git checkout master
git pull
git submodule init
git submodule update
hugo -D
主要不要忘记 chmod +x /var/www/blog_deploy.sh
赋予它可执行权限。
webhook配置编写
配置文件位于 /etc/webhook/hooks.json
,使用vim打开键入如下内容并保存;
[
{
"id": "blog_deploy",
"execute-command": "/var/www/blog_deploy.sh",
"command-working-directory": "/var/www/blog",
"trigger-rule":
{
"and":
[
{
"match":
{
"type": "payload-hash-sha1",
"secret": "这里填写你自己在GitHub WebHook配置页面上填写的密码",
"parameter":
{
"source": "header",
"name": "X-Hub-Signature"
}
}
},
{
"match":
{
"type": "value",
"value": "refs/heads/master",
"parameter":
{
"source": "payload",
"name": "ref"
}
}
}
]
}
}
]
webhook服务启动
切换到 blog 用户,执行如下指令启动webhook服务;
nohup webhook -port 9001 -ip 127.0.0.1 -hooks /etc/webhook/hooks.json > /dev/null 2>&1 &
优秀的同学可以使用 supervisord
进行进程守护,本文将不再赘述,只是贴一下配置文件内容;
[program:WebHook]
command = webhook -port 9001 -ip 127.0.0.1 -hooks /etc/webhook/hooks.json
autorestart = true
autostart = true
startretries = 2
numprocs = 1
stderr_logfile = /dev/null
stdout_logfile = /dev/null
stopsignal = KILL
stopsignal = INT
user = blog
webhook服务nginx转发
在自己的 nginx 配置中添加如下转发配置并reload,这个路径完全可以根据自己的喜好自定义;
location ~ ^/XXXXXXXX/webhook/(.*) {
proxy_pass http://127.0.0.1:9001/$1;
}
GitHub端
进入仓库的 Settings 页卡,选择 Webhooks 选项,在页面上进行 webhook 添加;
执行完上述配置之后,我们随便修改一下文章内容,然后进行一次Git提交和推送,博客的文章就能自动更新啦!
Server酱通知
根据Server酱官方网站上的接入流程,登录账号获取到自己的SCKEY,然后修改博客部署脚本为以下内容即可。
#!/bin/bash
# 博客文件拉取
cd /var/www/blog
git checkout master
git pull
git submodule init
git submodule update
# 获取编译结果
result=`hugo -D`
# 使用server酱进行通知
secret="Server酱官网获取到SCKEY"
# 标题、内容 URL编码
title=$(echo -e "Rick Chen Blog 更新完毕" | od -An -tx1 | tr ' ' % | xargs printf "%s")
content="以下为执行博客渲染指令输出内容\n\`\`\`\n${result}\n\`\`\`\n时间:"`date "+%Y-%m-%d %H:%M:%S"`
content=$(echo -e "${content}" | od -An -tx1 | tr ' ' % | xargs printf "%s")
curl "https://sc.ftqq.com/${secret}.send?text=${title}&desp=${content}"
然后再尝试推送看看,就能收到编译结果的通知啦。
总结
以上就是本博客搭建的整个过程了,花费的时间并不算多,大概半天的时间即可折腾出来。
但是将上述过程整理成本篇文章花费了不少时间,毕竟社畜一枚,平时太忙了。
好了,博客搭建完成了,希望自己能够持续学习,不断总结,一直进步。