我以前买过一个树莓派4B,本来想用它搭建一个独立博客,过程并不复杂,但外网发布遇到了点问题。因为没有公网IP,需要使用ngrok进行内网穿透,但域名和端口号都怪怪的,看着就不舒服,而且国内访问还可能被阻断,所以还是要用虚拟主机的思路。

购买域名

受Derek Sivers博客的影响,我想让域名中的字母尽可能短一些,比如http://shen.lb,但发现这个.lb的域名归黎巴嫩管理,申请它相当不易。

由于是个人博客,我不想使用.com、.org、.vip和.xyz,所以.me是比较中意的域名后缀。

购买域名的服务商非常多,Namesilo、Namecheap、GoDaddy、阿里云、华为云、腾讯云等等,随便选。

最后选定的域名是shenlb.me,一年只需要19元,不过续费1年则需要116元!对于.me域名,国内好像只有阿里云支持申请这种域名。购买过程非常简单,添加到购物车,电子支付即可,需要填写实名认证的信息。

购买虚拟主机

由于个人静态博客所需资源非常少,访问量也很少,尽量找便宜的虚拟主机,最后选定了华为云里的Flexus应用服务器L实例,只需38元(不过续费则要300多元)。2核,2G内存,40GB系统盘,弹性公网IP,2 Mbps峰值带宽,100GB流量包。

有了公网IP后,可以将域名解析到该IP地址,不过推荐在备案通过之后再绑定域名。

下面要安装操作系统,可以使用镜像安装,CentOS、Ubuntu、Debian、Huawei EulerOS都是免费的,安装完之后如果感觉不爽,花2分钟就可以免费切换到其它镜像。如果想换成Windows Server,则需要额外付费。在CentOS、Ubuntu和Debian这几个Linux操作系统之间,我最终选择了Ubuntu,主要因为它对于非Linux专业人士来说,更友好一些。由于我只用于个人博客的应用服务器,一直也没有使用Ubuntu的图形界面。

华为云推荐初学者使用CloudShell登录到Ubuntu的控制台。

安装完基本的操作系统后,需要自动更新一些软件包。

sudo apt update
sudo apt upgrade

安装nginx

一条命令可以完成安装。

sudo apt install nginx

设置nginx开机后默认开启,使用下面的命令:

sudo systemctl start nginx

查看nginx的状态:

sudo systemctl status nginx

我比较偷懒,想使用nginx的默认设置,将hugo的网页发布内容全部复制到nginx的默认页,只修改了/etc/nginx/sites-available/default文件中的server_name:

server {
    root /var/www/html; #没变
    server_name shenlb.me;
}

访问http://shenlb.me,结果一直无法访问。更换CentOS、Debian系统镜像,仍然无法访问网站。折腾了几个小时,后来发现是系统主机里的网络访问控制里需要配置安全组,主方向规则里需要放开80端口。

终于网站可以访问了,可惜好景不长,没过几个小时,网页又无法打开,提示网站未备案,主机已经被阻断。

ICP备案

华为云有专门的APP,其中有一个备案模块,建议网页端和APP端联合进行备案相关的材料提交。

备案期间,将域名解析暂停。大致要提交几个关键材料:

(1)身份证正反面

(2)签字的ICP备案真实性承诺书

(3)ICP备案真实性告知书,并按要求录一小段视频

(4)域名证书,从域名申请的服务端那里可以导出PDF报告。

(5)我在江苏省备案,还需要提供居住证或房产证

华为云的技术人员负责初审,如果资料齐全无误,1-2个工作日就可以完成初审。然后资料提交到管局,这个过程就比较慢了,3-20个工作日。我的备案经过了5个工作日。

通过之后,可以收到邮件和短信通知,到工信部备案系统可以查询到详细信息。

HUGO安装和配置

建站前,问了一下大模型,建立静态的个人博客,HUGO比较流行和成熟,速度快,模板丰富,markdown编辑文章,一个命令生成全部静态页,部署非常方便。

HUGO的官网是 https://gohugo.io,安装包采用了官网上预编译好的Windows-v0.134.3版本,解压后只有一个78M的exe文件。

建站确实非常方便,只需几个命令行,麻烦的地方在于选模板和修改配置。

模板挑来挑去,最后选定了PaperMod

配置信息,我采用yaml格式,修改后的内容:

baseURL: http://shenlb.me/
#languageCode: zh-cn
title: 申龙斌的程序人生
theme: PaperMod

# paginate: 10    #was deprecated in Hugo v0.128.0 
pagination.pagerSize : 10

hasCJKLanguage: true # 自动检测是否包含中文日文韩文,如果文章中使用了很多中文引号的话可以开启
enableInlineShortcodes: true
enableRobotsTXT: true
buildDrafts: false
buildFuture: false
buildExpired: false
enableEmoji: true
pygmentsUseClasses: true
mainsections: ["posts", "papermod"]

minify:
  disableXML: true
  # minifyOutput: true

languages:
  en:
    languageName: "Chinese"
    weight: 1
    taxonomies:
      category: categories
      tag: tags
      series: series
    menu:
      main:
        - name: 文章
          url: archives
          weight: 5
        - name: 🔍搜索
          url: search/
          weight: 50
        - name: 🔖标签
          url: tags/
          weight: 20
        - name: 分类
          url: categories/
          weight: 30

outputs:
  home:
    - HTML
    - RSS
    - JSON

params:
  DateFormat: "2006年1月2日"  
  footer: 
      text : "苏ICP备2024135327号"
  categories:
    enable: true  # 启用分类
    title: 分类  # 分类页面的标题
    description: 查看我的所有分类  
    layout: categories  # 分类页面的布局

  env: production # to enable google analytics, opengraph, twitter-cards and schema.
  description: "个人主页"
  author: 申龙斌
  # author: ["Me", "You"] # multiple authors

  defaultTheme: auto
  # disableThemeToggle: true
  # ShowShareButtons: true
  ShareButtons : ['wechat']
  # ShowReadingTime: true
  # disableSpecial1stPost: true
  displayFullLangName: true
  ShowPostNavLinks: true
  ShowBreadCrumbs: true
  ShowCodeCopyButtons: true
  ShowRssButtonInSectionTermList: true
  ShowAllPagesInArchive: true
  ShowPageNums: true
  ShowToc: true
  TocOpen: true
  ShowWordCounts: true
  VisitCount: true
  enableOtherPosts : true
  # comments: false
  images: ["images/papermod-cover.png"]

  profileMode:
    enabled: false
    title: PaperMod
    imageUrl: "#"
    imageTitle: my image
    # imageWidth: 120
    # imageHeight: 120
    buttons:
      - name: Archives
        url: archives
      - name: Tags
        url: tags
      - name: Content
        url: content

  homeInfoParams:
    Title: "申龙斌"
    Content: >
      70后程序员,精通C#,一直致力于数字油气田工作。

      - 当前为中石化地球物理公司的信息专家,工作地点在南京。

      - 读书、写作、编程、投资、锻炼,一切皆定投……

      -

      - <h1>在其它地方的小窝:</h1>

      - [博客园](https://www.cnblogs.com/speeding)、[CSDN](https://shenlb.blog.csdn.net/)、[Github](https://github.com/slofslb)


  assets:
    disableHLJS: true


markup:
  goldmark:
    renderer:
      unsafe: true
  highlight:
    noClasses: false


services:
  instagram:
    disableInlineCSS: true
  twitter:
    disableInlineCSS: true

HUGO里的网页模板可以随意定制,建议适可而止,够用就行。

编辑文章

文章放在HUGO主文件夹下的content/posts下,为了方便管理,我采用一篇文章放在一个子文件夹下,markdown文件名必须为index.md。

文章采用主流的markdown语法,需要在文件头上增加几行信息。我为了让文章的链接尽可能的短小,每篇文章专门设置url值,比如本文的最终链接就是http://shenlb.me/hugo

+++
title = "使用hugo搭建个人独立博客"
date = 2024-10-21T19:08:00+08:00
draft = false
author = "申龙斌"
summary = "申请域名、虚拟主机、备案、HUGO建站的全过程。"
tags = ["HUGO", "备案"]
categories = ["随笔"]
url = "/hugo"
+++
后面写正文。

发布文章

使用hugo命令,可以一次性编译生成网站的全部静态网页,再把./public文件夹里的全部内容放到Linux机器的指定文件夹即可。我使用Winscp进行文件夹的远程复制。



至此,个人独立博客建立完成。

后续优化与调整

评论系统

多方对比,选用了isso评论系统。主要参考了becool.vip的这篇文章 ,还有官方的教程

1)安装:

apt install python3-pip python3-virtualenv sqlite3 build-essential

2)创建一个虚拟环境:

virtualenv isso
source /root/isso/bin/activate

3)此时进入isso虚拟环境,安装isso:

pip install isso

为了方便运行,建立一个符号链接:

ln -s /root/isso/bin/isso /usr/local/bin/isso

4)新增一个配置文件:/root/isso/isso.cfg

[general]
# 数据库文件位置
dbpath = /root/isso/comments.db

# 你准备部署的主机域名,多个域名用换行隔开,例如
host = http://shenlb.me/

# 允许用户修改/删除评论的最长时间
max-age = 5m

# 新评论提醒方式,默认为 stdout
notify = stdout

# 日志文件,可以不开启
log-file = /root/isso/isso.log


[server]
# 需要监听的地址
listen = http://localhost:8080/


[moderation]
# 是否开始评论审核,以及多少天未审核的评论自动删除
enabled = false
purge-after = 30d


[guard]
# 开启 Spam 过滤
enabled = true

# 每分钟最多评论数
ratelimit = 2

# 评论最多回复次数
direct-reply = 3

# 能否回复自己的评论
reply-to-self = false

# 评论必须输入用户名
require-author = true

# 评论必须输入邮箱
require-email = true


[admin]
# 是否开启后台管理,开启后通过 http://shenlb.me/isso/admin 访问
enabled = true
password = your_password

5)启动isso

注意加上nohup,让控制台窗口关闭的时候不关闭isso进程。

nohup /usr/local/bin/isso -c /root/isso/isso.cfg &

6)配置nginx,在server配置中添加以下内容:

location /isso {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Script-Name /isso;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://localhost:8080;
    }

重启nginx:

sudo systemctl restart nginx

7)验证

浏览器打开 http://shenlb.me/isso/ 有下面提示说明成功

Bad Request
missing uri query

浏览器打开 http://shenlb.me/isso/admin/ 输入密码即可以管理评论。

支持数学公式

Hugo 0.122版本以后,原生支持数学公式渲染,不再像以前需要修改很多地方才可以渲染数学公式。配置之前请确认你使用的Hugo版本高于 0.122。

第一步:修改配置文件

我的Hugo配置文件采用了yaml格式,所以需要修改 config.yaml 文件。添加goldmark的扩展功能,位于markup → goldmark → extensions里的内容。我的goldmark里启用了unsafe,所以内容是这样的。

markup:
  goldmark:
    renderer:
      unsafe: true
      
    extensions:
      passthrough:
        delimiters:
          block:
          - - $$
            - $$
          inline:
          - - $
            - $
        enable: true

第二步:选择数学公式渲染引擎

Hugo支持两种渲染引擎:MathJax和KaTeX。MathJax支持的数学公式更全面,兼容性更好,但加载速度比KaTeX要慢一点。另外,KaTeX在使用内嵌符号(行内公式)$…$渲染公式的时候可能出现错误。

我已经习惯了$…$的内嵌公式(行内公式),所以我选择了MathJax。

需要在模板主题里增加一个文件,因为我使用PaperMod主题,文件名就是:

d:\slb-blog\themes\PaperMod\layouts\partials\math.html

内容如下:

"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
<script>
  MathJax = {
    tex: {
      displayMath: [['$$', '$$']],  // 多行公式
      inlineMath: [['$', '$']]   // 内嵌公式
    }
  };
</script>

第三步:修改baseof文件

需要修改的文件名是: d:\slb-blog\themes\PaperMod\layouts_default\baseof.html 在<head> … </head>块里增加3行内容,我的文件内容是这样的:

<head>
    {{- partial "head.html" . }}
	{{ if .Param "math" }}
    {{ partialCached "math.html" . }}
    {{ end }}
</head>

第四步:在文章中添加数学公式

首先要在文件头里 front matter (头部信息)里增加一行“math = true”的信息,下面是我的费马大定理这篇文章中的头部信息内容:

+++
title = "《费马大定理》"
date = 2023-09-27T08:37:00+08:00
draft = false
author = "申龙斌"
summary = "从勾股定理,到椭圆曲线,一部辉煌壮丽的数学史诗。"
tags = ["费马"]
categories = ["读书"]
url = "/fermat"
math = true
+++

行内公式(内嵌公式)

使用单个美元符号 $...$ 来包裹公式,例如:

这是一个行内公式:$E = mc^2$

渲染结果:$E = mc^2$。

多行公式

使用双美元符号 $$...$$ 来包裹公式,公式将单独占一行显示。

例如:

欧拉公式:
$$ e^{i\pi} + 1 = 0 $$
柯西积分公式
$$ f(a) = \frac{1}{2\pi i} \oint_{\gamma} \frac{f(z)}{z-a} dz $$

渲染效果:

$$ e^{i\pi} + 1 = 0 $$$$ f(a) = \frac{1}{2\pi i} \oint_{\gamma} \frac{f(z)}{z-a} dz $$

实际渲染效果请看我写的几篇含有数学公式的文章:

参考来源

https://gohugo.io/content-management/mathematics/

https://www.yoghurtlee.com/hugo-math-rendering/

内嵌PDF预览

anvithks提供了一个方案,步骤如下:

(1)下载主题

https://github.com/anvithks/hugo-embed-pdf-shortcode.git 下载主题的zip压缩包,把内容放在 slb-blog/themes 文件夹下,记得修改文件夹名称为 hugo-embed-pdf-shortcode

(2)修改hugo.yaml

theme: ["PaperMod", "hugo-embed-pdf-shortcode"]

(3)把 slb-blog/themes/hugo-embed-pdf-shortcode/layouts/shortcodes/embed-pdf.html 复制到自己的文件夹 slb-blog/layouts/shortcodes 下,如果shortcodes 文件夹不存在,就自己创建一个。

注意:据说这里有一个小BUG,需要修改文件里的这一行内容:

<script src= '/js/pdf-js/build/pdf.js'></script>

(4)把 slb-blog/themes/hugo-embed-pdf-shortcode/static/js/pdf-js/ 这个文件夹复制到自己的 slb-blog/static/js 文件夹之下。

(5)现在可以在文章里使用短代码嵌入PDF

{{< embed-pdf url="/shenlb.me.pdf" >}}

(6)效果展示

每天写给孩子一页纸

参考文章:

https://github.com/anvithks/hugo-embed-pdf-shortcode.git

https://discourse.gohugo.io/t/embed-pdf-file-into-a-page-or-post-papermod-theme/36440