缘起:为什么选择自己折腾?
为了更好地沉淀个人的项目经验与学习心得,我决定搭建一个纯粹、极简、完全属于自己的学术展示主页。没有选择臃肿的动态博客框架(如 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 容器编排,到前端的主题配置、本地的自动化脚本编写,这次建站犹如一次全栈工程的微缩演练。把重复的操作交给脚本,把精力的焦点还给内容,这大概就是折腾技术最大的乐趣所在。
接下来,就是不断往这个“基站”里填充有价值的思想了。