0%

How to Build a Personal Blog

个人博客=域名+IP地址(+证书)

是的就这么简单, 成本无非是前者, 买个域名ochicken.top, 以及后者, 买个可以公网接入的服务器(VPS). 个人搭网站可以选择免费的证书.

可以理解域名为地名, 理解IP地址为蓝球上的地理位置. 地名有可能相同, 但在蓝球上的地理位置显然存在且唯一. 譬如说武汉有个柏林站, 显然不是德意志的柏林.
域名要自己买一个. 用英文单词拼接起来的就是域名. 不过后缀名, 即顶级域名, 各种各样都有, 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服务器的交易. 过程如下

![域名解析](20190930-How-to-Build-a-Personal-Blog/DNS.jpg) 域名解析

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



Personal Blog 个人博客

先学着如何在本地搭建博客并发布到现成的网站OChicken.github.io有助于理解相关概念.

GitHub Pages

GitHub Pages上有很多现成的主题, 挑一个, 访问github仓库clone, 到本仓库OChicken.github.io, 可以索性覆盖掉自己尝试写的内含有Hello World的index.html无用文件. 直接改index.md, 然后git commit push, 浏览器输入OChicken.github.io, 就会看到带主题的界面. 不过这仅仅是首页, 第一篇Blog还要进一步操作.

然而GitHub Pages的主题很不灵活. 你仅仅是能够有一个方便编辑的md文件而已, 另写一篇Blog并在主页上添加Archive等按钮都很不方便. 就GitHub提供的主题来看, 很遗憾, 配置复杂, 文件凌乱.


Hexo

为了能够尽快看到个人博客的搭建成果, 我把repo设置在OChicken.github.io上. GitHub本身就是个VPS(只不过我们不可能知道自己的账号对应的VPS的IP地址是多少), 如果想要自己造轮子搭建VPS, 可看VPS一章.
我主要采用的是如何用github page搭建博客? - 工匠羅的回答 - 知乎的回答. 其对应博文在用 Hexo 和 GitHub Pages 搭建博客 | 猎 日

预览

1
2
3
4
5
6
7
cd QuantumInfOChicken/        #cd到博客主目录
sudo npm install -g hexo-cli
hexo init
npm install #安装依赖包
hexo g (= hexo generate) #生成网页
hexo s (= hexo server) #浏览器里输入 http://localhost:4000/, 就可以看到刚才的成果了
Ctrl+Shift+C #结束

每次 在本地 发布一篇Blog, 都要执行hexo ghexo s命令来预览.

Remarks: Port 4000 has been used. Try other port instead.—一个本地编辑时常见的错误
这是因为结束的时候用了Ctrl+Z, 进程依然在后台. 不信? 用netstat -ant | grep 4000或者ps都可以看到4000端口被占用. 用kill -9 进程号关闭进程 (没有-9你还根本关不了).

生成一篇博客, 用

1
hexo new "My First Post"

发布

在主目录下的

1
2
3
4
deploy:
type: git
repo: https://github.com/OChicken/OChicken.github.io.git
branch: master

然后

1
2
3
hexo c (= hexo clean)
hexo g (= hexo generate) #生成网页
hexo d (= hexo deploy) #部署到云

如无意外, 浏览器输入OChicken.github.io就有东西了.

Remarks::

  1. Your site is having problems building: The value '{}' was passed to a date-related filter that expects valid dates in /_layouts/default.html or one of its layouts
    如果博客主目录QuantumInfOChicken/.git/非空的且掌管了该目录下的 所有文件, 就有可能报错, 特别是.gitignore这个文件: hexo是自带git功能的! 一山不容二虎. 使用hexo你根本不需要用git pull git push, 如果硬要用, 会报一大堆错误, 领头的错误就是上面这条.
    解决方法是对.git/info/exclude增加.gitignore这个文件本身以及.gitignore里面的内容.

  2. Cannot read property 'replace' of null
    注意到_config.yml里的第15行

    1
    ## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'

我当时想, deploy是把public/的内容推到repo, 而index.html正是在public/里面. 于是手多把第17行改成public/
实际上, hexo d是自动地只把public/的内容发布到GitHub repo. 设置https://ochicken.top/即可, 那两行不必动.
hexo 报错 Cannot read property ‘replace’ of null - 简书

主题

Hexo下载的是默认的landscape主题. 当然可以换别的. 最常用的是NexT.
旧的NexTiissnan/hexo-theme-next: Elegant theme for Hexo.
新的NexTtheme-next/hexo-theme-next: Elegant and powerful theme for Hexo.
Hexo官方合集: Themes | Hexo

1
git clone https://github.com/theme-next/hexo-theme-next themes/next

这样, themes目录下有两个文件夹, 一个是自带的landscape, 一个是刚下载的next. 到主目录下把主题从landscape改为next:

1
theme: next #landscape

Remarks:

  1. WARN No layout: index.html?—更改主题时常见的错误
    这是忘记更改主题, 或者主题对应的名字不对. hexo本地测试运行重启后页面空白,提示 : WARN No layout: index.html? - 知乎

  2. 注意到, theme/landscapetheme/next里面都有_config.yml文件. _config.yml是个很重要的文件, 主目录和themes目录 都掌管着各自的前端, 所以不要以为有重于是把主题的_config.yml覆盖到博客主目录的_config.yml上面. 这是个很弱智的错误.

其他(到后期美(kou)化(tu)的时候可以再看)

Refs:
Hexo博客设置以及Next主题美化 | 麻瓜码农
使用 Hexo + Github Pages 搭建独立博客 | WildPointer

1
2
3
4
npm install --save hexo-deployer-git
npm install --save hexo-asset-image
npm install --save hexo-asset-link
npm install --save hexo-directory-category

apt - How can I update my nodeJS to the latest version? - Ask Ubuntu

avatar存放于主题目录下的source/, 即 Blog/themes/next/source/images/avatar.gif, 而不是博客主目录下, Blog/source/images/avatar.png. 记得把url去屏蔽: url: /images/cola.png (url给人一种网页链接的感觉, 实际上当然是可以指向本地的)

tags & categories:

  1. cd to Blog folder
  2. hexo new page tags, hexo new page categories
  3. in source/tags/index.md, add type: tag1, tag2, …

Remarks: 留个坑: 到目前为止, 图片的相对路径插入还没搞定… 我本地是用 Sublime Text 的Markdown插件编译的, 按照md语法可以正常显示; 可是到Hexo发布的时候就不能显示了, 我找遍了Google能找到的一切博文都没有一个能解决.


WordPress

WordPress.com: Create a Free Website or Blog
然而按照手把手建站教程 - 知乎的第三篇建站教程(三):在Ubuntu上配置Nginx+MySQL+PHP7 - 知乎和第四篇建站教程(四):基于Nginx部署WordPress - 知乎, 我预感到这条路的技术路线非常长. 因为当时我对怎么搭建服务器并不了解. 玩了Hexo之后被圈粉, 就远离WordPress了.

WordPress支持Markdown的插件也是有的: Search Results for “markdown” | WordPress.org



Domain name 域名

有OChicken.github.io不就行了? 为什么还要另外买域名?
因为直接用GitHub的服务器有点过于弱智了XD: 自己搭服务器是个不错的训练, 然而服务器仅仅是个IP地址, 没有名字. 域名就是个跟IP地址绑定的名字.
关于域名的扫盲可以看DigitalOcean的文档: Domains and DNS :: DigitalOcean Product Documentation.

本章并不会涉及服务器的搭建, 而是会重点涉及域名的指向: 如何选用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.108111.153. 然而这是行不通的. 因为一连4栋别墅185.199.108111.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的话](./images/A_record.png) 如果只添加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绑定, 是个空壳域名.


Server 服务器

可选的服务器有3种, 按配置复杂度从低到高: github.com, 自购VPS 服务器, 树莓派.
要明确一点: GitHub的服务器跟自己搭建的VPS并没有什么两样. 有教程说, 结合WordPress要安装mysql, php等乱七八糟的东西… 不用的. 仅仅有gitNginx就可以了.
树莓派多了个麻烦是内网穿透.

github.com服务器

GitHub自带, 买都不用买, 又不用自己配置. 这个优势是显然的.

当然, 直接用GitHub的服务器有点过于弱智了: 自己搭服务器是个不错的训练, 除此之外还能顺便帆樯. 下面就来谈谈如何在VPS服务器上搭建个git仓库并publish个Blog.


VPS服务器

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
相对关键的是主机名. 强迫症的我把它起为DigitalOcean.com. 在本地ssh添加快捷方式

1
2
Host DigitalOcean.com
HostName 134.209.239.83

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

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

远程git仓库

关键词是「VPS 自建git仓库」. 我们所做的无非是建立一个跟github.com/OChicken类似的VPS来托管自己的代码而已.
廖雪峰的搭建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
#账户名设为OChicken, 密码随意, 记住就好
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给ab123456设置了密码登录, 所以目录ab123456/.ssh里面并没有任何公钥文件. 后来我给ab123456加上我的公钥, 的确实现了免密登录.

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

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

  1. 为什么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博客).

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

(本节可以跳过, 但是不加进来枉费我爬了一整天的博客教程踩了一整天的坑还重新申了一次证书…)

上Google搜包括但不限于「VPS DigitalOcean SSL证书 letsencrypt name.com 阿里云」等关键词, 弹出来的博客教程的博主所采用的CA都不尽相同.

Name.com
Name.com通配符SSL证书购买与安装配置方法 - 个人技术博客
Name.com是因为跟GitHub.com的学生优惠包有勾搭所以才瞄上的. 不过也仅仅如此而已, 最多是买域名有discount, 证书没调查过.

StartSSL的方案:
如何为自己的VPS服务器安装免费SSL证书 - Linux大神博客(这篇讲得比较好)
How To Set Up Apache with a Free Signed SSL Certificate on a VPS | DigitalOcean
如何在VPS上使用免费签名的SSL证书设置Apache(是上面那篇的机翻)
然而StartSSL这个CA已经过期了…

GoDaddy的方案:
How To Install An SSL Certificate On Your VPS Running Apache | Archi FX LLC. | Web Design Experts in Tampa Bay
GoDaddy在买域名的时候就注意到了. 但是已经在阿里云买了就没走这条路.

Let’s Encrypt的方案 (一个跟Certbot(生成用于CA证书的公钥和私钥的包)搭配):
Let’s Encrypt配置免费SSL证书建立HTTPS(Ubuntu+Apache)-Linux运维日志
使用 Let’s Encrypt 在 VPS 上为 Nginx 配置 SSL | 落格博客
How To Secure Apache with Let’s Encrypt on Ubuntu 16.04 | DigitalOcean
教程:Vultr VPS上部署SSL启用HTTPS全攻略 | VPS评测网
letsencrypt 工具改名 certbot | 落格博客
教程:Vulte VPS免费SSL证书申请、安装图文教程 | 国外VPS排行榜TOP5
因为DigitalOcean的教程就是用的Let’s Encrypt所以才尝试着去用 (但是进行了一次失败的尝试, Notes写在archive/Let's Encrypt.md). 不过即便Let’s Encrypt的CA证书能用, 但也是不方便的, 因为证书只有3个月, 而不是阿里云的1年.
在使用openssl的时候会要求输入邮箱姓名手机号居住地等信息, 但certbot就没要求. 哪个更加坚嘢一目了然.
更恶心的是, 当时它居然把我写好的/etc/nginx/sites-available/default改得面目全非[腾讯微笑].

阿里云的方案:
老客户了. 阿里云证书的公钥是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 //查看运行状态

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


树莓派

树莓派最关键的是要摆平内网穿透, 其他的跟VPS没什么不同.
对国内的情形, 还得自行搞定动态域名解析(DDNS)问题 (使用frp实现内网穿透,访问内网web服务以及ssh内网服务器 - 知乎)

树莓派作为VPS需要用到的技术有
树莓派搭建私人服务器 - 掘金
Search · DDNS
一分钟实现内网穿透(ngrok服务器搭建) - 学习笔记 - CSDN博客

留个坑以后填.