> ## Content Index
> Fetch the complete content index at: https://blog.uptime.bet/llms.txt
> Use this file to discover other available public pages before exploring further.

# Gotify 3: Self-Hosted Push Notifications with OIDC Login and Docker Compose
- URL: https://blog.uptime.bet/gotify-self-hosted-push-notifications-docker/
- Published: 2026-11-02T08:00:00.000Z
- Updated: 2026-11-02T08:00:00.000Z
- Description: Gotify is a tiny, MIT-licensed push notification server for your homelab. What is new in Gotify 3 (OIDC, session elevation, env-only config) and how to run it with Docker Compose.
- Author: Alexandre Nebeling
- Tags: Trending, Self-Hosted, Open Source, Docker, Homelab, Notifications, Monitoring

If you read our [ntfy guide](https://blog.uptime.bet/ntfy-self-hosted-push-notifications-docker/), you already know how handy it is when your servers can simply *tell* you that a backup finished, a disk is filling up or someone logged in via SSH. ntfy is not the only option, though. **Gotify** has been a homelab favourite for years, and this summer it got its biggest update in a long time: **Gotify 3** brings OpenID Connect single sign-on, step-up authentication for sensitive actions and a cleaner, environment-only configuration. The current release is **v3.1.1** (15 September 2026).

In this post we look at what Gotify is, what changed in version 3, and how to run it with Docker Compose behind a reverse proxy.

## What is Gotify?

Gotify (the project calls its server `gotify/server`) is a small, self-hosted server for **sending and receiving messages in real time**. You push a message with a plain HTTP request, and every connected client receives it instantly over a WebSocket. It is written in Go, ships with a built-in web UI and is released under the **MIT license**.

The project's own intro is refreshingly honest: the maintainers wanted a simple, self-hostable server for real-time messages, and most existing open-source options were abandoned at the time. With more than 16,000 GitHub stars and regular releases, Gotify has clearly outgrown that origin story.

![Gotify web interface showing a list of messages from a Windows PC, a Raspberry Pi and a cloud server](https://blog.uptime.bet/content/images/2026/11/gotify-ui.webp)

The Gotify web UI with messages from different applications. This screenshot from the README shows an older UI version. [Source: gotify/server repository](https://github.com/gotify/server?ref=blog.uptime.bet) (MIT)

## How Gotify works

Gotify has a simple model with three building blocks:

- **Users** log in to the web UI or the apps. Each user only sees their own messages.
- **Applications** are senders, for example "Backup server" or "Raspberry Pi". Each application has its own token and can only *push* messages.
- **Clients** are receivers, such as the web UI, the Android app or the CLI. A client token can read and manage messages.

This separation is great for security: the token you put into a cron script can send notifications, but it cannot read or delete anything.

## Key features

- **REST API for sending** messages, **WebSocket for receiving** them in real time
- **Built-in web UI** to manage users, applications and clients
- **Android app** on [Google Play](https://play.google.com/store/apps/details?id=com.github.gotify&ref=blog.uptime.bet) and [F-Droid](https://f-droid.org/packages/com.github.gotify/?ref=blog.uptime.bet) (also MIT licensed)
- **CLI** ([gotify/cli](https://github.com/gotify/cli?ref=blog.uptime.bet)) for pushing messages from the shell
- **Message priorities** that control how intrusive a notification is
- **Message extras** for Markdown rendering, click URLs and images in notifications
- **Plugin system** for extending the server
- **SQLite by default**, with MySQL and PostgreSQL as alternatives
- **Multi-arch Docker images** for amd64, i386, arm64, armv7 and riscv64, so a Raspberry Pi is fine

## What's new in Gotify 3

Version 3.0.0 landed in July 2026, followed by 3.1.0 in August and the 3.1.1 bugfix release in September. The highlights:

- **OpenID Connect (OIDC) login.** You can sign in with an identity provider such as Authelia, Dex or Pocket ID. The provider must support PKCE. Since 3.1 you can also map admin rights from OIDC groups, rename the login button, auto-redirect to your provider and even disable local username/password login completely (`GOTIFY_LOCALAUTH_ENABLED=false`).
- **Session elevation.** Sensitive, hard-to-undo actions (changing your password, deleting clients or applications, managing users) now require you to re-authenticate first. In 3.1.1, creating users also requires an elevated session, which fixed a security advisory.
- **Tokens are shown only once.** Application and client tokens are no longer returned by the API or web UI after creation; you see them once, on creation or rotation. Tokens are also no longer stored in plain text.
- **Environment-only configuration.** The `config.yml` file is gone. Gotify 3 reads environment variables, optionally from an env file, and every variable supports a `_FILE` suffix for Docker secrets.
- **Automatic cleanup** of inactive clients and sessions.

On the project's main branch, the documentation already describes an MCP (Model Context Protocol) endpoint so AI agents can send you notifications. As of v3.1.1 this is **not part of a release yet**, so treat it as a preview of what's coming.

## Installing Gotify with Docker Compose

Here is a minimal, production-style setup. It uses SQLite (perfectly fine for a homelab) and keeps the initial admin password out of the Compose file.

### 1\. Create a project folder

```bash
mkdir -p /opt/gotify && cd /opt/gotify

```

### 2\. Create an env file

Create `gotify.env` and set a strong password for the first admin account. It is only used when the database is created for the first time.

```bash
# gotify.env
TZ=Europe/Berlin
GOTIFY_DEFAULTUSER_NAME=admin
GOTIFY_DEFAULTUSER_PASS=change-me-to-something-long
GOTIFY_REGISTRATION=false

```

Lock down the file so only root can read it:

```bash
chmod 600 gotify.env

```

### 3\. Create the Compose file

```yaml
# compose.yaml
services:
  gotify:
    image: gotify/server:3.1.1
    container_name: gotify
    restart: unless-stopped
    env_file: gotify.env
    ports:
      - "8080:80"
    volumes:
      - ./data:/app/data

```

The container listens on port 80 internally; here it is published on port 8080\. The `/app/data` folder holds the SQLite database, uploaded application images and plugins, so **include `./data` in your backups**.

Pinning a version tag (instead of `latest`) is a good habit. The image is also available as `ghcr.io/gotify/server` if you prefer GitHub's registry.

### 4\. Start it

```bash
docker compose up -d
docker compose logs -f gotify

```

Open `http://your-server:8080` and log in with the admin account from your env file. If you ever start Gotify without setting a password, the default is `admin` / `admin`, so change it immediately.

### Running behind Traefik

Push notifications usually travel across the internet, so you will want HTTPS. If you already run Traefik with a Let's Encrypt resolver, replace the `ports` section with labels like these (adapt the entrypoint and resolver names to your setup):

```yaml
services:
  gotify:
    image: gotify/server:3.1.1
    restart: unless-stopped
    env_file: gotify.env
    volumes:
      - ./data:/app/data
    labels:
      traefik.enable: "true"
      traefik.http.routers.gotify.rule: Host(`gotify.example.com`)
      traefik.http.routers.gotify.entrypoints: websecure
      traefik.http.routers.gotify.tls.certresolver: letsencrypt

```

Behind a proxy, two settings are worth adding to `gotify.env`:

```bash
# Only send session cookies over HTTPS
GOTIFY_SERVER_SECURECOOKIE=true
# Trust X-Forwarded-For from your proxy network (adjust to your setup)
GOTIFY_SERVER_TRUSTEDPROXIES=172.16.0.0/12

```

Note the Gotify 3 syntax: lists are comma-separated now, not YAML-style `[a, b]` arrays.

## Sending your first message

1. In the web UI, open **Apps** and create an application, for example "Backups".
2. Copy the token right away. Since Gotify 3 it is only shown once.
3. Push a message with curl:

```bash
curl "https://gotify.example.com/message" \
  -H "X-Gotify-Key: <apptoken>" \
  -F "title=Backup finished" \
  -F "message=Nightly backup completed successfully" \
  -F "priority=5"

```

Only `message` is required. If you leave out `priority`, the application's default priority is used.

A practical example is a backup script that reports failures:

```bash
#!/usr/bin/env bash
if ! /usr/local/bin/backup.sh; then
  curl -s "https://gotify.example.com/message" \
    -H "X-Gotify-Key: $GOTIFY_TOKEN" \
    -F "title=Backup FAILED on $(hostname)" \
    -F "message=Check the logs" \
    -F "priority=8" > /dev/null
fi

```

Pair that with a dead man's switch like [Healthchecks](https://blog.uptime.bet/healthchecks-self-hosted-cron-job-monitoring-docker/), which alerts you when a job doesn't run at all, and you're covered from both sides.

## Priorities on Android

The priority decides how loud a notification is. The Android app maps them like this:

| Priority | Notification on Android      |
| -------- | ---------------------------- |
| 0        | No notification              |
| 1 to 3   | Icon in the notification bar |
| 4 to 7   | Icon plus sound              |
| 8 to 10  | Icon, sound and vibration    |

The web UI shows a browser notification for every message and plays a sound from priority 4 upwards.

![Gotify Android app showing a list of notifications from several applications](https://blog.uptime.bet/content/images/2026/11/gotify-android-1.webp)

The Gotify Android app with messages, including a Markdown message with an image. [Source: gotify/android repository](https://github.com/gotify/android?ref=blog.uptime.bet) (MIT)

## Optional: single sign-on with OIDC

If you already run an identity provider, Gotify 3 can use it. A minimal configuration looks like this:

```bash
GOTIFY_OIDC_ENABLED=true
GOTIFY_OIDC_ISSUER=https://auth.example.com
GOTIFY_OIDC_CLIENTID=gotify
GOTIFY_OIDC_CLIENTSECRET=your-client-secret
GOTIFY_OIDC_REDIRECTURL=https://gotify.example.com/auth/oidc/callback

```

A few tips from the docs:

- The redirect URL must end with `/auth/oidc/callback` and match your provider's client config **exactly**.
- For OIDC login in the Android app, also register `gotify://oidc/callback` as a redirect URL.
- With `GOTIFY_OIDC_GROUPS_CLAIM`, `GOTIFY_OIDC_GROUPS_USER` and `GOTIFY_OIDC_GROUPS_ADMIN` you can control who may log in and who becomes admin based on groups in your identity provider.
- By default an OIDC login is rejected if a local user with the same name already exists. `GOTIFY_OIDC_LINK_BY_USERNAME=true` links them, but only enable that if usernames really map to the same people.

The Gotify docs include ready-made examples for several providers, and Pocket ID has its own [Gotify client example](https://pocket-id.org/docs/client-examples/gotify?ref=blog.uptime.bet).

## Upgrading from Gotify 2.x

Gotify 3 has breaking changes, so read the [migration guide](https://gotify.net/docs/migrate-to-3?ref=blog.uptime.bet) before you bump the tag. The most important points:

- **`config.yml` no longer works.** Convert it with the built-in `migrate-config` command:

```bash
docker run --rm -v "$(pwd)/config.yml:/app/config.yml" gotify/server:3.0.0 \
  migrate-config config.yml > gotify-server.env

```

- **List and map environment variables changed syntax.** Lists are comma-separated, maps are JSON objects.
- **Scripts that read tokens via the API will break**, since tokens are only shown once. Existing tokens keep working.
- **Scripts using client tokens for sensitive endpoints** may now get a `403` and need basic auth or an elevated session. Application tokens for sending messages are not affected.

As always: back up `/app/data` first.

## Limitations

- **No official iOS app.** The project offers an Android app, the web UI and a CLI. If your household is on iPhones, ntfy is the easier choice.
- **Not a full alerting system.** Gotify delivers messages; it doesn't check whether your services are up. Use it together with tools like [changedetection.io](https://blog.uptime.bet/changedetection-io-self-hosted-website-change-monitoring-docker/), Healthchecks or Uptime Kuma.
- **Breaking changes in v3.** The upgrade is well documented, but older scripts and configs need attention.

## Gotify vs. ntfy

Both are open source, self-hostable and great at what they do. The biggest practical differences:

|             | Gotify                                                       | ntfy                                   |
| ----------- | ------------------------------------------------------------ | -------------------------------------- |
| License     | MIT                                                          | Apache-2.0 / GPLv2 (dual)              |
| Model       | Users, applications (send) and clients (receive) with tokens | Topics you publish to and subscribe to |
| Mobile apps | Android                                                      | Android and iOS                        |
| Sending     | HTTP POST with an app token                                  | HTTP PUT/POST to a topic               |

In short: Gotify's strict separation of senders and receivers feels very tidy if you mainly push alerts from servers to your own Android phone. ntfy shines if you need iOS or want the simplest possible "publish to a topic" workflow.

## Conclusion

Gotify does one thing and does it well: it gets messages from your machines to your screens, instantly and without a third-party service in the middle. Version 3 makes it noticeably more secure with OIDC, session elevation and one-time tokens, while setup is still a single container with an SQLite database. If you are on Android and want a clean, self-hosted notification hub for your homelab, Gotify 3 is well worth an afternoon.

Do you use Gotify, ntfy or something else for your homelab alerts? Let us know!

## Sources

- [gotify/server on GitHub](https://github.com/gotify/server?ref=blog.uptime.bet) (README, LICENSE, releases)
- [Gotify v3.1.1 release notes](https://github.com/gotify/server/releases/tag/v3.1.1?ref=blog.uptime.bet), [v3.1.0](https://github.com/gotify/server/releases/tag/v3.1.0?ref=blog.uptime.bet), [v3.0.0](https://github.com/gotify/server/releases/tag/v3.0.0?ref=blog.uptime.bet)
- [Gotify documentation: installation](https://gotify.net/docs/install?ref=blog.uptime.bet), [configuration](https://gotify.net/docs/config?ref=blog.uptime.bet), [push messages](https://gotify.net/docs/pushmsg?ref=blog.uptime.bet), [message priority](https://gotify.net/docs/priority?ref=blog.uptime.bet)
- [Gotify documentation: OIDC](https://gotify.net/docs/oidc?ref=blog.uptime.bet) and [migrating to 3.x](https://gotify.net/docs/migrate-to-3?ref=blog.uptime.bet)
- [gotify/server env example (v3.1.1)](https://github.com/gotify/server/blob/v3.1.1/gotify-server.env.example?ref=blog.uptime.bet)
- [gotify/android on GitHub](https://github.com/gotify/android?ref=blog.uptime.bet)
- [gotify/server on Docker Hub](https://hub.docker.com/r/gotify/server?ref=blog.uptime.bet)