Files
hoelee-blog/src/content/posts/zh/running-production-infrastructure-solo.md
T
hoelee 68771101ea edit(content): review batch-1 editorial pass across 24 posts (EN + ZH)
- voice: first-person throughout (we/our -> I/my), matching the post guideline
- privacy: internal LAN IPs replaced with placeholder hostnames
  (n8n.internal, gpu-node.internal); one compose volume path generalised
- ZH twins: Traditional -> Simplified characters (site serves zh-Hans),
  whole-file renormalisation where the twin was still Traditional
- dynamicCta: true on 12 posts so the contextual dual-track CTA renders
- long configs wrapped in <details class="tech-deep-dive"> with a summary
  naming the artefact and line count
- self-hosted-tts: token refresh now writes .tmp + atomic mv, with a note on
  the 401 race the old truncating redirect created
2026-10-27 03:29:03 +08:00

7.7 KiB
Raw Blame History

title, description, pubDate, category, blueprint, blueprintLayer, tags, ogImage, banner, draft
title description pubDate category blueprint blueprintLayer tags ogImage banner draft
一个人跑生产基础设施:三台主机、162 个容器 一个人、三台主机、78 个 compose stack 里的 162 个容器——Traefik、SSO、监控、邮件、CI/CD 与备份,以及两次改变了我「怎么核对数字」的故障。 2026-10-06 case-studies self-hosted-infrastructure L1-compute-storage-network
docker
traefik
monitoring
infrastructure
devops
/og/zh-running-production-infrastructure-solo.jpg /banners/running-production-infrastructure-solo.jpg false

为什么这件事重要

卖软件的公司其实同时需要两样东西:一个能干活的应用,以及底下那套让它随时可达、有备份、够安全的机器。大多数情况是这两件事被拆开——开发的人看不见服务器,托管公司又读不懂代码。

我两件都做。也就是说,写这个应用的人,也是在 TLS 自动续期挂掉时被叫醒的人,而且能直接修应用,而不是把问题推给平台。

这是我自己的生产环境:三台自管的 Docker 主机,162 个容器分布在 78 个 compose stack 上,跑着真正对外的服务——客户网站、邮件平台、CI/CD、工作流自动化、访问统计,以及这个博客。没有云平台把它粘在一起,也没有团队在运维。下面是这套架构,以及两次改变了我「怎么检查自己的工作」的故障。

它的样子

主机 承担什么 容器 Compose stack
Synology DSM 存储、SSO、大部分内部服务 86 44
unRaid CI runner、媒体流水线、监控 37 21
Ubuntu 24.04 VPS 公网入口、邮件平台、客户站点 39 13

这个划分是刻意的,不是历史遗留。公网 VPS 承担的是「即便本地私有化节点上行链路维护或波动,也必须保持低延迟与高可用」的核心入口服务,因为公网流量和客户邮件都落在那里。Synology 承担需要磁盘和稳定文件系统的部分,以及所有其他服务都信任的身份源。unRaid 跑 CI runner 和那些又重又突发的批处理任务——否则它们会和服务抢内存。

让三台主机像一套系统的东西

统一的入口模式。 每台主机都跑一个 Traefik 反向代理,配自动化的 ACME 证书,所以证书自己续期,也没有哪个服务需要自己保管证书文件。后面是一套统一的路由和跳转约定,公网域名前面再套 Cloudflare。

统一的身份源。 authentik 用 OIDC 和 proxy provider 做 SSO,所以新增一个内部服务是「在一个地方加一个应用」,而不是「在表格里再加一个密码」。对外的服务保持匿名可访问;其余的都从这里认证。

统一的监控。 Prometheus、Grafana、cAdvisor 和 node-exporter 铺在三台主机上,收进同一个 Grafana 而不是三块面板——因为真正有意思的故障,都是跨主机的那种。

统一的交付路径。 自建的 Gitea Actions runner 负责构建和部署。这个博客就是走这条流水线:提交、runner 接单、容器重建、Cloudflare 把新构建送出去。

经过验证、而不是假设的备份。 NAS 上的快照备份,加上 Duplicati 和 restic 任务,并把恢复步骤写下来——因为没验证过的备份只是一种感觉,不是备份。

失败一:仪表盘在骗我

搭监控的时候我选择相信 Grafana 显示的东西,结果有三块面板是错的。

cAdvisor 报出来的「容器」其实是 cgroup 的伪条目,把容器数量虚报了。我的「总容量」面板把一个 NAS 卷算了三遍,因为三个看起来差不多的挂载点被当成独立文件系统抓取了——这个数字看起来完全合理,而「看起来合理」正是它危险的地方。还有一台虚拟机根本不导出 CPU 频率,于是那块面板一直是空的,而我把它读成「暂时没数据」,而不是「这个 exporter 配错了」。

这三件事都没有弄坏任何服务。但三件事都会让我向客户报出一个假数字,因为仪表盘上的错数字和真数字长得一模一样。整个过程我写在 One Prometheus for unRaid, a Synology NAS, and a VPS 里了。

失败二:少了一个配置文件,三种故障模式

我的团队密码管理器 Passbolt 开始返回 504,它的定时任务看起来卡住了。最后发现是三种不同的故障模式、同一个根因:一个只存在于运行中的容器里、从来没进 compose 文件的配置值。

空的 GPG fingerprint 让邮件发不出去,而发邮件这一步被放在定时任务里,于是整个任务挂住,UI 跟着一起挂。修好之后确实好了——直到容器被重建,配置被抹掉,原来的症状又回来了,看起来像问题自己复发。接着我为了追这两个问题引入的 ssl.force,在反向代理后面造成了跳转循环。

三个症状、三个晚上、一个教训:没有进版本控制的配置,就不算配置。完整的过程写在 Passbolt UI Kept Hanging — Three Failure Modes From One Missing Config File。

我怎么让数字保持诚实

简历上的数字会悄悄过期。我的数字是可以重新算出来的:一个小脚本通过 Portainer API 读活的 Docker 端点,逐台主机统计容器和 compose stack 的数量,所以「162 个容器、78 个 compose stack」是按需重新测量,而不是记住它曾经为真的那一天。同一个脚本还会打印出一份「绝不能出现在任何对客户材料里」的服务清单。

背后的规则很简单:一个无法被重新核对的数字,就是一个没人能在面试里、在报价里、在客户问「你怎么算出来的」那一通电话里守住的说法。凡是不能重新测量的数字,就不写进文档。

我会做得不一样的地方

第一天就把每一个配置值放进 compose 文件,包括那些感觉「属于机器而不是属于服务」的。Passbolt 那次复发,只因为一个修复活在容器里。

对「没有数据」告警,而不是只对「坏数据」告警。 一块空白的面板和一台健康服务,在仪表盘上长得一样。如果某个 exporter 十分钟没送来任何东西,那就是该告警的事件。

用专门用来衡量可用性的东西去衡量可用性。 指标流水线告诉你系统现在表现如何,它并不统计「成功请求 ÷ 总请求」。如果一个百分比要出现在客户面前,它需要一个按计划探测端点并记录结果的探针;否则诚实的回答是「有监控」,而不是一个数字。这个区别比数字本身更重要。

结果

三台主机、162 个容器、78 个 compose stack、一个人——加上自动化证书、统一 SSO、跨主机监控、经过验证的备份和自建 CI/CD。它同时跑过客户网站、一个邮件平台、一个 Telegram 客服 bot、排程自动化和这个博客;也正是它让我能把项目从「这是需求」做到「已经上线、有监控、有备份」,而不用把后半段交给别人。

想给你的生意也做一套?

如果你需要一个既能写应用、又能跑它脚下那套基础设施的人——Docker 和 Traefik、自动化 TLS、SSO、监控、邮件、备份、CI/CD——我做的就是这个,而且我更想聊你的环境,而不是发一份宣传单。

WhatsApp:+60 12-797 2969 · Email:[email protected] · hoelee.com

网站设计开发是我的主业;自托管基础设施、监控与自动化是它的另一半。