本文是个人服务运维的唯一参考源,不是教程。所有记录以此刻实际情况为准,每次改基础设施必须同步更新这里,否则下次出事你就等着对着半年前的配置挠头吧。
0x00 操作系统与初始配置
操作系统标准
新机器统一装服务商提供的最新 Debian 稳定版。现在能买到的机器,要么 Debian 13,要么 Debian 12。优先级:
- Debian 13(首选,能用新的就别用旧的)
- Debian 12(备选,部分服务商模板更新慢)
- 连 Debian 12 都提供不了的厂商直接拉黑
装机后必做清单
拿新机器第一步:
# 1. 主机名 & hosts
hostnamectl hostname <name>
echo "127.0.1.1 <fqdn> <hostname>" >> /etc/hosts
# 2. 时区 & NTP
timedatectl set-timezone Asia/Shanghai
timedatectl set-ntp true
# 3. 基础包
apt-get update && apt-get install -y curl wget git vim sudo htop net-tools \
dnsutils ca-certificates
# 4. SSH 加固
# 5. 防火墙
ufw default deny incoming
ufw default allow outgoing
ufw limit 55822/tcp
ufw enable
# 6. 换源
# 见 0x0C 章节
# 7. BBR
sysctl net.ipv4.tcp_congestion_control
# 8. 装 Docker
# 见 0x06 章节
# 部分机器可跳过
这 8 步做完机器才算达到上线标准。缺任何一步都不要往上面跑服务。
Homelab 物理服务器
配置如下:
| 项目 | 规格 |
|---|---|
| CPU | Intel Xeon E5 系列,48 核心 |
| 内存 | 128 GB DDR3 |
| 存储盘 1 | 2 TB SSD,无 RAID |
| 存储盘 2 | 2 TB HDD,无 RAID |
| 虚拟化平台 | Proxmox VE 8,单节点集群 |
| 客户端类型 | KVM 主力 + LXC 跑基础设施 |
| LXC 备份 | 每日双异地备份 |
| KVM 备份 | 目前裸奔 —— 需要补上 restic 备份 |
| PBS | 未部署(计划中) |
| 公网接入 | IPv6 公网 + IPv4 NAT1 |
| 外部桥接 | vmbr0(直通公网) |
| 内网通信 | vnet1 |
| 功耗 | ~180 W |
| 运行时间 | >2 年,稳如老狗 |
SSH 配置
文件:/etc/ssh/sshd_config
| 参数 | 值 | 备注 |
|---|---|---|
| Port | 55822 | 非标端口是第一道防线,防脚本小子的 |
| PermitRootLogin | prohibit-password | Root 允许密钥登录,禁用密码 |
| PubkeyAuthentication | yes | |
| PasswordAuthentication | no | 密码登录一律关掉,别犹豫 |
| UsePAM | yes | 部分服务需要 |
| AuthenticationMethods | publickey | 只认公钥 |
密钥路径:~/.ssh/authorized_keys
防火墙规则
管理工具:ufw(有在想迁到 nftables,但目前 ufw 除了难用和傻逼没出过问题,所以优先级不高)
| 方向 | 端口 | 协议 | 源 | 描述 |
|---|---|---|---|---|
| 入站 | 55822 | TCP | 0.0.0.0/0, ::/0 | SSH 远程管理 |
| 入站 | 80 | TCP | 0.0.0.0/0, ::/0 | HTTP(重定向用) |
| 入站 | 443 | TCP | 0.0.0.0/0, ::/0 | HTTPS |
| 入站 | 179 | TCP | 对等 IP 段 | BGP(Bird) |
| 入站 | 51820 | UDP | 指定对端 | WireGuard 隧道 |
其余端口由 Docker iptables 集成或反向代理负责放行。ufw 只管主机层面的出入口,应用层面交给反代和 WAF。
内核参数
# /etc/sysctl.d/99-bbr.conf
# BBR 拥塞控制 —— 新内核默认就有
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
# /etc/sysctl.d/98-conntrack.conf
# conntrack 表容量 —— 默认 65536 对大多数场景够用
net.netfilter.nf_conntrack_max = 262144
net.netfilter.nf_conntrack_buckets = 65536
日常管理
-
系统更新:
apt update && apt upgrade -y && apt autoremove -y每月至少跑一次。内核更新后需要重启,别忘了。
-
日志轮转:目前各服务自己管自己的日志,没有统一方案。Docker 容器日志建议加
--log-opt max-size=10m --log-opt max-file=3配置在compose.yml里,不然/var/lib/docker迟早撑爆。 -
查看磁盘:
df -h du -sh /var/lib/docker # 这个目录最容易暴涨 docker system prune -a # 快速清理 Docker -
查实时连接:
ss -tunp lsof -i # 计数 ss -s
0x01 命名规范
主机命名规则
格式:[分组-]国家-类型-标识符
- 分组(可选):环境或项目前缀(
prod、dev、infra) - 国家:ISO 3166-1 二位国家代码(
us、jp、de、sg) - 类型:虚拟化方式(
systemd-detect-virt输出值,如kvm、lxc) - 标识符:服务商缩写(≤5 字符,如
vultr、buyvm)
示例:infra-us-kvm-vultr、prod-jp-kvm-ali
这套规则最大的价值:看名字就知道机器在哪、跑在什么上面、是谁家的。出事了随手
ssh hostname不用翻笔记。
标签规范
| 标签 | 用途 |
|---|---|
infra | 基础设施(DNS、监控、反向代理) |
prod | 生产业务 |
dev | 开发测试 |
bgp | BGP 路由器 |
s3 | 存储节点 |
0x02 DNS 管理
托管商
域名分散托管于多家主流 DNS 提供商:
- Cloudflare — 主力 DNS,大部分网站通过 CF 代理
- Aliyun DNS — 傻逼
- 华为云 DNS — 大部分有合规要求的域名
- 腾讯云 DNSPod — 懒得改 NS 的域名
- 火山引擎 TrafficRouter — 没啥用的 100% SLA
- AWS Route53 — 部分业务
- Google Cloud DNS — 部分业务
分散托管的原因:鸡蛋不放一个篮子里,单家出问题不影响所有域名解析。代价是管理复杂度增加了,所以必须上 DNSControl 等 IaC 方案。
Zone 管理
- 管理工具:DNSControl
- 配置仓库:
https://git.6l.ink/liuzhen932/dns(私有仓库) - 自动化:Forge Actions 触发
工作流程:
- 修改 DNSControl 配置(
dnsconfig.js) - 提交到 Git
- Forge Actions 自动执行
dnscontrol push同步到各 DNS 服务商
禁止手动在 DNS 面板修改记录,否则不一致将造成服务停机
DDNS
- 客户端:ddns-go(默认端口 9876)
- 部署方式:Docker
- 适用场景:动态 IP 的机器
ddns-go 的 Web 管理界面很直观,配好之后自动轮询公网 IP 变化并更新 DNS 记录。接入多个 DNS 提供商也支持。
0x03 SSL/TLS 证书续签方案
ACME 客户端
| 客户端 | 用途 | 部署方式 | 自动化方式 |
|---|---|---|---|
| Caddy | Caddy 反代的域名证书 | Caddy 内置 | 自动申请与续期,无需任何配置 |
| Certimate | 非 Caddy 托管的域名 | Docker | 内置流水线编排,自动推送部署 |
ACME 账户邮箱:tls#932.moe
Caddy 自动续期
Caddy 的 ACME 客户端是内置的,只要有:
example.com {
reverse_proxy 172.17.0.1:8080
}
Certimate 管理
对于不用 Caddy 的服务(OpenResty、自建 API 等),用 Certimate 编排:
- 证书申请(支持 HTTP-01 / DNS-01 challenge)
- 证书保存
- 自动部署到目标服务器(通过 SCP / API / 文件写入等方式)
0x04 BGP 路由策略
资源
| 项目 | 值 |
|---|---|
| ASN | AS213891 |
| IPv6 段 | 2a0e:aa07:e150::/44 等 |
| 有效 /48 | 10+ 个 |
| IPv4 | 无 |
| RIR | RIPE NCC |
| 网络类型 | Educational / Research |
| 流量特征 | 100–1000 Mbps,大部分出站 |
| RPKI ROA | 全局启用 |
| Looking Glass | https://lg.932.moe/ |
| Peering 策略 | Selective |
Upstream
| ASN | 名称 | IPv6 |
|---|---|---|
| AS53667 | FranTech Solutions (BuyVM) | ✔ |
| AS20473 | Vultr | ✔ |
| AS34927 | iFog GmbH | ✔ |
| AS16509 | AWS | ✔ |
| AS204211 | 忘记了 | ✔ |
| AS209533 | iFog GmbH — BGPTunnel | ✔ |
| AS213605 | Liu HaoRan | ✔ |
| AS212895 | Johannes Ernst | ✔ |
| AS41051 | Freetransit Project | ✔ |
对等 ASN
除上行和 IXP 成员外,还维持了少量直接对等:
| ASN | 名称 |
|---|---|
| AS198025 | Steve87 |
| AS210440 | AKAERE NETWORKS |
其他都不认识。
社区标记
用于路由策略标记:
| 社区 | 含义 |
|---|---|
213891:1:10 | Learned from Peers(从对等处学来的) |
213891:1:11 | Learned from Upstreams(从上游学来的) |
213891:2:X | Learned from AS X |
213891:10:X | Learned at router X(多路由器场景区分来源) |
BIRD2 配置
托管于私有仓库:https://git.6l.ink/liuzhen932/as213891.conf
BIRD 配置用 Git 管理最大的好处是回滚。某次改策略把路由搞崩了,
git revert然后birdc configure,没有版本控制的配置就是定时炸弹。
运维
# 查看 BGP 会话状态
birdc show protocols
# 查看路由表
birdc show route
# 重新加载配置(不中断会话)
birdc configure
# 查看特定前缀的传播情况
birdc show route for 2a0e:aa07:e150::/44 all
0x05 OID 分配表
- 根 OID:
1.3.6.1.4.1.64517 - 用途:SNMP 监控的自定义 OID,暂只注册了根节点
目前没有用 SNMP 监控任何东西,Prometheus 生态更香。
0x06 容器与编排
运行环境
| 项目 | 值 |
|---|---|
| Docker 版本 | 始终用最新版 |
| Compose 版本 | 始终用最新版 |
| 运行模式 | root 模式 |
| Compose 文件路径 | /opt/<项目名>/compose.yml |
| 网络模式 | bridge 为主,部分服务用 host 减少损耗 |
Docker 安装脚本
curl -fsSL https://get.docker.com | sh
容器化服务清单
所有自定义镜像托管于 docker.io/liuzhen932/*,私有镜像除外。
反向代理
| 镜像 | 名称 | 说明 |
|---|---|---|
app-openresty | OpenResty | 主力反代 + WAF |
app-caddy | Caddy | 次要反代 |
app-typecho | Typecho | 博客 |
app-blessing-skin-server | Blessing Skin | Minecraft 皮肤站 |
app-openstatus | OpenStatus | 状态页 |
app-opengrok | OpenGrok | 代码搜索 |
app-rustpad | Rustpad | 协作编辑器 |
网络 & 隧道
| 镜像 | 名称 | 说明 |
|---|---|---|
app-cloudflared | Cloudflare Tunnel | CF 隧道,用于没有公网 IP 的机器 |
app-derper | DERP Relay | Tailscale DERP 中继节点 |
app-warp | Cloudflare WARP | WARP 出口 |
app-tor | Tor | Tor 出口节点 |
BGP & 网络监控
| 镜像 | 名称 | 说明 |
|---|---|---|
bird2-docker | Bird2 | 容器化部署 BIRD |
dn42-docker | DN42 | DN42 实验网络 |
app-bgpalerter | BGPalerter | BGP 异常检测 |
app-xenoeye | Xenoeye | Netflow 流量分析 |
app-fastnetmon | FastNetMon | DDoS 检测 |
Compose 配置规范
所有服务统一目录结构:
/opt/<项目名>/
├── compose.yml # 服务定义
├── .env # 环境变量
└── data/ # 持久化数据
日志配置
每个 compose.yml 里建议加上:
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
更新策略
- 镜像更新检测:Diun(监控 Docker Hub / GHCR 的镜像更新)
- 实际操作:手动执行
cd /opt/<项目名>
docker compose pull && docker compose up -d
为什么不全自动更新?全自动滚动更新一旦出问题很难定位。个人运维场景,手动跑一条命令比半夜被告警吵醒划算。Diun 负责通知你有新版本,收到通知后挑个方便的时间手动更新。
Docker daemon 配置
// /etc/docker/daemon.json
{
"features": { "buildkit": true },
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
全局限制日志大小,防止日志撑爆磁盘。
0x07 端口与服务映射
公网入站
| 端口 | 协议 | 服务 | 备注 |
|---|---|---|---|
| 80 | TCP | HTTP → 301 跳转 443 | Caddy/OpenResty 负责 |
| 443 | TCP | HTTPS(Caddy / OpenResty) | 主力 Web 流量入口 |
| 179 | TCP | BGP(Bird) | 仅限对等 IP |
| 55822 | TCP | SSH | 自定义端口 |
| 51820 | UDP | WireGuard | 隧道互联 |
其余端口(如各服务管理端口)按需放行,但只对特定来源 IP 开放。基本原则:默认全关,按需放行。
反向代理
| 角色 | 配置路径 |
|---|---|
| Caddy | /opt/caddy/Caddyfile |
| OpenResty | /opt/openresty/nginx.conf + conf.d/*.conf |
OpenResty 负责主要流量的反向代理和 WAF;Caddy 负责次要服务和新项目的快速部署,优势是零配置 HTTPS。
Tailscale
Tailscale 作为运维通道使用,不暴露到公网:
| 节点角色 | 用途 |
|---|---|
| 认证节点 | Tailscale 网络入口,各服务器通过 Tailscale SSH 管理 |
| DERP 中继 | 自建 DERP 节点,降低对 Tailscale 官方中继的依赖 |
| 客户端 | 本地 PC / 手机通过 Tailscale 接入内网服务 |
Tailscale 最大的价值:不管机器在哪个国家、有没有公网 IP、NAT 类型是什么,只要它能联网,Tailscale 就能把它拉进你的网络。IPv4 NAT 后面裸 SSH ?还是 Tailscale 吧。
0x08 关键服务备忘
邮件
没有自建邮件服务器。自建邮件是运维界公认的深坑——IP 信誉、反 spam 配置、DKIM/SPF/DMARC、各大厂商拒收……为个人博客搞一套不值当。
| 项目 | 方案 |
|---|---|
| 入站转发 | Cloudflare Email Routing(CF 收邮件后转发到目标邮箱) |
| 发信 | 依托第三方服务的 SMTP(具体看服务需要) |
| 个人邮箱 | 阿里邮箱 / 飞书邮箱 / QQ 邮箱 |
CI/CD
| 项目 | 值 |
|---|---|
| 平台 | Forgejo Actions |
| Runner | 自建的 Forgejo Runner,运行在 homelab |
| 仓库 | 自建 Forgejo 实例(git.6l.ink) |
自动化流水线:
- DNS 发布:提交 DNSControl 配置 → 自动
dnscontrol push - Docker 构建:提交 Dockerfile → 自动构建并 push 到 Docker Hub
- 博客发布:提交文章 → 自动构建并部署
日志
| 项目 | 值 |
|---|---|
| 集中日志平台 | ELK + OpenObserve(全自建) |
| 采集方式 | Filebeat / Vector 从各节点采集 |
日志是出事之后唯一的上帝视角。平时没人看,但真出问题了没日志你连从哪查起都不知道。
现状:ELK 和 OpenObserve 已经部署,但还没把所有服务的日志都接入。持续完善中。
0x09 数据持久化与备份
重要数据路径
所有持久化数据都在各服务的 /opt/<项目名>/ 目录下:
/opt/<项目名>/
├── compose.yml # 服务定义
├── .env # 环境变量
├── data/ # 数据库、文件存储等持久化数据
└── config/ # 配置文件(如果是卷映射出来的)
备份现状
| 环境 | 工具 | 频率 | 范围 |
|---|---|---|---|
| Homelab LXC | 自定义脚本 + rsync/scp | 每日 | 全量备份,推送双异地存储 |
| Homelab KVM(其中一台) | restic 0.18.1 | 每日 | 全量 /opt 目录 |
| 云 VPS | ❌ 尚无备份 | — | — |
这个是最大短板。云 VPS 上的数据目前没有统一备份方案。理论上服务商有快照功能,但快照不是备份——机房起火你的快照也跟着烧了。TODO:restic 覆盖所有云 VPS。
Restic 备份命令(快速参考)
# 初始化仓库
restic init --repo s3:https://<endpoint>/<bucket>
# 创建快照
restic --repo <repo> backup /opt
# 查看快照
restic --repo <repo> snapshots
# 恢复
restic --repo <repo> restore latest --target /
凭据存储
| 类型 | 存储位置 | 备注 |
|---|---|---|
| CI/CD 密钥 | Infisical | 密钥管理平台,支持环境变量注入 |
| 应用密钥 | .env 文件或 compose.yml | 明文写入 compose.yml 仅限无外网的内部服务 |
| 备份密钥 | 离线存储 + 密码管理器 | 备份加密密钥不能跟备份放在一起 |
跟凭据有关的核心原则:
.env文件不入库。compose.yml里用${VAR}引用环境变量,.env写本地.gitignore里。不小心 push 了密钥怎么办?一个字:换。
0x0A 监控与告警
监控栈
| 组件 | 用途 | 部署方式 |
|---|---|---|
| Prometheus | 指标采集与存储 | Docker(homelab) |
| Grafana | 可视化与告警面板 | Docker(homelab) |
| AlertManager | 告警路由与通知 | Docker(homelab) |
| Node Exporter | 主机指标采集 | 每台机器上跑一个 |
| cAdvisor | 容器指标采集 | 每台 Docker 主机上跑一个 |
| Blackbox Exporter | 外部探活 | Docker(homelab) |
告警渠道
| 渠道 | 状态 | 备注 |
|---|---|---|
| ntfy | 启用 | 主要通知渠道,推送到手机 |
| SMTP | 启用 | 邮件告警,备用渠道 |
| 已废弃 | 之前用 QQ 机器人,后来弃了 |
ntfy 是真的好用。手机装个 App,收到告警推送直接点开看。比邮件快,比 QQ 稳定,而且不依赖国内生态。
关键告警阈值
| 指标 | 告警阈值 | 处理方式 |
|---|---|---|
| 磁盘使用率 | > 80% WARN, > 90% CRIT | 清理日志、扩容、或迁移数据 |
| 内存使用率 | > 90% | 检查 OOM 日志,看是否需要加内存 |
| CPU 使用率 | > 90% 持续 5 分钟 | 查哪个进程在吃 CPU |
| SSL 证书到期 | < 14 天 | 自动续签(Caddy / Certimate),如果续签失败则手动排查 |
| Ping 丢包 | > 10% 持续 3 次采样 | 检查网络链路 |
| BGP 会话中断 | 任何会话 Down | 检查对端状态和网络连通性 |
| Docker 容器状态 | 容器退出(非预期) | 查容器日志,恢复服务 |
告警处理流程
- 收到告警 → 确认告警真实性(不是误报)
- 如果是误报 → 调优告警规则,避免下次再误报
- 如果是真问题 → 按 SOP 处理
- 处理完 → 记录到本文的对应章节
- 如果是同类问题第二次出现 → 考虑自动化修复
0x0B 安全防护
WAF — 两层防护
| 层 | 方案 | 参考 |
|---|---|---|
| 边缘(Edge) | Cloudflare WAF | Cloudflare WAF 规则 |
| 源站(Origin) | OpenResty (Nginx) WAF | OpenResty WAF 规则 |
Cloudflare WAF 挡掉大部分常见攻击流量(SQL 注入、XSS、路径遍历等)。但不要把安全全押在 CF 上——
为什么源站还要 WAF:CF 不是万能的。有些人直接扫源站 IP 绕过 CDN,或者你的服务有一部分没走 CF(API 直连、非 Web 服务等)。源站 WAF 是最后一道防线。
fail2ban & CrowdSec
| 组件 | 应用场景 | 封禁时长 | 备注 |
|---|---|---|---|
| fail2ban | SSH 暴力破解 | 1 hour | [sshd] jail |
| CrowdSec | Nginx 恶意请求 | 4 hours | nginx-http 场景 |
两者的区别:fail2ban 只管自己机器上的日志;CrowdSec 有社区威胁情报网络,一台机器发现恶意 IP 会同步给其他用户。
实际效果:fail2ban 主要是挡住了 SSH 扫描脚本。CrowdSec 的数据更有价值,能识别到一些普通的 WAF 规则没挡住的异常请求模式。
登录审计
# 近期 SSH 登录记录
last -n 20
# sudo 执行记录
journalctl -t sudo --since "7 days ago"
# 所有登录失败的 IP
lastb | awk '{print $3}' | sort | uniq -c | sort -rn | head -10
# 当前登录用户
who
SSH 日志是安全排查的第一站。
lastb看暴力破解的来源,last看有没有陌生 IP 成功登录。
0x0C 软件源/镜像加速
apt
大厂内网的机器用服务商提供的内部镜像源(延迟最低,带宽不限),其余机器统一用 中科大 USTC 镜像。
# /etc/apt/sources.list — USTC 镜像(Debian 12 Bookworm)
deb https://mirrors.ustc.edu.cn/debian/ bookworm main contrib non-free
deb https://mirrors.ustc.edu.cn/debian-security bookworm-security main contrib non-free
deb https://mirrors.ustc.edu.cn/debian/ bookworm-updates main contrib non-free
Debian 13(Trixie)发布后把 bookworm 替换为 trixie 即可。
pip
# ~/.pip/pip.conf
[global]
index-url = https://mirrors.ustc.edu.cn/pypi/web/simple
trusted-host = mirrors.ustc.edu.cn
npm
npm config set registry https://mirrors.ustc.edu.cn/npm/
Docker
Docker 镜像源在 daemon.json 里配置,但目前没配国内的 mirror。在大陆的机器可能 pull 得慢,考虑加一行 "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]。
USTC 镜像是目前国内最靠谱的开源镜像站之一,维护团队靠谱、更新及时、容量够大。清华 TUNA 也可以做备选。
0x0D 续费与到期日历
域名
| 域名 | 说明 | 注册商 | 到期提醒 |
|---|---|---|---|
932.moe | 主力域名,个人站点、邮箱 | Cloudflare | 到期前 30 天邮件提醒 |
liuzhen932.top | 备用域名,博客、Abuse 联系 | 阿里云 | 到期前 30 天邮件提醒 |
6l.ink | 短链接/Git 服务 | Cloudflare | 到期前 30 天邮件提醒 |
| 其余 30+ 域名 | 分散注册 | 多家服务商 | 需要统一管理 |
30 多个域名分散在多家注册商,这就是个管理噩梦。目前靠邮箱收续费提醒,真漏了一个就完了。TODO:搞个域名管理看板或脚本,统一监控到期日。
VPS / 服务器
各厂商续费策略:大部分按年付(便宜)、少数按月付。
| 厂商 | 续费周期 | 备注 |
|---|---|---|
| BuyVM | 月付 | 随时可停 |
| Vultr | 按小时 | 用了付钱,不用停 |
| 阿里云 | 年付 | 大促时囤的 |
| 其他 | 月/年付 | 见各厂商账单 |
VPS 续费没有统一的日历管理。到期的钱不多,但忘了续导致服务停摆就尴尬了。目前靠手机日历设提醒。
SSL 证书
全部 Let’s Encrypt,Caddy 和 Certimate 自动续期。没有手动过期风险,只需要确保 ACME 客户端正常运行。
0x0E GitOps / IaC 速查
配置仓库
| 仓库 | 用途 | 管理工具 |
|---|---|---|
git.6l.ink/liuzhen932/dns | DNS 配置 | DNSControl |
git.6l.ink/liuzhen932/as213891.conf | BGP 配置 | Bird + Git |
部署流程
# DNS 变更
修改 dnsconfig.js → git push → Forge Actions 自动 dnscontrol push
# BGP 变更
修改 bird.conf → git push → 登录机器 → birdc configure
# 服务更新
cd /opt/<项目名>
docker compose pull
docker compose up -d
# 配置文件更改
修改 compose.yml 或 config 文件 → docker compose up -d(重建容器)
敏感文件管理
| 类型 | 管理方式 |
|---|---|
| CI/CD 密钥 | Infisical |
| 应用密钥 | .env 文件或 compose.yml 明文 |
原则:所有敏感信息都不进 Git。.env 和 compose.yml 里的明文密码只用在 homelab 内网机器上,云 VPS 上必须用 Infisical 或环境变量注入。
0x0F 服务依赖关系
启动顺序
数据库(PostgreSQL / MySQL / SQLite)
→ 后端服务(API / Web 应用)
→ 反向代理(Caddy / OpenResty)
→ 监控(Prometheus / Grafana / AlertManager)
反过来,关机顺序:监控 → 反代 → 后端 → 数据库。
故障影响矩阵
| 服务挂了 | 影响范围 | 恢复优先级 |
|---|---|---|
| 反向代理 | 所有 Web 服务不可达 | P0 |
| 数据库 | 依赖该 DB 的所有服务不可用 | P0 |
| DNS | 域名解析失败,Tailscale/内网 IP 仍可访问 | P1 |
| BGP | 部分路由失效,具体看影响哪些前缀 | P1 |
| 监控栈 | 不影响核心业务,但无法收到告警 | P2 |
| 镜像仓库 | 无法拉取新镜像,已运行的容器不受影响 | P5 |
0x10 灾难恢复 SOP
服务器完全挂了的恢复步骤
- 从提供商控制台进入救援模式(Rescue Mode / Live CD)
- 挂载系统盘
mount /dev/sdaX /mnt - 检查文件系统
fsck /dev/sdaX - 从备份恢复 /opt 目录数据
restic --repo <repo> restore latest --target /mnt/opt - 重装系统(同版本 Debian)
- 执行装机后必做清单(见 0x00)
- 安装 Docker
- 恢复 compose.yml 和 .env
docker compose up -d恢复所有服务- 验证各服务正常运行
恢复后的验证清单
# 1. SSH 能登
ssh -p 55822 root@<host>
# 2. 反代正常运行
curl -I https://<domain>
# 3. 数据库连接正常
docker compose exec db pg_isready # PostgreSQL 为例
# 4. 备份已恢复
restic --repo <repo> snapshots
# 5. 监控正常
curl http://localhost:9090/api/v1/query?query=up
# 6. DNS 解析正常
dig <domain>
离线入口
| 方式 | 可用条件 | 备注 |
|---|---|---|
| Tailscale SSH | Tailscale 可达 | 优先尝试,只要没把 Tailscale 的流量堵了就能进 |
| 提供商 VNC / IPMI | 有控制台权限 | 救援模式入口 |
| 备用 SSH 端口 55822 | 防火墙正常 | 在防火墙规则中显式放行 |
灾难恢复最重要的是恢复前想清楚先恢复什么。数据库 → 反代 → 服务,按这个顺序恢复最快能让用户访问到服务。不要试图把所有服务同时恢复,先让核心业务跑起来,其他的慢慢来。
预防性措施
除了这条文档本身,以下措施能显著减少灾难恢复的工作量:
- 所有 compose.yml 放在 Git 仓库里
- 关键配置截图/存一份离线备份
- 定期做恢复演练
- 多地域备份
- 备份失败要有告警