Uptime Kuma
Uptime monitoring and alerts for every service
| Host | ShineoriServer |
| Category | Networking & monitoring |
| Status | 🟢 running |
| Exposed? | LAN only |
| Port | 3001 |
Compose file: stacks/uptime-kuma/
🚚 Moved from ShiNAS to ShineoriServer in October 2026 to free up RAM on the NAS. From there it watches the NAS from the outside, including a ping monitor for the NAS itself, so it can report when the NAS goes down instead of going down with it. Full story: Moving services off the NAS.
Why I run it
With services spread across two machines, I needed one place that tells me what's up, what's down, and since when, instead of finding out when an app doesn't load. Uptime Kuma checks every service every minute and keeps a history, so I can spot problems early and see patterns (like everything failing at the same moment).
Architecture
flowchart LR
me([Me, on the LAN]) --> kuma[Uptime Kuma<br/>ShineoriServer]
kuma -- HTTP checks --> nas[Apps on ShiNAS]
kuma -- HTTP checks --> laptop[Apps on ShineoriServer]
kuma -- ping --> host[ShiNAS itself]
kuma --> db[(./data<br/>kuma.db SQLite)]
homarr[Homarr dashboard] -- status page --> kuma
| Piece | Job |
|---|---|
| Monitors | One HTTP check per web app, using the machine's LAN address (never localhost), plus a ping check for the NAS |
| Tags | Group related monitors, like the arr tag for the media-automation apps |
| Status page | A read-only page that Homarr reads to show live status on my dashboard |
./data |
Everything (settings, monitors, history) lives in one SQLite database in a bind-mounted folder |
Security decisions
| Decision | Why |
|---|---|
| LAN only | It isn't published through the tunnel. It shows the layout of my whole lab, which doesn't need to be on the internet. |
| Status pages are public by design | Anyone who can reach the app can view a status page without logging in. That's fine on the LAN, but it's a reason to think before ever publishing it. |
| Runs on a different machine than most of what it watches | So a NAS outage gets reported instead of taking the monitor down too |
| Image pinned to major version 2 | Updates within v2 only, no surprise major upgrade |
Setup notes
docker compose up -dwith./datamounted to/app/data- Create the admin account on first visit to
http://<LAN_IP>:3001 - Add monitors using LAN IPs, not
localhostor container names, so they keep working no matter which machine Uptime Kuma runs on - Pause monitors for on-demand services (Flowcase, Ghiro) so only real outages show red
- Create a status page for the Homarr widget
- Moving it: stop the container first, then copy the folder. Stopping merges SQLite's write-ahead log (
kuma.db-wal) intokuma.db, so the copy isn't half-saved.
Troubleshooting log
| Date | Problem | Root cause | Fix |
|---|---|---|---|
| 2026-10-11 | "Cannot connect to the socket server" | Not Uptime Kuma itself: the whole NAS was overloaded by Immich (diagnosis), and Uptime Kuma ran on that same NAS | Fixed the overload, then moved Uptime Kuma to the other machine so it can report the next one |
| 2026-10-11 | 12 monitors red at once, burying anything real | Services I'd stopped on purpose (on-demand apps, things paused during the overload) still had active monitors | Paused monitors for services that are meant to be off |
| 2026-10-11 | Couldn't log in after the move | I'd forgotten the admin password | Reset it inside the container with npm run reset-password. Monitors and history are untouched. It's in my password manager now. |
| 2026-10-11 | Homarr's Uptime Kuma widget returned 404 | Homarr reads a status page, and with no slug set it asks for one called default, which didn't exist |
Created a status page and gave Homarr its slug |
What I'd harden next
- [ ] Discord notifications on the important monitors, so an outage reaches my phone
- [ ] A push monitor as a dead-man's switch for the nightly backup (alerts if the backup doesn't run at all)
- [ ] Monitors for NAS load and swap, to catch the next overload before apps time out
What I learned
- Monitoring belongs outside what it monitors. When the NAS overloaded, the monitor running on it went down too instead of warning me.
- Alert fatigue is real. A dashboard with 12 expected reds hides the one unexpected red, so "intentionally off" needs to look different from "broken".
- Design for moving: monitors that use LAN addresses survived the move to a new machine without a single edit
- SQLite's write-ahead log: recent changes can live in a separate
-walfile, so you stop the app before copying its database