← All articles
AUTOMATION Self-Hosting Gotify: Simple Push Notifications for Y... 2026-02-08 · gotify · notifications · push-notifications

Self-Hosting Gotify: Simple Push Notifications for Your Server

Automation 2026-02-08 gotify notifications push-notifications monitoring alerts

Your server sent a backup failure alert at 3 AM. Where did it go? A log file nobody reads? An email buried in spam? You need push notifications — real ones, on your phone, immediately.

Gotify is a self-hosted push notification server. It sends messages to your phone or desktop via a simple REST API. No third-party services, no accounts to create, no rate limits. Send a curl request, get a notification.

Gotify vs. ntfy

These are the two main self-hosted notification servers, and they take different approaches:

Feature Gotify ntfy
Protocol WebSocket HTTP (Server-Sent Events)
Android app Yes (Google Play + F-Droid) Yes (Google Play + F-Droid)
iOS app No Yes
UnifiedPush Yes (via plugin) Yes (built-in)
Web interface Yes (with history) Yes
Authentication Required (token-based) Optional (open by default)
Message priority Yes (1-10) Yes (1-5)
File attachments No Yes
Click actions No Yes
Markdown support Yes (with plugin) Yes
Self-hosted Yes Yes (or use ntfy.sh)
Written in Go Go
Resource usage Very low Very low

Which one should you choose?

Choose Gotify if you:

Choose ntfy if you:

This guide covers Gotify. For ntfy, see our ntfy guide.

Self-Hosting Gotify: Setup

Server requirements

Gotify is tiny:

Docker Compose setup

version: "3.8"

services:
  gotify:
    container_name: gotify
    image: gotify/server:latest
    ports:
      - "8080:80"
    volumes:
      - gotify-data:/app/data
    environment:
      GOTIFY_DEFAULTUSER_NAME: admin
      GOTIFY_DEFAULTUSER_PASS: your-secure-password-here
    restart: always

volumes:
  gotify-data:

Starting Gotify

docker compose up -d

Access the web interface at http://your-server:8080. Log in with the default credentials you set.

First-time setup

  1. Create an application: Go to AppsCreate Application. Each application represents a notification source (e.g., "Backup System", "Uptime Monitor", "Server Alerts"). You'll get a unique token for each.

  2. Install the Android app: Download from Google Play or F-Droid. Enter your server URL and login credentials.

  3. Send a test notification:

curl -X POST "http://your-server:8080/message?token=YOUR_APP_TOKEN" \
  -F "title=Test" \
  -F "message=Hello from Gotify!" \
  -F "priority=5"

Your phone should buzz within seconds.

Sending Notifications

Basic API usage

Every notification is a simple HTTP POST:

# Simple message
curl -X POST "http://your-server:8080/message?token=APP_TOKEN" \
  -F "title=Alert" \
  -F "message=Disk space low on server1"

# With priority (1-10, higher = more urgent)
curl -X POST "http://your-server:8080/message?token=APP_TOKEN" \
  -F "title=Critical" \
  -F "message=Database connection lost" \
  -F "priority=8"

# With Markdown (if plugin installed)
curl -X POST "http://your-server:8080/message?token=APP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Deploy Complete",
    "message": "**v2.1.0** deployed to production\n- 3 new features\n- 2 bug fixes",
    "priority": 5,
    "extras": {
      "client::display": {
        "contentType": "text/markdown"
      }
    }
  }'

Priority levels

Priority Meaning Android behavior
0 Minimum Silent, no notification
1-3 Low Normal notification, no sound
4-7 Normal Sound + vibration
8-10 High Sound + vibration + wakes screen

Integration Examples

Cron job monitoring

Wrap any cron job to get notified on failure:

#!/bin/bash
GOTIFY_URL="http://your-server:8080"
GOTIFY_TOKEN="YOUR_APP_TOKEN"

# Run the backup
if ! /usr/local/bin/backup.sh 2>&1; then
    curl -s -X POST "$GOTIFY_URL/message?token=$GOTIFY_TOKEN" \
      -F "title=Backup Failed" \
      -F "message=Daily backup failed at $(date)" \
      -F "priority=8"
fi

Disk space monitoring

#!/bin/bash
THRESHOLD=90
GOTIFY_URL="http://your-server:8080"
GOTIFY_TOKEN="YOUR_APP_TOKEN"

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

if [ "$USAGE" -gt "$THRESHOLD" ]; then
    curl -s -X POST "$GOTIFY_URL/message?token=$GOTIFY_TOKEN" \
      -F "title=Disk Space Warning" \
      -F "message=Root partition at ${USAGE}% usage" \
      -F "priority=7"
fi

SSH login alerts

Get notified when someone logs into your server. Add to /etc/pam.d/sshd:

session optional pam_exec.so /usr/local/bin/gotify-ssh-alert.sh

Create /usr/local/bin/gotify-ssh-alert.sh:

#!/bin/bash
if [ "$PAM_TYPE" = "open_session" ]; then
    curl -s -X POST "http://your-server:8080/message?token=APP_TOKEN" \
      -F "title=SSH Login" \
      -F "message=User $PAM_USER logged in from $PAM_RHOST" \
      -F "priority=5"
fi

Docker container monitoring

#!/bin/bash
GOTIFY_URL="http://your-server:8080"
GOTIFY_TOKEN="YOUR_APP_TOKEN"

# Check if critical containers are running
for container in postgres redis nginx; do
    if ! docker ps --format '{{.Names}}' | grep -q "^${container}$"; then
        curl -s -X POST "$GOTIFY_URL/message?token=$GOTIFY_TOKEN" \
          -F "title=Container Down" \
          -F "message=$container is not running" \
          -F "priority=9"
    fi
done

Integration with monitoring tools

Prometheus Alertmanager:

Use the Alertmanager webhook receiver:

# alertmanager.yml
receivers:
  - name: gotify
    webhook_configs:
      - url: "http://gotify:8080/message?token=APP_TOKEN"

You'll need a small webhook-to-Gotify adapter since Alertmanager sends JSON in a different format. Several community adapters exist on GitHub.

Uptime Kuma:

Uptime Kuma has built-in Gotify support:

  1. Go to SettingsNotifications
  2. Select Gotify as the notification type
  3. Enter your server URL and application token

Grafana:

Grafana supports Gotify via webhook alert channel:

  1. Go to AlertingContact Points
  2. Add a webhook contact point
  3. Use http://gotify:8080/message?token=APP_TOKEN as the URL

Message History and Management

Web interface

The Gotify web interface shows:

API for reading messages

# Get all messages
curl -H "X-Gotify-Key: CLIENT_TOKEN" "http://your-server:8080/message"

# Get messages for a specific app
curl -H "X-Gotify-Key: CLIENT_TOKEN" "http://your-server:8080/application/1/message"

# Delete all messages for an app
curl -X DELETE -H "X-Gotify-Key: CLIENT_TOKEN" "http://your-server:8080/application/1/message"

Note: Use a client token (not an app token) for reading messages. App tokens are for sending; client tokens are for receiving.

Reverse Proxy Setup

For HTTPS access (important for mobile apps over the internet):

Caddy:

gotify.yourdomain.com {
    reverse_proxy localhost:8080
}

Nginx:

server {
    server_name gotify.yourdomain.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket support (required for real-time notifications)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

WebSocket support is required — Gotify uses WebSockets to push notifications to clients in real-time.

Plugins

Gotify supports plugins for extended functionality:

Plugins are Go shared libraries placed in the data/plugins directory.

Honest Trade-offs

Gotify is great if you:

Choose ntfy instead if you:

Consider a commercial service if you:

The bottom line: Gotify does one thing well — send push notifications to your devices. The API is dead simple (one curl command), the server is tiny, and it just works. If you're on Android and want to know when things break on your server, Gotify is all you need.