Even RaspberryPi Deserve to Be Heard

After self-hosting a few services and monitoring their state like the Raspberry Pi’s temperature, RAM, and disk usage I wanted a solution that could send me real-time notifications when certain thresholds were reached. I needed something reliable and privacy-focused, without relying on third-party platforms like Telegram bots that handle my data externally. That’s when I discovered ntfy. The best part? It’s completely self-hostable, and integrating it into my existing infrastructure was simple and seamless.

ntfy

What is ntfy ?

ntfy (pronounced notify) is an HTTP-based publish/subscribe notification service that lets you send messages to your phone or PC. You can trigger notifications using simple scripts via its REST API or through apps with built-in integrations. The best part? It’s fully open-source, well-documented, and completely self-hostable—meaning you stay in control of your data instead of relying on third-party services. Even better, I can easily integrate it to notify me when a new device connects to my Wi-Fi, or tie it into my existing Grafana/Prometheus containers for real-time alerting.

To get started, you’ll need a few things:

  • A domain with an A record pointing to your public IP address. Example: ntfy.yourdomain.com123.123.123.123

  • A web server or router with port forwarding enabled for ports 80 (HTTP) and 443 (HTTPS), so that external clients can reach your ntfy server.

  • A host machine to run ntfy on. (In my case, I used a Raspberry Pi, which is perfect for low-power, 24/7 self-hosted services.)

I’ll demonstrate how to run ntfy using Docker, which is the easiest and most portable option. You can also use the direct installation method by downloading the binary from the official ntfy website or GitHub releases, if you prefer a more lightweight setup.

Setting up ntfy’s Configuration

With Docker now setup we can pivot to getting ntfy up and running. Create the directories to house the docker-compose.yml, cache, user.db, and the server.yml config file.

sudo mkdir -p /opt/docker/ntfy

sudo mkdir /opt/docker/ntfy/cache

sudo mkdir /opt/docker/ntfy/config

sudo chown -R $USER:$USER /opt/docker

You don’t have to follow the exact installation path like /opt/docker/ntfy, you can choose a different path that suits your convenience.

Next create the docker-compose.yml file and edit it.

cd /opt/docker/ntfy
nano docker-compose.yml
version: "3"

services:

 server:

   restart: always

   logging:

     driver: "json-file"

     options:

       max-size: "500k"

       max-file: "1"

   image: binwiederhier/ntfy

   command: serve

   environment:

     - TZ=Asia/Kolkata

   user: "${UID}"

   volumes:

     - /opt/docker/ntfy/cache:/var/cache/ntfy

     - /opt/docker/ntfy/config:/etc/ntfy

   ports:

     - 8002:8002

In this example, I’ll be using port 8002 for HTTP, but you can use port 80 if it’s available. Since I’ve already reserved port 80 for other services, I’m opting for a different one. Also, make sure to adjust the TZ setting to match your local time zone.

cd config/ nano server.yml

default-host: "https://ntfy.yourdomain.com"

base-url: "https://ntfy.yourdomain.com"

listen-http: ":8002"

cache-file: "/var/cache/ntfy/cache.db"

tls-cert-file: "/etc/letsencrypt/live/ntfy.yourdomain.com/fullchain.pem"

tls-key-file: "/etc/letsencrypt/live/ntfy.yourdomain.com/privkey.pem"

behind-proxy: false

attachment-cache-dir: "/var/cache/ntfy/attachments"

keepalive-interval: "45s"

auth-file: "/etc/ntfy/user.db"

auth-default-access: "deny-all"

web-root: "disable"

Save and close the file. Now we need to create a user in ntfy. First start the container

come out from the config folder and hit command docker compose up -d

You can either install a web server like NGINX or Caddy as a reverse proxy with TLS certificates, or you can run the service directly without one. If you choose to use a reverse proxy, make sure to set behind-proxy: true.

ntfy_web

If you’re not using a web server to serve ntfy, you can access the web UI directly at the IP address and port of the machine hosting it. Now that ntfy is up and running, we can secure it. First, we need to disable the web app (skip this step if you plan to use the web app), as we won’t be using it. Open the server.yml file and uncomment the web-root line.

Creating a User in ntfy

Since we’ve already set the auth-file and auth-default-access, we can skip ahead to adding our first user. To do this, we’ll need to access the ntfy container environment and run a few commands. Make sure to replace ntfy-server-1 with the name of your container.

docker exec -it <container name or ID> /bin/sh

ntfy user add yourusername

Once inside the container invoke the ntfy cli and add your first user.

user

Running this command with a username will automatically prompt you to create a password for the new user. Once the user is created, we can subscribe them to our first notification topic.

ntfy access nameofuser temp_value wo

The wo specifies the access level of the user for the temp_value topic. Since this user will be used to send notifications, we need to grant them the ability to write to the topic. Therefore, we set the access level to wo = “write-only”. You can also use rw for read-write, ro for read-only, or deny to restrict access. Access permissions can be updated at any time by re-running the command with a different access level.

temp_value

User Access Tokens

At this point, the user can post messages to the topic. However, to make things even easier, we will create an access token for the user account. This token can be used in place of the username and password when sending messages. To add the access token, run the following command inside the ntfy Docker container.

ntfy token add user1

When you receive the output, copy the token to your notes as we will need it later. Type exit to leave the container interface.

token

Systemctl service for monitoring tempreture of RaspberryPi

systemd service to monitor the Raspberry Pi’s temperature and trigger a mobile notification if it exceeds a defined threshold—using a simple shell script to handle the monitoring.

Create the script file

# Create the script file
sudo touch /opt/docker/ntfy/temp_pi.sh

# Make the script executable
sudo chmod +x /opt/docker/ntfy/temp_pi.sh

sudo nano /opt/docker/ntfy/temp_pi.sh

#!/bin/bash



# User access token and URL to post notification messages

NTFYTOKEN=tk_80g8gomels9qj6h91e9ubjzr5uvsp

NTFYURL=https://ntfy.yourdomain.com/temp_value



# Get the temperature

TEMP_RAW=$(cat /sys/class/thermal/thermal_zone0/temp)

TEMP_C=$(echo "scale=1; $TEMP_RAW / 1000" | bc)



# Threshold

THRESHOLD=47.0



# Compare and send alert if temperature is above threshold

if (( $(echo "$TEMP_C > $THRESHOLD" | bc -l) )); then

 curl -H "Title: ${HOSTNAME} -- Temp Alert" \

      -u :$NTFYTOKEN \

      -H "Priority: 5" \

      -H "X-Tags: temperature,alert" \

      -d "Temperature is ${TEMP_C}°C on ${HOSTNAME}" \

      $NTFYURL

fi

Create a Systemd Service

Create the temp-alert.service file

nano /etc/systemd/system/temp-alert.service

[Unit]
Description=Temperature Alert Service

[Service]
Type=oneshot
ExecStart=/opt/docker/ntfy/temp_pi.sh

Create the temp-alert.timer

nano /etc/systemd/system/temp-alert.timer

[Unit]
Description=Run temperature alert script every 1 minute

[Timer]
OnBootSec=1min
OnUnitActiveSec=1min

[Install]
WantedBy=timers.target

The temp-alert.timer checks the temperature threshold every minute.

Enable and Start the timer

sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable --now temp-alert.timer

Check the status of both services using the following commands: systemctl status timers.target and systemctl status temp-alert.service

Configuring the Android Mobile App

First download the app from Google Play Store, here (f-droid), and after it installs launch it.

app

When you launch the app for the first time, you’ll see a blank screen with no topics. To connect it to your self-hosted NTFY instance, open the settings menu (three-dot menu > Settings), then go to Manage Users under the General section. Tap Add new user, and in the Service URL field, enter the URL of your NTFY instance. Use the Username and Password for the user you created earlier. Once all fields are filled, tap ADD USER. Your user should now appear in the list, similar to the image above.

Subscribing to a Topic

On the app home screen, tap on the green ”+” button and enter the name of the topic you created earlier during the user access step. Then tap “SUBSCRIBE.” If done correctly your new topic should show up on your app’s home screen.

After everything setup correctly you will able to receive notification on your device.

app_pub