VPS 折腾:Uptime Kuma 监控告警——博客挂了第一时间知道
前几天博客出了档子怪事:十几篇文章从数据库里凭空消失,原因到现在还没查出来。那次之后我就在想——服务器上跑的东西,真出事的时候,我能不能第一时间知道,而不是某天心血来潮打开网站才发现?
答案是装个监控。别被"监控告警"四个字吓到,今天这个 Uptime Kuma,一个 Docker 容器就跑起来,配好之后博客挂了、证书快过期了、SSH 连不上了,Telegram 第一时间喊你。
监控到底在盯什么
先把概念掰开。监控不是"看服务器负载多高"那种运维大屏,对个人博客来说,盯住四件事就够了:
服务还活着吗:打开 https://halo.nya.je,状态码是不是 200
内容还对吗:页面能打开,但内容被掏空了呢?(别笑,刚发生过)
证书快过期了吗:Let's Encrypt 90 天一换,忘了续期网站就变"不安全"
端口还通吗:SSH 22 端口要是没响应,你连修服务器的门都进不去
为什么选 Uptime Kuma
个人博客选 Uptime Kuma:轻、快、数据全在自己手里。
部署:三分钟跑起来
在 VPS 上建个目录,放一个 compose 文件:
mkdir -p /opt/uptime-kuma && cd /opt/uptime-kuma
compose.yaml 内容:
services:
uptime-kuma:
image: louislam/uptime-kuma:1
container_name: uptime-kuma
volumes:
- ./uptime-kuma-data:/app/data
ports:
- "3001:3001"
restart: unless-stopped
启动:
docker compose up -d
[+] Running 2/2
✔ Network uptime-kuma_default Created 0.1s
✔ Container uptime-kuma Started 0.6s
确认跑起来了:
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
NAMES STATUS PORTS
uptime-kuma Up 5 seconds 0.0.0.0:3001->3001/tcp
浏览器打开 http://服务器IP:3001,第一次会让你创建一个管理员账号。用户名密码设个强的——这页面现在暴露在公网上,一会儿我们再把它藏到反代后面。
添加第一个监控:博客首页
进 Dashboard 点 Add New Monitor,按下面填:
Monitor Type:HTTP(s)
Friendly Name:博客首页
Heartbeat Interval:60 秒
Retries:3
勾选 Certificate Expiry Notification(证书到期前 21 天告警)
解读一下这两个数字:60 秒检查一次,连续 3 次失败才判 DOWN。为什么不是一次失败就告警?因为网络抖动太常见了,一次超时就喊,你的 Telegram 会被误报淹没。3 次 × 60 秒 = 最多 3 分钟发现故障,对个人博客这个延迟完全可以接受。
证书过期通知是顺手捡的大便宜:Caddy 会自动续期,但万一续期失败,提前 21 天就有人告诉你,而不是等用户说"你的网站显示不安全"。
进阶:关键词监控——页面 200 但内容没了也能发现
这是本期最想讲的一个。普通 HTTP 监控只看状态码:那晚文章消失的时候,首页照样返回 200,普通监控哑巴一样,一点动静没有。
Uptime Kuma 有个 Keyword 类型的监控,逻辑是反过来的:页面必须包含某个关键词才算正常。
Monitor Type:Keyword
URL:一篇固定文章的归档页,比如 L15《自动化备份实战》的地址
Keyword:自动化备份
其他同上:60 秒间隔,3 次重试
原理很直白:文章页要是被删了,Halo 会返回 404 页面,页面里自然没有"自动化备份"这四个字,监控判 DOWN,告警就来了。首页标题"Root 日记"一直在,也可以拿来当关键词,但盯一篇具体的文章更准——标题栏一直在,骗不了关键词。
再加几个:端口和容器
博客之外,顺手把另外两个要命的东西也盯上:
SSH 端口:Monitor Type 选 TCP Port,Host 填服务器 IP(或 127.0.0.1),Port 填 22。SSH 要是没响应,你连上去修的机会都没有,这个必须第一时间知道。
Docker 容器:Monitor Type 选 Docker Container,能直接盯 halo、caddy 这些容器在不在运行。但要先给 Uptime Kuma 挂载 Docker 的控制 socket,compose 文件加一行:
volumes:
- ./uptime-kuma-data:/app/data
- /var/run/docker.sock:/var/run/docker.sock:ro
改完重建:docker compose up -d。多说一句:挂载 docker.sock 等于给了容器操作宿主机 Docker 的权力,方便但有风险,:ro 只读能稍微收敛一点。个人单机用可以接受,心里要有数。
通知:让 Telegram 第一时间喊你
监控配好了,告警发到哪?邮件太慢,Telegram 最合适,手机实时推送。
第一步:Telegram 搜 @BotFather,发 /newbot,按提示起个名字,会拿到一串 token,长这样:
123456789:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw
第二步:在 Telegram 里给你的 Bot 发一句话(随便发个"你好"),然后浏览器打开:
https://api.telegram.org/bot<你的token>/getUpdates
返回的 JSON 里找 "chat":{"id":123456789,这个数字就是你的 Chat ID。
第三步:回 Uptime Kuma,右上角 Settings → Notifications → Setup Notification,类型选 Telegram:
Bot Token:填第一步的 token
Chat ID:填第二步的数字
点 Test 发条测试消息,手机上能收到就说明通了
第四步:回到每个监控项的编辑页,在 Notifications 里勾上刚建的这个 Telegram 通知。注意:建了通知渠道不等于监控会用它,每个监控项要单独勾选,这一步最容易漏。
实战演练:亲手搞挂一次
告警链路配完,一定要演练一次。不演练的监控等于没装——真出事那天你才发现 Bot token 填错了,就搞笑了。
docker stop halo # 把博客容器停掉,模拟一次故障
然后等 3 分钟(3 次重试 × 60 秒),手机上应该收到:
🔴 [博客首页] 🔻 Down
恢复服务:
docker start halo
再过一会儿会收到恢复通知。这一停一起,整条链路——检查、判定、推送——全验证了一遍。
数据备份:监控本身也要备份
Uptime Kuma 的所有数据(监控项配置、历史记录)都在 ./uptime-kuma-data 这一个目录里。监控要是丢了配置,等于白搭,顺手加进备份:
tar -czf /backup/uptime-kuma-$(date +%F).tar.gz -C /opt/uptime-kuma uptime-kuma-data
$ ls -lh /backup/ | grep kuma
-rw-r--r-- 1 root root 1.2M Oct 13 09:50 uptime-kuma-2026-10-13.tar.gz
L15 那篇《自动化备份实战》里写的 nightly 脚本,加一行就行。备份监控的人,自己也要被备份,这很合理。
可选:藏到 Caddy 反代后面
现在 Kuma 的 3001 端口直接暴露在公网,登录页谁都能看到。收尾工作:只让它监听本地,用 Caddy 给个子域名。
compose 的 ports 改成:
ports:
- "127.0.0.1:3001:3001"
docker compose up -d 重建。然后 Caddyfile 加一块:
status.nya.je {
reverse_proxy 127.0.0.1:3001
}
别忘了 DNS 先给 status.nya.je 加一条 A 记录指到 VPS IP,然后重启 Caddy 容器。以后访问 https://status.nya.je,自动 HTTPS,还能顺手给这个状态页设个 Kuma 自带的公开状态页——朋友问"你的博客是不是挂了",直接甩链接。
小结
监控不是为了制造焦虑,是为了把"被动发现"变成"主动知道"。服务器不会自己修好,但第一时间知道,和几天后才知道,完全是两件事。那晚消失的文章,要是当时就有个关键词监控盯着,至少能早几个小时发现——这就是今天这篇存在的意义。