Qball's Weblog
Getting NTFY.sh going
Doing a lot in home-automation one key part is notifications. In my opinion notification needs to satisfy the following:
- Work everywhere.
- Appear instantaneous.
- Easy to use.
- Simple to integrate.
- Easy to dismiss or ignore and to catch up later.
In the past I tried the following options:
- E-mail.
- Mattermost.
- Matrix.
This one fails on almost all points but the first. In the end this was not practical at all. The e-mail box I used for this became a mess, sometimes it would take ages for the notification to arrive and it turned out useless.
Mattermost
This worked well for mobile notifications. However this was the only good thing, the application often did not work and ate up the battery. It also was not very convenient on the desktop and integrating this into my setup was a pain (via node-red). I did end up using this method for a long time, but it was only 1/2 a solution.
Matrix
While this solved the notification issue on both the desktop as phone. It was a heavy solution, the desktop application was based on electron and a mess. It was also a 3rd party solution I was not very happy with.
The solution?
At this point I came across ntfy.sh. This looked like a good solution:
- It can be self-hosted.
- It is instantaneous.
- It is very easy to integrate.
- Has a native mobile application.
- It support multiple users that can be given read/write access per topic.
- Configurable history.
Setting up
Since I now have a gigabit internet connection at home, I decided to host this
myself. Because it all works over an https
connection, can be put on any
port and has authentication I feel it is safe enough to open to internet. The
guides on the ntfy.sh website where enough to quickly
get me up and running. I created a setup with multiple topics:
- Home: For home-automation.
- Hosting: Status of my home hosting.
- Work: Critical notifications from work.
Depending on the topic I have different users that can push notifications and users that can read notifications. I disabled the unauthenticated user.
The last few changes I made in the default config was to enable an on-disk cache for old messages, extended how long messages are kept and disabled the web-interface.
Integration
This is where I think ntfy really shines. Beside being trivial to integrate and the fact it is already integrated with many tools.
There is an ntfy client you can call to push and read messages, there is a GET/POST interface most applications can use and bindings for many programming languages. The documentation is full of examples for each.
Phone
For the phone there is a native application that works pretty well, once configured to use websocket it no longer shows up in my battery statistics. I do notice the occasional delay of 10-30 seconds before the message pops up, but this to me is acceptable.
Kuma
For monitoring several services I use kuma, luckely kuma has native integration for ntfy. So if any of my hosting at home or at work goes down, I get a notification. I do now have the brilliant setup of kuma using ntfy to notify me of ntfy being down.
MQTT
For home-automation I do almost everything via MQTT, so using a nice rust
crate I wrote a small bridge. This bridge automatically
forwards all messages from mqtt ntfy/{topic}
topic toward ntfy. This made it
trivial to integrate with the rest of my setup. If there is interest in this
bridge let me know.
Crowdsec
While no default template for this was available it was trivial to create using the http post method:
type: http # Don't change
name: http_default # Must match the registered plugin in the profile
# One of "trace", "debug", "info", "warn", "error", "off"
log_level: info
# group_wait: # Time to wait collecting alerts before relaying a message to this plugin, eg "30s"
# group_threshold: # Amount of alerts that triggers a message before <group_wait> has expired, eg "10"
# max_retry: # Number of attempts to relay messages to plugins in case of error
# timeout: # Time to wait for response from the plugin before considering the attempt a failure, eg "10s"
#-------------------------
# plugin-specific options
# The following template receives a list of models.Alert objects
# The output goes in the http request body
format: |
{{range . -}}
{{$alert := . -}}
{{range .Decisions -}}
IP {{.Value}} {{.Type}} for next {{.Duration}} for triggering {{.Scenario}} on machine {X}
{{end -}}
{{end -}}
# The plugin will make requests to this url, eg: https://www.example.com/
url: https://{user}:{password}@{server}:{port}/{topic}
# Any of the http verbs: "POST", "GET", "PUT"...
method: POST
---
# type: http
# name: http_second_notification
# ...
Desktop
The documentation of ntfy.sh describes how to forward the messages from ntfy to
your local notification daemon via notify-send
. While this works well, but it
is easy to miss messages. For this purpose I made a small plugin for rofi that
shows a list of previous notifications. This also shows how easy it is to
integrate into other applications. The plugin can be obtained
here.
Future work
With the above setup I can cover my use-cases pretty easy. I am constantly thinking on how I can improve it further. One of the things that came to mind is doing a reverse job. Instead of piping ntfy notifications into the local notification system, forward local notifications into ntfy. On every machine I can see all notification with rofi or directly on my phone. There are also many features (e-mail, attachments) I have not explored yet.
comments powered by Disqus