Jason Pan

手把手带你搭建个人博客

黄杰 / 2022-10-19


一、背景

为了敦促自己不断学习总结并提高个人影响力,我在 2020 年 5 月搭建起了自己的博客,至今已经两年多了。当前部署方案基于 Markdown 本地编写、迁移、转载到 KM 都非常灵活方便,更新网站内容也只需本地一次 Git Push 操作

方便易用的个人博客方案,能够提高个人分享的积极性,至少不会成为你分享道路上的绊脚石。

最近总结下我个人博客的详细方案,包括部署方式、内容组织、网站被索引等内容,供诸君参考。

*部署过程要求对 Linux 基本操作有些了解。*文末也提供了其他的替代方案简介和对比,也有说明个人为什么选择了当前的方案。

二、Hugo 博客框架

本节介绍 MacBook 上安装 Hugo,创建网站和第一篇博客,编写内容、插入图片,并在本地启动 HTTP 服务可以通过浏览器访问。

2.1 QuickStart

参考 Hugo 官方文档 - Quick Start

# 安装 Hugo
brew install hugo

# 创建一个新的网站(本地)
hugo new site quickstart && cd quickstart

# 拉取并设置主题
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
echo theme = \"ananke\" >> config.toml

# 创建一篇新文章
hugo new posts/my-first-post.md

# 构建静态网站文件,并启动 HTTP 服务
hugo server -D

执行完上述操作,就可以通过浏览器访问 http://localhost:1313/ 。可以看到自己刚创建的网站与第一篇文章:

first-blog-home-page

2.2 推送到远端仓库

Coding 上创建一个项目,在项目下再创建一个仓库,默认参数即可(私有仓库)。这里会获得一个仓库地址:git@e.coding.net:panzhongxian/blog/quickstart.git

我仓库有多个 remote,一个是 Github,一个是 Gitee,一个 Coding。GitHub 在国内服务器访问速度差;而 Gitee 偶尔会出现故障;目前用的 Coding。

cd quickstart
git remote add origin git@e.coding.net:panzhongxian/blog/blog.git
git push -u origin "master"

2.3 页面中插入图片

以 Markdown 格式插入图片:

wget /images/landscape.png -qO static/landscape.png
echo '![img](/landscape.png)' >> ./content/posts/my-first-post.md

上边的操作分成了两步:先将图片放到了 static 目录下,然后在 Markdown 文件中指定图片,这里是要切掉 static 目录的。

[DIY] 文末提供了一个简单的工具处理图片:使用 Typora 工具可以随便贴图,通过该工具可以将所有图片复制或下载到指定的目录,而无需手动一张张处理。

2.4 使用 HTML 标签

Hugo 使用的 Markdown 引擎是 Goldmark,它默认是不会渲染原始的 HTML 语句的。需要执行在配置文件中打开一个开关:

[markup]
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = true

插入网页图片 + HTML 宽度设置为 50%:

echo '<img src="/images/wxmp/qrcode-search.png" alt="qrcode-search" style="width:50%;" />' >> ./content/posts/my-first-post.md

操作完上边两种方式的图片插入,效果如下:

first-post-page

2.5 Hugo 文件组织形式简要说明

上边的Quick Start 和插入图片的介绍中,文件统一放在了 content/post 目录下,图片统一放在 static 目录下。这种组织方式不是很清晰,比如一篇博客中就可能有很多图片,如果多篇的文章的图片都放在一个目录下,就会很乱。

要理解 Hugo 只是一个静态的网站框架,如果你不指定特殊配置的情况下,他就像个文件系统,在服务器上创建文件夹,就只是对应到网址中的一层地址而已。我自己是这么安排的:

比如本文的地址是 content/cn/log/2022-10-19-build-personal-blog-step-by-step.md ,图片目录是 static/images/build-personal-blog-step-by-step/

三、部署方案

上一节实际已经在个人主机上搭建起了个人博客的服务,通过 http://127.0.0.1:1313 进行本地访问。本节介绍如何将这种服务进行部署,让所有人都能访问到。

我的博客是部署在【腾讯云】(2核2G 低至50元/1年) 的 CVM 上的,使用 HTTPs 服务访问。具体的进程和文件信息如下:

deployment

具体地:

3.1 基本资源购置

这种部署方式,只需要在【腾讯云】 简单购置和配置就能满足需求。

购置 CVM:要让别人能够访问到你的博客内容,不一定非得自己租服务器,但是使用 CVM 是最灵活、最直接的方式。如果后期要执行个相关的脚本,找个远程机器做点别的事,也非常的方便。

购置了 CVM 会有外网 IP,通过外网 IP 我们可以 SSH 上去,后期如果部署了服务,也可以通过 IP 访问。

我之前有使用 CentOS 相关发行版的经历,所以这里的镜像也是选择的 CentOS。选择不同的操作系统,主要区别在包管理软件的使用上,比如是用 yum 还是用 apt-get。

购置域名:如果想被人记住,肯定不能每次都通过 IP 访问,而是需要申请域名。腾讯云上购置域名之后,需要进行实名认证。

如果要搭建自己的博客网站,还需要网站备案,这将耗费1个月左右的时间。备案完成后,会有一个网站备案号,需要在主页下方展示。但是网站备案并不影响你域名的解析和网站上线(不影响域名解析,但是影响访问,详见最后一小节分析)

配置域名解析:配置 A 记录类型,将记录值修改为 CVM 外网地址,TTL 10 分钟,主机记录可以加个 www@ 两种。配置之后,过一会可以通过 nslookup 等指令进行域名解析,看能否解析出自己的地址。

申请免费 SSL 证书:直接通过 HTTP 是没有加密的明文访问,浏览器也会提示不安全。你是不是也不想让自己的网站看上去很 Low?那就为域名申请一个免费的证书。产生的免费证书有多种形式,我这里选择的 Nginx 使用的证书类型,后边配置 HTTPS 服务会用到。

3.2 安装 Git & Docker

前面介绍了,服务器上的文件同步使用 Git,这里也需要安装一下:

yum install git

为了避免后边迁移服务时因为平台差异带来麻烦,所以几个服务都是选择使用 Docker 进行部署。

在安装其他部署之前,就需要先安装 Docker Engine,可以参考官方文档-Install Docker Engine on CentOS,其他的操作系统也有相关的文档。

sudo yum install -y yum-utils
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin

3.3 Git 定时任务

存储用户凭证,并拉取网站仓库内容:

git config http.postBuffer 524288000
git config --global credential.helper store
git clone git@e.coding.net:panzhongxian/blog/blog.git
## 上边语句 Clone private 仓库需要输入用户名密码
cd blog
git pull

在命令行执行 crontab -e 增加每分钟定时任务:

*/1 * * * * cd /root/blog && git pull

如果确定不会上机器修改什么文件,完全使用 仓库中的内容,可以强制使用远程分支

*/1 * * * * cd /root/blog && git fetch --all && git reset --hard origin/master

这样,一旦你在本地更新了博客文件,并 Push 到主分支上,服务器就会接近实时地拉取到最新内容。

3.4 部署 Hugo 容器

直接使用 Docker 部署 hugo,这里将容器内的 1313 端口映射到主机的 13131 端口。另外,需要手动指定 Blog 的目录(替换下边的 $(blog_path) ):

docker run --rm -v $(blog_path):/src -p 0.0.0.0:13131:1313 klakegg/hugo "server --bind=0.0.0.0"&

拉起服务后可以看看本机的 13131 端口是否正在监听。可以直接通过 {CVM 外网IP}:13131 进行一下访问测试。

3.5 部署 Envoy 容器

我这里用到的 HTTPS 网关选择了 Envoy,选择一个自己熟悉的即可。我将我的 Dockerfile 和配置文件上传到了仓库: https://github.com/panzhongxian/https-blog-envoy-docker

clone 下该仓库之后,需要先替换配置中的 your-site.cn 为你自己的域名,另外有几项配置我这里固定的,如果有需要,可以做手动修改:

最后启动时,指定存储证书文件的文件映射到容器内部的目录:

git clone git@github.com:panzhongxian/https-blog-envoy-docker.git
cd https-blog-envoy-docker
# 替换配置中的网址
sed -i "s/your-site.cn/panzhongxian.cn/g" envoy.yaml

# 构建镜像
docker build -t envoy:v1 .

# 运行容器
docker run -d --add-host host.docker.internal:host-gateway \
  -v /etc/ssl/panzhongxian.cn_nginx:/etc/ssl/panzhongxian.cn \
  -p 9901:9901 -p 443:443 envoy:v1

至此,外网用户已经可以通过 https://www.{你的域名} 访问你的网站了。

3.6 开机启动

CVM 不太容易直接毁掉,但是毕竟还是存在重启的风险。如果期望在重启 CVM 之后,原来拉起的服务能够自动拉起,则需要结合 Linux 的 systemctl 添加开机启动服务。

这里暂时不做具体介绍。

四、辅助工具

4.1 让引擎搜索到

每种静态网站框架都会提供 sitemap 的功能,sitemap 可以提交给主流的搜索引擎,让他们的用户能够搜索到。

配置 Hugo sitemap

在 config.toml 文件中添加以下配置,本地测试的话,会在 http://localhost:1313/sitemap.xml 中展示网站中有哪些页面:

[sitemap]
  changefreq = 'daily'
  filename = 'sitemap.xml'
  priority = 0.5

在 Google / Baidu 中配置和效果

Google 搜索控制台网址是 https://search.google.com/search-console。首先要将自己的域名添加到搜索站点中。该过程中,需要证明这个网站是属于你的,是通过让你给域名 DNS 解析中添加一条特别的记录来实现的。这个过程按照各个搜索引擎的指引即可。

然后,通过【网站地图】页面可以提交我们的 sitemap URL。

google-search-sitemap

添加上自己的网址之后,Google 稍后就会收录,用户搜索、展示、点击的效果也会在 Google 搜索控制台上展示:

google-search-result

Baidu 也有类似的页面进行配置,地址:https://ziyuan.baidu.com/dashboard/index。我博客的访问来源基本都是 Google 过来的,不知道我在百度的配置有什么问题,这里就不列举具体的操作了

4.2 页面访问量统计

页面访问量统计工具的工作原理是:浏览器加载页面,执行页面的 Javascript 脚本,上报相关信息到网站访问量统计的服务。上报的信息包括用户的网址、地区、来源等信息。

看页面访问统计主要是能帮助你了解网站是否健康,哪些页面比较受欢迎,受众主要如何分布等,当然,知道有不少人访问自己的网站,也能带来一些成就感。

各个平台的统计工具类似,不用每个平台都加,不然会给用户加载带来负担。

我这里主要使用的是 https://tongji.baidu.com,可以按照他的指引,添加网站、将需要执行的脚本贴到 Hugo 的模板中即可。

baidu-tongji-report

Google 也有类似的服务叫谷歌分析,地址 https://analytics.google.com/

4.3 自动处理图片路径工具

我平时使用 Typora 编写 Markdown 文档,通常有插入图片的需求,会直接贴进去。这带来了一个问题,图片往往是绝对路径、相对路径或者 HTTP URL 地址,在我正式发布之前需要将这些图片归档到 博客静态目录中,如前边所说,会放到 static/images/{特定文章相关命名文件夹}

我这里用 Python 自己实现了一个工具,可以自动化的下载、拷贝、替换 Markdown 中图片的内容,实现上边的操作。工具托管在 PyPI,使用和安装都非常简单。其中,--dst_md_file 选项如果省略,则默认为替换当前文件,有一定风险,建议产生新文件后比较,没问题再替换:

python3 -m pip install markdown-image-replacer

python3 -m markdown_image_replacer \
   $HOME/quickstart/content/posts/my-first-post.md \
   --src_img_root $HOME/quickstart/static \
   --dst_md_file $HOME/quickstart/content/posts/my-first-post2.md \
   --dst_img_root $HOME/quickstart/static \
   --dst_img_rel_dir images/my-first-post

替换之后,可以查看 my-first-post2.md 文档中内容变化,以及 static 目录的变化。

工具还有很多需要完善的地方,有兴趣的话,可以提 PR 修改。https://github.com/panzhongxian/markdown_image_replacer

4.4 留言工具

国内留言小插件基本都被禁用了,目前只能使用 utterances 利用 GitHub ISSUE 的方式进行,国内用户也是无法使用的。

五、其他部署方式简介与比较

以上五种,我都有折腾过,下面来说说相比于我当前部署,这几种方式的限制

六、网站不备案是否能够访问?

之前的文章被选入了看一看精选,其中关于备案的问题,没有做详细的说明。本文先回答网站不备案是否能够访问,主要篇幅介绍背后隐含的网络知识。

结论先行-国内服务不备案不能访问

如果服务器在国内,比如从腾讯云、阿里云购置的CVM,是必须备案的。两年前搭建博客网站的时候,在未备案阶段还可以访问。最近(2023年1月)刚购买一个新域名,发现如果不备案,HTTP(特指80端口) 和 HTTPS(特指443端口) 两种方式都是无法访问的。

根据国务院令第292号《互联网信息服务管理办法》和《非经营性互联网信息服务备案管理办法》规定,国家对经营性互联网信息服务实行许可制度,对非经营性互联网信息服务实行备案制度。未获取许可或者未履行备案手续的,不得从事互联网信息服务,否则属于违法行为。 – From 腾讯云

接下来通过三个问答的方式,来介绍一下**“不备案无法访问”背后的网络知识**。

Q1: 为什么无法通过未备案的域名进行访问?

从浏览器到服务器之间,会经过不少路由器/交换机,比如云服务商为了符合国家规定,可以在自己的网关入口做一些设置,如果检测到 HTTP/HTTPS 请求,是可以配置一些网络策略,以达到终止的目的的。

从服务端抓包(下边附图),可以清楚地看到:

抓包-HTTP

Q2: 为什么访问未备案域名站点,使用 HTTP/HTTPS 显示不同界面?

以下两张图中,上图是通过 HTTP 协议访问未备案域名的网站(跳转到腾讯云网站),下图是通过 HTTPS 协议访问的结果(ERR_CONNECTION_CLOSED):

网站无法访问-HTTP网站无法访问-HTTPS

我这里从客户端抓包来解释这一现象:

抓包-HTTPS

Q3: 为什么要用 HTTPS 建站?

上边已经简单介绍了 HTTPS 工作原理:使用 SSL/TLS 协议对通信进行加密传输 HTTP 协议。从而防止假冒。通过上边的抓包和分析,你大概也能理解以下几点客户端和服务端都应该选择 HTTPS 的理由:

  1. 服务端提供 HTTPS 服务,在浏览器是可以显示是安全的,让用户觉着这个网站更易信赖
  2. HTTPS 数据在传输的两个方向上都会得到加密,请求和返回中的敏感数据或个人数据不会在传输中被泄漏
  3. SSL/TLS 还可确认网站服务器是其真实身份,从而防止DNS劫持攻击(假冒网站)