Say how to close the ntfy topic and set the Kuma monitor up #16

Merged
branderson merged 1 commits from alerting-setup into main 2026-08-29 00:01:48 -07:00
Collaborator

Summary generated by LLM agent

The alerting section named the two services and left their setup to the reader, on the two settings that decide whether an alert reaches anybody.

ntfy, when the server is yours

auth-default-access: deny-all, a write-only account for the guard, read-only for the phone.

deny-all is server-wide — ntfy has no per-topic default — so it takes anonymous publishing with it. dejima-notify-watch has no token to offer, so its topic is granted back by name with ntfy access everyone dejima-notify read-write. Nothing about dejima has to change, and the devbox still ends up with no access to the alert topic at all, read or write. A test holds the grant to the advice, since recommending deny-all without it would break notifications on the box being watched.

write-only rather than read-write for the guard: it never reads the topic, and this machine can be taken too. Read access would hand whoever took it every alert ever sent about the devbox, and the gaps between them are as informative as the contents.

ntfy, when it is not

Worth stating plainly rather than assuming everyone can run the above: on a shared server, one topic cannot be closed properly. Access falls back to auth-default-access whenever no ACL entry matches, so denying the alert topic means an entry for everyone and one for every account that exists — and the next account somebody adds inherits publish rights to the channel reporting on the devbox. It works today and fails open later.

What is left is an unguessable topic name, which is not access control and is labelled as such; a second server for the one topic, which carries a few hundred bytes a day and does not have to be the busy one; or alert_command, which leaves ntfy entirely.

Either way a stolen guard token can still publish — forge an all-clear, or bury a real alert under noise. Nothing in ntfy prevents that, and it is part of why the heartbeat is a separate channel on a separate server.

Checked against docs.ntfy.sh rather than written from memory: the permission keywords and their aliases, the everyone pseudo-user, tk_ token prefix, and two things that matter more than syntax — auth-default-access is the fallback for authenticated non-admin accounts and not only for anonymous ones, which is what makes the deny-list approach fail open; and admins bypass the ACL entirely, so an admin account is a key to the alert topic that no entry can take away. Both are now in the page. The second is the one I would have shipped wrong by omission.

Uptime Kuma

Monitor type Push, where the push URL comes from, and the two settings that matter.

The heartbeat interval has to exceed dejima-guard's rather than match it. Kuma counts from the last ping, so equal intervals put every ping on the deadline — and the gap is never exactly 900s anyway, since the timer adds up to 60s of deliberate jitter and the cycle takes two SSH round trips. A monitor set to match goes down on a healthy guard, which is the false alarm that gets a monitor deleted. Retries at 0, because a missed ping is the finding rather than a symptom to confirm.

Also

The host path gets its own heading, so a reader who wants the container can see where to start skipping. Tests hold the documented intervals against the Dockerfile and the timer.

Tested: 82 passing.

**Summary generated by LLM agent** The alerting section named the two services and left their setup to the reader, on the two settings that decide whether an alert reaches anybody. ## ntfy, when the server is yours `auth-default-access: deny-all`, a `write-only` account for the guard, `read-only` for the phone. `deny-all` is server-wide — ntfy has no per-topic default — so it takes anonymous publishing with it. `dejima-notify-watch` has no token to offer, so its topic is granted back by name with `ntfy access everyone dejima-notify read-write`. **Nothing about dejima has to change**, and the devbox still ends up with no access to the alert topic at all, read or write. A test holds the grant to the advice, since recommending `deny-all` without it would break notifications on the box being watched. `write-only` rather than `read-write` for the guard: it never reads the topic, and this machine can be taken too. Read access would hand whoever took it every alert ever sent about the devbox, and the gaps between them are as informative as the contents. ## ntfy, when it is not Worth stating plainly rather than assuming everyone can run the above: on a shared server, one topic cannot be closed properly. Access falls back to `auth-default-access` whenever no ACL entry matches, so denying the alert topic means an entry for `everyone` and one for every account that exists — and the next account somebody adds inherits publish rights to the channel reporting on the devbox. It works today and fails open later. What is left is an unguessable topic name, which is not access control and is labelled as such; a second server for the one topic, which carries a few hundred bytes a day and does not have to be the busy one; or `alert_command`, which leaves ntfy entirely. Either way a stolen guard token can still publish — forge an all-clear, or bury a real alert under noise. Nothing in ntfy prevents that, and it is part of why the heartbeat is a separate channel on a separate server. Checked against docs.ntfy.sh rather than written from memory: the permission keywords and their aliases, the `everyone` pseudo-user, `tk_` token prefix, and two things that matter more than syntax — `auth-default-access` is the fallback for authenticated non-admin accounts and not only for anonymous ones, which is what makes the deny-list approach fail open; and **admins bypass the ACL entirely**, so an admin account is a key to the alert topic that no entry can take away. Both are now in the page. The second is the one I would have shipped wrong by omission. ## Uptime Kuma Monitor type `Push`, where the push URL comes from, and the two settings that matter. The heartbeat interval has to exceed dejima-guard's rather than match it. Kuma counts from the last ping, so equal intervals put every ping on the deadline — and the gap is never exactly 900s anyway, since the timer adds up to 60s of deliberate jitter and the cycle takes two SSH round trips. A monitor set to match goes down on a healthy guard, which is the false alarm that gets a monitor deleted. Retries at `0`, because a missed ping is the finding rather than a symptom to confirm. ## Also The host path gets its own heading, so a reader who wants the container can see where to start skipping. Tests hold the documented intervals against the `Dockerfile` and the timer. Tested: 82 passing.
dejima-agent force-pushed alerting-setup from 74f5656c0d to d6ddc83149 2026-08-28 23:36:47 -07:00 Compare
dejima-agent added 1 commit 2026-08-28 23:49:54 -07:00
The alerting section named the two services and left the setup to the reader,
on the two settings that decide whether an alert reaches anyone.

ntfy, on a server you control: auth-default-access deny-all, a write-only
account for the guard and a read-only one for the phone. deny-all is
server-wide - there is no per-topic default - so dejima's own topic is granted
back to everyone by name. dejima-notify-watch has no token to offer and does
not need one; nothing about dejima changes, and the devbox still ends up with
no access to the alert topic at all.

Neither account may be an admin, which is the caveat that undoes the rest of
it: an admin is not subject to the ACL and has read-write everywhere, so an
admin token is a key to the alert topic that no entry can take away.

On a server that is not yours to reconfigure, one topic cannot be closed
properly, and the page says so rather than pretending. Access falls back to the
default whenever no entry matches - for authenticated users as much as for
anonymous ones - so a deny list covers the accounts that exist and not the next
one somebody adds, and existing admins keep access regardless. What is left is
an unguessable topic name, which is not access control and is named as such, a
second server for the one topic, or alert_command.

Checked against docs.ntfy.sh rather than written from memory: the permission
keywords, the everyone pseudo-user, that auth-default-access is the fallback
for non-admin accounts too, and that admins bypass the ACL.

Uptime Kuma: the monitor type, where the push URL comes from, and the two
settings that matter. The interval has to exceed this program's own, since Kuma
counts from the last ping and the timer adds up to 60s of jitter on top - a
monitor set to match goes down on a healthy guard, which is the false alarm
that gets a monitor deleted. Retries at zero, because a missed ping is the
finding rather than a symptom to confirm.

The host path gets a heading of its own, so a reader who wants the container
can see where to start skipping.

Tests hold the documented numbers against the Dockerfile and the timer, and
hold the deny-all advice to carrying both the grant that keeps dejima working
and the admin caveat.
dejima-agent force-pushed alerting-setup from d6ddc83149 to 03e5617d24 2026-08-28 23:49:54 -07:00 Compare
branderson approved these changes 2026-08-29 00:01:36 -07:00
branderson merged commit 40ebbecda4 into main 2026-08-29 00:01:48 -07:00
Sign in to join this conversation.