How to monitor Home Assistant from outside your network
Updated Aug 19, 2026
Home Assistant is very good at telling you a sensor went unavailable. It is useless at telling you that Home Assistant itself went away, because the thing that would send the alert is the thing that died.
The alerts you will never receive
Every notification automation you have built shares a single point of failure with the automation engine. A notify action fires from inside Home Assistant, over your LAN, through your router, using your DNS. Knock out any layer underneath and the alert is never created at all.
None of these produce a message from the instance itself:
- The recorder database fills the disk and Home Assistant refuses to start after the next restart.
- A core update leaves the frontend serving a 500 while the container stays alive, so a naive port check still passes.
- Your ISP or router drops, which is exactly when outbound push cannot leave the house.
- The SD card under Home Assistant OS goes read only. Automations appear to run and quietly write nothing.
An external prober sits on the far side of all of that. It notices silence, which is the one signal an instance can never send about itself.
What to check, precisely
Home Assistant Container listens on port 8123. New Home Assistant Operating System installs from release 2026.8 onwards default to port 80 instead, while existing installs keep whatever they were already using, so confirm what yours actually binds rather than assuming.
The REST API root is the honest health signal. GET /api/ returns the JSON body {"message": "API running."} and requires an Authorization header carrying a long lived access token. Without one you get a 401, so a 200 proves the HTTP stack, the auth layer, and the core event loop are all alive.
| What to hit | Auth needed | What a failure means |
|---|---|---|
| /api/ | Yes, bearer token | Core is down, wedged, or mid restart |
| /api/webhook/<id> | No, the ID is the secret | Inbound automation triggers are broken |
| TCP 8123 or 80 | No | Process or port binding is gone |
Webhook endpoints need no authentication beyond knowing a valid ID, but GET and HEAD are not enabled on a webhook trigger by default, so allow them explicitly if you intend to point an HTTP check at one.
Create the token from your profile, on the Security tab, under Long Lived Access Tokens. It is shown once. Undownable stores custom request headers encrypted, so the token is not sitting in plaintext.
A JSON check beats a plain HTTP check here: assert the dot-notation path message equals "API running." and a proxy returning its own branded 200 fails instead of passing.
If your instance is exposed
Plenty of people publish Home Assistant through a reverse proxy or a Cloudflare tunnel. If that is you, check the public hostname:
curl -fsS https://ha.example.com/api/ \
-H 'Authorization: Bearer YOUR_LONG_LIVED_TOKEN'
# {"message": "API running."}
Add an SSL check on the same hostname. Certificate expiry causes more outages than crashes do, and escalating expiry warnings turn it into a reminder. Behind Cloudflare Access, add the service token headers and the check passes the policy like your scripts do.
If your instance is not exposed
Not exposing Home Assistant is the right default, and you can still be watched from outside. Have the instance phone out on a schedule; if the call stops arriving, you get paged.
*/2 * * * * curl -fsS -m 10 https://undownable.com/ping/your-monitor-id > /dev/null
That only proves the cron host is alive. Gate it on a real local probe so the heartbeat stops when Home Assistant stops:
*/2 * * * * curl -fsS -m 10 -o /dev/null \
-H "Authorization: Bearer $HA_TOKEN" http://homeassistant.local:8123/api/ \
&& curl -fsS -m 10 https://undownable.com/ping/your-monitor-id > /dev/null
The second curl only runs when the first exits zero, and a skipped ping is what the heartbeat monitor is watching for. Set the expected interval a little over twice the cron period so one dropped run is forgiven.
Home Assistant can also do this natively, with no cron host at all:
rest_command:
undownable_heartbeat:
url: "https://undownable.com/ping/your-monitor-id"
automation:
- alias: Undownable heartbeat
triggers:
- trigger: time_pattern
minutes: "/2"
actions:
- action: rest_command.undownable_heartbeat
The rest_command integration defaults to GET and heartbeats accept GET or POST. This is the most honest version, because it only fires while the automation engine is genuinely executing automations.
Alerting that works when the house is offline
The design collapses if the alert path runs back through the network that just failed. Pick channels delivered from outside your LAN:
- ntfy, including self hosted, as long as that server is not in the same house. An access token beginning with tk_ is sent as a bearer token, stored encrypted.
- Telegram, the pragmatic choice when your ntfy server shares a rack with Home Assistant.
- Email, the fallback that survives you reinstalling your phone.
Use a confirmation threshold so a restart does not wake you, and maintenance windows around your update ritual.
Does /api/ work without a token?
No, it returns 401, which is exactly what makes a 200 meaningful: it proves the HTTP stack, the auth layer, and the core event loop are all alive. If you would rather not hand a token to anything, use the gated heartbeat instead of hunting for an unauthenticated endpoint.
Is a long lived access token safe to give a monitoring service?
Treat it like any API credential. Undownable stores custom request headers encrypted rather than in plaintext, and you can revoke the token from your profile at any time without changing your password.
What check interval makes sense?
Two to five minutes is plenty for a house. The free plan checks every five minutes, which catches a dead instance long before you notice a light not turning on.
Should I monitor Home Assistant or the host?
Both. A heartbeat gated on the local /api/ probe catches application failure; a ping or TCP check catches the network or hardware dying. The pair tells you which it was.
Related reading
Monitoring that watches from the outside
Free plan with 10 monitors, plus a 14-day Pro trial. No credit card required.
Start free