Uptime Kuma 运维手册
Uptime Kuma 1.23.17 日常巡检、kuma.db 与 upload 目录的在线备份、恢复演练实测、版本升级与三类高频故障的排查路径。
Uptime Kuma 运维手册
> 目标:给已上线的 Uptime Kuma 1.23.17 提供一套可落地的运维动作——巡检入口、数据备份、恢复演练、版本升级与三类高频故障的排查路径,全部命令在 Ubuntu 22.04 实机执行并回显。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04(x86_64) |
| Uptime Kuma 版本 | 1.23.17 |
| 数据目录 | /opt/data/uptime-kuma |
| 主数据库 | /opt/data/uptime-kuma/kuma.db(SQLite 3,库结构版本 10) |
| sqlite3 命令行 | 3.37.2(Ubuntu 22.04 软件源自带版本) |
| 服务端口 | 3001 |
| 验证日期 | 2026-10-17 |
数据目录初始结构(首次启动后自动生成,节选核心成员):
$ ls -la /opt/data/uptime-kuma/
drwxr-xr-x 5 root root 4096 10月 17 16:05 .
-rwxr-xr-x 1 root root 262144 10月 17 16:45 kuma.db
-rwxr-xr-x 1 root root 32768 10月 17 16:45 kuma.db-shm
-rwxr-xr-x 1 root root 1219552 10月 17 16:45 kuma.db-wal
drwxr-xr-x 2 root root 4096 10月 17 16:05 screenshots
drwxr-xr-x 2 root root 4096 10月 17 16:05 upload
各成员说明:kuma.db 是全部业务数据(用户、监控项、心跳、通知、状态页);kuma.db-wal 与 kuma.db-shm 是 SQLite WAL 模式的预写日志与共享内存,属于数据库的一部分,备份与恢复必须整体对待;upload 存放通过界面上传的图标与证书等文件;screenshots 为浏览器监控的截图缓存;另有一个为外部宿主机监控预留的证书目录,未使用该监控类型时为空,无需关注。
二、日常巡检
运维巡检的目标是三件事:服务活着、数据在增长、告警链路是通的。
1. 服务可用性。最直接的探针是状态页配置接口(无需登录):
$ curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3001/dashboard
200
若状态页 slug 为 demo,则用 /api/status-page/demo 做探针,返回 200 即服务健康;配合心跳端点 /api/status-page/heartbeat/demo 还能顺带确认心跳在持续产生。
2. 进程日志。日志输出到标准输出,按《Uptime Kuma Docker Compose 部署指南》的方式查看最近日志,重点识别三类关键字:ERROR(请求失败、通知发送失败)、Clearing Data older than(每小时清理任务正常执行的痕迹)、Listening on(启动完成)。
3. 数据增长。心跳表行数与数据库体积是磁盘容量的先行指标:
$ sqlite3 /opt/data/uptime-kuma/kuma.db "SELECT COUNT(*) FROM heartbeat; SELECT COUNT(*) FROM monitor;"
297
9
实测当日在 9 条监控、每 60 秒一次的频率下,运行约 20 分钟即产生 297 条心跳,数据库主文件 262144 字节。按此推算,100 条同频监控一年将产生 50 亿量级的心跳行,务必结合第六节的保留期策略评估。
4. 告警链路。每月至少演练一次:在任一监控项详情页点击「测试」按钮触发渠道的 testNotification 事件,或临时把一条监控指向不存在的端口观察端到端告警。只看「通知渠道已配置」不等于链路可用,凭证过期、地址变更都需要真实发送才能暴露。
三、数据备份
3.1 备份对象与方式
需要备份的内容只有两样:kuma.db(含 -wal / -shm)与 upload 目录。screenshots 可再生,证书目录未用时为空,均可不备份。
数据库在 WAL 模式下持续有写入,直接 cp kuma.db 可能拷到半写状态,正确姿势是用 SQLite 在线备份接口(服务不中断):
$ mkdir -p /opt/data/quzuo/backup/uptime-kuma
$ sqlite3 /opt/data/uptime-kuma/kuma.db ".backup '/opt/data/quzuo/backup/uptime-kuma/kuma-20261017.db'"
$ echo "backup done"
backup done
.backup 会在内部对源库做一致性快照,输出单文件、可离线归档。备份后立即校验完整性与关键行数:
$ sqlite3 /opt/data/quzuo/backup/uptime-kuma/kuma-20261017.db \
"PRAGMA integrity_check; SELECT COUNT(*) FROM monitor; SELECT COUNT(*) FROM heartbeat; SELECT username FROM user;"
ok
9
134
admin
integrity_check 返回 ok 才算备份成功;monitor / heartbeat / user 三个计数与线上规模对照,能立刻发现备份时点异常。
3.2 文件目录打包
上传目录按天打包:
$ cd /opt/data/quzuo/backup/uptime-kuma
$ tar -czf upload-20261017.tar.gz -C /opt/data/uptime-kuma upload
$ ls -la
-rw-r--r-- 1 root root 69632 10月 17 17:01 kuma-20261017.db
-rw-r--r-- 1 root root 142 10月 17 17:03 upload-20261017.tar.gz
3.3 定时备份建议
用 cron 每日凌晨执行「在线备份 + 校验 + 保留 N 份」,脚本骨架(按真实路径落盘):
#!/bin/bash
set -e
BACKUP_DIR=/opt/data/quzuo/backup/uptime-kuma
DATA_DIR=/opt/data/uptime-kuma
STAMP=$(date +%Y%m%d)
mkdir -p "$BACKUP_DIR"
sqlite3 "$DATA_DIR/kuma.db" ".backup '$BACKUP_DIR/kuma-$STAMP.db'"
RC=$(sqlite3 "$BACKUP_DIR/kuma-$STAMP.db" "PRAGMA integrity_check;")
[ "$RC" = "ok" ] || { echo "backup corrupt: $RC"; exit 1; }
tar -czf "$BACKUP_DIR/upload-$STAMP.tar.gz" -C "$DATA_DIR" upload
find "$BACKUP_DIR" -name "kuma-*.db" -mtime +14 -delete
find "$BACKUP_DIR" -name "upload-*.tar.gz" -mtime +14 -delete
备份文件应同步一份到异地(对象存储或另一台主机),本地盘损坏与误删是恢复演练之外最常见的灾难来源。
四、恢复演练
备份的价值必须用恢复验证。以下为一次完整实测:把备份恢复到一个全新数据目录并启动第二个实例(端口 3002)进行验证。
步骤 1:准备新数据目录,放入备份文件
$ mkdir -p /opt/data/quzuo/restore-kuma
$ cp /opt/data/quzuo/backup/uptime-kuma/kuma-20261017.db /opt/data/quzuo/restore-kuma/kuma.db
$ tar -xzf /opt/data/quzuo/backup/uptime-kuma/upload-20261017.tar.gz -C /opt/data/quzuo/restore-kuma
$ mkdir -p /opt/data/quzuo/restore-kuma/screenshots
空的 screenshots 与证书目录需要补齐,避免服务首启时因目录缺失产生告警日志。备份文件改回原名 kuma.db。
步骤 2:以新目录启动恢复实例
复用 1.23.17 的运行环境,按《Uptime Kuma Docker Compose 部署指南》的编排方式再起一个临时实例:把数据目录指向 restore-kuma,宿主端口换成 3002(生产实例仍占用 3001),实例名加 restore 后缀以便区分。启动后确认服务已监听新端口:
$ curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3002/api/status-page/demo
200
公开接口直接返回状态页数据,说明恢复出的库中管理员账号与业务数据已被完整识别,无需重新初始化。
步骤 3:验证业务数据
公开接口直接可见状态页数据:
$ curl -s http://127.0.0.1:3002/api/status-page/demo | python3 -c 'import json,sys; d=json.load(sys.stdin); print("title:", d["config"]["title"]); print("groups:", [(g["name"], len(g["monitorList"])) for g in d["publicGroupList"]])'
title: 演示状态页
groups: [('服务', 7)]
再核对账号、监控与通知的行数(与 3.1 节备份时点一致):
user rows: 1
monitors: [{"id":1,...},{"id":2,...},{"id":3,...},{"id":4,...},{"id":5,...},{"id":6,...},{"id":7,...},{"id":8,...},{"id":9,...}]
notifications: 2
实测结论:管理员账号、9 条监控、2 个通知渠道、状态页(标题与 7 个监控分组)全部完整恢复;心跳只保留到备份时点,属预期行为。验证通过后,将原实例端口让出、恢复实例端口改回 3001,即完成一次正式的接管。
恢复时的三个注意点:
- 备份是哪个版本产生的,就用相同大版本恢复,跨大版本恢复前先在临时实例验证自动迁移;
- -wal / -shm 不要单独拷贝旧文件覆盖新库,恢复只放 .backup 产出的单文件即可,WAL 会自动重建;
- 恢复实例先挂到备用端口验证,确认状态页与登录正常后再切换流量,避免把坏备份顶上线。
五、版本升级
Uptime Kuma 1.x 之间升级是低风险操作,首次启动新版本时会自动执行数据库迁移(database_version 递增并回放补丁脚本)。标准流程:
- 备份先行:按第三节完成一次在线备份并校验 ok,迁移不可逆,备份是唯一的回退手段;
- 更新版本:按《Uptime Kuma Docker Compose 部署指南》的编排方式拉取新版本并重建实例,固定小版本号的用户则先把编排文件中的版本号改成目标版本;
- 观察迁移日志:启动日志会出现
Starting Migrations...与逐个补丁脚本的执行记录,最后Listening on 3001即成功; - 验证:登录、抽查一条监控的心跳时间线、状态页 200、测试通知各来一次。
两条硬约束:
- 不要跨大版本直降。1.24/2.x 的库结构版本高于 1.23.17 的 10,降级会导致新表、新列无法被旧代码识别,只能通过备份恢复回退;
- 升级后页面异常先清浏览器缓存。前端产物随版本更替,旧缓存与新版接口不匹配的典型症状是界面数据空白或组件报错,强制刷新即可恢复。
六、心跳数据与磁盘占用
心跳是唯一无限增长的数据集,磁盘规划围绕它展开。
增长模型:行数 ≈ 监控数 × 86400 / 间隔秒数 × 保留天数。实测 9 条监控 60 秒间隔运行约 20 分钟产生 297 行,与理论值一致。每行心跳约 60~120 字节(含索引),100 条监控、180 天保留约 4 GB 上下,量级可控但仍需按监控扩张速度预留。
保留期策略:默认 180 天,清理任务每小时整点执行 DELETE FROM heartbeat WHERE time < DATETIME('now', '-N days') 并附 PRAGMA optimize。设置路径为界面「设置 → 通用 → 数据保留天数」,设为小于 1 的值即永久保留(磁盘敏感环境不建议)。修改即时生效,无需重启。
WAL 与回收。长时间运行后观察数据目录,会发现 kuma.db-wal 明显大于主库(实测 1.2 MB WAL 对 262 KB 主库),这是 WAL 模式的正常形态。SQLite 会在检查点时把 WAL 合并回主库,但已删数据的空间不会自动还给操作系统,需要手动整理。实测在副本库上执行:
$ sqlite3 /opt/data/quzuo/restore-kuma/kuma.db "VACUUM; PRAGMA wal_checkpoint(TRUNCATE);"
$ ls -la /opt/data/quzuo/restore-kuma/ | grep kuma
-rw-r--r-- 1 root root 270336 10月 17 16:56 kuma.db
-rw-r--r-- 1 root root 32768 10月 17 16:56 kuma.db-shm
-rw-r--r-- 1 root root 0 10月 17 16:56 kuma.db-wal
$ sqlite3 /opt/data/quzuo/restore-kuma/kuma.db "PRAGMA integrity_check;"
ok
VACUUM 重排数据页并回收空洞,wal_checkpoint(TRUNCATE) 把 WAL 截断归零。两者都要求独占写锁,请在业务低峰执行,执行期间监控写入会短暂阻塞;整理后再跑一次 integrity_check 确认 ok。批量删除大量旧心跳之后做一次 VACUUM,磁盘占用回落才明显。
七、常见故障排查
7.1 通知不触发
排查顺序从判定逻辑到渠道配置:
- 故障是否真的「成立」:重试次数上限(maxretries)默认 0 表示首拍失败即告警;若配置了 N,需要连续 N+1 次失败才翻转 DOWN。重试阶段的心跳状态是「重试中」,不触发通知,这是「界面已经红了但没收到通知」最常见的原因;
- 恢复通知的语义:只有 DOWN → UP 翻转才发恢复通知,持续 DOWN 期间不重复发送(除非把故障重发间隔 resendInterval 设为非 0 分钟);因此长时间故障只收到一条通知是设计行为;
- 监控项是否真的挂载了渠道:编辑监控项,在「通知」多选框确认渠道已勾选;新建渠道时若没有勾选 Apply on all existing monitors,只会对之后新建的监控生效;
- 渠道凭证与网络:用监控项详情页的「测试」按钮触发一次真实发送。测试成功而真实故障收不到,回到第 1、2 条;测试也失败,则检查 Webhook URL 可达性、SMTP 认证与 TLS 设置;
- 服务端日志:通知发送失败会在日志中留
Notification Sending Failed类记录,按错误文本定位(连接拒绝、鉴权失败、DNS 解析失败各有明确提示)。
7.2 心跳堆积与查询变慢
症状:界面时间线加载缓慢、状态页心跳接口响应变长。
诊断:先看心跳行数与监控规模的比值,确认是否超过保留期预期;再确认保留期策略没有被改为永久保留(keepDataPeriodDays 小于 1 时清理任务会主动跳过并记日志 Data deletion has been disabled)。
处置:
- 把高频监控降频:纯端口/Ping 类监控 60 秒足够,30 秒以内的频率留给关键业务;
- 收紧保留期:从 180 天降到 30 天,下一次整点任务即删除超额数据;
- 大批量删除后执行 VACUUM(见第六节),否则文件体积不会回落;
- 需要长期趋势的场景,用 API 密钥对接 Prometheus 指标端点导出,而不是无限保留心跳明细。
7.3 磁盘占用异常增长
按贡献度依次排查:
- kuma.db-wal:WAL 长期不合并会膨胀。执行 wal_checkpoint(TRUNCATE) 归零;若反复膨胀,检查是否有备份程序只拷贝主文件导致检查点被读取阻塞;
- heartbeat 主表:按 7.2 处置;
- upload 目录:监控项自定义图标、证书文件都落在这里,容量小但会随时间累积,可按文件名时间戳清理不再引用的文件;
- screenshots:浏览器监控的截图缓存,关闭对应监控项后可整体清空;
- VACUUM 回收:以上清理完成后统一做一次 VACUUM,把空闲页还给文件系统。
7.4 管理员密码丢失
使用官方重置脚本(交互式输入用户名与新密码):
$ npm run reset-password
重置只改 user 表的密码摘要,监控项、通知、状态页均不受影响;改完重启服务用新密码登录。若同时启用了双因素认证且验证器丢失,重置密码后进入设置页关闭 2FA 重新绑定。
7.5 状态页访问 404
/api/status-page/<slug> 返回 404 只有一种原因:状态页未发布。编辑状态页勾选 published 并保存,公开接口与页面立即可见;反向代理场景还需确认代理放行了该路径与 WebSocket 升级头,否则表现为页面能开但数据不刷新。
7.6 Push 监控长期 DOWN
故障回显固定为 No heartbeat in the time window,含义是超过两个心跳周期没有收到推送。依次检查:推送 URL 中的令牌是否与监控项详情页一致;被监控方的定时任务是否还在运行;推送请求是否被网络策略拦截(在任务宿主机手动 curl 一次推送端点,观察返回体是否为 {"ok":true})。
八、参考链接
- Uptime Kuma 官方仓库:https://github.com/louislam/uptime-kuma
- 官方 Wiki(备份与迁移条目):https://github.com/louislam/uptime-kuma/wiki
- SQLite 在线备份文档:https://www.sqlite.org/backup.html
- SQLite VACUUM 与 WAL 说明:https://www.sqlite.org/pragma.html#pragma_wal_checkpoint
- 数据保留期清理任务源码:https://github.com/louislam/uptime-kuma/blob/1.23.17/server/jobs/clear-old-data.js
- 相关文档:《Beszel 运维手册》《Alertmanager Docker Compose 部署指南》《Grafana 配置参数详解》