记一次硬核又优雅的个人学术主页建站之旅

缘起:为什么选择自己折腾?

为了更好地沉淀个人的项目经验与学习心得,我决定搭建一个纯粹、极简、完全属于自己的学术展示主页。没有选择臃肿的动态博客框架(如 WordPress),而是走向了“静态生成 + 容器化部署 + 自动化脚本”的硬核极客路线。

这套方案不仅对服务器资源消耗极低,而且将内容的绝对控制权掌握在了自己本地的电脑里。


🛠️ 我的建站工具流 (Toolchain)

整个网站的运转就像一条精密的流水线,涉及的工具可以分为“云端基础设施”和“本地内容生产”两部分。

1. 云端基础设施 (Server-Side)

  • 宿主机:某云厂商的入门级轻量应用服务器(内存不足 2GB,所以对资源分配要求极高)。
  • 管理面板CasaOS。一个基于 Docker 的极简轻量级面板,作为整个服务器的“可视化物业管理”。
  • 反向代理网关Nginx Proxy Manager (NPM)。负责霸占服务器的 80 和 443 端口,未来等域名备案通过后,统一负责域名的流量转发和 SSL 证书(HTTPS 小绿锁)的自动续签。
  • 前端展示基础版 Nginx 容器。只分配了 128MB 的内存限制,占用内部的 8080 端口,纯粹用来挂载和展示静态的 HTML 网页文件。

2. 本地内容生产 (Local-Side)

  • 静态网站生成器Hugo。极其强大的 Go 语言静态博客框架,配合极简的 PaperMod 主题,瞬间将 Markdown 转化为漂亮的网页。
  • 编辑器Typora。配合 Hugo 的 Page Bundle(页面打包)机制,开启“复制图片到当前文件夹”功能,彻底告别图床失效和路径错乱的烦恼。
  • 自动化部署自定义 PowerShell 双子星脚本
    • new_post.ps1:一键选择板块(项目/随笔)并生成标准化 Markdown 模板。
    • deploy.ps1:一键执行 Hugo 编译、打包 ZIP,并通过 SSH/SCP 自动推送到服务器并解压覆盖。实现了“本地敲完字,回车即上线”的极致体验。

🕳️ 踩坑实录与避坑指南

折腾的过程并非一帆风顺,期间遇到了几个非常经典的工程问题:

坑 1:80 端口的“假性占用”

一开始准备部署 NPM 时,命令行提示 80 端口被占用。用 lsof -i :80 查阅后,发现是云厂商自带的监控插件和元数据代理。 破案: 仔细观察网络状态发现是 ESTABLISHED(主动向外请求)而不是 LISTEN(本地监听)。所以本地 80 端口其实是空闲的,直接绕过报错强行启动 Docker 即可。

坑 2:内存告急与 Docker 的“紧箍咒”

云服务器内存不到 2G,如果不对 Docker 容器设限,极端情况下可能会导致宿主机死机。 解决: 放弃纯 UI 操作,改用 docker-compose.yml 结合 sudo tee 强力写入,在配置中加入 deploy.resources.limits.memory。给 NPM 限制 512M,给静态 Nginx 限制 128M,把每一兆内存都用在刀刃上。

坑 3:Let’s Encrypt 证书申请报 “Internal Error”

在 NPM 里配置好域名后,死活申请不下来 SSL 证书,一直报内部错误。 破案: 域名还在 ICP 备案审核期!云厂商的骨干网在流量到达服务器前就直接拦截了所有通过 80 端口查水表的 Let’s Encrypt 验证请求。目前只能用“IP+端口”的模式曲线救国,静候管局佳音。

坑 4:自动化脚本乱码与页面“神秘失踪”

在编写 PowerShell 脚本时遇到了字符吞噬的报错,在终于把文件传到服务器后,网页列表却空空如也。 解决: 1. 脚本报错是因为 PowerShell 默认编码问题,将 .ps1 文件另存为带 BOM 的 UTF-8 即可解决。 2. 页面不显示是因为 Hugo 默认过滤草稿。将 .md 文件头的 draft: true 改为 false,并在 hugo.toml 中明确配置 mainSections = ["posts", "projects"],文章瞬间完美呈现。


结语

从底层的防火墙放行、Docker 容器编排,到前端的主题配置、本地的自动化脚本编写,这次建站犹如一次全栈工程的微缩演练。把重复的操作交给脚本,把精力的焦点还给内容,这大概就是折腾技术最大的乐趣所在。

接下来,就是不断往这个“基站”里填充有价值的思想了。

小葱的学术基站