0%

How to Build a Personal Blog

概念区分

首先得理解服务器, 一般是Linux系统. 一个最裸的Linux主机是孤立的, 给它安装了Web网页服务器之后就可以外网访问这个Linux主机. 关于网页有两个重要的概念:

  • Web网页服务器可以是Apache2也可以是Nginx, 配置文件都位于/etc/*/sites-available/default (或者类似于default的文件名), 但是这仅仅是默认网页服务器而已, 浏览器点开IP里是Apache2的介绍页, 这个介绍页就位于Linux主机上.
  • 网页的内容都放在/var/www/a_certain_dir (a_certain_dir可以是html也可以是blog等随便一个目录名). 打开浏览器输入IP看到的Apache2的介绍页就是/var/www/html/index.html所控制的. (/var/www/的原生内容就一个./html/文件夹, 里面就一个./html/index.html文件.)

网页框架的default文件默认是指向/var/www/html/的. 在云Linux主机上安装特定包并在浏览器上直接写博客的方式尽可不去管Web网页服务器的设置, 而是用shell登录后, 直接在/var/www/html/里配置即可, 然后浏览器点开IP就有东西了. 而在本地写好博客然后发布到云Linux机的方式则需要考虑博客的内容是放在/var/www/下的blog/亦或是html/; 若是前者, 则需要设置一下/etc/*/sites-available/default, 让其指向/var/www/blog/.

上面是最简化版的搭博客过程. 但是这样的博客很”简单”: 因为访问者只能访问, 而不能作为用户登录这个网页并写comments. 这其实区分了读和写的两个权限, 访问者对网页的”写”过程要反馈到云Linux主机的/var/www/html/中, 这涉及到比较多的权限问题. 在网页搭建的这个圈分别对应于可写和不可写分别对应”静态”和”动态”. 要实现访问者能够”写”网页的目的, 还需要MySQL和PHP, 加上Linux, 合起来就是LAMP或者LNMP — 不少介绍搭博客的博客都说用”宝塔LAMP”搭博客, 就是指这个东西.

然后区分域名和IP. 域名是跟IP地址绑定的较易识别的名字, 在浏览器里输入IP来访问网页很不方便因为IP是一串数字, 但是输入形如ochicken.top这样的名字就易记很多, 这就是域名. 可以理解域名为地名, 理解IP地址为蓝球上的地理位置. 地名有可能相同, 但在蓝球上的地理位置显然存在且唯一. 譬如说武汉有个柏林站, 显然不是德意志的柏林.

IP往往跟可被外网访问的云Linux主机联系在一起, 并以服务器指代; 不能被外网访问的本地Linux主机没有它专属的IP, 也因此不得名服务器. 所谓外网访问就是您在浏览器里输入IP所得到的网页是托管在一个Linux主机上的, 这样就说您可以外网访问它. GitHub以及自购的VPS都是可以外网访问的, 而PC不能被外网访问, 因为PC的联网方式是PC->局域网WIFI->外网: 局域网一来给PC提供了一个内部IP使得它可以跟外界交互, 使得全世界如此多台的PC都不用独立分配一个IP (否则有限的IPV4会很快被用完), 另一方面也保护了PC不会被外网入侵者通过直接登录的方式随意入侵.
其实PC并不是绝对不可以被外网登录的: 像远程登录技术就是很显然的例子. 其实是它设置了内网穿透这个功能. 但是我们一般不会拿自己的PC来被外网访问; instead, 作为一个toy model, 会拿树莓派作为内网穿透的尝试.
GitHub自购VPS的区别在于, 前者不能通过shell以输入用户名和密码的方式登录, 但是后者可以. 所以GitHub并不是一个足够好玩的toy model.
自购VPS & 树莓派都可以通过shell输入账户密码登录, 进而可以看到Linux的网页相关的配置并可以DIY设置, 所以都是个不错的toy model, 除此之外还能顺便帆樯.

总结起来, 可选的服务器有3种, 按配置复杂度从低到高: GitHub, 自购VPS服务器, 树莓派:

  • GitHub服务器是GitHub自带的, 您只需有一个GitHub账号即可在上面布局博客, 这个优势是显然的; 劣势在于不能被shell登录, 没法看到Linux的网页相关的配置, 所以不是一个很好的练习对象. 实际上, OChicken/OChicken.github.io里面的内容就相当于/var/www/html/里的内容, 只是GitHub把这些都隐藏起来了.
  • 比较有训练价值以及有帆樯的实用价值的是VPS. 我们讲在本文主要讨论它.
  • 树莓派比VPS更难的一处是要摆平内网穿透, 其他的跟VPS没什么不同. 内网穿透的设置具体见RaspberryPi/RaspberryPi_config.md, 本文不涉及内网穿透的配置.

如果用GitHub服务器来搭博客的话, 跟它绑定的域名就是OChicken.github.io, 这是GitHub博客要求这样做的; 而用VPS或者树莓派来做的话则需要自行购买一个域名.

SSL证书相当于一个网站的”身份证”, 证明这个网站是有一个真实存在的自然人所有的, 因为cyber space上有相当多的一部分网站并不是由自然人所有, 或者说是为不怀好意的黑客所有, 访问这些网站是不安全的. 没有”身份证”也不妨碍您的博客可以被访问, 但现在Chrome已经将没有证书的网站的搜索排序放到偏后的位置了.
GitHub本身就自带证书, 因为github/ochicken这个账号的所有者就是一个自然人.

重要的概念大概这么多, 接下来进入操作部分, 先从VPS的购买以及用shell登录说起.

选择一个VPS并用shell登录

VPS服务器的选择非常多, Vultr, DO(DigitalOcean), 搬瓦工, Linode, 阿里云, 百度云, … flyzy小站 - Learning on the way有做相关测评.
我用的是DO. 借助GitHub提供的DigitalOcean学生优惠还能褥一波羊毛. 2019年The code is 2019GITHUB50-83f52d0d. 下面这些链接讲述了褥羊毛.
GitHub提供的DigitalOcean学生优惠 - 知乎
GitHub Student Developer Pack - GitHub Education
How to use github promo code (student developer pack) | DigitalOcean

有了IP之后, 就可以用ssh root@134.209.239.83登录.
相对关键的是主机名. 我把它起为OChicken.top. 在.ssh/config添加快捷方式

1
2
Host OChicken.top
HostName 134.209.239.83

登录时用ssh root@OChicken.top即可.
开心的话可以把快捷方式起名为全幼儿园最可爱的LovelyBoy. 如果不嫌麻烦, 每次登录都输IP地址134.209.239.83也可以.

登录服务器后, 显示其主机名是IP地址(比较丑), 也是可以改的: vim /etc/hostsvim /etc/hostname, 然后reboot (不是restart!) (How do i change hostname? | DigitalOcean)

搭博客

我们会涉及在GitHub以及用VPS(包括自行购买的VPS, 以及树莓派)两类平台上搭建博客的方式.
在VPS上搭博客分为两种方式: 一种是在云Linux主机上安装特定的包, 使得您可以直接在Chrome上在线编辑博客; 另一种是在云Linux主机上搭建一个git仓库, 使得您可以在本地编辑博客, 然后以类似于git push的方式把本地的内容同步到云Linux. 通过这两种方式您已经可以在浏览器里输入IP地址看到您发布的内容了.

在GitHub上搭博客: by GitHub Pages

GitHub Pages上有很多现成的主题, 挑一个, 访问github仓库clone到本仓库OChicken.github.io, 然后直接改index.md, 然后git commit push, 浏览器输入OChicken.github.io, 就会看到带主题的界面. 不过这仅仅是首页, 第一篇Blog还要进一步操作.
然而GitHub Pages的主题很不灵活. 你仅仅是能够有一个方便编辑的md文件而已, 另写一篇Blog并在主页上添加Archive等按钮都很不方便. 就GitHub提供的主题来看, 很遗憾, 配置复杂, 文件凌乱.

在云Linux主机上安装特定的包在线编辑

这个所谓的包即是指WordPress或者Drupal. 这种方式尽可不去管Web网页服务器的设置, 而是用shell登录后, 直接把包的内容解压到/var/www/html/里, 然后浏览器点开IP就有东西了.
如果你想保留html/index.html, 则可以把它重命名为html.old, 而WordPress的包解压出来的内容就放在./html/里. Web网页服务器的配置(下一小节会讲)是指向/var/www/html/而不是指向/var/www/html.old/的所以尽可重命名.
你会看到无论哪个包, 解压出来的东西都含有index.php或者index.html等类似的文件. 这个文件显然很重要因为它是被网页服务器的配置文件定向指定的, 但里面写的啥并不必关心.

本地编辑博客然后同步到云

这里所谓”同步”是通过git push或者deploy等类似操作. 满足这一需求的博客框架是Hexo.
要实现”同步”意味着我们必须在云Linux主机有一个git仓库. github.com/OChicken就是一类天然带了git仓库的VPS (只不过是我们没法shell登录, 也不知道专属的IP是多少), 仓库位于./OChicken.github.io/; 我们自己购买的VPS并不像GitHub那样有git仓库, 所以得自己配置. 在VPS上自建git仓库来托管本地的代码就是下面的主题; 这一步之后如何用Hexo本地写博客则详见Blog/Hexo.md.

远程git仓库

关键词是「VPS 自建git仓库」. 廖雪峰的搭建Git服务器 - 廖雪峰的官方网站写得最简单也最快能够实现. 除此以外还参考过在个人服务器上搭建git服务,创建属于自己的私人仓库 - 掘金. 但是为了实现跟github.com一样的形式以及配置Blog, 是有很多东西要补充的.

安装git包并做全局配置

1
2
3
sudo apt-get install git
git config --global user.email "Ma.Seoyin@gmail.com"
git config --global user.name "OChicken"

配置文件在/root/.gitconfig.

创建git用户并实现免密登录

创建git用户于/home/git:

1
2
3
4
adduser --home /home/git git
#密码随意, 记住就好, Full Name []及以下部分都可以忽略
chmod 755 /home/git
su git

Remarks: 创建了git用户之后, 首先想到的是, 可以从本地以ssh git@DigitalOcean.com输入密码登录吗? 不行, 提示Permission denied (publickey). 解决这个问题, 首先想到可以 加公钥 解决, 此外还能以root身份设置git的 密码登录 (root设置用户以密码登录的方法不在本Blog的讨论范围内).

将本地公钥上传到/home/git/.ssh并将公钥加入authorized_keys. 首先, 在服务器端,

1
2
3
su git
mkdir .ssh && chmod 700 .ssh
touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys

回到本地, 把自己的公钥上传,

1
scp ~/.ssh/id_rsa.pub root@DigitalOcean.com:/home/git/.ssh

然后回到服务器,

1
2
cd /home/git/.ssh
cat id_rsa.pub >> authorized_keys

这样, 可以从本地用ssh git@DigitalOcean.com免密登录服务器了.

Remarks: 公钥免密登录的优先级是高于密码登录的. 学院的服务器是root给sm213398设置了密码登录, 所以目录sm213398/.ssh里面并没有任何公钥文件. 后来我给sm213398加上我的公钥, 的确实现了免密登录.

git用户的权限设置

在继续本节的讨论之前先问一下:

  • 为什么创建的用户是git而不是ochicken? 对前面的设置的解读是不是有毛病? 是不是应该说, git是用户组, ochicken是用户?

  • 所以问题在于, 关于用户和用户组: 如何解读git clone git@github.com:OChicken/OChicken.github.io.git冒号后面一长串? 显然OChicken是我的用户名, 那git是不是GitHub.com服务器的一个用户组呢?

  • 就一般的经验来讲, 应该是user1@hostname, user2@hostname. 然而GitHub的为什么是git@hostname:User1/, git@hostname:User2/?

  • 看自建git服务器的教程(包括廖雪峰), 都是「创建一个用户git」. 显然, 顺着他们讲的一步一步下来能够实现git clone git@hostname:user1/Project1.git. 然而这都只是对单一用户来讲的. 对多个用户, 如果东西都托管在同一个VPS里, 显然不能创建同名的git. 这不是很奇怪吗?

我觉得合理的解释是, 每在GitHub.com创建一个用户, 相当于在总机上划出一个VPS, 这个VPS是「我」的专属服务器, 每开一个账号就相当于在总机上划出一片VPS区域, 里面自动创建一个用户git, 并在/home/git目录下生成/User1, 声明这个VPS是User1的. 为此,

1
mkdir /home/git/OChicken

这样传输文件的时候就会写成这样: scp git@DigitalOcean.com:OChicken/file.py ./. 这跟GitHub.com有几乎一样的格式:

`git@DigitalOcean.com:OChicken/` v.s. `git@github.com:OChicken/`

所以root也是「我」, git也是「我」, IP地址134.209.239.83就是「我」的账号对应的VPS. 因此git需要有跟root一样的sudo权限

1
2
3
4
5
6
chmod 740 /etc/sudoers          #原权限是440
vim /etc/sudoers
# User privilege specification
root ALL=(ALL:ALL) ALL #增加楼下一行
git ALL=(ALL:ALL) ALL
chmod 440 /etc/sudoers

虽然root和git都是「我」, 但是用ssh git@DigitalOcean.com登录服务器并不是我们的目的: git用户只是用来作为版本控制的远端保存的工具, 所以不允许git登录shell:

1
2
3
vim /etc/passwd
git:x:1000:1000:OChicken,,,:/home/git:/bin/bash #改为楼下
git:x:1000:1000:OChicken,,,:/home/git:/usr/bin/git-shell

这里, 我们为git用户指定的git-shell使得每一次尝试登录git, 一登录就自动退出, 换句话收, 这种设置下, 「我」无法以git的身份登录shell. 可以试试在VPS端执行su git或者本地尝试ssh git@DigitalOcean.com, 一登录就退出.

用于传输文件的scp命令也不能用了. 能够实现传输的只剩下git clone.

在服务器端创建OChicken.DigitalOcean.io的git仓库

创建一个repository:

1
2
cd /home/git/OChicken
git init --bare OChicken.DigitalOcean.io.git

并且把owner改为git:

1
chown -R git:git OChicken.DigitalOcean.io.git

Remarks:

  1. 但是cd到文件夹OChicken.DigitalOcean.io.git里并ls会看到这么一种画风:

    1
    HEAD  branches  config  description  hooks  info  objects  refs

    是不是上面几行的操作有问题? 放心, 没有问题的, 往下走就知道.

  2. 为什么git init --bare, 要有个--bare参数? 不然一定报错, 理由详见Git Push error: refusing to update checked out branch - Stack Overflow, 细节我也不懂 (当时为了要不要这个--bare参数在坑里陷了好久).

回到本地, 测试远程push操作. 先clone,

1
git clone git@DigitalOcean.com:OChicken/OChicken.DigitalOcean.io.git

(跟git clone git@github.com:OChicken/OChicken.github.io.git长得几乎一样!) clone下来的文件名是OChicken.DigitalOcean.io, 这也是我们熟悉的形式. 接下来尝试做些commits:

1
2
3
4
5
echo "Hello World" > README.md
git add README.md
git commit -m "README.md: 1st commit."
git log --pretty=oneline
git push origin master #不要在本条前加git pull origin master

如无意外是能够上传成功的, 说明我们的确成功地建立了一个远程仓库. Yeah!

服务器端仓库和本地仓库: Remarks

不同点在于

主机 文件夹名/仓库名 内容
本地端 Project README.md, file1,py, file2.cpp, …
服务器 Project.git HEAD branches config description hooks info objects refs

无论本地git commit push多少次, 服务器端的Project.git/除了该目录本身大了一点点以外, 并没有看到README.md, file1.py, file2.cpp等文件. 不信的话, 不妨把第一次commit过后的服务器端的Project.git/再clone到本地, 发现README.md的确在本地的Project/里. 这不奇怪. 因为git就是 代码 的版本控制系统, 可不管什么文件呢.

即使服务器端那么的反人类我们也不用太管它什么事, 因为幸运的是clone到本地端就是人话了. 不过也不必太过纠结这个问题, 毕竟它只是个远程仓库, git push就行了.

相同点是,

(本地的)Project/.git/contents == (服务器的)Project.git/contents
且contents就是这几个配置文件和目录: HEAD branches config description hooks info objects refs, 不会因为我commit过100次而增加内容. 每次commit后, 会发现「本地的Project/.git/」和「服务器的Project.git/」的每个文件可能增加大小, 目录里的子目录的内容会增加, 譬如object/.

在github.com服务器上, 也就是我们常用的网页版UI, 创建一个repository时, GitHub就已经将仓库里的东西「翻译」为人类容易看懂的一个一个的文件. 这个「翻译」并不是什么特别高大上的trick, 看过后面的git hooks配置你会有点想法的.

网页端Nginx: Let’s open to the world

网页接口文件: /var/www/blog

1
2
3
cd /var/www
mkdir blog
chown -R git:git blog

配置git hooks, 指向/var/www/blog

1
2
3
cd /home/git/OChicken/OChicken.DigitalOcean.io.git/hooks
touch post-receive
vim post-receive

输入如下内容后保存退出.

1
2
3
4
5
6
7
8
#!/bin/bash
GIT_REPO=/home/git/OChicken/OChicken.DigitalOcean.io.git
TMP_GIT_CLONE=/tmp/blog
PUBLIC_WWW=/var/www/blog
rm -rf ${TMP_GIT_CLONE}
rm -rf ${PUBLIC_WWW}/*
git clone $GIT_REPO $TMP_GIT_CLONE
cp -rf ${TMP_GIT_CLONE}/* ${PUBLIC_WWW}

第7行$GIT_REPO是source, $TMP_GIT_CLONE是target. 别忘了修改读取权限和所有者

1
2
chmod 755 post-receive
chown -R git:git post-receive

再来一次git commit push, 应该能够在/var/www/blog看到non-trivial的内容—你提交的README.md.

git hooks的配置无非是在/var/www/blog也同时同步了我们对仓库的修改, 而且这是一个一个分立的文件哦, 没准github.com就是以这种user friendly的方式把文件展示给用户看的.

但是现在, 服务器也还仅仅是一个孤立的主机, /var/www/blog是有跟外界进行交互的potential, 但要真的做到跟外界交互, 还要再进一步.

安装和配置Nginx

在本博客里, 需要修改的仅仅是/etc/nginx/sites-available/default这个文件而已, 不排除修改别的配置文件也能实现目标, 但不在讨论范围.
这一步主要是参考Hexo搭建个人博客并使用Git部署到VPS - 简书「安装配置nginx」一节. 此外才参考了:
VPS搭建个人Hexo博客 - - SegmentFault 思否
在VPS上搭建hexo博客,利用git更新 | WikiLibrary
安装Node.js和Nginx. 安装目录在/etc/nginx.

1
2
cd /etc/nginx/sites-available
cp default blog

vim blog修改代码:

监听80端口(not secure so far)
1
2
3
4
5
server {
listen 80 default_server;
listen [::]:80 default_server;
# blablabla
}
log文件
1
2
3
4
5
6
7
server{
# blablabla
access_log /var/log/nginx/blog_access.log;
error_log /var/log/nginx/blog_error.log;
error_page 404 = /404.html;
# blablabla
}
网页配置文件(文本)

优先响应文本(无需加载延迟)

1
2
3
4
5
6
7
8
9
10
server {
# blablabla
root /var/www/blog;

# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;

server_name ochicken.top www.ochicken.top;
# blablabla
}
网页配置文件(图片)

然后响应图片

1
2
3
4
5
6
7
8
9
server{
# blablabla
location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {
root /var/www/blog;
access_log off;
expires 1d;
}
# blablabla
}
网页配置文件(视频)

最后响应视频

1
2
3
4
5
6
7
8
9
server {
# blablabla
location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {
root /var/www/blog;
access_log off;
expires 10m;
}
# blablabla
}
若有其他非文本/图片/视频格式的请求, 中断
1
2
3
4
5
6
7
8
9
10
11
12
server{
location / {
root /var/www/blog;
if (-f $request_filename) {
rewrite ^/(.*)$ /$1 break;
}
}
location /nginx_status {
stub_status on;
access_log off;
}
}

要注意的是:

  1. 只要带/var/www/html字样的, 都把html改为blog;
  2. 原46行的server_name _;, 改为自己注册好的域名server_name ochicken.top www.ochicken.top;;
    我把default保存在了VPS_config/default_80方便粘贴.

Remarks: 在讲到为网页添加证书的时候/etc/nginx/sites-available/default还会再用VPS_config/default_443修改. 添加证书往往是最后一步, 因为即使你不添加, 也是能打开网页的.

保存退出后,

1
2
3
4
5
nginx -t               //检查Nginx文件是否有语法错误, 无错的话应该弹出OK
service nginx restart //重启nginx
service nginx start //启动nginx
service nginx enable //设置开机自动启动
service nginx status //查看运行状态

Simultaneously Deploy

按照下面的设置可以同时发布在github.com和自建VPS上: 回到本地, 放Blog文件的那个目录, 在_config.yml末尾修改为

1
2
3
4
5
6
7
deploy:
- type: git
repo: git@github.com:OChicken/OChicken.github.io.git
branch: master
- type: git
repo: git@134.209.239.83:OChicken/OChicken.DigitalOcean.io.git
branch: master

注意 缩进! 配置好再hexo ghexo d. 在浏览器里输入ochicken.top, 看看弹出了什么?
Ref: hexojs/hexo-deployer-git: Git deployer plugin for Hexo.

为VPS安装SSL证书

仅仅是把东西publish到网页还不能满足我强迫症的小小心灵: connection is not secure. 但是我们总可以让它secure—安装证书. 可以把证书理解为把站点从not secure变为secure的一个放在服务器里的文档, 并不是什么特别高大上的东西.

证书是由通信双方—站长我自己, 以及访问ochicken.top站点的各个访客—以外的第三方机构, 作为证书发布者, certificate authority, 简称 CA. 全世界有大大小小的CA.
面向个人建站的 CA证书 往往是免费的, 是谓免费型DV SSL. CA证书包括但不限于两个文件: 公钥, 私钥, 以及别的内容.
一个DV SSL证书生效的套路是:

  1. 用指定的用于CA验证的程序包, openssl, 在服务器上生成一对公钥和私钥;
  2. 把公钥和私钥上传到CA机构的网站, 等待申请成功;
  3. 申请成功之时, 用户可以从CA机构网站上下载对应建站框架(Nginx, Apache2, …)的证书, 并部署到服务器上(也就是修改配置文件).
  4. 申请成功之时, CA机构会把公钥广播到全世界的域名解析服务器, 当后者都收到这把公钥并加入解析列表的时候, 全世界的访客就都可以通过在浏览器里输入ochicken.top来安全地(https)访问博主的站点了.

生成证书的前两步也可以直接在CA机构购买. 我就是在阿里云0元购的, 前面在讲域名的时候就顺便办了只是当时不知道怎么用. 「购买证书」蓝色按钮右边有一个「上传证书」白色按钮, 需要填写 证书名称, 上传 证书文件(pem编码)**和 **证书私钥(pem编码), 证书文件对应公钥, 证书私钥顾名思义. 不同的CA机构有不同的上传格式的要求, 常见公钥后缀: pem, crt, key; 常见私钥后缀: pfx, p12, pem, key (证书之间的转换(crt pem key) - 何惜戈 - CSDN博客).

Domain name 域名

域名要自己买一个. 用英文单词拼接起来的就是域名. 不过后缀名, 即顶级域名, 各种各样都有, eg, gov, com, cn, org, edu, 甚至 .monster… 显然, 如果我用a指代不同的东西肯定会引起混淆, 因为a们都是放在全世界的网页上的, 你可以认为都是放在 int main(){}里面的变量. 因此为加以区分, 令 a_gov, a_edu, a_com, … 所以域名抢注是很常见的事情.

域名解析就是将域名映射到ip地址的操作. 地球上任意一个用户在ta的浏览器里输入域名 -> 计算机寻找域名指定的DNS服务器 -> DNS服务器解析该域名对应的IP地址 -> IP地址返回给用户的浏览器 -> 用户浏览器紧接着把信息传递到地球上 IP地址 对应的服务器主机 -> 与Blog主三次握手通信. 这么算下来, 来回共5次, 前2次是跟DNS服务器的交易. 过程如下

域名解析

服务器在全世界有唯一ip地址. 服务器里面还会再分多几个ip地址. 面向世界的服务器是防止被登录的, 而像192.168.77.14就是自己的小主机可以随便登录.

本章将涉及域名的指向: 如何选用A记录还是CNAME记录. An Introduction to DNS Terminology, Components, and Concepts | DigitalOcean的CNAME Records一节能够初步帮助澄清概念.

购买域名和证书

按照GitHub Pages自定义域名 - 掘金, 要做5件事情:

  1. 配置 GitHub Page: OChicken.github.io. 前面搭博客已经是可以靠OChicken.github.io来发布网页的了;

  2. 「申请/购买」一个域名;
    域名可以取为ochicken.top, ochicken.site, ochicken.monster(= =)等等 (如今顶级域名已经花样百出了). 我是用阿里云国内版买的. 阿里云国际版在知乎2018年阿里云国际版注册教程与方法 - 知乎有讲解申请方法. 除此之外, 周街都见的GoDaddy和flyzy小站推荐过的NameSilo也可以尝试: 因为涉及到第二年续(xu)费(ming)的情况, 褥老客户羊毛的情形是很常见的, 所以关注相关测评还是必要的…

  3. Ali Cloud 上设置域名解析, 详情见下节 (实际上购买域名和设置域名解析是两件事, 阿里云把这两个一并解决了; 鹅厂的DNSPod也可以做);

  4. 购买证书, 证书可以把上述域名变成 secure 的. 阿里云的DNS在证书生效没多久就把相关信息记录到域名列表里了.

好了, 就这么简单.
如何将证书跟域名和VPS绑定我们放到用VPS搭博客的那一章再讲, 因为我觉得这需要对VPS的Nginx配置文件有一定的理解.

域名解析: A记录还是CNAME记录?

先下结论:

  1. 若项目托管在GitHub.com, 则采用CNAME记录, 指向 域名ochicken.github.io, 同时repo里要有CNAME文件, 内容为所购买的域名ochicken.top;

  2. 若项目托管在DigitalOcean.com的VPS, 则采用A记录, 指向 IP地址134.209.239.83.

Ref: GitHub Pages 自定义域名实践整理 - 自学之地 - SegmentFault 思否, 有图会讲得比我清晰.

为方便解释, 假设我已经在DigitalOcean买了一个服务器, IP地址为134.209.239.83.

  1. 若项目托管在ochicken.github.io, 即主机为GitHub的主机 (185.199.108~111.153, 在荷兰的数据中心), 则
    A 记录解析, 表明ochicken.top指向IP地址185.199.108~111.153. 然而这是行不通的. 因为一连4栋别墅185.199.108~111.153都是GitHub.com的主机, 「我」的账号虽然从中分了一个房间, 但是从外网看, 并不能得知「我」到底在哪个房间, 从而指向指定仓库git@github.com:OChicken/是不可能的.
    CNAME记录解析, 表明ochicken.top是指向ochicken.github.io的 快捷方式; ochicken.github.io并不是一个空壳域名, 它由更高级的CA保证, 默认指向主机185.199.108~111.153.
    当然也可以给ochicken.github.io添加个A记录解析, 指向185.199.108~111.153的其中一个. 不过这个操作比较trivial. (github怎么绑定自己的域名? - 知乎)
    经测试, 如果DNS只添加A record, 则在浏览器中输入ochicken.top将显示GitHub的404页面, 如下. 这表明ochicken.top的确是指向了GitHub的服务器, 但并没有检索到OChicken的仓库.
    如果只添加A record而不添加CNAME record的话. 这是GitHub.com的404页面.

可见, 在阿里云DNS只添加CNAME记录就可以将ochicken.top与OChicken.github.io绑定.

  1. 若项目托管在134.209.239.83, 即主机为DigitalOcean的一个VPS(我的为134.209.239.83), 则
    A 记录解析, 表明ochicken.top指向IP地址134.209.239.83.
    没法做CNAME记录解析, 因为要求ochicken.top指向某个非空壳的域名, 假设是ochicken.digitalocean.io, 但这个域名其实并不指向任何IP地址, 并不跟VPS主机134.209.239.83绑定, 是个空壳域名.

为VPS安装SSL证书

各类CA以及对应的添加到服务器的方法(链接综述)

阿里云的方案:
老客户了. 阿里云证书的公钥是pem(分两段, 第一段为服务器证书, 第二段为CA中间证书), 私钥是key.
阿里云帮助中心-阿里云,领先的云计算服务提供商

Nginx配置文件指向证书

到阿里云上下载Nginx的证书即可, 命名为2888440_ochicken.top_nginx.zip. 我们所要做的, 就是把CA证书放到服务器里(随便放哪应该无所谓, 有放在/etc的, 也有放在/etc/nginx的), 并对/etc/nginx/sites-available/default稍作修改.
Ref: Nginx 配置 SSL 证书实现 HTTPS 访问 | 虾丸派

永久指向https://ochicken.top

1
2
3
4
5
6
7
8
9
10
11
12
server{
if ($host = ochicken.top){
return 301 https://$host$request_uri;
}
if ($host = www.ochicken.top){
return 301 https://$host$request_uri;
}
listen 80 ;
listen [::]:80 ;
server_name ochicken.top www.ochicken.top;
return 404;
}

或者

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80 ;
listen [::]:80 ;
server_name ochicken.top www.ochicken.top;

access_log /var/log/nginx/blog_access.log;
error_log /var/log/nginx/blog_error.log;
error_page 404 = /404.html;

rewrite ^/(.*)$ https://ochicken.top/$1 permanent;
}

注意这里80端口并没有default_server—我们希望把default_server留给443端口.
把对80端口的监听独立为一个server block, 第二个server block是443端口的.

加入SSL证书

1
2
3
4
5
6
7
8
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;

# SSL configuration
ssl_certificate /etc/nginx/ssl/2888440_ochicken.top.pem;
ssl_certificate_key /etc/nginx/ssl/2888440_ochicken.top.key;
}

其他网页配置内容

跟前面的配置一样.

我把default保存在了VPS_config/default_443方便粘贴. 保存退出后,

1
2
3
nginx -t               //检查Nginx文件是否有语法错误, 无错的话应该弹出OK
service nginx restart //重启nginx
service nginx status //查看运行状态

然后就看到网页变为安全的了.

Welcome to my other publishing channels