速读#
这篇是整个部署系列的说明书:部署不是一串步骤,而是可达、守护、防护、可观测、配置密钥、变更、数据、运维入口八个面。每加一个新服务,按面问“缺了会怎样”,比照抄别人的清单更贴自己的规模。
框架怎么冒出来的#
最早部署是一串步骤:买 VPS → Docker → Nginx → 证书 → 防火墙 → 自启。按顺序做,做完一步忘上一步。
转折在换用 Cloudflare Tunnel。那次迁移只动了「服务怎么被访问到」这一件事——systemd、防火墙、密钥、数据全都原样没碰,站照常跑。这个事实本身就是证据:部署不是一串前后咬合的步骤,而是几件互相独立、各自可验证的事。Tunnel 只解决可达,不解决进程崩了怎么办、出事谁通知我、密钥放哪。
既然彼此独立,就能拆开,每件单独问「缺了会怎样」——就有了八面。
八面,每面一个问句#
| 面 | 问句 | 我的典型落地 |
|---|---|---|
| 可达 | 外面怎么访问到服务? | Cloudflare Tunnel 出站 |
| 守护 | 进程挂了谁拉回来? | systemd Restart=always |
| 防护 | 不该进来的怎么挡? | ufw + fail2ban、SSH 密钥登录 |
| 可观测 | 出事了谁通知我? | 哪吒探针、journalctl |
| 配置密钥 | 密钥 / token / 密码放哪? | .env + gitignore、CI Secrets |
| 变更 | 代码怎么从本地到线上? | Git、GitHub Actions |
| 数据 | 数据存哪、怎么不丢? | 命名卷、MySQL / SQLite |
| 运维入口 | 我从哪登进去管? | FinalShell、SSH |
核心不是「分得对不对」,是每面独立可验证:单独检查有没有缺,不牵连其他面。分类边界也不必刚性——把端口只绑回环,既算防护、也算收紧可达,归哪面都行。重叠不碍事,分面的目的不是给动作归档,是保证每个问句都被问过。
为什么分面,而不是抄清单#
| 抄清单 | 分面 |
|---|---|
| 别人的规模未必匹配你 | 按自己规模问缺什么 |
| 静态列表,不教判断 | 每加服务动态过一遍 |
| 容易配了但不懂 | 只补缺的面,补的都懂 |
我的博客单台 VPS,不需要 K8s、多区域容灾。抄了反而制造理解缺口。
每加一个服务,照表过一遍:缺的才补,不相关的承认存在不展开。
不是每面都要满分#
| 标记 | 含义 |
|---|---|
| 在用 | 有方案且验证过 |
| 评估中 | 想试还没上 |
| 承认缺口 | 知道存在,这规模不构成问题 |
目标不是「八面全满」——那是过度工程。价值是把「隐隐觉得还差点什么」变成「知道差哪面、差到什么程度」。
拿一个新服务实际过一遍#
假设要在 VPS 上加一个自托管的小工具,照表自问:
- 可达:挂进现有 Tunnel,加一条子域路由——不开新端口
- 守护:容器加
restart: unless-stopped,或写个 systemd unit - 防护:只在 Docker 内网
expose,不绑宿主机端口 - 可观测:先蹭哪吒的整机监控,服务级探活缺口先承认
- 配置密钥:管理密码进
.env,确认 gitignore 盖得住 - 变更:
compose.yml进仓库,改动可 diff 可回滚 - 数据:确认它写不写文件——写就挂命名卷,否则删容器即丢
- 运维入口:无新增,仍走 SSH
十分钟过完,缺什么、赌什么,上线前就是明账。比装完再被动发现「哦原来它有数据要存」强得多。
这篇本身不占任何一面——它是八面的说明书。工具会换,问句不换。
