Monitoring
Recipes
Monitor a database that other services need, and home DNS through Pi-hole.
Hosts named in from need an agent.
A database other services depend on
Check the database port from its host, and declare which services need it:
[[service]]
name = "postgres"
hosts = ["db-1"]
[[service]]
name = "api"
hosts = ["vps-1"]
depends_on = ["postgres"]
[[check]]
name = "Postgres port"
service = "postgres"
tcp = "127.0.0.1:5432"
from = "db-1"
[[check]]
name = "API health"
service = "api"
url = "https://api.acme.com/health"
expect = [{ json = "$.db", equals = "ok" }]When Postgres is down, the API’s alert joins the Postgres incident, and api appears
under Also affected instead of notifying separately. If the API check fails first,
the incident moves to Postgres when its check fails too.
The port check passes while Postgres accepts connections. The JSON assertion also
catches failed queries if the API’s health endpoint reports "db": "ok"
(Assertions).
If both services run on one host and two or more signals measured on that host fail, the
host becomes the incident’s root. See grouping
and depends_on.
Home DNS through Pi-hole
Put the Pi-hole host in a dns service, look up a public name from it, and check its
port by address:
[[service]]
name = "dns"
hosts = ["pihole"]
[[service]]
name = "jellyfin"
hosts = ["nas"]
depends_on = ["dns"]
[[check]]
name = "Pi-hole lookup"
service = "dns"
dns = "example.com"
every = "1m"
from = "pihole"
[[check]]
name = "Pi-hole port"
service = "dns"
tcp = "192.168.1.2:53"
[[check]]
name = "Jellyfin"
service = "jellyfin"
url = "http://jellyfin.lan:8096/health"
from = "nas"- DNS checks run every 5 min by default;
every = "1m"finds an outage sooner. - The port check uses an address, so it does not need the DNS it checks. It runs from the
server, which must be in the home network; otherwise set its
fromto an agent host that is. - With
depends_on = ["dns"], home services’ alerts join thednsincident when Pi-hole stops. Name-resolution errors show as thetls_or_dnslikely cause. - If the Pi-hole host goes offline, its agent falls silent and the host becomes the incident’s root.
Resolve through Pi-hole alone
A DNS check asks the nameserver lines of /etc/resolv.conf on the host that runs it,
in order; the next one answers when one fails or does not respond.
- On the Pi-hole host,
/etc/resolv.confcan list Pi-hole alone, asnameserver 127.0.0.1. - With systemd-resolved,
/etc/resolv.confusually lists only its stub,127.0.0.53, which forwards to resolved’s own servers (resolvectl dns); those must be Pi-hole alone. The stub caches answers, so the lookup can pass for a while after Pi-hole stops. - In Docker, the agent reads the container’s
/etc/resolv.conf, which withnetwork_mode: hostDocker copies from the host’s resolver settings; with systemd-resolved it can list resolved’s servers instead of the stub. The image has no shell, so print the file withdocker cp <container>:/etc/resolv.conf - | tar -xO.
Another home host that resolves through Pi-hole alone can run the lookup. Its failing
checks count as signals on that host, so with two or more, that host becomes the
incident’s root instead of dns.