这个博客是怎么搭起来的

有朋友问这个站是怎么搭的,顺手写一篇,把技术栈和取舍说清楚。
整体结构
整站只有两个部分:
- 生成器:
build.py,纯 Python 标准库,把content/posts/*.md渲染成静态 HTML - 服务器:一个 Caddy 容器,负责发文件、自动管证书
没有数据库,没有后台,没有 Node.js 工具链,没有依赖要更新。整站的体积不到 200 KB。
为什么不用现成的博客程序
WordPress 之类的动态程序功能全,但代价是:需要一个数据库、需要定期升级、暴露的后台是个长期风险面。对于"主要就是写字"的需求,这些成本都不划算。
静态生成的好处是攻击面几乎为零——服务器上没有任何能执行写入的接口。
为什么不用现成的静态生成器
Hugo、Hexo 都很成熟,功能比这个 build.py 强得多。但本站的需求非常窄:
- 文章列表和文章页
- 标签归档
- RSS 和 sitemap
这几个加起来不到 400 行 Python。自己的生成器意味着没有版本升级焦虑,也不会在某次大版本更新后需要重写主题。
当然,如果你想要主题生态和更多功能,Hugo 是更好的选择——这是取舍,不是优劣。
目录结构
hahaha-blog/
├── build.py 生成器
├── config.toml 站点配置
├── content/
│ ├── posts/ 文章(Markdown)
│ └── about.md 关于页
├── templates/ HTML 模板
├── static/ CSS、图标
├── site/ 生成结果(被容器挂载)
├── Caddyfile Caddy 配置
└── docker-compose.yml 编排文件
发一篇文章的流程
# 1. 新建 Markdown
vim content/posts/2026-09-20-some-title.md
# 2. 重新生成
python3 build.py
# 3. 完成 —— Caddy 直接读取静态文件,不需要重启
Markdown 文件开头的 front matter 决定元信息:
---
title: 文章标题
date: 2026-09-20
tags: 标签一, 标签二
cover: /assets/img/cover-build.jpg
summary: 列表页显示的摘要
---
关于成本
一台最低配的云服务器足够。Caddy 容器的常驻内存大约 15 MB,CPU 空闲时几乎为零。真正的瓶颈只有一个:带宽,而不是算力。
静态站点的另一个隐形好处是抗压——即使被流量打到,也就是 nginx/Caddy 拼命发文件的区别,不会有数据库被拖垮的连锁反应。
如果你也打算搭一个,需要的东西真的只有三样:一台服务器、一个域名、一个下午。