在Linux服务器上搭建Hexo:OS X、Windows与Linux本地环境

什么是Hexo?

Hexo是一个基于node.js的静态博客生成系统。它使用markdown语法来写作,同时支持丰富的自定义标签系统。用户在本地安装Hexo系统并进行写作,通过一条命令,Hexo可以自动生成静态页面,并发布到多个平台上。

这是Hexo的官网:Hexo(支持中文)
中文文档

为什么要使用Hexo?

如上一节所说,Hexo最终生成的是一个静态博客。这就意味着它拥有其他博客系统无法比拟的低负载与高速度的特性。同时,Hexo支持丰富的第三方服务,包括统计、评论、搜索等,使得它的功能相对于动态博客系统并不是多么逊色。最后,Hexo使用简洁的YAML标准来建立配置文件。通过修改配置文件可以方便快捷地修改站点的多个选项,例如为主题导航栏添加项目,只需要简单的在配置文件中增加一行即可。

如果你之前使用其他的博客系统,也可以很方便的迁移到Hexo。

我可以使用Hexo吗?

这类静态博客系统最大的一个缺陷就在于要求用户具有一定的技术水平。吐槽一句:Hexo是我见过最难建立的博客系统,就连同样基于node.js的Ghost搭建难度都远不如Hexo。

要建立Hexo博客系统,你需要的相关知识如下:

  • Linux操作系统
  • Git版本控制系统(可选,如果使用Git部署)
  • nginx web server
  • (可选)理解和使用HTTPS/TLS协议
  • (至少)了解HTML/JavaScript/CSS
  • 了解Markdown语法和YAML语法
  • (Windows)了解安装node.js和Git的方法,会配置环境变量
  • (OS X/Linux)熟悉自己系统的包管理工具
  • 有自己进行研究解决问题的能力,英语阅读能力(必须!)

这篇教程面向有一定技术基础的读者,但我也会尽可能的写得简单明了。虽然并不能做到看得懂中文就看得懂教程,不过我会争取降低理解本文的技术门槛。这并不意味着可以不思考读懂本文

这篇教程会达到什么目的?

  1. 在本地建立Hexo站点文件夹
  2. 介绍使用Hexo的写作方式
  3. 在自己的VPS/虚拟主机上部署Hexo

Getting Started

在本地安装Hexo

Hexo系统没有GUI,只有一个命令行工具,为了使用Hexo系统,首先需要在本地安装Hexo命令行工具。

OS X

执行以下命令安装node.js

1
brew install node

如果提示

1
bash: brew command not found

强力安利一发OS X下最强大的命令行包管理工具Homebrew,官网在这里(有中文版)。通过这个工具可以快速安装一系列Linux下的软件包。例如安装python,只需要:

1
brew install python3

执行以下命令可以快速安装homebrew:(需要Xcode Command Line Tools)

1
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

测试一下node.js是否安装成功:

1
node -v

1

然后执行以下命令安装git

1
brew install git

执行git --version查看Git是否安装成功。
1-2

PS:如果brew显示安装成功,但无法运行上述命令,请将/usr/local/bin目录加入系统PATH变量中。bash(默认)用户编辑~/.bashrc文件,zsh用户编辑~/.zshrc文件,找到export PATH行,并在变量值中加入/usr/local/bin项目。如下图所示:

并重启终端。

执行以下命令即可安装Hexo:

1
npm install -g hexo-cli

PS:目前npm官方源在国内访问并不稳定,如果你无法直接安装,请更换国内npm源或挂上全局代理。
执行以下命令更换淘宝npm源:

1
npm config set registry https://registry.npm.taobao.org

测试是否安装成功:

1
hexo version

如下图所示:

Linux

Hexo文档中只有Debian系以及RHEL系的安装方法,其他发行版请参考自己的包管理器用法。

执行以下命令用nvm(node version manager)安装node.js:

1
wget -qO- https://raw.github.com/creationix/nvm/master/install.sh | sh

安装完成后执行:

1
nvm install stable

即可安装node.js,测试方法同上。

执行以下命令安装Git:

1
2
sudo apt-get install git-core#debian/ubuntu
sudo yum install git-core#RHEL/centos

执行以下命令即可安装Hexo:

1
npm install -g hexo-cli

PS:目前npm官方源在国内访问并不稳定,如果你无法直接安装,请更换国内npm源或挂上全局代理。
执行以下命令更换淘宝npm源:

1
npm config set registry https://registry.npm.taobao.org

测试是否安装成功:

1
hexo version

如下图所示:

Windows系统

到node.js官方网站下载安装包。点击这里直达。
安装没什么好说的,注意到下图这一步时,勾选npm package manager以及Add to PATH选项。

我选择的是v6.3.1(即写作本文时的“当前版本”,LTS版本是否可用我没有进行过测试。)

这里可以下载Git for windows。这个套件不仅仅在windows上安装了Git版本控制系统,最重要的是这个套件提供了Git Bash,一个可以在windows上运行的Linux风格shell,除非你够硬核,能忍受win的cmd,否则通过Git Bash使用hexo无疑是最佳选择。下图的选项建议勾选,视觉效果有明显提升。其余选项保持默认即可。(下载地址北墙,请挂上代理)

运行Git Bash,之后请参考5.1.2节即可完成Hexo的安装。附图一张:(Git Bash中粘贴请右键Paste)

初步了解Hexo

Hexo的文件夹结构

在初始化一个hexo站点文件夹之后(详见下一节),该文件夹的目录结构如下:

  • _config.yml是YAML格式文件,也是Hexo的站点配置文件(敲黑板!重点重点!)
  • node_modules包含使用Hexo需要的其他node.js模块,以后安装的hexo相关模块也放在这里
  • package.json配置hexo运行需要的node.js包,不用手动更改(PS:通常不需要干预它,不过其中有一条"name": "hexo-site"起着告诉hexo该文件夹是hexo站点的作用,因此更加不要修改该文件内容,安装hexo其他模块也依赖该文件)
  • scaffolds模板文件夹,不过这里的“模板”概念没有那么高端。这个“模板”就是指新建的markdown文件的模板,每新建一个markdown文件(由于Hexo使用markdown语法,在渲染生成静态HTML页面之前,源文件都是markdown文件),就会包含对应模板的内容。该文件夹内有三个模板:
  1. draft.md,草稿的模板
  2. page.md,页面的模板
  3. post.md,文章的模板
  • source源文件文件夹,此处存有渲染生成静态页面需要的所有源文件,包括markdown文件、图片文件。默认此文件夹下只有一个_post文件夹,存放文章的markdown源文件。每个页面有一个以该页面命名的文件夹,也存放在source文件夹下。该文件夹下除了_post外,所有以下划线开头的或以.开头的文件夹都会被忽略。
  • themes主题文件夹,Hexo的主题作用与WordPress相同。
  • public文件夹,默认没有,存放生成的静态文件。
Hexo命令使用

PS:<参数>为必填参数,[参数]为可选参数。以下命令全部需要在hexo站点文件夹下运行。

1
hexo init <folder>

此命令用于执行站点的初始化。执行后,folder文件夹会成为一个Hexo站点文件夹,执行过程中涉及安装多个nodejs模块包以及git clone操作,因此最好挂上代理。

1
hexo new [layout] <title>

新建一个markdown文件。[layout]是该文件的类型,取值有postdraftpage三种,分别对应新建文章、草稿、页面。在运行该命令时,会调用scaffolds下的对应模板。

1
hexo clean

清理Hexo缓存。该操作会强制Hexo清空已生成的全部静态文件以及Hexo自身的数据库,有时候相当有效(更换主题后建议运行)。

1
hexo generate

生成静态页面。在生成时可以加上-d--deploy参数在生成后立即部署。生成的静态文件在public文件夹下,没有则会自动建立。

1
hexo deploy

部署站点。也就是将public目录下生成的静态文件上传到某个特定的位置,Hexo支持多种部署方式,下文详解。部署时可以加上-g--generate参数,在部署前先生成一遍静态文件。

1
hexo publish <title>

发布某篇草稿(即将该markdown文件转移到_post文件夹下)

1
hexo server

在本地http://localhost:4000启动一个hexo服务器,可以用来预览hexo站点的效果。

PS:这里只介绍了Hexo的常用命令,详细命令请参考中文文档

Hexo markdown文件的结构

每个由Hexo建立的markdown文件包含如下两部分:

Frone-matter

类似于HTML中的元信息,HTTP包中的头部等等。它也使用YAML格式,定义了一系列Hexo程序需要使用的变量。例如我撰写这篇文章时的Front-matter内容如下图所示:

正文

使用普通的markdown语法,这是你的文章或页面的内容。

YAML基本语法
YAML基本组件

YAML的基本组件都有区块(即所谓的代码块)和行内(即写在一行)两种形式。
1.清单
如字面意思所言,“清单”所表示的就是一系列有序的值。类似于数组。
清单的区块表达方式类似如下:

1
2
3
---
- v1
- v2

这就是一系列的简单字符串。
而其行内表示形式如下:

1
[v1,v2]

其表达方式十分类似于Python的列表。
2.杂凑表
杂凑表是一系列key: value对,它有点像其他语言中的“字典”。由于它的特性,Hexo配置文件使用的主要是杂凑表形式。
杂凑表的区块方式如下:

1
2
name: John Smith
age: 33

而其行内表达形式与Python字典几乎相同:

1
{name: John Smith, age: 33}

需要注意的是,杂凑表的key和value均允许任意的空格,不需要用引号将它们括起来。

注意事项
  1. 杂凑表的key:后必须有一个空格
  2. 一个清单的一个元素可以是一个杂凑表,一个杂凑表的一个元素可以是一个清单,清单和杂凑表可以自身嵌套。嵌套时请注意缩进。
  3. 掌握这两项基本元件编写Hexo配置文件已经够用,需要了解更多语法请参考维基百科上的YAML

使用Hexo建站:初始化、配置、更换主题、写作、预览与部署

初始化

首先建立一个文件夹。

1
mkdir hexo_blog

执行hexo命令初始化文件夹

1
hexo init hexo_blog

你可以选择你喜欢的文件夹名称。注意,该步骤最好挂上代理。

基本配置

PS:有关部署配置在部署一节中讲解
用你喜欢的文本编辑器打开站点文件夹下的_config.yml文件,我用的是Sublime Text 3(吃我一发强力安利!最强大的几个文本编辑器之一,强烈推荐!)。

本节内容以Hexo官方文档中的有关内容为主,想了解更多的话强烈建议阅读官方文档(纯中文!毫无障碍,有疑问可以到文章下方留言)

用一个对代码支持友好的文本编辑器打开文件后,可以看到标准的YAML文件内容,如下图所示,涉及到的语法我在图中有所提示:

再次提醒,嵌套元件请注意缩进!注意空格!(敲黑板!重点!)

对一个新站点来说,需要编辑的项目有:

1
2
3
4
5
6
7
8
9
10
11
12
title: Hexo #站点的标题
subtitle: #站点的副标题
description: #站点的描述,写一段话来介绍你的博客吧:),主要为SEO使用
author: John Doe #显示的文章作者名字,例如我配置的是fourstring
language: #语言。简体中文是zh-Hans
timezone: #时区,可以不配置,默认以本地时区为准
url: http://yoursite.com #你的站点地址,如果是全站HTTPS记得写成https://domain.com
root: / #如果您的网站存放在子目录中,例如 http://yoursite.com/blog,则请将您的 url 设为 http://yoursite.com/blog 并把 root 设为 /blog/。(引用自官方文档)
permalink: :year/:month/:day/:title/ #固定链接格式。这项配置的格式为:变量1/变量2/变量3...,其中合法的变量格式为“:变量名”(注意,:是变量的组成部分!)这样生成的效果为/2016/08/10/文章标题。默认的固定链接格式存在一些问题,下文讲解
per_page: 10 #设置每页文章篇数,设为0可以关闭分页功能
theme: #使用的主题。下文讲解
deploy: #部署配置,其值是一个杂凑表,注意缩进,下文详细讲解

如果你想了解更多自定义配置项(就个人安装体验来说,其实很多选项保持默认即可),请看上面的官方文档链接。

更换主题

PS:下文以home代指Hexo根目录
Hexo的主题存储在home/themes目录下(我使用unix的文件路径表示法,Git Bash可以兼容这种表示法)。我们只要将喜欢的主题下载到这个目录下,解压为文件夹,然后将_config.yml中的

1
theme:

配置项改为对应主题文件夹名称即可。
这里特别提醒,主题自身也有一个_config.yml配置文件,配置主题本身需要的一系列选项。语境中通常称为主题配置文件,请勿与站点配置文件混淆。

另外,强力推荐本站使用的Hexo主题:Next,功能极其强大,是目前github上star第一的Hexo主题。传送门官方文档讲解非常详细,鉴于篇幅,这里只提一个小技巧,在文章中加入<!--more-->标签,主题会自动将标签之前的内容截取作为文章摘要输出在首页。(可见本站效果)。
顺便说一句,Hexo自带的主题颜值也是很不错的(秒杀WordPress几千倍),不妨用用~

写作

执行

1
hexo new post "标题"

可以新建一篇文章。post参数可以省略,_config.yml中的default_layout:设置了默认类型,默认值是post,你可以改成draft来默认存储为草稿(PS:感觉并没有什么卵用,草稿也可以存为post,不生成部署即可)

然后用任意你喜欢的编辑器打开home/source/_post/标题.md文件就可以写作了。(PS:Windows下优雅的markdown编辑器实在是少之又少,OS X下我用的是MWeb,功能非常强大)

下面讲解一下写作中可能碰到的几个问题。

自定义链接格式太蠢

可能语言不是很严谨,不过给我的第一感觉就是这样。由于链接最后没有带上.html后缀名,而且生成文件的MIME类型似乎不太对,导致用默认链接格式的话,nginx web server会直接进行文件下载。。。能不能像WordPress那样,为每篇文章自定义一个简短的英文名称作为链接呢?

答案是可以的。我们需要用到Hexo的permalinkFront-matter选项。先编辑模板文件home/scaffolds/post.md,在其Front-matter中加入permalink:即可。如下图所示:

记得在写一篇新文章时设置一下这个值。

分类和标签

默认的主题菜单栏是没有标签和分类两个页面的。而且默认的模板中Front-matter也只有tags选项,没有分类选项。是不是Hexo没有这些功能呢?答案是否定的。

PS:这两个选项的值都是一个清单,注意缩进。

编辑模板文件home/scaffolds/post.md,加入categories:,如图所示:

然后执行

1
2
hexo new page categories
hexo new page tags

创建标签和分类页面,如果你的主题支持,它们不需要填充任何内容,主题会自动生成这两个页面的内容,你只需要将它们加入菜单栏即可。(这并不意味着不用生成这两个页面)
默认主题菜单栏修改方法如下:
编辑home/themes/landscape/_config.yml文件,在menu:项下加入显示名称: 路径即可,如下图所示:

评论功能

这个主要看主题是否支持。例如我使用的next主题,支持多说和disqus两套系统。特别提醒,由于本身是静态化的,所以必须依靠第三方服务提供评论功能。

如果想让某篇文章禁用评论功能,next主题需要在Front-matter中加入:

1
comment: false

一般来说页面都不需要评论功能,可以编辑home/scaffolds/page.md,在Front-matter中加入

1
comment: false

搜索功能

仍然依靠主题支持(逃)
再次安利一波next主题。

OS X下优雅的写作方式

(对不起Windows读者,毕竟win下实在没有像OS X的MWeb这么优雅的Markdown编辑器,sublime text可以勉强顶上)
强烈推荐OS X下的优雅的Markdown编辑器MWeb for OS X。点这里直达MAS下载免费试用版。(试用版功能同样强大,我正在考虑是否入正)

写作时最大的一个问题是如何优雅的插入图片。MWeb提供了高效解决方案。在home/source下新建一个images文件夹,然后打开MWeb,按command+E打开外部模式,然后如图设置:

选择“引入文件夹”。定位到home下,点击source,并单击“选择”按钮(免费版外部模式只能引入一个文件夹。)如下图配置:

在写作时,只要把图片文件拖入编辑器中,就能自动复制到iamges下并且在文档中插入markdown图片链接,简直coooooooooool有木有!而且还支持直接从剪贴板插入图片,截图后只需command+V,同样自动复制到images下并帮你加好markdown标记。

另外,OS X 10.11及以上可以使用Split Views功能来实现优雅的分屏。长按窗口左上角的绿色最大化按钮,即可启动,此时该app占据新虚拟桌面的一半,然后点击另一个桌面上的窗口,即可自动将两个app在同一桌面中分屏。你也可以启动mission control后,直接将一个窗口状态的app拖到任何一个space中,也可自动分屏。我的写作界面如下图所示。

预览

执行

1
hexo generate

命令,生成静态文件。
执行

1
hexo server

命令,本地开启服务器,然后浏览器访问http://localhost:4000即可看到预览效果了。

部署

敲黑板!最后一个重点难点内容,如何将public文件夹下的内容发布到服务器上。

1.Github Pages
这个服务允许github用户发布静态页面,无限空间流量,适合轻度用户。我没有采用这种方法,限于篇幅也不会介绍,如果你需要,Google之。

2.直接复制
理论上可行的方法。毕竟public下的文件到哪里都能直接变成一个可运行的站点。但是这种方法太蠢了,看似可行,其实蕴含着一大堆问题,比如,无效流量、重复文件……

3.Git版本控制系统
官方支持的部署方式之一。利用Git版本控制系统的强大功能,通过ssh上传文件。这也是我采用并且下文讲解的方法。

4.Heroku
没有了解过这个方式。

5.Openshift
Openshift是著名厂商Red Hat的PaaS服务,功能十分强大。关于如何使用该服务的教程网上已经很多,限于篇幅不再介绍。(如果各位有需要,我会考虑另开文章讲解,毕竟这个平台是相当好用的,请留言)

6.rsync
利用强大的同步工具rsync进行同步,这种同步方式只需要用户提供一个能访问bash的Linux用户,并且服务器上安装了rsync软件包,其余一切涉及rsync命令的操作都由hexo自动完成,更加简单。推荐新手使用这种方式。

7.FTPsync
直接通过FTP协议进行同步。如果购买了虚拟主机,可以考虑这种方式。然而这个插件写得也很蠢。第一次使用必须自己手动上传所有文件,否则会无限报连接被重置错误(我就不配图了,工作量有点大)。

基于上述方式的优缺点,本文将讲解如何使用Git和rsync进行服务端部署。

Git版本控制系统
服务端配置

PS:从此开始home不再代指Hexo安装目录
1.编译安装nginx
执行以下命令下载nginx源码:

1
2
3
cd /usr/local/src
wget http://nginx.org/download/nginx-1.11.3.tar.gz
tar xzf nginx-1.11.3.tar.gz

编译cloudflare patch过的openssl(如果你不使用HTTPS可以跳过本步骤)

1
2
3
4
5
6
cd /usr/local/src
wget https://www.openssl.org/source/openssl-1.0.2h.tar.gz
tar xzf openssl-1.0.2h.tar.gz
git clone https://github.com/cloudflare/sslconfig
cd openssl-1.0.2h
patch -p1 < ../sslconfig/patches/openssl__chacha20_poly1305_cf.patch

编译安装nginx

1
2
3
4
5
6
7
8
9
apt-get install libpcre3 libpcre3-dev zlib1g zlib1g-dev #非Debian/Ubuntu系统请参考自己的包管理器
groupadd www
useradd www -g www -s /sbin/nologin
cd /usr/local/src/nginx-1.11.3
./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-http_v2_module --with-openssl=../openssl-1.0.2h
make -j`$(nproc)`
make install
ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx
#如果你不需要SSL,请在configure时去掉--with-http_ssl_module与--with-http_v2_module,鉴于ipv6并不普及,我也没有使用ipv6

执行nginx -V测试是否安装成功。

2.配置Git仓库
我习惯把网站目录放在/home/wwwroot下,因此先建立文件夹:

1
2
mkdir -p /home/wwwroot/hexo.git #Git仓库,不存储网站文件
mkdir /home/wwwroot/hexo #实际存储网站文件目录

执行

1
apt-get install git #Debian系系统,其他发行版参考自己的包管理器

安装Git。
执行如下命令,初始化空的Git仓库:

1
git init --bare /home/wwwroot/hexo.git

然后进入该仓库,配置post-receivehooks。

钩子(hooks)是一些在”$GIT-DIR/hooks”目录的脚本, 在被特定的事件(certain points)触发后被调用 。当”git init”命令被调用后, 一些非常有用的示例钩子文件(hooks)被拷到新仓库的hooks目录中; 但是在默认情况下这些钩子(hooks)是不生效的 。 把这些子文件(hooks)的”.sample”文件名后缀去掉就可以使它们生效了。
需要关注的是post-receive的钩子,当push操作完成之后这个钩子就会被调用。


1
cd /home/wwwroot/hexo.git/hooks

建立post-receive文件,输入:

1
2
#!/bin/sh
git --work-tree=/home/wwwroot/hexo --git-dir=/home/wwwroot/hexo.git checkout -f

赋予可执行权限:

1
chmod +x post-receive

上述所有命令记得替换成你自己的文件路径
之后来配置登陆Git需要的用户。
执行

1
adduser git

要求填写密码和一系列信息。完成后自动建立/home/git主目录以及git用户组。
先确认一下你的SSH服务端配置,因为hexo的Git部署不支持使用密码登陆,我们需要生成一对密钥。

1
vim /etc/ssh/sshd_config#Debian系系统可用,其他系统参考自己的路径

检查这三行是否被注释以及值是否正确。

1
2
3
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys

如果不正确进行修改,重启ssh

1
service ssh restart#服务名不同发行版不同,这是Debian系的名称

然后生成一对ssh认证密钥。

1
2
3
4
5
su git
cd /home/git
mkdir .ssh
cd .ssh
ssh-keygen -t rsa

在生成密钥时,会要求你输入一个加密密码,可以不填写,实现无密码登陆。

生成完成后,.ssh目录下有id_rsaid_rsa.pub两个文件,其中.pub文件是公钥文件,存放于服务器,另一个是私钥文件,存放于客户端。两者都是文本文件,可以直接用cat命令读取。将id_rsa下载回本地保存好。之后配置需要用到。
将公钥id_rsa.pub重命名并授予正确的权限。

1
2
3
4
5
cd /home/git/.ssh
mv id_rsa.pub authorized_keys
chmod 0600 authorized_keys
chmod 0700 .
rm id_rsa

3.nginx web server配置
首先建立虚拟主机配置文件夹:

1
mkdir /usr/local/nginx/conf/vhost

修改主配置文件

1
vim /usr/local/nginx/conf/nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
user www;
...
event{
...
use epoll;
}
http{
...
sendfile on;
tcp_nopush on;
tcp_nodelay on;
...
include vhost/*.conf;
...
server{
...
}
...
}
...

修改后文件内容如上,…代表省略内容。
然后建立虚拟主机配置文件。

1
2
cd /usr/local/nginx/conf/vhost
touch hexo.conf

一个最基本的Hexo配置如下:

1
2
3
4
5
6
server{
listen 80;
server_name domain.com; #与你在_config.yml中的配置相同(不需要带上协议)
root /home/wwwroot/hexo; #Hexo文件存储路径,非Git仓库
index index.html;
}

加入缓存配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server{
listen 80;
server_name domain.com; #与你在_config.yml中的配置相同(不需要带上协议)
root /home/wwwroot/hexo; #Hexo文件存储路径,非Git仓库
index index.html;
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|ico)$ {
expires 30d;
access_log off;
}
location ~ .*\.(js|css)?$ {
expires 7d;
access_log off;
}
}

本站是全站HTTPS,使用Let’s encrypt证书,对HTTPS有大量配置,下面是本站的配置文件:

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
server{
server_name hexo.n4l.pw;
listen 80;
location ^~ /.well-known/acme-challenge/ {
alias /home/wwwroot/challenges/;
try_files $uri =404;
}
location / {
rewrite ^/(.*)$ https://hexo.n4l.pw/$1 permanent;
}
}
server {
server_name hexo.n4l.pw;
listen 443 ssl http2 reuseport fastopen=3;
root /home/wwwroot/staticblog;
server_tokens off;
ssl_certificate /root/ssl/n4l.pw.chained.pem;
ssl_certificate_key /root/ssl/private-ecc.key;
ssl_certificate /root/ssl/rsas/n4l.pw.rsa.chained.pem;
ssl_certificate_key /root/ssl/rsas/n4l.pw.rsa.key;
ssl_dhparam /root/ssl/dhparams.pem;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp384r1;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ct on;
ssl_ct_static_scts /root/ssl/scts;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 10s;
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
add_header Public-Key-Pins 'pin-sha256="YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=";pin-sha256="Fbs+o+IxVNTHBpjNQYfX/TBnxPC+OWLYxQLEtqkrAfM=";max-age=2592000; includeSubDomains';
index index.html;
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|ico)$ {
expires 30d;
access_log off;
}
location ~ .*\.(js|css)?$ {
expires 7d;
access_log off;
}
}

保存你的配置文件,执行以下命令建立nginx服务并设置开机启动:

1
2
3
wget https://raw.github.com/JasonGiedymin/nginx-init-ubuntu/master/nginx -O /etc/init.d/nginx
chmod +x /etc/init.d/nginx
update-rc.d nginx start 20 2 3 4 5

完成之后,执行

1
service nginx start

即可启动nginx。

本地配置

1.本地SSH配置。
本地ssh命令也依靠一个配置文件。用户定义配置文件的路径是~/.ssh/config(PS:这一路径对Windows是可用的,如果你使用Git Bash,这就是为什么我强烈推荐Git Bash的原因)
建立文件夹:

1
2
mkdir ~/.ssh
touch ~/.ssh/config

编辑config文件,写入如下配置:

1
2
3
4
5
Host hexo #SSH主机配置的识别名,配置好后直接"ssh 识别名"即可快速连接
HostName xxx #SSH主机的地址
Port 22 #SSH主机端口
User git #用户,本例是Git
IdentityFile ~/.ssh/testkey #私钥文件的存放地址,建议复制到~/.ssh下统一管理

然后执行

1
2
chmod 0600 ~/.ssh/testkey #换成你自己的私钥路径
ssh hexo

如果可以正常连接,说明我们的Git服务端已经配置成功。为了安全考虑,git用户禁止登陆shell,以root用户登陆服务器,编辑/etc/passwd文件,找到git:x:1002:1002:,,,:/home/git:内容,修改为git:x:1002:1002:,,,:/home/git:/usr/bin/git-shell。git-shell一旦登陆就会自动退出,但又能正常使用Git版本控制功能。(PS:中间的两个数字是UserID和GroupID,可能有所不同,没有影响,不要随意修改

2.配置部署选项
PS:此节中home代指Hexo站点目录
执行以下命令安装hexo git部署模块

1
2
cd home
npm install hexo-deployer-git --save

编辑home/_config.yml文件,找到deploy项目,修改如下:

1
2
3
4
deploy:
type: git #用户名
repo: git@hexo:/home/wwwroot/hexo.git #Git仓库地址,:符号后为Git仓库服务器路径
branch: master #分支,由于我们只用Git进行发布,master即可。

保存,进入home目录,执行:

1
2
hexo clean
hexo deploy -g

即可将静态文件发布到服务端了。

至此,一切(woc终于结束了)搭建步骤完成,快访问你的域名看看效果吧~(解析请自行完成)

rsync远程同步工具
服务端配置

1.安装rsync服务端
执行以下命令安装rsync

1
2
3
apt-get install rsync #Ubuntu安装
yum install rsync #centos安装
pacman -S rsync #archlinux安装

建立服务端的网站文件夹

1
mkdir -p /home/wwwroot/hexo #我习惯将网站文件存储在/home/wwwroot下,你可以更改成你自己的喜好

2.配置rsync用户
执行

1
adduser hexo

要求填写密码和一系列信息。完成后自动建立/home/hexo主目录以及hexo用户组。
先确认一下你的SSH服务端配置,因为hexo的rsync部署也需要连接ssh,不支持使用密码登陆,我们需要生成一对密钥。

1
vim /etc/ssh/sshd_config#Debian系系统可用,其他系统参考自己的路径

检查这三行是否被注释以及值是否正确。

1
2
3
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys

如果不正确进行修改,重启ssh

1
service ssh restart#服务名不同发行版不同,这是Debian系的名称

然后生成一对ssh认证密钥。

1
2
3
4
5
su hexo
cd /home/hexo
mkdir .ssh
cd .ssh
ssh-keygen -t rsa

在生成密钥时,会要求你输入一个加密密码,可以不填写,实现无密码登陆。

生成完成后,.ssh目录下有id_rsaid_rsa.pub两个文件,其中.pub文件是公钥文件,存放于服务器,另一个是私钥文件,存放于客户端。两者都是文本文件,可以直接用cat命令读取。将id_rsa下载回本地保存好。之后配置需要用到。
将公钥id_rsa.pub重命名并授予正确的权限。

1
2
3
4
5
cd /home/hexo/.ssh
mv id_rsa.pub authorized_keys
chmod 0600 authorized_keys
chmod 0700 .
rm id_rsa

3.nginx
执行以下命令下载nginx源码:

1
2
3
cd /usr/local/src
wget http://nginx.org/download/nginx-1.11.3.tar.gz
tar xzf nginx-1.11.3.tar.gz

编译cloudflare patch过的openssl(如果你不使用HTTPS可以跳过本步骤)

1
2
3
4
5
6
cd /usr/local/src
wget https://www.openssl.org/source/openssl-1.0.2h.tar.gz
tar xzf openssl-1.0.2h.tar.gz
git clone https://github.com/cloudflare/sslconfig
cd openssl-1.0.2h
patch -p1 < ../sslconfig/patches/openssl__chacha20_poly1305_cf.patch

编译安装nginx

1
2
3
4
5
6
7
8
9
apt-get install libpcre3 libpcre3-dev zlib1g zlib1g-dev #非Debian/Ubuntu系统请参考自己的包管理器
groupadd www
useradd www -g www -s /sbin/nologin
cd /usr/local/src/nginx-1.11.3
./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-http_v2_module --with-openssl=../openssl-1.0.2h
make -j`$(nproc)`
make install
ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx
#如果你不需要SSL,请在configure时去掉--with-http_ssl_module与--with-http_v2_module,鉴于ipv6并不普及,我也没有使用ipv6

执行nginx -V测试是否安装成功。

之后进行nginx配置。
首先建立虚拟主机配置文件夹:

1
mkdir /usr/local/nginx/conf/vhost

修改主配置文件

1
vim /usr/local/nginx/conf/nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
user www;
...
event{
...
use epoll;
}
http{
...
sendfile on;
tcp_nopush on;
tcp_nodelay on;
...
include vhost/*.conf;
...
server{
...
}
...
}
...

修改后文件内容如上,…代表省略内容。
然后建立虚拟主机配置文件。

1
2
cd /usr/local/nginx/conf/vhost
touch hexo.conf

一个最基本的Hexo配置如下:

1
2
3
4
5
6
server{
listen 80;
server_name domain.com; #与你在_config.yml中的配置相同(不需要带上协议)
root /home/wwwroot/hexo; #Hexo文件存储路径,非Git仓库
index index.html;
}

加入缓存配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server{
listen 80;
server_name domain.com; #与你在_config.yml中的配置相同(不需要带上协议)
root /home/wwwroot/hexo; #Hexo文件存储路径,非Git仓库
index index.html;
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|ico)$ {
expires 30d;
access_log off;
}
location ~ .*\.(js|css)?$ {
expires 7d;
access_log off;
}
}

本站是全站HTTPS,使用Let’s encrypt证书,对HTTPS有大量配置,下面是本站的配置文件:

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
server{
server_name hexo.n4l.pw;
listen 80;
location ^~ /.well-known/acme-challenge/ {
alias /home/wwwroot/challenges/;
try_files $uri =404;
}
location / {
rewrite ^/(.*)$ https://hexo.n4l.pw/$1 permanent;
}
}
server {
server_name hexo.n4l.pw;
listen 443 ssl http2 reuseport fastopen=3;
root /home/wwwroot/staticblog;
server_tokens off;
ssl_certificate /root/ssl/n4l.pw.chained.pem;
ssl_certificate_key /root/ssl/private-ecc.key;
ssl_certificate /root/ssl/rsas/n4l.pw.rsa.chained.pem;
ssl_certificate_key /root/ssl/rsas/n4l.pw.rsa.key;
ssl_dhparam /root/ssl/dhparams.pem;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp384r1;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ct on;
ssl_ct_static_scts /root/ssl/scts;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 10s;
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
add_header Public-Key-Pins 'pin-sha256="YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=";pin-sha256="Fbs+o+IxVNTHBpjNQYfX/TBnxPC+OWLYxQLEtqkrAfM=";max-age=2592000; includeSubDomains';
index index.html;
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|ico)$ {
expires 30d;
access_log off;
}
location ~ .*\.(js|css)?$ {
expires 7d;
access_log off;
}
}

保存你的配置文件,执行以下命令建立nginx服务并设置开机启动:

1
2
3
wget https://raw.github.com/JasonGiedymin/nginx-init-ubuntu/master/nginx -O /etc/init.d/nginx
chmod +x /etc/init.d/nginx
update-rc.d nginx start 20 2 3 4 5

完成之后,执行

1
service nginx start

即可启动nginx。

本地配置

1.本地SSH配置。
本地ssh命令也依靠一个配置文件。用户定义配置文件的路径是~/.ssh/config(PS:这一路径对Windows是可用的,如果你使用Git Bash,这就是为什么我强烈推荐Git Bash的原因)
建立文件夹:

1
2
mkdir ~/.ssh
touch ~/.ssh/config

编辑config文件,写入如下配置:

1
2
3
4
5
Host hexo #SSH主机配置的识别名,配置好后直接"ssh 识别名"即可快速连接
HostName xxx #SSH主机的地址
Port 22 #SSH主机端口
User hexo #用户,本例是hexo
IdentityFile ~/.ssh/testkey #私钥文件的存放地址,建议复制到~/.ssh下统一管理

然后执行

1
2
chmod 0600 ~/.ssh/testkey #换成你自己的私钥路径
ssh hexo

如果连接成功就说明用户配置成功了。注意,这种方式需要用户具有访问bash的权限,因此请注意自己服务器的权限控制。
2.配置部署选项
执行以下命令安装hexo rsync部署模块

1
2
3
cd home
npm install hexo-deployer-rsync --save #OS X和Linux用户执行
npm install hexojs/hexo-deployer-rsync --save #Windows用户执行,npm上的该模块在windows下有bug

PS:此节中home代指Hexo站点目录
编辑home/_config.yml文件,找到deploy项目,修改如下:

1
2
3
4
5
6
7
8
9
deploy:
type: rsync
host: hexo #在~/.ssh/config中配置的host名称
user: hexo #登陆用户名
root: /home/wwwroot/hexo #网站文件夹
port: 873 #登陆后在服务器上开启rsync的端口,如果你的VPS有防火墙,需要开放该端口
delete: true #是否删除旧文件,可选true或false
verbose: false #是否输出调试信息,如果不能部署成功可以开启看原因
ignore_errors: true #是否忽略错误,可选true或false

以root登陆VPS,执行

1
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 873 -j ACCEPT #记得换成你自己的端口

来开放_config.yml中配置的rsync端口,如果没有iptables可以跳过这一步。
保存,进入home目录,执行:

1
2
hexo clean
hexo deploy -g

即可将静态文件发布到服务端了。

至此,一切(woc终于结束了)搭建步骤完成,快访问你的域名看看效果吧~(解析请自行完成)

TroubleShooting

如果各位在阅读本文过程中有任何不理解的问题,或者任何步骤出错,解决方法如下:

  1. 再仔细看一遍本文,是否有遗漏步骤
  2. 由于系统环境不同,你的系统可能与我有很大差别,请Google搜索你的错误信息
  3. 若上述方法无果,或你发现本文有任何错误,欢迎在评论区留言指出,对于有意义的问题,我会摘录在这一节中。
  4. 如果您发现本文引用或涉及了您的有关文章,请在下方留言,我会尽快加入参考中。

@咖啡费德克士 提出的问题:

我的博客中既有http又有https,然后浏览器就给拦截了部分js,有什么解决方法吗?

出于安全策略,浏览器默认不会加载HTTPS网页中的HTTP脚本文件。如果网站有HTTP和HTTPS版本,建议先对自己网站的访客做一个统计,看一下他们的软件版本。如果兼容性不是太大的问题,建议切换到全站HTTPS,禁用HTTP。

如果是引用了一些公共库,比如jQuery之类,建议直接Google搜索:公共库名+HTTPS+CDN,即可找到对应公共库支持HTTPS的CDN。PS:目前主流浏览器支持自适应协议栈,即写链接时省略协议栈,写成//domian.com,浏览器会根据当前页面的协议自动选择HTTP/HTTPS

另外,也可以使用一些简单粗暴的办法。比如直接将HTTP资源下载到本地,然后引用本地的链接。如果是多说评论头像之类,可以尝试反代评论头像。

更新记录

2016-08-11
更新rsync部署方式,重新调整文章排版,修复了一些小的bug
鸣谢V2EX @Remember

参考

PS:本文写作时间:一整天+一个晚上