一台独立开发者常用的 1C2G 或 2C4G VPS,最怕的不是机器坏,而是你以为自己有备份。云厂商备份、Restic、Uptime Kuma 各管一段:云备份管整机回滚,Restic 管单文件和配置找回,Uptime Kuma 管故障发现,恢复演练管这套东西到底能不能跑起来。

这篇按 2026 年 5 月 24 日比对的 Restic、Uptime Kuma、Hetzner Cloud 和 DigitalOcean 文档来写。没有假设你有 SRE 团队,默认就是一个人维护 SaaS、博客、API、Stripe webhook 和几个 Docker 服务。

最低配置到底是哪几项?

把目标压低:不是做银行级容灾,而是让一台 VPS 在误删文件、升级失败、磁盘坏掉、机房故障时有路可退。最低配置是 4 件事。

最低配置频率解决什么问题
文件级备份Restic 备份 /etc、应用目录、数据库导出每日 1 次找回配置、上传文件、单表导出
整机镜像云厂商自动备份或手动快照每日或发布前系统级回滚、快速复制机器
可用性监控Uptime Kuma 外部探测 HTTPS / TCP / 证书1 分钟比用户更早知道挂了
恢复演练新建临时 VPS 还原一次每季度 1 次验证密码、命令、依赖和文档

Restic 官方文档把一次目录备份称为 snapshot,restic backup 会保存目录在某一刻的内容,并用快照 ID 标识。云厂商的 snapshot 也是某一刻磁盘镜像,但它通常不能优雅处理运行中的数据库写入,也不方便只恢复一个文件。

Restic 怎么配才算能用?

先别追求复杂仓库。个人项目用一个远端仓库,按主机名和路径分组,能恢复就行。你至少要备份三类目录:系统配置、应用目录、数据库导出目录。

export RESTIC_REPOSITORY="sftp:backup@example:/srv/restic/saas-prod"
export RESTIC_PASSWORD_FILE="/root/.config/restic/pass"

restic init

mkdir -p /var/backups/app
sqlite3 /srv/app/data/app.db ".backup '/var/backups/app/app.db.sqlite'"

restic backup /etc /srv/app /var/backups/app \
  --exclude /srv/app/node_modules \
  --exclude /srv/app/.next/cache \
  --exclude /srv/app/logs

如果是 Postgres 或 MySQL,不要直接把正在写入的数据目录丢给 Restic,用 pg_dumpmysqldump、物理备份工具或应用自带导出生成一致文件,再让 Restic 备份导出结果。

保留策略不要太贪心。一个轻量 SaaS 可以先用这条:

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check

Restic 文档说明,删除快照需要 forget,真正清理不再引用的数据需要 pruneforget --prune 可以合在一起做。prune 会锁仓库,安排在业务低峰,不要和备份任务撞在同一分钟。

Uptime Kuma 放在哪里?

Uptime Kuma 不该和被监控业务放在同一台 VPS。官方安装页在 2026 年 4 月更新后给出的 Docker 示例使用 louislam/uptime-kuma:2,并把数据挂到 /app/data。那页还提醒 SQLite 需要 POSIX 文件锁,/app/data 要映射到本地目录或本地卷,别放到不可靠的网络文件系统上。

docker run -d \
  --restart=unless-stopped \
  -p 3001:3001 \
  -v uptime-kuma:/app/data \
  --name uptime-kuma \
  louislam/uptime-kuma:2

最低监控项我会这样建:

监控项类型间隔告警条件
首页或健康检查HTTP(s)60 秒非 2xx/3xx 或超时
API 端口TCP Port60 秒端口不通
证书HTTPS 证书每日剩余天数过低
关键 webhookHTTP(s)60 秒Stripe / GitHub 回调入口失败
备份心跳Push Monitor每日Restic 任务没汇报成功

最容易漏的是备份心跳。备份脚本最后一行 curl 一下 Uptime Kuma 的 push URL;如果 cron 没跑、密码文件丢了、远端仓库挂了,你会在第二天发现,而不是一个月后恢复时才发现。

云快照和自动备份怎么选?

云厂商备份是兜底,不是唯一备份。Hetzner 文档写得很清楚:Backups 和 Snapshots 都是服务器磁盘副本,可以用于 rebuild 原服务器或创建新服务器;Backups 自动每日创建,每台服务器最多 7 个槽位,满了会删最旧的;Snapshots 手动创建,保留到你自己删除。

DigitalOcean 的 Droplet backups 是自动创建的磁盘镜像,文档列出 4 小时、6 小时、12 小时、每日、每周等间隔;它也提醒备份不包含 volumes。DigitalOcean snapshots 则是按需磁盘镜像,可以创建新 Droplet,也可以把现有 Droplet 恢复到某个时间点,但恢复会替换原 Droplet 上该时间点之后的数据。

场景用什么操作习惯
每天防整机事故自动备份打开云厂商 Backups,记下保留周期
发布大版本前手动快照发布前创建,验证后保留 7-14 天
误删单个文件Resticrestic ls latest 找路径后恢复
数据库逻辑错误数据库导出 + Restic找最近一次一致导出,不直接回滚整机
迁移到新区域快照创建新机器DNS 切换前先跑健康检查

快照的坑在 volumes。Hetzner 明确说 Backups 和 Snapshots 不包含挂载到 server 的 Volumes;DigitalOcean 也说明 Droplet automated backups 不包含 volumes,要单独给 volume 做 snapshot。你的上传文件、Postgres 数据、MinIO 数据如果放在独立 volume 上,必须单列一条备份任务。

恢复演练按什么顺序做?

恢复演练不要在生产机上赌。新建一台临时 VPS,先不切 DNS,跑完之后删掉。目标不是漂亮截图,而是拿到三个数字:恢复耗时、缺失项、人工步骤。

步骤动作通过标准
1新建临时 VPS,装 Docker、Caddy 或 Nginx机器能 SSH,基础端口打开
2安装 Restic,配置仓库地址和密码文件restic snapshots 能列出生产快照
3恢复到临时目录restic restore latest --target /tmp/restore 成功
4拷贝配置和应用文件.env、compose 文件、反代配置齐全
5导入数据库导出应用能读到最近一份数据
6临时域名或 hosts 访问首页、登录、支付回调健康检查通过
7记录结果写下 RTO、缺文件、下次要自动化的命令

Restic 支持用 latest 恢复最近快照,也支持按 --host--path 过滤。别一上来原地覆盖生产目录;Restic 文档提醒,原地恢复如果中断,目标文件可能处于部分恢复状态。先恢复到 /tmp/restore,确认内容后再复制。

哪些东西不要备份?

不要把缓存、构建产物和依赖目录塞进备份仓库。node_modules.next/cache、Docker layer、临时上传缓存、日志压缩包都可能让备份变慢,还会让恢复时看不清真正重要的数据。

真正要保住的是这些:

  • /etc/nginx/etc/caddy、systemd unit、cron 文件
  • docker-compose.yml.env.example、实际环境变量的安全副本
  • SQLite 文件的一致副本,或 Postgres / MySQL dump
  • 用户上传目录、发票 PDF、授权文件、手写脚本
  • DNS、支付 webhook、OAuth callback 这类后台路径的截图或文本记录

李辰在小李出海笔记写工具栈文章时,默认读者是一个人维护产品。这个规模下,最贵的不是多买一份备份,而是半夜恢复时才发现 .env 只在旧服务器上,备份仓库密码也只存在旧服务器上。

这套方案不覆盖什么?

这不是多区域高可用方案。它不能保证数据库零丢失,不能替代应用层审计日志,也不能解决你误把坏数据同步进所有备份的问题。

它也没有覆盖 Kubernetes、对象存储版本控制、Postgres PITR、主从复制和跨云热备。等你的项目有付费团队、合规要求或明确 RPO/RTO 指标,再把这些加进来。个人 SaaS 的第一步,是把「能从昨天恢复」落实。

相关阅读

实际演练中容易忽略的坑

备份仓库密码怎么传递?

密码不要只放在 VPS 本机。放到密码管理器或团队密钥库,并保留一份离线应急记录。团队协作时用共享 vault 而不是聊天窗口发密码。

备份心跳怎么接进日常?

备份脚本最后一行 curl Uptime Kuma 的 push URL;如果 cron 没跑、密码文件丢了、远端仓库挂了,第二天就能发现,而不是下个月恢复时才察觉。

SQLite、Postgres、MySQL 的备份先后顺序

SQLite 小站先做 .backup 再让 Restic 收走;Postgres 用 pg_dump,MySQL 用 mysqldump。核心原则都一样:先生成一致副本,再让 Restic 备份导出结果,绝不直接备份运行中的数据文件。