博客迁移之旅

博客迁移之旅

2020-08-04 | |

前言

之前博客是直接托管到 Github 上的,由于它不是很稳定经常挂掉,而且访问速度也很慢,所以后面就干脆把它部署到自己的服务器上,顺便记录一下整个部署的流程,方便以后查看。

关于服务器

服务器我选的是腾讯云(主要是新用户有折扣,比较便宜,之前买过阿里云的,就不是新用户了),个人服务器,考虑到服务器主要是用作个人博客(静态页面),没啥并发量,对性能没有太高的要求,所以就选了一个最低配置。

服务器配置清单

流程

博客的整个部署流程分为服务端与客户端(本地)两个部分,具体的步骤会后面会描述,这里先说一下整体的流程。

  1. 创建博客的远程仓库
  2. 本地安装配置 hexo
  3. 推送本地生成的静态页面到远程仓库
  4. 服务端获取最新博客文件并部署上线

这里可能会产生一个疑问:博客的远程仓库在哪创建?是 Github 还是在服务器上。为了解答这个疑问,我们先介绍下这两种方式:

远程仓库建在 Github 上

发布博客时,只要登录到服务器,通过 git 工具去仓库上拉取最新的文件,然后部署上线即可。如果需要集成自动部署功能(在本地执行完 hexo deploy 命令后,服务器能够自动去拉取最新静态页进行部署,不用再登录服务器手动操作),则需要使用到 Github 给我们提供的 Webhooks 勾子,来实现对 push 事件的监听。

远程仓库建在服务器上

发布博客时,服务器可以直接拿到最新的静态页进行部署,如果想自动部署,则可以使用 git 工具给我们提供的 post-receive 钩子文件,来实现对 push 事件的监听。


比较一下上述的两种方式,我个人是推荐第二种,即:在服务器上创建博客的远程仓库,Why?

在集成自动部署时,如果仓库建在 Github 上,则需要在 Github 中新增一个 webhook 钩子,并配置好回调地址,当仓库监测到 push 事件后,会调用这个回调地址,来通知服务器进行后续的操作。

服务器端需要完成以下四件事:

  1. 提供一个服务来让 Github 调用,也就是 webhook 上配置的的回调地址所对应的服务。
  2. 安装 git 工具,然后创建一个博客仓库与远程仓库进行关联,用来拉取远程仓库中的博客文件。
  3. 当服务被调用时,需要使用 git pull 命令去拉取最新的博客文件。
  4. 在获取到最新的博客文件后,通过 nginx 反向代理博客静态页(部署)。

这里涉及到服务器与 Github 的通信,而 Github 又不是很稳定,可能存在信息丢失的风险,导致博客不能被即时部署。
如果是将远程仓库建在服务器上,当我们提交完最新的博客页后,服务器就能拿到本地提交的文件,而且可以通过 git 工具的 post-receive 钩子文件,来监听本次的 push 事件,从而进行后续的操作。另外,由于这些操作都是在服务器内部完成的,不需要与外部进行通信,所以就不存在部署不及时的问题。

步骤

我采用的是第二种方式(在服务器搭建远程仓库),后续也是基于这种方式来进行介绍。

具体拆解下来,分为服务器端与本地客户端两个部分的操作。

服务器

注:服务器上的操作都是在 root 权限下进行的。

  1. 安装并配置 Docker

博客是通过 Docker 容器来部署的,所以需要在服务器上下载安装 Docker。也可以不用 Docker,直接使用 nginx 来部署。这里主要是为了以后迁移方便(如果以后需要更换服务器,只需要将 Docker 脚本以及相关的配置文件打包走即可,不用再重新配置 nginx ),同时自己也想熟悉一下 Docker 的相关用法。

1
2
3
4
5
6
7
8
# 安装 docker,因为我的服务器预装了 CentOS 系统,所以可以直接使用 yum 命令
yum install docker -y

# 启动 docker
service docker start

# 配置开机启动
chkconfig docker on

国内访问 Docker Hub 较慢,可以添加国内的镜像源来加速访问 Docker Hub,我这里使用的是腾讯云提供的镜像源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 创建 docker 配置文件目录
mkdir /etc/docker

# 2. 添加新的镜像源
cat >> /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
EOF

# 3. 加载配置文件
systemctl daemon-reload

# 4. 重启 docker
service docker restart

配置好 Docker 的镜像源后,我们就可以通过 Docker 来拉取 nginx 镜像。

1
2
# 拉取 nginx 镜像
docker pull nginx

安装 docker-compose

注:docker-compose 在这里不是必需的,它是用来解决多个容器编排的一种方案。因为这里只用到了 nginx 镜像,完全可以用一个 Dockerfile 文件来进行定制。

1
2
# 下载安装 docker-compose
yum install docker-compose -y

接下来需要修改一下 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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 1. 在 /home 目录底下新建一个 blob 目录,并进入到该目录底下。
# 这个目录就是博客的部署目录,里面存放着博客的静态文件以及与 nginx 相关的配置文件。
cd /home && mkdir blob && cd blob

# 2. 创建 docker-compose.yml 文件
vim docker-compose.yml

# 3. 在 docker-compose.yml 文件中输入以下内容
version: '3'
services:
nginx:
restart: 'always'
image: 'nginx'
ports:
- '80:80'
- '443:443'
volumes:
# a. volumes 将物理主机目录挂载到容器中
# b. 以 : 为分隔符,前半部分为服务器目录,后半部分是容器中的目录
# c. 挂载建立的是双向关联,类似于软连接
# d. 当修改了服务器中的文件,则容器中所关联的文件也会同步更新,无需重新构建
#
# /home/blob/www/public 为服务器目录,里面存放的是博客的静态文件
# 将它挂载到容器内的 /usr/share/nginx/html 目录中,将来服务器中的博客文件更新后,容器内会同步更新
- '/home/blob/www/public:/usr/share/nginx/html'
# 挂载 nginx 的日志文件
- '/home/blob/log:/var/log/nginx'
# 挂载 nginx 的配置文件
- '/home/blob/conf:/etc/nginx/conf.d'

# 4. 创建 nginx 相关的配置文件
# 在 conf 目录底下创建一个 default.conf 文件,此文件将来会被挂载到 nginx 容器中并作为它的配置文件
cd /home/blob/conf && vim default.conf

# 5. 在 default.conf 文件中输入以下内容(注:此处没有配置 https)
server {
listen 80;
server_name localhost;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
}

autoindex on;
autoindex_exact_size on;
autoindex_localtime on;

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

# 6. 启动容器
cd /home/blob && docker-compose up -d

至此,所有与 nginx 相关的步骤都已经完成,接下来就是 git 相关的配置了。

  1. 安装并配置 Git

因为博客的远程仓库是在服务器上创建的,所以需要在服务器上安装 git 工具。

1
2
# 下载安装 git 
yum install git -y

安装完 git 后,在 /home 目录底下创建一个 blob.git 的仓库,该仓库就是博客的远程仓库。

注:博客的远程仓库以及上文中提到的博客的部署目录,并不一定要在 /home 目录下创建,可以根据自己的需要在服务器上选择一个合适的目录即可。

1
2
3
4
5
# 创建博客的远程仓库
#
# --bare:表示创建一个裸的仓库,没有工作区(没有 .git 目录)
# 远程仓库是用作共享的版本库,只保存 git 提交的版本信息,本身不存储推送过来的源文件,也不允许直接在该仓库底下进行 git 操作
cd /home && git init --bare blog.git

创建 post-receive 钩子文件。

注:post-receivegit 在收到 push 事件以后执行的一个脚本文件,通过它可以实现对 push 事件的监听,从而达到自动部署的目的。
参考:自定义-Git-Git-钩子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1. 进入到 blob.git 仓库中的 hooks 目录中,所有的钩子文件都在这个目录下
cd blog.git/hooks

# 2. 创建 post-receive 文件
vim post-receive

# 3. 在 post-receive 文件中输入以下内容
# 该命令会将本地 push 过来的博客文件移动到 --work-tree 所指定的目录中
# 由于前面我们已经将 /home/blob/www/public 目录挂载到 nginx 容器内,所以就不用再手动的部署了
#
# --work-tree 指定工作目录,本地 push 过来的文件会被放入它所指定的目录中
# --git-dir 指定 git 仓库的位置
git --work-tree=/home/blob/www/public --git-dir=/home/blob.git checkout -f

# 4. 分配这个文件的可执行权限
chmod +x post-receive
  1. 创建一个新用户,用来维护 git 仓库

前面所创建的 git 仓库,是在 root 权限下操作的。当外界访问仓库时(本地的 push),就需要拥有 root 权限,而直接使用 root 账号来操作并不是一个很好的选择,所以我们需要单独创建一个用户来维护 git 仓库,以保证服务器的安全。

1
2
3
4
5
# 添加 git 用户(这里的 git 是用户名,可以随意命名)
adduser git

# 设置 git 用户的密码
passwd git

执行完上述命令后,会在 /home 目录底下生成一个 git 的目录,该目录就是 git 用户的家目录。
接下来是给 git 用户分配相应的操作权限,这里只需给它分配 git 仓库和博客部署目录的使用权限即可。

1
2
3
4
5
# 1. 设置 git 仓库的拥有者为 git 用户
chown -R git:git /home/blob.git

# 2. 设置博客部署目录的拥有者为 git 用户
chown -R git:git /home/blob

注:这里没有禁用掉 git 账户的 shell 登录权限,因此本地可以通过 shell 来登录服务器上的 git 账户。这样做的目的是为了方便后续添加 ssh 密钥,从而实现服务器的免密登录。如果直接禁掉了 git 账户的登录权限,后面在服务器上添加 ssh 密钥时会比较麻烦。

至此,服务器上的所有操作都已经完成,剩下的就是本地客户端的操作了。

  1. 服务器目录结构图
本地
  1. 配置 ssh 密钥,实现服务器的免密登录

ssh 可以基于密码进行认证,也可以基于密钥去认证用户,基于密钥认证时可以实现免密码登录服务器。

1
2
# 生成密钥对
ssh-keygen

注:直接执行 ssh-keygen 命令,会进入交互模式,并等待用户输入生成密钥文件的路径,在不输入任何路径的情况下,私钥与公钥默认生成在当前用户家目录下的 .ssh 目录中,如果不指定其他路径,直接回车即可。随后,会提示我们输入密码,如果设置了密码,则每次在使用的时候,都会提示我们输入密码,因为我们想实现的就是免密码登录,所以这里直接回车,不设置密码,最后再次回车即可。

当生成完密钥对后,就可以在当前用户的家目录(~/.ssh)中找到这队密钥文件(id_rsaid_rsa.pub),现在只需将公钥(id_rsa.pub)上传到服务器上的 git 账户中,就可以免密登录服务器上的 git 账户了,本地 push 文件到服务器上的远程仓库时就不用再输密码。

1
2
# 上传公钥到服务器(请将 IP 替换成你服务器的公网IP(主机名))
ssh-copy-id -i ~/.ssh/id_rsa.pub git@IP

注:传输公钥时,会要求我们输入 git 账户的密码,这种密码验证只需要进行一次即可。

  1. 安装并配置 hexo

注:关于 hexo 的安装和使用请参考 文档 | Hexo ,这里我们只讨论 _config.yml 文件的配置。

当执行 hexo deploy 命令时,hexo 会将生成的 public 目录中的文件和目录推送至 _config.yml 中指定的远端仓库和分支中,并且完全覆盖该分支下的已有内容。所以,只需要将 _config.yml 文件中的 deploy 参数进行修改,就可以将本地生成的静态文件推送到服务器上的 git 仓库中。

1
2
3
4
5
6
7
8
9
10
11
12
# 1. 进入到本地博客根目录中,编辑 _config.yml 文件
#
# 注:请将 xxx 替换成你本地博客根目录的路径
cd xxx && vim _config.yml

# 2. 配置 _config.yml 文件中的 deploy 参数
#
# repo 博客远程仓库地址
# 注:请将 IP 替换成你服务器的公网IP(主机名)
deploy:
- type: git
repo: root@IP:/home/blob.git

至此,所有的迁移工作全部完成。