binwiederhier / ntfy

Send push notifications to your phone or desktop using PUT/POST
https://ntfy.sh
Apache License 2.0
17.68k stars 687 forks source link

New Feature: deadmanssnitch #254

Open eikaramba opened 2 years ago

eikaramba commented 2 years ago

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

binwiederhier commented 2 years ago

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.

binwiederhier commented 2 years ago

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

eikaramba commented 2 years ago

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.

binwiederhier commented 2 years ago

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.

binwiederhier commented 2 years ago

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.

c33s commented 2 years ago

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

eikaramba commented 2 years ago

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.

binwiederhier commented 2 years ago

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.

MayeulC commented 2 years ago

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

```http PUT /launchcontrol HTTP/1.1 id: rocketstatus delay: 3s Communication with rocket lost! ``` \ ```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 ```
binwiederhier commented 1 year ago

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

sparchatus commented 1 year ago

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.

binwiederhier commented 1 year ago

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

karmanyaahm commented 1 year ago

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

Lykos153 commented 10 months ago

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.

marxjohnson commented 3 months ago

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!