将Hexo博客部署到Linux云服务器

摘要: 在阿里云CentOS服务器上创建私有Git仓库, 通过Git hooks(钩子),将Hexo生成的博客静态页面文件,推送到Nginx web服务器的托管目录, 完成部署。

前言

Github Pages的缺陷

在此之前,Hexo个人博客部署在GitHub Pages上。因为Github Pages服务器在国外,所以访问速度比较慢,同时,Github屏蔽了百度的爬虫,不能被百度收录。为此,决定将Hexo博客部署到阿里云CentOS服务器上。

最终成果

部署在Github Pages上的博客:https://gerongcun.github.io/
部署在阿里云CentOS服务器上的博客:http://www.gerongcun.xyz/

gerongcun.xyz网站主页

涉及到的知识

服务器:购买阿里云服务器、Linux;
域名:注册域名、域名解析、ICP备案、公安联网备案;
部署博客:Linux、Nginx、Git、Node.js;

服务器和域名

购买服务器

阿里云推出云翼计划,年龄在12岁~24岁之间的大陆个人实名认证用户和大陆全日制在校大学生在学生认证有效期内,满足上述任一条件即可享受优惠价格。
参考了老骥伏枥阿里云ECS、轻量应用服务器、云虚拟主机、云速成美站自助建站系统该如何选择文章,购买了1核2G、1M带宽、40G高效云盘的云服务器ECS。

参考资料:
云翼计划购买链接
阿里云ECS、轻量应用服务器、云虚拟主机、云速成美站自助建站系统该如何选择

选择操作系统

一开始选的是Windows Server,发现网上教程太少,换用Linux系统。CentOS和ubuntu是两款比较火的Linux系统。网上的观点是CentOS更适用于服务器(稳定、bug少),Ubuntu则更适用于个人桌面(图形界面、功能更新快)。同时,搜索了部署Hexo博客教程,感觉CentOS关于部署Hexo博客的教程比较多,就选择了CentOS系统。
参考文献:ubuntu与centos对比

注册域名

域名注册网站有国外的GoDaddy和国内的阿里云(万网)。因为国外域名不能备案,所以选择了阿里云。
参考文献:云师兄-关于域名备案那些事

域名备案

域名备案分为ICP(Internet Content Provider,网络内容提供商)备案和公安联网备案,流程如下图所示:
域名备案图片
ICP备案可以用阿里云ICP代备案管理系统;公安联网备案只能登录全国互联网安全管理服务平台操作。
参考资料:阿里云-ICP备案流程概述

备案相关规定
《互联网信息服务管理办法》指出互联网信息服务分为经营性和非经营性两类。国家对经营性互联网信息服务实行许可制度;对非经营性互联网信息服务实行备案制度。未取得许可或者未履行备案手续的,不得从事互联网信息服务。

备案实例
ICP百度百科词条网页为例。下滑到网页底部,可以看到:
域名备案图片
“京ICP证030173号”是域名baidu.com的ICP备案编号,“京公网安备11000002000001号”是公安联网备案编号。

部署Hexo博客

部署Hexo博客原理

设置Nginx根目录
整个流程就是本地将*.md 渲染成静态文件,然后Git推送到服务器的repository,服务器再通过git-hooks同步到网站根目录(Nginx服务的托管目录),完成部署。
参考资料:
Hexo部署在阿里云服务器上

学习Linux

在部署Hexo之前,需要学习Linux。我找了两份教程,分别是Linux Tools Quick Tutorial Linux工具快速教程蔡德明-鸟哥的linux私房菜
本着先入门再精通的原则,选择了篇幅比较少的Linux Tools Quick Tutorial,看了两章,觉得解释太少,看不下去;又开始看《鸟哥的linux私房菜》,篇幅长是长了点,但是解释得好,可以看下去。刚好借此机会,熟悉了繁体字(鸟哥是台湾人)。
参考资料:程序员良许-学习Linux有没有比《鸟哥的Linux私房菜》更好的书

SSH远程连接Linux服务器

shell、Xshell、SSH介绍

什么是shell
inux系统由硬件、内核(核心、kernel)、shell三部分组成。

shell
操作系统(kernel,核心)是一组软件,控制整个硬件与管理系统的活动监测。如果这组软件能被用户随意的操作,若使用者应用不当,将会使得整个系统崩溃!但是我们总是需要让用户操作系统的,所以就有了在操作系统上面发展的应用程序(shell,壳程序)啦!

linux组成
用户可以透过shell来指挥核心,让核心达成我们所需要的硬件任务!我们可以发现shell其实是在最外层,就如同鸡蛋的外壳一样,因此就被称呼为壳程序 (shell) !

只要能够操作应用程序的接口都能够称为壳程序。狭义的壳程序指的是命令行之类的软件。 广义的壳程序则包括图形接口的软件!因为图形接口其实也能够操作各种应用程序来呼叫核心工作啊!

参考文献:
linux系统组成——硬件、内核、shell
鸟哥-认识BASH这个Shell

下载Xshell
Xshell可以在Windows界面下用来访问远端不同系统下的服务器,从而比较好的达到远程控制终端的目的。下载地址:Xshell官网。用途请选择个人使用,提交邮箱信息。

SSH原理
Secure Shell(SSH) 是由 IETF(The Internet Engineering Task Force) 制定的建立在应用层基础上的安全网络协议。它是专为远程登录会话(甚至可以用Windows远程登录Linux服务器进行文件互传)和其他网络服务提供安全性的协议,可有效弥补网络中的漏洞。通过SSH,可以把所有传输的数据进行加密,也能够防止DNS欺骗和IP欺骗。还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。目前已经成为Linux系统的标准配置。

SSH的安全机制
SSH之所以能够保证安全,原因在于它采用了非对称加密技术(RSA)加密了所有传输的数据。

传统的网络服务程序,如FTP、Pop和Telnet其本质上都是不安全的;因为它们在网络上用明文传送数据、用户帐号和用户口令,很容易受到中间人(man-in-the-middle)攻击方式的攻击。就是存在另一个人或者一台机器冒充真正的服务器接收用户传给服务器的数据,然后再冒充用户把数据传给真正的服务器。

但并不是说SSH就是绝对安全的,因为它本身提供两种级别的验证方法:

第一种级别(基于口令的安全验证):只要你知道自己帐号和口令,就可以登录到远程主机。所有传输的数据都会被加密,但是不能保证你正在连接的服务器就是你想连接的服务器。可能会有别的服务器在冒充真正的服务器,也就是受到“中间人攻击”这种方式的攻击。

第二种级别(基于密钥的安全验证):你必须为自己创建一对密钥,并把公钥放在需要访问的服务器上。如果你要连接到SSH服务器上,客户端软件就会向服务器发出请求,请求用你的密钥进行安全验证。服务器收到请求之后,先在该服务器上你的主目录下寻找你的公钥,然后把它和你发送过来的公钥进行比较。如果两个密钥一致,服务器就用公钥加密“质询”(challenge)并把它发送给客户端软件。客户端软件收到“质询”之后就可以用你的私钥在本地解密再把它发送给服务器完成登录。与第一种级别相比,第二种级别不仅加密所有传输的数据,也不需要在网络上传送口令,因此安全性更高,可以有效防止中间人攻击。
SSH原理

远程主机上的authorized_keys文件中可以保存多个公钥。多个公钥直接追加在末尾。
了解ssh免密登录的过程,再回过头来,我们发现其实这种方式和远程主机的密码没有任何关系,我们无需知道密码,或者密码随便更改,我们只要保证远程主机有我们的公钥,而我们本地有这么一对公钥和私钥就可以了。

SSH只是一种协议,存在多种实现,既有商业实现,也有开源实现。OpenSSH是免费开源实现在Ubuntu、CentOS中的应用。OpenSSH分为客户端openssh-client和服务器openssh-server,阿里云CentOS服务器默认安装了openssh。

SSH口令远程登录

口令登录非常简单,只需要一条命令,命令格式为:ssh 客户端用户名@服务器ip地址,如ssh root@118.31.174.117,然后输入口令(密码)。
CentOS服务器的默认账号是root,密码需要自己设置。设置方法如下:
进入阿里云控制台,点击更多-实例设置-重置实例密码。
设置实例密码

SSH密钥远程登录

每次登录远程主机都需要输入密码是很不方便的,如果想要省去这一步骤,可以利用密钥对进行连接,还可以提高安全性。

1、在本机生成密钥对
使用Git Bash而不是xshell。
输入ssh-keygen -t rsa #-t表示类型选项,这里采用rsa加密算法
生成密钥
这里强烈建议不要使用默认文件名id_rsa作为文件名,后面会提到(覆盖了Github的SSH密钥,导致hexo d时,无法连接github仓库;以后还会提到),可以添加客户端用户名信息,比如id_rsa_root(root为用户名)。

下面的命令提示输入密钥的密码:
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
直接连按两次Enter,不设置密码。

密钥一般存放在~/.ssh文件目录内。~表示用户家(home)目录,一般是C:\Users\+用户名,比如我的家目录是C:\Users\16121,用户名为16121。

用Git Bash进入.ssh文件目录后,
输入cat id_rsa_root.pub
查看windows本机上的公钥。

2、将公钥复制到远程主机中
使用ssh-copy-id命令将公钥复制到远程主机。ssh-copy-id会将公钥写到远程主机的~/.ssh/authorized_key文件中。
输入
ssh-copy-id root@118.31.174.117
没有指定密钥,则将id_rsa.pub复制到远程主机。
ssh-copy-id -i id_rsa_root root@118.31.174.117
指定了密钥,则将对应的公钥文件id_rsa_root.pub复制到远程主机。

在远程主机上
cd ~/.ssh
打开家目录下的.ssh目录
cat authorized_keys
查看公钥文件是否写入了authorized_keys文件。

可能还要设置.ssh和authorzied_keys的权限
chmod 600 ~/.ssh/authorzied_keys
chmod 700 ~/.ssh

报错Add correct host key
报错信息:

1
2
3
4
ERROR: Add correct host key in /c/Users/16121/.ssh/known_hosts to get rid of this message.
ERROR: Offending ECDSA key in /c/Users/16121/.ssh/known_hosts:8
ERROR: ECDSA host key for 118.31.174.117 has changed and you have requested strict checking.
ERROR: Host key verification failed.

报错Add correct host key

报错原因及解放方法:
查看本机的.ssh目录下的known_hosts文件;
因为我重装了CentOS系统,known_hosts文件残留之前的主机信息;
删除之前的信息,再次复制公钥,成功。

3、验证是否可以SSH密钥登录
在Xshell或者Git Bash(Git Bash也能远程登录!)中输入:
ssh root@118.31.174.117
如果登录成功,表明可以密钥登录。

在远程主机上,输入
cat ~/.ssh/authorized_keys
可以查看添加的公钥信息。

参考文献:
SSH简介及两种远程登录的方法

安装Nginx、Git、Hexo

安装Nginx

安装Nginx
CentOS默认安装Nginx。
通过yum search nginx看看是否已经添加源成功。如果成功则执行下列命令安装Nginx。
sudo yum install -y nginx
启动Nginx并设置开机自动运行
sudo systemctl start nginx.service
sudo systemctl enable nginx.service

检验是否安装成功
在浏览器输入远程主机的ip或者域名;如<118.31.174.117>或者<www.gerongcun.xyz>。
显示如下画面:
安装Nginx成功后的画面
如果没有成功,可能是端口没打开。默认端口是80端口(http协议默认端口),如果没有打开,可以进入阿里云控制台,添加安全组规则。

nginx的常用命令
验证配置是否正确: nginx -t
查看Nginx的详细的版本号:nginx -V
查看Nginx的简洁版本号:nginx -v
启动Nginx:nginx
快速停止或关闭Nginx:nginx -s stop
正常、完整停止或关闭Nginx:nginx -s quit
重新打开日志文件nginx -s reopen
重新启动service nginx restart
配置文件修改重装载命令:nginx -s reload
用man nginx查看其他用法
Nginx配置文件:/etc/nginx/nginx.conf

参考文献:
Linux使用yum安装nginx
nginx实战操作(常用命令及配置)
service nginx restart 重启快吗

安装Git

新建Git用户
useradd -m git
设置git用户的密码
passwd git
然后添加公钥(参考上面“SSH密钥远程登录”章节),实现SSH密钥远程登录。

创建git用户的目的是,用git用户(其实用root用户也可以)更新博客。我们可以禁用git用户的shelll登录权限配置,可以参考文献HEXO部署到云服务器详细指南

安装Node.js

安装Hexo之前,需要安装Node.js和npm。
yum安装是将yum源中的rpm包下载到本地,安装这个rpm包。这个rpm包是别人编译安装好的二进制包。这种方式方便快捷,特别是不用考虑包依赖。
输入以下命令,安装node.js和npm
yum -y install nodejs
检查Node.js和npm版本
node -v
npm -v

参考文献:
Linux(CentOS)安装Node.JS和npm的两种方式(yum安装和源码安装)

安装Hexo

输入:
npm install hexo-cli hexo-server -g
我们使用Node.js的包管理器npm安装 hexo-cli 和 hexo-server
hexo-cli 是 Hexo 的命令行工具,可用于快速新建、发布、部署博客;hexo-server 是 Hexo 的内建服务器,可用于部署前的预览和测试。-g 选项,表示全局安装。

参考文献:
HEXO部署到云服务器详细指南

git仓库和网站根目录

git仓库、根目录位置选择

将git仓库和网站根目录放在哪里是个值得考虑的问题。我现在也不是很清楚。我放在了默认目录/var/www(比较随意)。
git仓库:/var/www/gerongcun_xyz/blog.git
网站根目录:/var/www/gerongcun_xyz/website20200404/blog
website20200404表示20200404版本。

新建git仓库

定位到/var/www/gerongcun_xyz
输入git init –bare blog.git
新建一个名为blog的git仓库(空库)
改变blog.git目录的拥有者为git用户
chown -R git:git blog.git

检验新建git仓库是否成功
当上述步骤都完成后,我们就可以测试下git仓库是否创建成功,最简单的方法便是使用clone
在Git Bash中输入:
git clone git@118.31.174.117:/var/www/gerongcun_xyz/blog.git
如果复制成功,表明git仓库创建成功!

网站根目录

编辑Nginx配置文件:
vi /etc/nginx/nginx.conf
设置Nginx根目录
将root设置为/var/www/gerongcun_xyz/website20200404/blog

最后重启服务,让 Nginx 生效:
service nginx restart
PS: 不要用nginx -s reopen,这是重新打开日志的命令

改变根目录目录的拥有者为git用户
chown -R git:git /var/www/gerongcun_xyz/website20200404/blog
配置权限
chmod -R 755 /var/www/gerongcun_xyz/website20200404/blog

检验设置根目录是否成功
进入网站根目录
cd /var/www/gerongcun_xyz/website20200404/blog
创建一个txt文件
vi test.txt
输入一些内容,比如This is a file.
然后在浏览器输入gerongcun.xyz/test.txt
查看是否显示txt文件内容
判断设置根目录是否成功

参考文献:
HEXO部署到云服务器详细指南

Git hooks钩子

Git hooks简介

和其它版本控制系统一样,Git能在特定的重要动作发生时触发自定义脚本。有两组这样的钩子:客户端的和服务器端的。客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。你可以随心所欲地运用这些钩子。

钩子都被存储在 Git 目录下的 hooks 子目录中。 也即绝大部分项目中的 .git/hooks 。 当你用 git init 初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本。 这些脚本除了本身可以被调用外,它们还透露了被触发时所传入的参数。 所有的示例都是 shell 脚本,其中一些还混杂了 Perl 代码,不过,任何正确命名的可执行脚本都可以正常使用 —— 你可以用 Ruby 或 Python,或任何你熟悉的语言编写它们。 这些示例的名字都是以 .sample 结尾,如果你想启用它们,得先移除这个后缀。

参考资料:
git官方中文教程-自定义Git-Git 钩子

配置hooks

要用的是post-update钩子(用post-receive也可以,文件内容一样)
cd /var/www/gerongcun_xyz/blog.git/hooks
移除example后缀
mv post-update.example post-update
添加执行权限
chmod +x post-update
注释如下行:
exec git update-server-info
添加如下代码:
git –work-tree=”静态文件VPS存放目录” –git-dir=”刚才新建的VPS git地址” checkout -f
例如:
git –work-tree=/var/www/gerongcun_xyz/website20200404/blog –git-dir=/var/www/gerongcun_xyz/blog.git checkout -f
编辑post-update

上面那句 git 命令可以在我们每次 push 完之后,把部署目录更新到博客的最新生成状态。这样便可以完成达到自动部署的目的了。

参考文献:
HEXO部署到云服务器详细指南
在vps上搭建hexo博客

更新博客

编辑站点配置文件

编辑站点配置文件_config.yml
添加gerongcun_xyz: git@118.31.174.117:/var/www/gerongcun_xyz/blog.git
编辑_config.yml
然后
hexo clean
hexo g
hexo d
部署成功
输入网址:http://www.gerongcun.xyz/

hexo d 报错

错误信息:
git@github.com: Permission denied (publickey).
git@github.com 拒绝访问
github.com没有权限

错误原因:
如果在“SSH密钥远程登录”章节,如果使用默认文件名id_rsa作为密钥的文件名,覆盖了Github的SSH密钥,导致hexo d时,无法连接github仓库。
最好的方法时,在“SSH密钥远程登录”章节,不要使用默认文件名,添加客户端用户名信息,比如id_rsa_root(root为用户名),作为文件名。

解决方法:
方法一:重新设置linux远程主机SSH远程登录(推荐)
假设与Github的SSH密钥(id_rsa)冲突的用户为root,将root用户SSH远程登录linux主机的密钥换成id_rsa_root;同时,将id_rsa.pub公钥添加到Github的公钥列表中。

方法二:重新设置github SSH远程登录(每次都要配置,烦)
在Git Bash中定位到本机的.ssh目录
cd ~/.ssh
重新生成密钥
ssh-keygen -t rsa -C “gerongcun@gmail.com
文件命名为 id_rsa_github
登录Github,删除旧公钥
添加新公钥id_rsa_github.pub
因为密钥名称不是id_rsa,所以需要添加到ssh代理
开启ssh代理
$ eval $(ssh-agent -s)
ssh-add ~/.ssh/id_rsa_github
添加id_rsa_github到代理中

参考文献:
GitHub如何配置SSH Key
Generating a new SSH key and adding it to the ssh-agent

GeRongcun wechat
欢迎扫描二维码关注公众号一起成长~
0%