hexo部署到私有云服务器

本教程旨在通过在私有云服务器上部署git仓库,使其作为hexo的服务器,并实现deploy博客的同时vps服务器与github仓库同步更新。
注意:本教程基于centos7.5,且在root用户下开始操作。

安装工具

首先要自行安装需要的工具git、node.js和nginx。

安装node.js和hexo

方法一(此方法可能报错,建议方法二)

node.js为hexo的基本运行环境

1
yum -y install nodejs

如果找不到相应package可以先安装epel-release

1
yum install epel-release

使用n更新到最新版nodejs

1
2
npm install -g n    #安装n工具
n latest #安装最新版本node.js

可使用n查看并切换node.js版本号,切换完后用node -v命令查看当前的版本。
如果安装最新版本后且n切换版本后仍然不成功的,使用which node查看node的目录是否是系统默认使用的/bin,n是在/usr/local/bin下安装node,在安装node.js时同时安装node与npm,故npm出现的现象也与node类似。

需要将/bin目录中的node和npm备份后将/usr/local/bin/软连接到/bin目录中

1
2
ln -s /usr/local/bin/npm /bin/npm
ln -s /usr/local/bin/node /bin/node

安装hexo

1
npm install hexo-cli hexo-server -g

如果执行上述语句报错

1
2
3
4
5
6
7
8
9
10
11
12
npm ERR! Linux 5.8.5-1.el7.elrepo.x86_64
npm ERR! argv "/usr/local/bin/node" "/usr/bin/npm" "install"
npm ERR! node v15.1.0
npm ERR! npm v3.10.10

npm ERR! cb.apply is not a function
npm ERR!
npm ERR! If you need help, you may report this error at:
npm ERR! <https://github.com/npm/npm/issues>

npm ERR! Please include the following file with any support request:
npm ERR! /root/npm-debug.log

用其他方法重新安装nodejs

卸载nodejs

1
yum remove nodejs -y

node.js安装方法二

  1. 首先安装wet(安装了可以跳过此步)
1
yum install wget -y
  1. 下载nodejs最新的bin包(不是源码)

    在nodejs官方下载页https://nodejs.org/en/download/ 中找到下载地址,然后wget获取

    1
    wget https://nodejs.org/dist/v14.15.0/node-v14.15.0-linux-x64.tar.xz
  2. 解压包

    1
    2
    xz -d node-v14.15.0-linux-x64.tar.xz
    tar -xf node-v14.15.0-linux-x64.tar
  3. 部署bin文件

    找到刚解压出来的bin包,执行下面指令创建关联

    1
    2
    ln -s ~/node-v14.15.0-linux-x64/bin/node /usr/bin/node
    ln -s ~/node-v14.15.0-linux-x64/bin/npm /usr/bin/npm

    ln关联命令(类似windows创建快捷方式)必须给全路径,否则可能出错。

  4. 测试

    1
    2
    node -v
    npm

测试好之后按照 方法一 安装hexo

安装完后验证

1
hexo

安装git、nginx

git用于搭建git仓库,nginx用于搭建静态网页服务器

1
yum install git nginx -y

搭建git仓库

新建git用户并设置密码

1
2
adduser git
passwd git

修改权限

1
2
chmod 740 /etc/sudoers
vim /etc/sudoers

找到root ALL=(ALL) ALL并在其下面添加

1
git     ALL=(ALL)       ALL

保存后改回sudoer权限:

1
chmod 400 /etc/sudoers

创建免密登陆证书

在服务器中打开RSA认证

1
vim /etc/ssh/sshd_config

找到并开启(若没有则添加)

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

切换到git用户并开始配置ssh

1
2
3
su git
cd ~
mkdir .ssh && chmod 700 .ssh

接着,要为git用户里的.ssh添加开发者公钥,以便免密向git仓库存储数据。
在本地客户端通过cat ~/.ssh/id_rsa.pub找到ssh的公钥,在服务端.ssh里新建authorized_keys文件并将其复制到里面。
注意:公钥在authorized_keys文件中是一行添加一个。

1
2
3
touch /home/git/.ssh/authorized_keys
sudo chmod 600 /home/git/.ssh/authorized_keys
vim /home/git/.ssh/authorized_keys

若之前未有上传文件至github等仓库的经历,本地客户端无ssh的keys,可以通过以下教程生成
generating SSH keys

修改git用户权限

给git用户设置权限,限制其只能使用git-shell向git仓库push或pull等,而不能登陆机器并取得普通shell命令控制系统。
使用which git-shell判断是否安装了git-shell。如果未安装,则yum install git
判断shells文件路径是否存在:cat /etc/shells,如果shells文件不存在或者文件中没有/usr/bin/git-shell,则

1
sudo vim /etc/shells

在最下面添加

1
/usr/bin/git-shell

创建仓库

在/var/repo创建裸仓库(切换为root用户)

1
2
3
mkdir /var/repo
cd /var/repo
git init --bare blog.git

配置git hooks使得在仓库更新的时候,nginx配置文件中root指向的目录同步更新(这里root指向的是/var/www/hexo,具体见后边nginx服务搭建)

1
vim /var/repo/blog.git/hooks/post-receive

添加

1
2
#!/bin/sh
git --work-tree=/var/www/hexo --git-dir=/var/repo/blog.git checkout -f

保存退出并设置权限

1
chmod +x /var/repo/blog.git/hooks/post-receive

更改blog.git拥有者

1
sudo chown -R git:git blog.git

使用chsh命令修改任意系统用户的shell权限

1
sudo chsh git

Login Shell [/bin/bash]后输入:/usr/bin/git-shell
修改完后验证cat /etc/passwd是否以git-shell结尾,例如:

1
git:x:1003:1003:,,,:/home/git:/usr/bin/git-shell

修改后,在本地客户端使用ssh git@服务器ip登陆将被拒绝(第一次登陆该网址会提示continue connecting,输入yes):

1
2
3
4
$ ssh git@gitserver
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
Connection to gitserver closed.

git测试

完成上述步骤后,通过测试判断git服务器是否部署成功,在本地客户端执行

1
git clone git@服务器ip:/var/repo/blog.git

如果远程服务器禁用22端口登陆,则可以使用如下语句:

1
git clone ssh://git@serverip:port/var/repo/blog.git

输入密码后(如果秘钥配置成功则不用输入密码)若blog.git中没有内容将会提示:

1
2
3
···
git@服务器ip`s password:
warning: You appear to have cloned an empty repository

搭建nginx服务

创建根目录

1
2
3
4
mkdir /var/www
mkdir /var/www/hexo
chown -R git:git /var/www/hexo
chmod -R 755 /var/www/hexo

修改nginx配置文件

为了让浏览器能直接访问静态页面,需要使用nginx将端口或者域名指向hexo静态文件目录可通过
nginx -t命令查找配置文件,centos默认配置文件位置/etc/nginx/nginx.conf

1
vim /etc/nginx/nginx.conf

找到root修改指向/var/www/hexo(git hook目录)

1
2
3
4
5
6
7
8
···
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name www.xxx.com; # 填写个人域名若没有则为默认_
root /var/www/hexo;
}
···

配置完后重启nginx服务器

1
service nginx restart

如果出现错误:

1
2
Redirecting to /bin/systemctl start nginx.service
Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.

按照提示使用systemctl status nginx.servicejournalctl -xe命令查看错误详情,比如80端口被占用,则kill占用程序或者重新分配端口,这里出现了nginx程序自身占用,所以将nginx进程kill后重新运行servcie nginx restart即可。

如果有防火墙,记得在防火墙中开启80和8080端口:

1
2
3
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload

本地配置

在本地已经装好hexo的客户端中修改_config.yml文件

1
2
3
4
5
6
7
8
# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
repo:
github: git@github.com:用户名/仓库名
vps: git@服务器ip:/var/repo/blog.git
branch: master

服务器ssh端口修改的可以使用

ssh://git@serverip:port/var/repo/blog.git 替代git@服务器ip:/var/repo/blog.git

之后使用hexo d命令便可判断部署完成情况,该命令没有问题后即可部署至服务器。

本地部署命令提示(需要在hexo服务文件夹下操作(~/blog):

1
2
3
4
5
6
7
8
9
10
11
12
#清理
a@a:~/blog$ sudo hexo clean

#生成
a@a:~/blog$ sudo hexo g

#本地预览(预览需要CTRL+C才能结束预览)
a@a:~/blog$ sudo hexo s

#部署(针对hexo服务没有安装在root用户下,具体看 遇到的问题 章节)
a@a:~/blog$ sudo chmod 777 -R ~/blog
a@a:~/blog$ hexo d

至此配置以及部署完成,用户只需输入服务器ip即可访问博客,下面是域名解析至ip的方法

域名解析至hexo博客的服务器

  1. 找到域名提供商的解析服务,添加解析信息,要添加两条

    第一条

    ​ 记录类型:A

    ​ 主机记录:WWW

    ​ 记录值:主机ipv4地址

    第二条

    ​ 记录类型:A

    ​ 主机记录:@

    ​ 记录值:主机的ipv4地址

    主机记录就是域名前缀,常见的用法有(假设域名为:abcd.com:

  • www:解析后的域名为 www.abcd.com

  • @:直接解析主域名 abcd.com

  • :泛解析,匹配其他所有域名 *.abcd.com 记录类型: 要指向空间商提供的 IP 地址,选择「类型 A」,要指向一个域名,选择「类型 CNAME」

  • A记录:地址记录,用来指定域名的IPv4地址(如:8.8.8.8),如果需要将域名指向一个IP地址,就需要添加A记录。

  • CNAME: 如果需要将域名指向另一个域名,再由另一个域名提供ip地址,就需要添加CNAME记录。

  • NS:域名服务器记录,如果需要把子域名交给其他DNS服务商解析,就需要添加NS记录。

  • AAA:用来指定主机名(或域名)对应的IPv6地址(例如:ff06:0:0:0:0:0:0:c3)记录。

  • MX:如果需要设置邮箱,让邮箱能收到邮件,就需要添加MX记录

  1. 修改nginx配置文件,添加用户域名,见搭建nginx服务章。

添加SSL证书以https访问

将ssl证书文件上传到服务器,修改nginx配置

1
2
[root@ecs-12TLU ~]# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
[root@ecs-12TLU ~]# vim /etc/nginx/nginx.conf

将server部分修改为

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
server {
listen 80;
server_name www.yaune.site, yaune.site;
return 301 https://www.yaune.site; #http重定向到https
}

server {
listen 443 ssl;
server_name www.yaune.site, yaune.site;
root /var/www/hexo;

ssl_certificate /etc/nginx/cert/证书名.pem; #此处填写上传的证书路径
ssl_certificate_key /etc/nginx/cert/证书名.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

include /etc/nginx/default.d/*.conf;

location / {
}

error_page 404 /404.html;
location = /404.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

reload nginx,同时别忘了在防火墙中开启433端口

1
2
3
nginx	-s	reload
firewall-cmd --zone=public --add-port=433/tcp --permanent
firewall-cmd --reload

遇到的问题

  1. 安装hexo-cli和hexo-server出错,执行hexo命令报错
    解决:将nodejs更新到最新版本即可,具体见上述教程

  2. 使用hexo d命令每次都要输入密码
    解决:查看客户端的公钥与git用户.ssh文件内的公钥是否匹配,个人出现的情况是公钥等ssh配置完全没问题,问题出现在本地安装hexo客户端的时候安装到了普通用户,而hexo generatehexo deploy等命令在修改hexo文件内的内容后出现权限问题,使用sudo权限执行hexo命令,即sudo hexo deploy后出现要求输入密码的情况。

  3. 使用sudo hexo d命令时git仓库拒绝访问,上传错误

    解决方法是在本地客户端root下重装hexo,或者更为简单的使用chmod修改blog整个目录的权限,然后不使用sudo而使用普通用户的hexo d进行上传。

  4. nginx访问出现403 forbidden

    查看nginx日志:

    1
    cat /var/log/nginx/error.log

    发现报错permission denied:

    1
    2020/11/06 21:58:11 [error] 376#0: *11 "/var/www/hexo/index.html" is forbidden (13: Permission denied), client: 103.129.196.142, server: _, request: "GET / HTTP/1.1", host: "103.129.196.142"

    解决:

    在开启SELinux情况下,会将nginx的主页屏蔽,变成403,Security-Enhanced Linux(安全增强型 Linux)简称 SELinux,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统。SELinux 主要由美国国家安全局开发,2.6 及以上版本的 Linux 内核都已经集成了该模块。SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。
    安全上下文是 SELinux 的核心。安全上下文分为「进程安全上下文」和「文件安全上下文」。只有两者的安全上下文对应上了,进程才能访问文件。它们的对应关系由政策中的规则决定。
    安全上下文有四个字段,分别用冒号隔开,形如:system_u:object_r:admin_home_t:s0

    开启SELinux的情况下 nginx 403的原因非常有可能是nginx的线程上下文和文件安全上下文 不一致导致nginx没有权限访问相关的文件。

    (1) 使用ps -efZ | grep nginx查看nginx进程SELinux信息:

    1
    2
    3
    4
    [root@ecs-12TLU www]#ps -efZ | grep nginx
    system_u:system_r:httpd_t:s0 root 463 1 0 Nov06 ? 00:00:00 nginx: master process /usr/sbin/nginx
    system_u:system_r:httpd_t:s0 nginx 464 463 0 Nov06 ? 00:00:00 nginx: worker process
    unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 2672 2641 0 16:12 pts/0 00:00:00 grep --color=auto nginx

    在nginx默认目录中查看SELinux信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [root@ecs-12TLU hexo]# ls /usr/share/nginx/html/ -Z
    -rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 404.html
    -rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 50x.html
    lrwxrwxrwx. root root system_u:object_r:httpd_sys_content_t:s0 en-US -> ../../doc/HTML/en-US
    drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 icons
    lrwxrwxrwx. root root system_u:object_r:httpd_sys_content_t:s0 img -> ../../doc/HTML/img
    lrwxrwxrwx. root root system_u:object_r:httpd_sys_content_t:s0 index.html -> ../../doc/HTML/index.html
    -rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 nginx-logo.png
    lrwxrwxrwx. root root system_u:object_r:httpd_sys_content_t:s0 poweredby.png -> nginx-logo.png

    在nginx指定的根目录中查看SELiunx信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@ecs-12TLU ~]# cd /var/www/hexo
    [root@ecs-12TLU ~]# ls -Z
    drwxrwxrwx. git git unconfined_u:object_r:var_t:s0 2019
    drwxrwxrwx. git git unconfined_u:object_r:var_t:s0 2020
    drwxrwxrwx. git git unconfined_u:object_r:var_t:s0 archives
    drwxrwxrwx. git git unconfined_u:object_r:var_t:s0 css
    drwxrwxrwx. git git unconfined_u:object_r:var_t:s0 images
    -rwxrwxrwx. git git unconfined_u:object_r:var_t:s0 index.html
    drwxrwxrwx. git git unconfined_u:object_r:var_t:s0 js
    drwxrwxrwx. git git unconfined_u:object_r:var_t:s0 lib

从以上信息可以看出nginx的SELinux信息为system_u:system_r:httpd_t,其中线程上下文为httpd_t

nginx默认目录文件的SELinux信息为system_u:object_r:httpd_sys_content_t,其中文件上下文为httpd_sys_content_t

www目录以及文件的SELinux信息为unconfined_u:object_r:var_t:s0,其中文件上下文为home_root_t

所以只需将www目录的文件上下文改成与nginx默认路径文件上下文一致即可(即改成httpd_sys_content_t)。

(2) 安装policycoreutils-python工具

1
yum -y install policycoreutils-python

(3) 在var目录 执行semanage命令(我的www目录位于/var/www)

1
2
3
[root@ecs-12TLU var]# semanage fcontext -a -t httpd_sys_content_t '/var/www(/.*)?'
[root@ecs-12TLU var]ls -Z
drwxrwxrwx. root root unconfined_u:object_r:var_t:s0 www

www目录文件SELinux信息还未修改过来,接下来执行restorecon即可

1
2
3
[root@ecs-12TLU var]# restorecon -R /var/www
[root@ecs-12TLU var]# ls -Z
drwxrwxrwx. root root unconfined_u:object_r:httpd_sys_content_t:s0 www

参考

CentOS 7下使用n工具更新Node.js
Hexo 个人博客部署到 CentOS 个人服务器
HEXO 部署到云服务器详细指南
搭建私有git仓库,免密pull and push
使用Nginx+Hexo光速搭建博客并实现服务器自动部署
开启SELinux情况下如何解决nginx 403