Every self-hosted setup eventually needs notifications. Watchtower updated a container? You want to know. Backup failed? Alert me. Server disk at 90%? Send a push notification to my phone.

Most people use Pushover ($5 one-time), ntfy (hosted service), or Discord webhooks. But if you’re self-hosting everything else, why not self-host your notifications too?

Gotify is a simple, self-hosted push notification server with a clean web UI, Android app, and dead-simple REST API. One curl command sends a notification to your phone.

Why Gotify?

  • Simple REST API — one HTTP call sends a notification
  • Android app — real push notifications (not polling)
  • Web UI — see all notifications in the browser
  • Priority levels — from silent to urgent
  • Applications — separate notification streams per service
  • Clients — subscribe to messages programmatically
  • Plugins — extend with webhooks and custom logic
  • Tiny footprint — runs on anything, ~10MB RAM

Limitations (Be Honest)

  • No iOS app — Apple requires push notification services that Gotify can’t self-host. Use ntfy if you need iOS.
  • No end-to-end encryption — messages are stored in plaintext on your server
  • Basic UI — functional but not fancy

If you’re on Android (or just use the web UI), Gotify is perfect. iPhone users should look at ntfy instead.

Installation

Step 1: Create the directory

mkdir -p ~/gotify && cd ~/gotify

Step 2: Docker Compose

services:
  gotify:
    image: gotify/server:latest
    container_name: gotify
    ports:
      - "127.0.0.1:8070:80"
    environment:
      GOTIFY_DEFAULTUSER_NAME: admin
      GOTIFY_DEFAULTUSER_PASS: "${GOTIFY_ADMIN_PASS}"
    volumes:
      - ./data:/app/data
    restart: unless-stopped

Step 3: Create .env

echo "GOTIFY_ADMIN_PASS=$(openssl rand -base64 16)" > .env
cat .env  # Note the password!

Step 4: Start

docker compose up -d

Step 5: Access

Open http://your-server:8070. Log in with admin credentials.

Setting Up HTTPS

Essential for sending notifications over the internet:

g}otifrye.vyeorusred_opmraoixny.cloomca{lhost:8070

See our reverse proxy guide for details.

Creating Applications

Each service that sends notifications gets its own Application with a unique token:

  1. Log into the web UI
  2. Go to Apps tab
  3. Click Create Application
  4. Name it (e.g., “Watchtower”, “Backup Script”, “Uptime Kuma”)
  5. Copy the token — you’ll need this to send messages

Create separate apps for each service so you can manage and mute them independently.

Sending Notifications

Basic curl

curl "https://gotify.yourdomain.com/message?token=YOUR_APP_TOKEN" \
  -F "title=Backup Complete" \
  -F "message=Daily backup finished successfully at $(date)" \
  -F "priority=5"

That’s it. One line. Your phone buzzes.

Priority Levels

PriorityBehavior (Android)Use Case
0Silent, no notificationDebug/verbose logs
1-3Notification, no soundInfo messages
4-7Notification with soundImportant alerts
8-10Notification, sound, wake screenCritical alerts

With Markdown

curl "https://gotify.yourdomain.com/message?token=YOUR_APP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Disk Alert",
    "message": "## Warning\n\nDisk usage on **server1** is at **92%**.\n\nClean up `/var/log` or expand the volume.",
    "priority": 8,
    "extras": {
      "client::display": {
        "contentType": "text/markdown"
      }
    }
  }'

Integration Examples

Watchtower (Container Updates)

Add to your Watchtower environment:

services:
  watchtower:
    image: containrrr/watchtower
    environment:
      WATCHTOWER_NOTIFICATION_URL: "gotify://gotify.yourdomain.com/YOUR_APP_TOKEN"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

Uptime Kuma

  1. In Uptime Kuma, go to Settings → Notifications
  2. Select Gotify as the notification type
  3. Enter your Gotify URL and application token
  4. Test and save

Now you get push notifications when services go down. See our Uptime Kuma guide for the full setup.

Bash Script Wrapper

Create a reusable notification function:

#!/bin/bash
# notify.sh - source this in your scripts
GOTIFY_URL="https://gotify.yourdomain.com"
GOTIFY_TOKEN="YOUR_APP_TOKEN"

notify() {
  local title="$1"
  local message="$2"
  local priority="${3:-5}"
  
  curl -sf "$GOTIFY_URL/message?token=$GOTIFY_TOKEN" \
    -F "title=$title" \
    -F "message=$message" \
    -F "priority=$priority" \
    >/dev/null 2>&1
}

# Usage:
# source ~/notify.sh
# notify "Backup" "Completed successfully" 3
# notify "CRITICAL" "Database is down!" 10

Cron Job Monitoring

#!/bin/bash
# backup.sh with notifications
source ~/notify.sh

if restic backup /data --repo /mnt/backup 2>&1; then
  notify "Backup" "✅ Daily backup completed" 3
else
  notify "Backup FAILED" "❌ Daily backup failed! Check logs." 10
fi

Disk Space Alert

#!/bin/bash
# disk-alert.sh — run via cron every hour
source ~/notify.sh

THRESHOLD=85
USAGE=$(df / | tail -1 | awk '{print $5}' | tr -d '%')

if [ "$USAGE" -gt "$THRESHOLD" ]; then
  notify "Disk Alert" "⚠️ Root partition at ${USAGE}% (threshold: ${THRESHOLD}%)" 8
fi

Docker Container Health

#!/bin/bash
# container-check.sh
source ~/notify.sh

CONTAINERS=("nextcloud" "immich" "traefik" "postgres")

for c in "${CONTAINERS[@]}"; do
  STATUS=$(docker inspect --format='{{.State.Status}}' "$c" 2>/dev/null)
  if [ "$STATUS" != "running" ]; then
    notify "Container Down" "🔴 $c is $STATUS" 9
  fi
done

Android App Setup

  1. Install Gotify Android from Play Store (or download the APK from GitHub)
  2. Enter your Gotify URL: https://gotify.yourdomain.com
  3. Log in with your user credentials
  4. Notifications will appear in real-time

Battery tip: Gotify uses a WebSocket connection, not polling. Battery impact is minimal, but add it to your battery optimization whitelist to prevent Android from killing it.

Web Client

The web UI at https://gotify.yourdomain.com shows all messages with:

  • Filtering by application
  • Delete individual or all messages
  • Real-time updates via WebSocket

No app installation needed — works in any browser.

Multi-User Setup

Create separate users for family members or team members:

  1. Admin → Users → Create User
  2. Each user gets their own message stream
  3. Users can create their own applications
  4. Admin sees everything

Resource Usage

Gotify is incredibly lightweight:

MetricValue
RAM~10-15MB
CPUNegligible
Storage~50MB + messages
Docker image~15MB

It’ll run on literally anything — Raspberry Pi Zero, old phone, any VPS.

Gotify vs Alternatives

FeatureGotifyntfyPushoverDiscord Webhook
Self-hosted
iOS support
Android appN/A
REST API
Priority levels
Markdown⚠️ Limited
Free✅ (hosted)$5 once
E2E encryption
Resource usage~10MB~10MBN/AN/A

Pick Gotify if you’re on Android and want full self-hosting. Pick ntfy if you need iOS. Pick Pushover if you don’t care about self-hosting and want the easiest setup.

Troubleshooting

Android app not receiving notifications: Check battery optimization settings. Android aggressively kills background apps. Whitelist Gotify in battery settings and disable “adaptive battery” for it.

Messages delayed: Verify WebSocket connection isn’t being terminated by your reverse proxy. For Nginx, add:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;

Can’t log in: Reset admin password by deleting ./data/gotify.db and restarting (this deletes all data). Or use the API to change it.

Conclusion

Gotify does one thing perfectly: gets notifications from your server to your phone. The API is dead simple, the Android app works great, and it runs on ~10MB of RAM.

Add it to your homelab and never miss a failed backup, downed container, or full disk again.

Related guides: