How to Send Self-Hosting Alerts with ntfy
Get fast push alerts from backups, cron jobs, and VPS health checks with ntfy, a lightweight open-source notification service.
How to publish ntfy messages from shell commands and scripts so important self-hosting events reach your phone quickly.
Solo operators and small setups that need practical alerting before adopting a full monitoring stack.
Sending too many low-value notifications trains you to ignore the ones that matter.
Before you begin
- A phone with the ntfy app installed, or a browser tab you can keep subscribed.
- A server, VPS, or local machine that can make outbound HTTPS requests.
- Shell access to the scripts or cron jobs you want to monitor.
ntfy is useful because it gives you a very small path from “something happened on my server” to “I saw it on my phone.” For many self-hosters, that is enough to catch failed backups, full disks, or deployment mistakes early without first wiring together Prometheus, Alertmanager, and a dozen exporters.
Step 1: Understand the ntfy model
ntfy works around topics. You publish a message to a topic name, and any subscribed device receives it. A topic can be public, obscure, or protected with access controls depending on how you run it. The simplest version uses the public ntfy service. The more private version self-hosts ntfy on your own server.
For a first setup, use a hard-to-guess topic name and keep the messages free of secrets. Do not send database passwords, API tokens, or full private logs through a notification channel unless you fully control the endpoint and understand the risk.
Step 2: Choose hosted ntfy or self-hosted ntfy
Fastest option: use the public service at https://ntfy.sh. This is good for simple alerts and testing.
More control: self-host ntfy later on your own VPS behind HTTPS. That is better when you want custom retention, access control, or stronger privacy.
For this guide, we will start with the public service. Pick a topic such as:
gcats-vps-7f4d8-statusOpen the ntfy mobile app or web app and subscribe to that topic.
Step 3: Send your first test alert
From any server with curl installed, publish a message:
curl -H "Title: VPS test alert" \
-H "Priority: default" \
-d "Your ntfy alerts are working." \
https://ntfy.sh/gcats-vps-7f4d8-statusYou should see the notification appear on your subscribed device within a few seconds.
You can also set higher urgency for important failures:
curl -H "Title: Backup failed" \
-H "Priority: urgent" \
-H "Tags: warning,skull" \
-d "Nightly backup on vps-01 failed. Check logs now." \
https://ntfy.sh/gcats-vps-7f4d8-statusUseful headers include Title, Priority, and Tags. Keep the message body short and actionable.
Step 4: Add ntfy alerts to real scripts
Here is a small shell wrapper you can reuse in scripts:
export NTFY_TOPIC="https://ntfy.sh/gcats-vps-7f4d8-status"
notify () {
local title="$1"
local priority="$2"
local body="$3"
curl -fsS \
-H "Title: $title" \
-H "Priority: $priority" \
-d "$body" \
"$NTFY_TOPIC"
}Use it in a backup script:
#!/usr/bin/env bash
set -euo pipefail
export NTFY_TOPIC="https://ntfy.sh/gcats-vps-7f4d8-status"
notify () {
local title="$1"
local priority="$2"
local body="$3"
curl -fsS -H "Title: $title" -H "Priority: $priority" -d "$body" "$NTFY_TOPIC"
}
if /usr/local/bin/backup-volumes.sh; then
notify "Backup succeeded" "default" "Nightly backup finished successfully on $(hostname)."
else
notify "Backup failed" "urgent" "Nightly backup failed on $(hostname). Review the backup log."
exit 1
fiUse it in a disk-space check:
#!/usr/bin/env bash
set -euo pipefail
USED=$(df / | awk 'NR==2 {gsub("%", "", $5); print $5}')
if [ "$USED" -ge 85 ]; then
curl -fsS \
-H "Title: Disk usage warning" \
-H "Priority: high" \
-d "Root filesystem is ${USED}% full on $(hostname)." \
https://ntfy.sh/gcats-vps-7f4d8-status
fiSchedule the disk check with cron:
crontab -e*/15 * * * * /usr/local/bin/check-disk-usage.shThat gives you a practical first alerting loop without much overhead.
Expected outcomes and verification
After setup, confirm that:
- Your phone or browser receives the test message.
- Success alerts arrive after a manually triggered script run.
- Failure alerts arrive when you simulate an error path.
- Your scripts still succeed or fail correctly even if ntfy is temporarily unreachable.
A good test is to change a script temporarily so it exits with a failure, then verify that the urgent notification appears and the job still logs the failure locally.
Rollback and recovery notes
If ntfy alerts become noisy or unreliable, remove the alerting lines from the script before changing the actual workload logic. Notification failures should not become the reason your backup or deployment stops working.
If you accidentally used a topic name that feels too guessable, create a new random topic, update your scripts, and unsubscribe from the old one. If you later self-host ntfy, rotate the endpoint there too.
Troubleshooting common ntfy problems
No notification arrives.
Make sure the device is subscribed to the exact same topic and that outbound HTTPS from the server works.
The script hangs on alert send.
Add --max-time 10 to the curl command so notification delivery does not block forever.
You get too many alerts.
Reduce frequency, send only state changes, or separate warning topics from critical topics.
You are worried about privacy.
Avoid secrets in alert bodies and move to a self-hosted ntfy instance with access control.
What to do next
Once alerting is in place, the next high-value improvement is safer app delivery. Continue with How to Deploy with GitHub Actions to a VPS.
