Image by saya@pixiv

在VPS上通过Jekyll搭建博客

Blog Supported by Jekyll on VPS

  linkthis    2018-03-07    6897 words

本文仅介绍简单的Blog搭建方法,及其相关软件的基础设置,提供一个快速入门的介绍。

Blog类型的选择及前期准备

基于尽量搭建一个便宜简单的Blog的目标,我选择了静态Blog,而不是需要较多资源的动态Blog。而在Jekyll、Hexo、Ghost等静态Blog之中我选择了由Github支持的有较为广泛使用的Jekyll。
在搭建Blog之前我们先要自行准备好一个域名和一台VPS,当然我们也可以直接使用Github Page来搭建Blog,但是为了保证自己能有更大的自主空间我选择了使用VPS,同时也意味着失去了CI等便利的功能。

安装Ruby

Jekyll是基于Ruby写成的,所以我们需要安装Ruby。我们可以选择在Linux或者Windows上安装Ruby,需要注意的是在VPS不一定要安装Ruby,因为Jekyll只是提供一个输出静态内容的功能,而网络服务功能则由其它软件实现。如果需要自己实现类似Github的功能则必须在VPS上安装Ruby。

Linux

选择使用rbenv这个Ruby版本管理工具,将它与ruby-build搭配使用,以实现自动编译安装Ruby、管理多个Ruby版本的目的。
在这里使用的Linux环境为Debian GNU/Linux 9.4 (stretch)

1.安装rbenv及ruby-build
首先安装一些必须的软件:

1
2
apt update
apt install bash-completion curl vim git apt-transport-https lsb-release ca-certificates libelf-dev socat

rbenvruby-build的源代码均托管在GitHub上,只需通过git命令直接clone到本机即可完成安装。
首先安装rbenv:

1
2
3
4
5
6
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src ##编译动态bash扩展以加速rbenv。即使编译失败rbenv也能正常运行(可选操作)
cd ..
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> .bashrc
echo 'eval "$(rbenv init -)"' >> .bashrc
source ~/.bashrc ##使已安装的rbenv在bash中即时生效

安装ruby-build,以便从源代码编译安装Ruby。提供的命令为rbenv install

1
2
mkdir -p "$(rbenv root)"/plugins
git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build

安装rbenv-update-rubies,可以升级已安装的Ruby版本(不可以跨大版本升级),升级之后插件会建议卸载过时版本。提供的命令为rbenv update-rubies

1
2
git clone https://github.com/toy/rbenv-whatis.git "$(rbenv root)"/plugins/whatis
git clone https://github.com/toy/rbenv-update-rubies.git "$(rbenv root)"/plugins/update-rubies

安装rbenv-update,以便更新rbenv和全部已安装的插件。提供的命令为rbenv update

1
git clone https://github.com/rkh/rbenv-update.git "$(rbenv root)/plugins/rbenv-update"

执行如下命令检查rbenv的安装配置情况:

1
curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash

2.安装Ruby
在安装Ruby之前,我们还需要准备编译安装Ruby所需的各种工具及依赖。通过如下列命令安装:

1
2
3
sudo apt install autoconf bison build-essential libssl-dev  \
libyaml-dev libreadline-dev zlib1g-dev libncurses5-dev \
libffi-dev libgdbm-dev

首先执行rbenv install -l获得可安装的Ruby版本列表,之后执行:

1
rbenv install 2.4.3

如果需要多版本,重复进行安装即可。

3.Ruby版本管理
rbenv 支持以下三种 Ruby 版本的环境管理:

  • global:设置全局的 Ruby 版本,换句话说,所有的 shell 都将使用该 Ruby 版本。
  • local:为本地的一个特定项目设置 Ruby 版本,注意这将覆盖全局设置。
  • shell:针对 shell 设置 Ruby 版本,该设置将覆盖 global 和 local 设置。

通过rbenv versions可以列出rbenv已知的所有Ruby版本,并在当前活动版本号旁边显示星号;而rbenv version只会列出当前激活的版本以其设置信息。
而要将之前安装的Ruby 2.4.3设置为全局性版本,应该执行:

1
rbenv global 2.4.3

Windows

在Window系统中,我们可以使用RubyInstaller或者Windows Subsystem for Linux(WSL)来安装Ruby环境。
在WSL中安装rbenv的操作与Linux下相同,只是在WSL下Jekyll的Auto-regeneration可能无法正常工作,而且WSL的版本不能过低,否则Jekyll可能无法正常运行。
RubyInstaller可以在此界面下载。在安装过程中,一定要勾选Add Ruby executables to your PATH,以便在CMD当中使用Ruby。需要注意的是,从Ruby 2.4.0开始,MSYS2 toolkit成为了官方开发工具,为了使用Ruby gems我们应该根据安装程序的引导安装MSYS2。

安装Nginx

选择使用轻量的Nginx作为Web Serve。由于各个发行版中提供的Nginx版本更新速度较慢且支持的模块较少,可以选择Nginx官方源或第三方源进行安装。
选择由Ondřej Surý提供的第三方源,执行以下命令添加源:

1
2
wget -O /etc/apt/trusted.gpg.d/nginx-mainline.gpg https://packages.sury.org/nginx-mainline/apt.gpg
sh -c 'echo "deb https://packages.sury.org/nginx-mainline/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/nginx-mainline.list'

更新源并安装Nginx:

1
2
apt update
apt install nginx

此时执行systemctl status nginx查看nginx运行情况。
之后创建一个简单的Nginx配置文件:

1
2
3
4
5
6
7
8
vi /etc/nginx/sites-enabled/default
## 修改为以下配置
server {
  listen 80;
  server_name example.com;
  root /var/www/my-awesome-site;
  index index.html
}

保存之后执行systemctl restart nginx重新载入配置文件。此时通过域名应该可以访问Blog了。

Acme.sh

为了提高网站的安全性和保证访问质量,我们需要让网站使用HTTPS连接,而我们首先需要申请一个受信任的证书。大牌提供商的SSL证书并不便宜,所以我们选择使用由Let’s Encrypt提供的免费证书。需要注意的是Let’s Encrypt提供的证书的有效期只有90天,所以我们需要使用脚本定期更新。而acme.sh实现了acme协议,可以从Let’s Encrypt生成免费的证书并自动更新。

ACME的全称为Automated Certificate Management Environment,即自动化证书管理环境,相关内容可以参看此仓库

安装acme.sh十分简单,只需执行如下命令:

1
curl  https://get.acme.sh | sh

其会安装到所在目录下的~/.acme.sh/中,并自动创建一个bashaliasacme.sh=~/.acme.sh/acme.sh。注意为了让安装在shell当中即时生效,我们需要执行:source .bashrc。安装过程不会污染任何已有的系统功能和文件, 所有的修改都限制在安装目录:~/.acme.sh/中。如果需要更高级的安装选项可以参看acme.shHow to install
acme.sh提供的验证方式当中我们选择使用DNS验证(不需要任何服务器和任何公网IP,只需要DNS的解析记录即可),不过我们需要同时配置Automatic DNS API,保证acme.sh自动更新证书。在此仅以Cloudflare为例,执行如下操作:

1
2
3
export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export CF_Email="[email protected]"
acme.sh --issue  --ocsp-must-staple --dns dns_cf -d example.com -d *.example.com

配置当中需要等待20s以便自动添加的txt解析记录生效。Cloudflare的API可以在My profile内找到,配置的CF_KeyCF_Email将被存储在~/.acme.sh/account.conf
其它域名商API的用法可以参看DNS API
由于acme协议和Let’s Encrypt CA都在不定期的更新, 因此acme.sh也需要更新以保持同步,执行如下命令:

1
2
3
acme.sh --upgrade #手动更新
acme.sh  --upgrade  --auto-upgrade #自动更新
acme.sh --upgrade  --auto-upgrade  0 #关闭自动更新

HTTPS

在为Nginx配置HTTPS之前,我们首先需要将刚才申请的证书安装到需要使用的地方,请不要使用~/.acme.sh/目录下的文件,里面的文件都是内部使用,而且目录结构可能会变化。首先应该创建存放使用证书的文件夹:

1
mkdir /etc/nginx/ssl/

然后使用--installcert将证书安装到指定位置:

1
2
3
4
acme.sh --install-cert -d linkthis.me \
--keypath       /etc/nginx/ssl/linkthis.me.key  \
--fullchainpath /etc/nginx/ssl/fullchain.cer \
--reloadcmd     "systemctl force-reload nginx.service"

需要指定--installcertreloadcmd保证证书更新以后自动调用新的证书给Nginx使用。同时我们使用的是fullchain.cer,防止SSL Labs测试时出现Chain issues Incomplete的错误。而Nginx应该使用force-reload保证重新加载证书。更加详细的参数可以参考Install the cert to Apache/Nginx etc
如果出现Failed to restart nginx.service: Unit nginx.service is masked.,则需要先执行:

1
systemctl unmask nginx

然后生成键值以启用Perfect Forward Security(PFS):

1
openssl dhparam -out dhparam.pem 4096

之后进行HTTPS配置的环境为:Nginx 1.17.3,OpenSSL 1.1.1c,支持HSTS和OCSP Stapling。 你可以使用如下命令查看Nginx和Openssl的版本:

1
2
nginx -v
openssl version

Nginx配置模板:

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
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # 使用301将HTTP访问重定向到HTTPS
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    access_log  /var/log/nginx/www.mydomain.com_access.log;
    error_log  /var/log/nginx/www.mydomain.com_error.log;

    # Let's Encrypt生成的文件
    ssl_certificate /etc/nginx/ssl/fullchain.cer;
    ssl_certificate_key /etc/nginx/ssl/<domain>.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;

    ssl_dhparam /etc/nginx/ssl/dhparam.pem;

    add_header Strict-Transport-Security "max-age=63072000" always;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
}

在浏览器打开http://www.mydomain.com,如果正常跳转到https://demo.mydomain.com,说明HTTPS配置成功。
你还可以使用SSL Labs测试自己网站的HTTPS配置。使用如下命令查看证书过期时间:

1
openssl x509 -noout -dates -in /etc/nginx/ssl/<domain>.key

Jekyll使用

首先安装Jekyll:

1
2
3
gem install jekyll bundle
jekyll new my-awesome-site
cd my-awesome-site

这样就完成了Jekyll的安装,并且使用了Jekyll自带的主题。不过为了使Blog有更好的效果,我们通常会使用自己编写的主题或者由他人提供的主题。在此仅列举几个主题网站和较好的主题:

在下载这些模板之后,根据README和注释进行修改,也可以根据自己的需求进行修改,即可快速完成Blog的搭建,需要注意的是,如果主题当中使用了Jekyll插件,需要通过Gem自行安装以达到主题Demo相同的效果。
在将自己的文章添加到_post之后执行jekyll serve,然后访问http://127.0.0.1:4000就可以实现本地预览。在完成调试之后执行如下命令生成静态Blog:

1
jekyll build --source /home/my-awesome-site --destination /var/www/my-awesome-site

至此你的个人Blog就完成了搭建。
如果需要使用Cloudflare作为CDN可以参看我之前的文章:Cloudflare使用记录

关于Git设置等操作日后再补。
本文采用CC BY-NC-ND 4.0许可协议进行许可,转载请注明出处。

本文最后更新时间为:2019-09-25-Wednesday-04:47:00 PM




Image of Wechat