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.

ntfyAlertsMonitoring basics
What you learn

How to publish ntfy messages from shell commands and scripts so important self-hosting events reach your phone quickly.

Best for

Solo operators and small setups that need practical alerting before adopting a full monitoring stack.

Risk to watch

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.

Expected outcome: By the end, you will have a private topic, a test alert, and reusable shell snippets for success and failure notifications.

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-status

Open 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-status

You 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-status

Useful 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
fi

Use 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
fi

Schedule the disk check with cron:

crontab -e
*/15 * * * * /usr/local/bin/check-disk-usage.sh

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

Warning: Alert fatigue is real. If every success, warning, and tiny fluctuation hits the same device all day, you will stop trusting the signal.

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.