在一台 2GB 树莓派上搭建个人网站
目录
很长一段时间里,我的自建服务都是"Mac 上 npm run dev,看完就关"。后来想通了:这些服务本来就该常驻。于是把它们全部搬上了一台树莓派——2GB 内存、SD 卡、被动散热,没有风扇。这篇文章记录现在的架构,以及两个踩过的坑。
架构:一个 Nginx 容器管所有站点
树莓派上只跑三个容器:nginx、certbot、以及一个业务容器。所有站点的 server block 都写在一个 nginx.conf 里,站点文件挂载进容器,改动配置后 docker compose up -d nginx 生效。对一个个人服务器来说,这比每个站点一套 compose 清爽得多。
每个站点一个目录,全部以只读方式挂载:
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./momentum:/usr/share/nginx/momentum:ro
- ./blog:/usr/share/nginx/blog:ro
证书:DNS 验证,不依赖 80 端口
家里宽带通常没有固定公网 IP,端口转发也未必开得起来。所以证书签发用的是 Let’s Encrypt 的 DNS-01 验证:certbot 通过 Cloudflare API 加一条 TXT 记录完成验证,全程不需要外部访问 80 端口。一个 certbot/dns-cloudflare 容器跑着 certbot renew 的 12 小时循环,续期全自动。
顺带一提:签发新子域证书时最好单独签一张,而不是 --expand 合并进已有证书——前者失败时不会影响其他站点的证书。
构建留在 Mac,Pi 只做静态服务
最初想过直接在树莓派上 npm ci && npm run build,很快放弃了:2GB 内存跑一个完整的 Vite 工具链随时可能 OOM,SD 卡的随机写也慢得让人失去耐心。现在的做法是 Mac 上构建、rsync 上传,树莓派只干一件事——把静态文件发出去。
代价是"发布"需要一条命令;收益是 Pi 的负载长期停在 0.05,内存只用了 540MiB。
两个必须配置的细节
- SPA 回退:
try_files $uri $uri/ /index.html;。少了这一行,刷新深链接就是 404。 - Service Worker 的缓存策略:
sw.js必须 no-cache,哈希资源才敢长缓存。PWA 还需要 HTTPS——这恰好是上面证书部分存在的意义。
账单
上线后的状态:负载 0.05,芯片 62.3°C,连续运行 67 天,从未降频。这台 2GB 的小机器同时跑着七八个站点和一个监控容器,依然有大把余量。树莓派做个人站点服务器,绰绰有余。