博客大事记之迁移博客到香港主机

前言

之前其实已经写过一篇博文: 迁移博客到香港虚拟空间,那为什么又要写这篇博客呢?

上次其实是把我的博客迁移到一个香港的虚拟空间里,但是不到半年的时间已经出现过 4 次宕机事件,每次持续时间 4~5 小时,阿里云UpTimeRobot 的监控报警报了一大堆,邮箱都快塞满了。想着宕机就宕机吧,至少还能恢复,还能凑合用,结果呢,就在前几天当时购买虚拟空间的官网都 GG 了,管理员跑路了。。。

可能他没挣到钱吧,买一台服务器打算开很多共享的虚拟空间来卖,可能也只有我买了一个,因为我后来看了下我的博客同 IP 的网站就两个,好嘛,结果就跑路了。。。这里就不点名是哪一家了,八字开头的一个云。

好吧,言归正传,正好双 11,那就干脆直接买服务器吧,所以就购买了腾讯的一台轻量级云服务器,峰值 30Mbps,月流量 1024G,能满足我的需求,况且有了服务器,能做的事情就很多了。比如我还有其他的博客也可以解析到这里,比如可以定制化一些动态博客,比如可以使用自动化发布等。

那本文大致就记录下迁移的一些过程以及踩坑优化等:

  • 服务器购买以及初始化
  • 安装部署 nginx
  • 部署博客源码
  • 解析域名
  • 设置 https 证书
  • 绑定多个域名
  • 使用 github actions 自动化部署博客(踩坑)
  • https 性能优化

服务器购买及初始化

双 11 活动,购买了一台轻量级的腾讯云服务器。然后就是初始化服务器,登录服务器,设置 ssh key 登录等。

注意这里一定要设置 ssh key 登录,因为后面用的到。

安装部署 nginx

安装

1
$ yum install nginx -y

启动

1
$ systemctl start nginx

然后浏览器访问:

1
$ curl http://your_public_ip

如果一切正常,说明 nginx 启动正常。接下来把 nginx 添加到系统启动项随开机启动:

1
$ systemctl enable nginx.service

部署博客源码

博客采用的是 hexo 生成的静态博客,所以只需要把博客仓库克隆下来就行:

安装 git

1
$ yum install git -y

克隆博客网站源码到某个目录:

1
$ git clone https://github.com/smaugx/smaugx.github.io.git  /root/

设置 nginx 配置文件中 80 端口的 root 为博客源码的目录:

1
2
# nginx.conf
root /usr/share/nginx/html/smaugx.github.io;

重启 nginx:

1
$ systemctl restart nginx

验证博客是否正常:

1
$ curl http://your_public_ip

正常能看到博客的主页了。

解析域名

接下来是把域名 rebootcat.com 解析到这台机器上, 如下:

1
2
3
4
5
6
7
主机|类型|线路|记录值|MX优先级|TTL|备注|状态
@ NS 默认 f1g1ns1.dnspod.net. 0 86400 正常
@ NS 默认 f1g1ns2.dnspod.net. 0 86400 正常
@ A 默认 101.33.123.30 0 600 正常
@ TXT 默认 google-site-xxx 86400 正常
www A 默认 101.33.123.30 0 600 正常
@ TXT 默认 mP8ROM8AEYs9Zxxxx 0 600 正常

解析生效之后,验证是否成功:

1
$ curl http://rebootcat.com

设置 https 证书

全程参考这篇博文:

Linux CentOS 7 下 Nginx 安装使用 Let’ s Encrypt 证书的完整过程

这篇文章已经写的很清楚了,照着操作就行。

设置完成应该就能使用 https 访问了:

1
$ curl https://rebootcat.com

绑定多个域名

我还把 loveyxq.online 也解析到了这台机器上,这是我另外一个博客,给我女朋友用的一个。

nginx 的配置见后文。

使用 github actions 自动化部署博客(踩坑)

经过了上面的步骤,博客已经算是迁移完成了,不过每次更新博客能否直接部署道这台机器上呢?

答案是能的,而且方法很多种。我采用的是 github 自家的持续部署工具 Github Actions.

添加 github 仓库配置

如上图所示,分别在 Secrets 项添加 3 个变量:

  • BLOG_DEPLOY_PRI_KEY : ssh 私钥
  • BLOG_HOSTNAME : rebootcat.com
  • BLOG_USER : root

编写工作流文件

在博客网站源码仓库创建文件:.github/workflows/deploy.yml,内容如下:

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
name: Deploy site files

on:
push:
branches:
- master # 只在master上push触发部署
paths-ignore: # 下列文件的变更不触发部署,可以自行添加
- LICENSE

jobs:
deploy:

runs-on: ubuntu-latest # 使用ubuntu系统镜像运行自动化脚本

steps: # 自动化步骤
- uses: actions/checkout@v2 # 第一步,下载代码仓库

- name: Deploy to Server # 第二步,rsync推文件
uses: AEnterprise/rsync-deploy@v1.0 # 使用别人包装好的步骤镜像
env:
DEPLOY_KEY: ${{ secrets.BLOG_DEPLOY_PRI_KEY }} # 引用配置,SSH私钥
ARGS: -avz --delete --exclude='*.pyc' # rsync参数,排除.pyc文件
SERVER_PORT: '22' # SSH端口
FOLDER: ./ # 要推送的文件夹,路径相对于代码仓库的根目录
SERVER_IP: ${{ secrets.BLOG_HOSTNAME }} # 引用配置,服务器的host名(IP或者域名domain.com)
USERNAME: ${{ secrets.BLOG_USER }} # 引用配置,服务器登录名
SERVER_DESTINATION: /usr/share/nginx/html/smaugx.github.io/ # 部署到目标文件夹
- name: Restart server # 第三步,重启服务
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.BLOG_HOSTNAME }} # 下面三个配置与上一步类似
username: ${{ secrets.BLOG_USER }}
key: ${{ secrets.BLOG_DEPLOY_PRI_KEY }}
# 重启的脚本,根据自身情况做相应改动,一般要做的是migrate数据库以及重启服务器
script: |
echo "update rebootcat.com blog" >> /tmp/github/blog.log

上述文件记得 push 到远端仓库。然后你可以随便修改一下博客源码并且 push 到远端,正常的话应该能看到如下的输出:

hexo deploy 踩坑

重点来了,上面两部其实是经过了 hexo deploy 的踩坑的。为啥?

由于 hexo generate 默认会忽略隐藏文件,所以生成的网站源码就会忽略 .github/workflows/deploy.yml,所以要设置一下博客根目录的 _config.yml:

1
2
3
4
5
6
7
8

# Include / Exclude file(s)
## include:/exclude: options only apply to the 'source/' folder
include:
- ".github/*"
- ".github/**/*"
exclude:
ignore:

很重要!!!

OK,现在你可以放心大胆的使用 hexo generate 来生成博客源码了,但是当你使用 hexo deploy 的时候问题又来了, hexo deploy 默认也是忽略隐藏文件的,而且好像上面那个配置对 hexo deploy 无效。

搜索了很多,没有找到针对 hexo deploy 如何避免忽略隐藏文件的解决方案,于是探索了一下:

1
2
3
4
5
6
7
8
$ hexo deploy
INFO Deploying: git
INFO Clearing .deploy_git folder...
INFO Copying files from public folder...
INFO Copying files from extend dirs...
On branch master
nothing to commit, working tree clean
...

可以看到,上面执行 hexo deploy 命令后的输出有一个 “.deploy_git folder”,看了一下真有这个隐藏目录,想必 hexo deploy 是把 public 目录与较旧的(上一次发布的)目录 .deploy_git 做比较,然后增量上传文件。

所以我直接把 .github/workflows/deploy.yml 拷贝到了 .deploy_git 目录,然后执行 hexo deploy 成功。

哈哈哈!!!

所以记住,如果后期修改了这个 deploy.yml ,需要手动拷贝一下,但是基本上不会再动这个文件了。

到这里,基本上就解决了利用github actions 自动化部署博客的问题了。

实测 push 仓库后到服务器上的网站源码成功替换时间很快,大概一分钟左右,Good!

https 性能优化

上面的一切搞定后,体验了一天访问我的博客 https://rebootcat.com,使用 chrome 控制台发现 ssl 握手时间很慢,第一次访问基本都要 3 ~ 4 s左右,无法忍受,再次访问就快了。

所以网上搜索了下关于 Let’s Encrypt 的优化,找到了一些解决方案以及 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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# config file name: /etc/nginx/nginx.conf


user root;
worker_processes 2;

error_log /var/log/nginx/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

pid /var/run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
worker_connections 1024;
}


http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

#access_log /var/log/nginx/access.log main;

sendfile on;
tcp_nopush on;
tcp_nodelay on;

#keepalive_timeout 0;
keepalive_timeout 65;
types_hash_max_size 2048;

gzip on;
gzip_vary on;
gzip_min_length 1k; #不压缩临界值,大于1k的才压缩,一般不用改
gzip_buffers 4 16k;
gzip_comp_level 6; #压缩级别,数字越大压缩的越好
gzip_types text/plain application/javascript application/x-javascript application/json text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png image/x-icon text/xml;

#记录160000个请求 超过将返回失败
limit_conn_zone $binary_remote_addr zone=addr:10m;
#单个请求小于20r/s
limit_req_zone $binary_remote_addr zone=one:10m rate=20r/s;


server {
listen 80;
server_name www.rebootcat.com rebootcat.com;
rewrite ^ https://$server_name$request_uri? permanent;
access_log /var/log/nginx/access_rebootcat.log main;
}


# HTTPS server

server {
listen 443 http2 ssl;
server_name www.rebootcat.com rebootcat.com;
access_log /var/log/nginx/access_rebootcat.log main;

charset utf-8;
root /usr/share/nginx/html/smaugx.github.io;
limit_conn addr 10;

location /api {
limit_req zone=one burst=10;

# 真实的客户端IP
proxy_set_header X-Real-IP $remote_addr;
# 请求头中Host信息
proxy_set_header Host $host;
# 代理路由信息,此处取IP有安全隐患
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 真实的用户访问协议
proxy_set_header X-Forwarded-Proto $scheme;
}

location ~.*\.(js|css|ico|png|jpg)$
{
expires 3d;
}

location /js
{
#add_header Cache-Control no-cache;
}

location / {
limit_req zone=one burst=30;
index index.html index.htm;
}

error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;


# 开启 ssl
#ssl on;

# letsencrypt生成的文件
ssl_certificate /etc/letsencrypt/live/rebootcat.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/rebootcat.com/privkey.pem;

ssl_session_timeout 20m;
ssl_session_cache shared:SSL:50m;
# 由客户端保存加密后的session信息
ssl_session_tickets on;

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

# 开启OCSP Stapling,由服务器验证证书在线状态,提高TLS握手效率
ssl_stapling on;
ssl_stapling_verify on;

# 开启HSTS,缓存http重定向到https,以防止中间人攻击
# 不包含子域(宝塔界面是http的)
# 不预加载(预加载要在https://hstspreload.org/中添加)
add_header Strict-Transport-Security "max-age=63072000;" always;

# 开启TLS False Start
ssl_prefer_server_ciphers on;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
# 一般推荐使用的ssl_ciphers值: https://wiki.mozilla.org/Security/Server_Side_TLS
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK';
}




server {
listen 80;
server_name www.loveyxq.online loveyxq.online;
rewrite ^ https://$server_name$request_uri? permanent;
access_log /var/log/nginx/access_loveyxq.log main;
}


# HTTPS server

server {
listen 443 http2 ssl;
server_name www.loveyxq.online loveyxq.online;
access_log /var/log/nginx/access_loveyxq.log main;

charset utf-8;
root /usr/share/nginx/html/smaugx.github.io;
limit_conn addr 10;

location /api {
limit_req zone=one burst=10;

# 真实的客户端IP
proxy_set_header X-Real-IP $remote_addr;
# 请求头中Host信息
proxy_set_header Host $host;
# 代理路由信息,此处取IP有安全隐患
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 真实的用户访问协议
proxy_set_header X-Forwarded-Proto $scheme;
}

location ~.*\.(js|css|ico|png|jpg)$
{
expires 3d;
}

location /js
{
#add_header Cache-Control no-cache;
}

location / {
limit_req zone=one burst=30;
index index.html index.htm;
}

error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;


# 开启 ssl
#ssl on;

# letsencrypt生成的文件
ssl_certificate /etc/letsencrypt/live/loveyxq.online/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loveyxq.online/privkey.pem;

ssl_session_timeout 20m;
ssl_session_cache shared:SSL:50m;
# 由客户端保存加密后的session信息
ssl_session_tickets on;

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

# 开启OCSP Stapling,由服务器验证证书在线状态,提高TLS握手效率
ssl_stapling on;
ssl_stapling_verify on;

# 开启HSTS,缓存http重定向到https,以防止中间人攻击
# 不包含子域(宝塔界面是http的)
# 不预加载(预加载要在https://hstspreload.org/中添加)
add_header Strict-Transport-Security "max-age=63072000;" always;

# 开启TLS False Start
ssl_prefer_server_ciphers on;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
# 一般推荐使用的ssl_ciphers值: https://wiki.mozilla.org/Security/Server_Side_TLS
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK';
}

}

重启 nginx 之后,再次使用 chrome 无恒模式打开控制台看一下访问速度,是不是有所好转。

或者直接使用 curl 命令:

1
2
3
4
5
6
7
8
$  curl -X GET -w '\n\n    time_namelookup:  %{time_namelookup}
time_connect: %{time_connect}
time_appconnect: %{time_appconnect}
time_pretransfer: %{time_pretransfer}
time_redirect: %{time_redirect}
time_starttransfer: %{time_starttransfer}
----------
time_total: %{time_total}\n' -H 'Cache-Control: no-cache' -o /dev/null -s "https://rebootcat.com"

输出如下:

1
2
3
4
5
6
7
8
   time_namelookup:  0.005120
time_connect: 0.257869
time_appconnect: 0.492787
time_pretransfer: 0.492887
time_redirect: 0.000000
time_starttransfer: 0.751222
----------
time_total: 1.339793

上面的 time_appconnect 减去 time_connect 的耗时就是 ssl 握手的耗时 0.2349s,比之前好了很多。

The END

OK,到这里算是把博客正式的迁移到腾讯云香港服务器上了,以后就一直打算用自己的服务器托管博客了。

参考

使用 GitHub Actions 实现博客自动化部署
提高https载入速度,记一次nginx升级优化

Blog:

2020-11-10 于杭州
By 史矛革

buy me a cola!

欢迎关注我的其它发布渠道