What is this
.155 is the Windows main machine at home and my daily workhorse. I’m often away, and the machine stays off. But the monitoring console doesn’t see it that way: it treats this machine as a server that must always be online, so as soon as I shut it down, it repeatedly raises alerts.
The problem shows up in several places: notify.py re-pushes “Still unresolved: this machine offline” every 6 hours; a failed Gatus SSH probe triggers an ntfy alert; the alert bar on the dashboard always shows a red critical item; and “Machines online 3 / 4” and “Data freshness” in the overview are dragged down by this machine’s data, showing as abnormal for long periods. Three channels sound off together, and even when I’m not home I still get nagged.
How it was solved
The core fix is just one sentence: add an "optional": True marker to this machine, meaning “allowed to be offline.” The frontend and the pusher both read the same field: when an optional node is offline, it is skipped directly—no issue, no push, no re-push; probes pointing to it are always display-only and are not counted in the success rate or alerts. On the dashboard, it shows a gray dot, “Powered off,” plus an explanation; data from before shutdown can be collapsed and expanded.
The key point is to let only the “powered off” state pass: when the machine is on, disk usage, memory, CPU/NVMe temperature, Defender, updates, and failed services are still checked and alerted on as usual. The corresponding endpoint in Gatus is kept, only the alerts: block is removed, and the dashboard still shows whether it is online.
Current status
The project has been archived. Both the shutdown and startup moments have been tested in practice, and false alarms no longer occur; to enable the same mode for a laptop or backup machine in the future, only one marker needs to be added.
Features
- 给节点加 `optional` 标记,「允许关机」的机器离线不再告警,也不重复推送
- 关机、开机瞬间的探测失败窗口只作展示,不计入正常率、不闪红
- 面板灰点加中性样式,关机前的历史数据可折叠查看
- 概览的在线数、探测数、数据新鲜度按同一套规则排除可选节点
- Gatus 对应端点保留监控但移除 `alerts:`,其余端点推送照旧
- 开机后磁盘、内存、CPU/NVMe 温度、Defender、更新、失败服务照常检查告警
Stack: Python · JavaScript · Gatus · ntfy · systemd · Docker · Wake-on-LAN
Deployment Steps
This set of changes is data-driven. The changes are concentrated in four files plus one Gatus configuration. Follow the order below.
1. Add the flag (dashboard machine .164)
Edit the node table in /opt/dashboard/server.py, and add a line to the target node's dictionary:
"win": {
# 这台工作站是主用机,人不在家就关着。离线属于正常状态。
"id": "win", ..., "stale_after": 170, "optional": True,
}
At the same time, add optional to the meta whitelist of stats(), otherwise the frontend cannot get this field.
2. Silence the notifier
In evaluate() of /opt/dashboard/notify.py, when an optional node is offline, skip it directly: do not generate a problem item, do not push, and do not re-push.
3. Dashboard display
app.js: in computeAlerts, offline is not counted as a fault; probes pointing to optional machines are display-only and are not included in the normal rate; cards use neutral styling, and stale data is collapsed; overview metrics exclude them as well; powered-off cards are sorted to the end. index.html adds styles such as .dot.idle, .card.idle, .idlenote, and .prow.skip.
4. Turn off Gatus alerts (.223)
In /opt/gatus/config/config.yaml, delete the alerts: block for the Windows .155(SSH) endpoint. Keep the endpoint itself, then run docker restart gatus.
5. Verification
- Construct snapshots and run
evaluate()directly: an optional machine offline returns[]; a normal machine offline still reportscritas usual; an optional machine that is powered on but has 95% disk usage still reports as usual. - Check online whether
problemsinnotify-state.jsonis empty. The log should show “Normal, 0 current problems”. - Check the dashboard top bar, the overview four-grid, and the machine cards, then go through each once at 430px narrow screen and at 1600px with four cards per row.
6. Rollback
Back up before making changes. To roll back, copy the backed-up app.js, index.html, server.py, and notify.py back to /opt/dashboard/ and restart the dashboard. On the Gatus side, overwrite with the config.yaml backup and restart the container.
Notes
The legacy win:offline problem was silently cleared by first clearing the state file and then restarting the service, so you will not receive an inexplicable “recovered” message. In addition, there is a brief window between the restarts of the two services when the probe has already failed but the node data has not yet expired. This is exactly the period that “probes are display-only” is meant to cover.