Gotify
A 20 MB push server with real tokens, an Android app, and no iOS client
Gotify is a self-hosted server for sending and receiving push messages over WebSocket, with a web UI and an official Android app. It replaces Pushover or Pushbullet for scripts and servers that need to notify you.
Our verdict on Gotify#
Gotify is the stricter of the two obvious push servers and it is the right pick when you want tokens rather than guessable topic names. Every sender gets an application token, every receiver gets a client token, and nothing is readable without one, which is exactly the opposite of ntfy's topic-as-password model. It is smaller too: one Go binary, one SQLite file, roughly 20 MB resident. The disqualifier for most households is iOS. There is an official Android app and there has never been an official iOS one, so iPhone users get the web UI or a third-party client, and there is no hosted Gotify instance to lean on for Apple push the way ntfy.sh provides. Development is real but unhurried: v3.0.0 in July 2026 moved configuration from config.yml to environment variables, and v3.1.0 followed in August 2026 with OIDC login. The default account is admin with password admin.
Who Gotify is for#
Choose it if
- Android-only households that want push with revocable per-sender tokens instead of a shared topic name.
- A small VPS where 20 MB of RAM and one SQLite file is the entire footprint you can spare.
- Setups where each script should be independently revocable: one application token per sender, deleted individually.
- People already running Keycloak or Authentik who want OIDC login on the web UI, which arrived in v3.1.0.
Look elsewhere if
- Anyone in the house uses an iPhone. There is no official iOS app and no hosted relay to route through Apple's push network.
- You want to publish with one line and no setup. Gotify makes you create an application and copy its token first, every time.
- You need searchable history or long retention. Messages are meant to be transient and there is no search over them.
What running it actually looks like#
One container. Mount a single directory at /app/data, which holds gotify.db, uploaded application images and any plugins. The server listens on port 80 inside the container. Configuration on v3 is environment variables (GOTIFY_SERVER_PORT, GOTIFY_DATABASE_DIALECT, GOTIFY_DEFAULTUSER_PASS and the rest) or an env file; the old config.yml path is v2 behavior, so a v2 to v3 upgrade means translating your YAML before the container behaves the way you expect. First run creates user admin with password admin, and GOTIFY_DEFAULTUSER_* only applies at that first creation, so changing the variable later does nothing. Change the password in the web UI immediately, create an application, copy its token, then POST to /message?token=.... Upgrades within v3 are a tag bump and a restart.
Resource profile#
- Memory
- 20 MB idle, around 50 MB in ordinary use. Estimated from small installs, not a documented minimum. One Go binary with SQLite; memory tracks the number of connected WebSocket clients.
- CPU and acceleration
- Negligible. Every client holds an open WebSocket, so concurrency costs sockets and file descriptors rather than cycles.
- Storage growth
- `data/gotify.db` grows with retained messages, and each application can be given a message limit to cap it. Uploaded application icons live in `data/images` and compiled plugins in `data/plugins`.
- Operational load
- 1 of 5, Set and forget. One container, one SQLite file, no external services and nothing to tune. It stays a 1 as long as you know that v3 moved configuration from `config.yml` to environment variables, which is a one-time translation rather than ongoing work.
Figures describe a small single-household install and are the working assumptions behind our stack planner. Your numbers will differ with library size, user count and hardware. See methodology.
Data and backup surface#
Everything lives in one directory. data/gotify.db is the SQLite database with users, applications, clients and retained messages; data/images holds uploaded application icons; data/plugins holds compiled plugin binaries, which you can rebuild from source. That is the entire backup. A live copy of the SQLite file is usually fine at this scale, but sqlite3 data/gotify.db ".backup out.db" costs nothing and is definitely consistent. If you switched GOTIFY_DATABASE_DIALECT to postgres or mysql, dump that instead and the directory then holds only images and plugins. Nothing here is regenerable except the plugins.
Derived backup shape
SQLite backup. sqlite3 <db> ".backup out.db" while running, or stop the container and copy. A live cp of a WAL-mode SQLite file can restore corrupt.
Traps and surprises#
The default account is admin with password admin
A fresh Gotify creates user admin with password admin and the web UI does not force a change. GOTIFY_DEFAULTUSER_NAME and GOTIFY_DEFAULTUSER_PASS are only read when that first user is created, so setting them on an existing install has no effect and people assume they are safe. Set them before the first start, or log in and change the password immediately, and never publish port 80 to the internet before you have.
v3 moved configuration from YAML to environment variables
Gotify 3.0.0 replaced the config.yml mechanism with environment variables loaded from gotify-server.env, $XDG_CONFIG_HOME/gotify/gotify-server.env or /etc/gotify/server.env. Upgrading a v2 install by bumping the tag leaves your old YAML ignored and the server running on defaults, which usually means a fresh database path and an apparently empty install. Translate the config first, and note that every variable also supports a _FILE suffix for Docker secrets.
No official iOS client, and no hosted fallback
The only first-party mobile app is on Android. iPhone users are limited to the web UI kept open in a browser or to third-party clients of varying quality, and unlike ntfy there is no public Gotify instance holding an Apple push certificate that you could relay through. If any part of the household is on iOS, this is a decision you cannot configure around later.
Application tokens end up in URLs and logs
The normal way to publish is POST /message?token=AbC123, which means the credential sits in query strings, shell history, cron output and any reverse proxy access log you keep. Anyone with that token can post as that application forever. Send the token in the X-Gotify-Key header instead, keep it out of curl lines in scripts you commit, and delete and recreate the application if one leaks.
PostgreSQL without TLS needs sslmode=disable
If you switch GOTIFY_DATABASE_DIALECT to postgres, the connection string must include sslmode=disable when the database is not serving TLS, otherwise the server fails to start with a connection error that reads like a credentials problem. The env example calls this out explicitly. For a single-host install this is the difference between a five-minute switch and an evening of debugging, and it is the main reason most people stay on SQLite.
Specifications#
- Category
- Chat, mail and notifications
- Licence
- MIT (Permissive)
- Written in
- Go / React
- First release
- 2018
- Maturity
- Stable
- Datastore
- SQLite (MySQL and PostgreSQL supported)
- Default ports
80- Ships as
- docker, native binary
- arm64 builds
- Yes
- Identity
- Native OIDC. OIDC login is built in from v3, with group claims mapped to user and admin roles and an optional auto-redirect; before v3 it was local accounts only.
- Replaces
- Pushover, Pushbullet, Prowl, Slack incoming webhooks
- Project site
- gotify.net
- Source
- github.com/gotify/server
- Documentation
- gotify.net/docs
Alternatives to Gotify#
Everything else in chat, mail and notifications, closest in operational weight first.
| Tool | Ops load | Idle RAM | Licence |
|---|---|---|---|
| ntfy | 1, Set and forget | 30 MB | Apache-2.0 (dual licensed with GPL-2.0) |
| Mattermost | 3, Moderate | 500 MB | AGPL-3.0 core, Mattermost Source Available License for `server/enterprise/`, Apache-2.0 for webapp and admin tools, MIT for official binaries |
| Stalwart | 3, Moderate | 150 MB | AGPL-3.0 for the Community edition, dual licensed with the proprietary Stalwart Enterprise License for gated features |
| Synapse | 4, Heavy | 700 MB | AGPL-3.0-only (or a commercial license from Element) |
| mailcow: dockerized | 4, Heavy | 3500 MB | GPL-3.0 for mailcow's own code; bundled components keep their own licenses |
Where Gotify comes up elsewhere#
Head to head
Sources#
Facts on this page were checked against the project's own material. Where a number is our own estimate rather than a published figure, the text says so.
Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.