Qball's Weblog

Getting NTFY.sh going

Tags ntfy  MQTT 

Doing a lot in home-automation one key part is notifications. In my opinion notification needs to satisfy the following:

In the past I tried the following options:


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.


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.


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:

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:

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.


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.


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.


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.


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.


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
# ...


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