[GH-ISSUE #254] New Feature: deadmanssnitch #200

Closed
opened 2026-05-07 00:21:22 +02:00 by BreizhHardware · 17 comments

Originally created by @eikaramba on GitHub (May 15, 2022).
Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/254

If stumpled across deadmanssnitch.com today. This is very similar to ntfy, just that it does the opposite :) The Website explains it better, but i think it is quite easy to add to ntfy as a feature right? Add a timer field to the channel and check every minute or so for expired channels and notify then. of course this would disable the notification upon receiving a new message.

FYI: I saw this here as an example https://litestream.io/alternatives/cron/#configuring-cron

Originally created by @eikaramba on GitHub (May 15, 2022). Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/254 If stumpled across deadmanssnitch.com today. This is very similar to ntfy, just that it does the opposite :) The Website explains it better, but i think it is quite easy to add to ntfy as a feature right? Add a timer field to the channel and check every minute or so for expired channels and notify then. of course this would disable the notification upon receiving a new message. FYI: I saw this here as an example https://litestream.io/alternatives/cron/#configuring-cron
BreizhHardware 2026-05-07 00:21:22 +02:00
Author
Owner

@binwiederhier commented on GitHub (May 15, 2022):

I love the feature, and I think it'd be a fantastic thing to add to ntfy. Though form an architecture and API perspective, it's quite tricky: in ntfy, a topic is ephemeral, so adding settings to it is not possible right now. I think think could be implemented on top of notifications though, if we made them updatable (#17, #187, ...). Then we could use the "Scheduled delivery" feature that we already have to schedule a message in, say 5 minutes, and then make sure we update it every 4 minutes or so. And if it's not updated, it fires and is sent out.

I think eventually I want to implement the updatability feature, but it has quite the large implications and nobody had any use for it last time. This would be the first actually useful feature.

<!-- gh-comment-id:1126942623 --> @binwiederhier commented on GitHub (May 15, 2022): I love the feature, and I think it'd be a fantastic thing to add to ntfy. Though form an architecture and API perspective, it's quite tricky: in ntfy, a topic is ephemeral, so adding settings to it is not possible right now. I think think could be implemented on top of notifications though, if we made them updatable (#17, #187, ...). Then we could use the "Scheduled delivery" feature that we already have to schedule a message in, say 5 minutes, and then make sure we update it every 4 minutes or so. And if it's not updated, it fires and is sent out. I think eventually I want to implement the updatability feature, but it has quite the large implications and nobody had any use for it last time. This would be the first actually useful feature.
Author
Owner

@binwiederhier commented on GitHub (May 15, 2022):

@eikaramba Just letting you know that this ticket has sparked a lot of interest on the Discord/Matrix. Thanks for reporting it.

<!-- gh-comment-id:1126978968 --> @binwiederhier commented on GitHub (May 15, 2022): @eikaramba Just letting you know that this ticket has sparked a lot of interest on the Discord/Matrix. Thanks for reporting it.
Author
Owner

@eikaramba commented on GitHub (May 15, 2022):

nice! Appreciate your fast response and also the overall excitment over that feature, which i share. already using ntfy on my server on notific.at (funny that it also sounds quite similar) and could use the dead man switch for the exact reason the article i mentioned described. to make sure a backup has run through. :)

too bad the architecture is not making it super easy. i think i will take a look myself the days to get familiar with the current code. i don't expect to be able to make a PR, but want to understand it more for sure.

<!-- gh-comment-id:1126997921 --> @eikaramba commented on GitHub (May 15, 2022): nice! Appreciate your fast response and also the overall excitment over that feature, which i share. already using ntfy on my server on [notific.at](https://notific.at) (funny that it also sounds quite similar) and could use the dead man switch for the exact reason the article i mentioned described. to make sure a backup has run through. :) too bad the architecture is not making it super easy. i think i will take a look myself the days to get familiar with the current code. i don't expect to be able to make a PR, but want to understand it more for sure.
Author
Owner

@binwiederhier commented on GitHub (May 16, 2022):

My idea for this would be:

POST /mytopic/mycanary HTTP/1.1
Tags: mycanary
In: 10 minutes

Your server has not responded in 10 minutes

The URL would be /mytopic/$id or /mytopic/$tag and it would only work if the message has not been delivered yet. Don't think we need a new parameter. The beauty of this is that it's a repeatable request, and you can pick your "id" (= tag).
So it's a cronjob that runs every minute or so, and if the server was down for 10 it'll fire.

<!-- gh-comment-id:1127634085 --> @binwiederhier commented on GitHub (May 16, 2022): My idea for this would be: ``` POST /mytopic/mycanary HTTP/1.1 Tags: mycanary In: 10 minutes Your server has not responded in 10 minutes ``` The URL would be `/mytopic/$id` or `/mytopic/$tag` and it would only work if the message has not been delivered yet. Don't think we need a new parameter. The beauty of this is that it's a repeatable request, and you can pick your "id" (= tag). So it's a cronjob that runs every minute or so, and if the server was down for 10 it'll fire.
Author
Owner

@binwiederhier commented on GitHub (May 16, 2022):

I don't really like it: https://asciinema.org/a/495059

The /mytopic/$tag thing is super awkward, because in the POST you have to specify the Tag twice to make it work. If the requirement truly is "initial HTTP request must be identical as all others" (so it can be put in a cronjob), then we have to either

  1. let people pick their own ID
  2. keep this awkward tag thing
  3. add a new endpoint for this.

For (1), I am not sure what the security implications are, and I don't know what happens when the message has been delivered. Since then I cannot update it anymore.

<!-- gh-comment-id:1128226560 --> @binwiederhier commented on GitHub (May 16, 2022): I don't really like it: https://asciinema.org/a/495059 The `/mytopic/$tag` thing is super awkward, because in the POST you have to specify the `Tag` twice to make it work. If the requirement truly is "initial HTTP request must be identical as all others" (so it can be put in a cronjob), then we have to either 1. let people pick their own ID 2. keep this awkward tag thing 3. add a new endpoint for this. For (1), I am not sure what the security implications are, and I don't know what happens when the message has been delivered. Since then I cannot update it anymore.
Author
Owner

@c33s commented on GitHub (May 16, 2022):

would love this feature. have to think about the api.

<!-- gh-comment-id:1128240635 --> @c33s commented on GitHub (May 16, 2022): would love this feature. have to think about the api.
Author
Owner

@eikaramba commented on GitHub (May 16, 2022):

Wow that was fast :)

info from https://deadmanssnitch.com/faq and https://deadmanssnitch.com/blog/snitch-check-in-alert-overview seems to indicate that that service is basically notifiying you for every period intervall (in your example every 10 seconds) until it was either paused or pinged again.

One could argue that for an MVP it is enough to be triggered once and the person needs to then delete the notification in order to be able to "reactivate" the trigger (i hope i understand the system correct, as updating it does not work anymore as you said).

Picking their own ID is fine i guess. honestly i don't understand the problem with the Tag thing. it is not required right? and if you want to use it then i would expect it to be needed for every call.

From a security standpoint is there any more attack surface than currently with the public topic ids? if not i don't see any problem here.

<!-- gh-comment-id:1128241298 --> @eikaramba commented on GitHub (May 16, 2022): Wow that was fast :) info from https://deadmanssnitch.com/faq and https://deadmanssnitch.com/blog/snitch-check-in-alert-overview seems to indicate that that service is basically notifiying you for every period intervall (in your example every 10 seconds) until it was either paused or pinged again. One could argue that for an MVP it is enough to be triggered once and the person needs to then delete the notification in order to be able to "reactivate" the trigger (i hope i understand the system correct, as updating it does not work anymore as you said). Picking their own ID is fine i guess. honestly i don't understand the problem with the Tag thing. it is not required right? and if you want to use it then i would expect it to be needed for every call. From a security standpoint is there any more attack surface than currently with the public topic ids? if not i don't see any problem here.
Author
Owner

@binwiederhier commented on GitHub (May 17, 2022):

As mentioned on Discord, I will pause this feature for now, since I hate the API and I'd rather not have the feature than have an awkward API.

<!-- gh-comment-id:1128921090 --> @binwiederhier commented on GitHub (May 17, 2022): As mentioned on Discord, I will pause this feature for now, since I hate the API and I'd rather not have the feature than have an awkward API.
Author
Owner

@MayeulC commented on GitHub (May 18, 2022):

I just saw that topic, and I find the idea interesting even if I have no use for it right now.
I read what you wrote here as well as on the Matrix room, which I just joined, and I am not sure why you would need a sub-endpoint.

Here are a couple of my thoughts on the topic:

Option 1: multiple messages

In an ideal REST world, there would be an endpoint to PUT or POST the new message, and then UPDATE its date regularly.

The disadvantage here is that it takes a round-trip, as I see it:

  1. POST an update with a delay
  2. get the notification ID or something as a return value
  3. UPDATE the delay as many times as desired

Therefore, a single invocation is not possible. It can be scripted, but it's slightly more convoluted to use, especially if one needs to check if there is a pending message before choosing to use a PUT or an UPDATE statement.

Option 2: new API/special topic

That use-case is different enough that a different topic type could be used. There could be a POST /timers/canarytopic with the message.

Option 3: The user specifies its message ID.

That is my favourite, and I don't think there are futher security considerations to be aware of, given that anybody who knows a topic might already write in it if they have the correct rights, knowing what kind of message is expected shouldn't allow one to impersonate it if they weren't already capable of posting.

PUT /canarytopic HTTP/1.1
id: mycanary
Delay: 10m
NotifyAdd: yes

Your server has not responded in 10 minutes

PUT here is supposed to be idempotent, I think it's a better fit than POST, and the server could return a 201 or 200 (maybe 204).
I also thought a new data field (NotifyAdd above) could be included to push a notification when ntfy receives a message for the first time:

[nothing, then the server stops updating]
Your server has not responded in 10 minutes
[2 days lapse]
New delayed notification for mycanary <maybe data here? Or make it configurable>
[everything is fine for a week]
Your server has not responded in 10 minutes

This would also allow the use of a DELETE statement to delete the pending notification, even if that's stretching the verb a bit, as the endpoint itself is not deleted:

DELETE /canarytopic HTTP/1.1
id: mycanary

I would also allow specifying a timestamp instead of a delay:

PUT /canarytopic HTTP/1.1
id: nextBirthday
NotifyAt:  1652867683
NotifyAdd: yes

Today is <X>'s birthday.

Fictious use-case

PUT /launchcontrol HTTP/1.1
id: rocketstatus
delay: 3s

Communication with rocket lost!

<repeat n times>

POST /launchcontrol HTTP/1.1

Starting orbit burn
PUT /launchcontrol HTTP/1.1
id: rocketstatus
delay: 5s

Communication lost during orbit burn
PUT /launchcontrol HTTP/1.1
id: payload
delay: 2s
NotifyAddMessage: Payload started to communicate

Lost communication with payload
<!-- gh-comment-id:1129837396 --> @MayeulC commented on GitHub (May 18, 2022): I just saw that topic, and I find the idea interesting even if I have no use for it right now. I read what you wrote here as well as on the Matrix room, which I just joined, and I am not sure why you would need a sub-endpoint. Here are a couple of my thoughts on the topic: ## Option 1: multiple messages In an ideal REST world, there would be an endpoint to PUT or POST the new message, and then UPDATE its date regularly. The disadvantage here is that it takes a round-trip, as I see it: 1. POST an update with a delay 2. get the notification ID or something as a return value 3. UPDATE the delay as many times as desired Therefore, a single invocation is not possible. It can be scripted, but it's slightly more convoluted to use, especially if one needs to check if there is a pending message before choosing to use a PUT or an UPDATE statement. ## Option 2: new API/special topic That use-case is different enough that a different topic type could be used. There could be a `POST /timers/canarytopic` with the message. ## Option 3: The user specifies its message ID. That is my favourite, and I don't think there are futher security considerations to be aware of, given that anybody who knows a topic might already write in it if they have the correct rights, knowing what kind of message is expected shouldn't allow one to impersonate it if they weren't already capable of posting. ```http PUT /canarytopic HTTP/1.1 id: mycanary Delay: 10m NotifyAdd: yes Your server has not responded in 10 minutes ``` PUT here is supposed to be idempotent, I think it's a better fit than POST, and the server could return a 201 or 200 (maybe 204). I also thought a new data field (`NotifyAdd` above) could be included to push a notification when ntfy receives a message for the first time: ``` [nothing, then the server stops updating] Your server has not responded in 10 minutes [2 days lapse] New delayed notification for mycanary <maybe data here? Or make it configurable> [everything is fine for a week] Your server has not responded in 10 minutes ``` This would also allow the use of a DELETE statement to delete the pending notification, even if that's stretching the verb a bit, as the endpoint itself is not deleted: ```http DELETE /canarytopic HTTP/1.1 id: mycanary ``` I would also allow specifying a timestamp instead of a delay: ```http PUT /canarytopic HTTP/1.1 id: nextBirthday NotifyAt: 1652867683 NotifyAdd: yes Today is <X>'s birthday. ``` <details><summary><h3>Fictious use-case</h3></summary> ```http PUT /launchcontrol HTTP/1.1 id: rocketstatus delay: 3s Communication with rocket lost! ``` \<repeat n times\> ```http POST /launchcontrol HTTP/1.1 Starting orbit burn ``` ```http PUT /launchcontrol HTTP/1.1 id: rocketstatus delay: 5s Communication lost during orbit burn ``` ```http PUT /launchcontrol HTTP/1.1 id: payload delay: 2s NotifyAddMessage: Payload started to communicate Lost communication with payload ``` </details>
Author
Owner

@binwiederhier commented on GitHub (Dec 12, 2022):

WIP PR here - https://github.com/binwiederhier/ntfy/issues/303

<!-- gh-comment-id:1346629759 --> @binwiederhier commented on GitHub (Dec 12, 2022): WIP PR here - https://github.com/binwiederhier/ntfy/issues/303
Author
Owner

@sparchatus commented on GitHub (Jan 4, 2023):

The way I currently achieve the same effect is using the awesome monitoring tool by louislam https://github.com/louislam/uptime-kuma where you can then add ntfy as a notification tool. Of course that's not quite the same but adding this here in case somebody is actively looking for a solution to the use case.

<!-- gh-comment-id:1371121216 --> @sparchatus commented on GitHub (Jan 4, 2023): The way I currently achieve the same effect is using the awesome monitoring tool by louislam https://github.com/louislam/uptime-kuma where you can then add ntfy as a notification tool. Of course that's not quite the same but adding this here in case somebody is actively looking for a solution to the use case.
Author
Owner

@binwiederhier commented on GitHub (Jan 4, 2023):

healthchecks.io also does that. It can also be selfhosted or used as a free service. And has ntfy integration

<!-- gh-comment-id:1371122700 --> @binwiederhier commented on GitHub (Jan 4, 2023): [healthchecks.io](https://healthchecks.io) also does that. It can also be selfhosted or used as a free service. And has ntfy integration
Author
Owner

@karmanyaahm commented on GitHub (Jan 6, 2023):

FWIW @MayeulC's option 3 is exactly what WebPush's Topic header and FCM's collapse_key do. So it has proven ground.

<!-- gh-comment-id:1373970117 --> @karmanyaahm commented on GitHub (Jan 6, 2023): FWIW @MayeulC's option 3 is exactly what WebPush's `Topic` header and FCM's `collapse_key` do. So it has proven ground.
Author
Owner

@Lykos153 commented on GitHub (Nov 8, 2023):

I would actually like to see this feature inside the receiving apps. Because only then can I be absolutely certain to be notified when any part of the alerting chain is broken. Otherwise ntfy.sh can just go down silently and I'd never know.

Also, this wouldn't need an API change. It would just be a toggle in the client to either alert on notifications (default) or alert on n seconds of silence.

<!-- gh-comment-id:1801751013 --> @Lykos153 commented on GitHub (Nov 8, 2023): I would actually like to see this feature inside the receiving apps. Because only then can I be absolutely certain to be notified when _any_ part of the alerting chain is broken. Otherwise ntfy.sh can just go down silently and I'd never know. Also, this wouldn't need an API change. It would just be a toggle in the client to either alert on notifications (default) or alert on n seconds of silence.
Author
Owner

@marxjohnson commented on GitHub (May 31, 2024):

I would really like this feature, as Lykos153 says it would make sense if it was a client-side setting, so the app could be configured to alert if a subscribed channel is silent for X minutes/hours/days. Thanks for considering it so far!

<!-- gh-comment-id:2142322494 --> @marxjohnson commented on GitHub (May 31, 2024): I would really like this feature, as Lykos153 says it would make sense if it was a client-side setting, so the app could be configured to alert if a subscribed channel is silent for X minutes/hours/days. Thanks for considering it so far!
Author
Owner

@binwiederhier commented on GitHub (Jan 18, 2026):

I think this will be implemented as part of #303 + #1142. Discussion in #1142

<!-- gh-comment-id:3764646504 --> @binwiederhier commented on GitHub (Jan 18, 2026): I think this will be implemented as part of #303 + #1142. Discussion in #1142
Author
Owner

@binwiederhier commented on GitHub (Jan 19, 2026):

This is done and documented here: https://docs.ntfy.sh/publish/#updating-scheduled-notifications

It'll be part of the server 1.26.x release

<!-- gh-comment-id:3766133666 --> @binwiederhier commented on GitHub (Jan 19, 2026): This is done and documented here: https://docs.ntfy.sh/publish/#updating-scheduled-notifications It'll be part of the server 1.26.x release
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ntfy#200
No description provided.