Deploy NTFY
Pushover alternative. Self-hosted ntfy push notification server
Just deployed
/var/lib/postgresql/data
Just deployed
ntfy-attachments
Bucket
Just deployed

Deploy and Host ntfy on Railway
ntfy is an open source pub-sub notification server that turns a plain HTTP request into a push notification on your phone, desktop or browser. POST a line of text to a topic URL and every subscriber gets it — no SDK, no app registration, no vendor account. Sysadmins use it to hear that a backup finished; developers wire it into CI, cron and shell scripts with one curl line. Self-host ntfy and every alert stays on infrastructure you control.
Deploy ntfy on Railway and what a production instance needs arrives wired together: the ntfy server, built from gridalpha/ntfy-railway on the official binwiederhier/ntfy image; PostgreSQL for the message cache, accounts, access rules and Web Push subscriptions; and an object storage bucket for attachments. All state lives in those two, so the container is stateless — no volume to size or migrate. Access control starts closed, an admin is created from your password, and Web Push keys are generated on first boot.

Getting Started with ntfy on Railway
Set NTFY_ADMIN_PASSWORD before deploying — the one value with no useful default. When the deploy goes green, open the Railway URL. The server requires a login, so you land on /login; sign in as admin (or your NTFY_ADMIN_USER). Click Subscribe to topic, name it something unguessable such as server-alerts, confirm, then publish from anywhere:
curl -u admin:YOUR_PASSWORD \
-H "Title: Nightly backup finished" \
-H "Tags: white_check_mark" \
-d "postgres dump 412 MB uploaded in 38s" \
https://your-app.up.railway.app/server-alerts
The message appears in the open tab immediately — the web app holds a live stream, so nothing reloads. That round trip is the quickest proof the deployment works; GET /v1/health returns {"healthy":true} unauthenticated for a machine check. Then install the Android or iOS app, point it at your server and add the topic.

About Hosting ntfy
ntfy solves a small problem with no cheap commercial answer: getting a notification out of a script and onto a phone. Teams self-host once they hit a free tier's daily cap, or once compliance says alert bodies cannot leave their stack.
Key features:
- Publish with plain
curl— a body plus optionalTitle,Tags,PriorityandActionsheaders - Subscribe over WebSocket, SSE or JSON stream, or via the Android, iOS, web and CLI clients
- Templates render a Grafana, Alertmanager or GitHub webhook payload as readable text
- Attachments, scheduled delivery, action buttons, markdown, per-topic access control
- Web Push for browser notifications with the tab closed, and UnifiedPush so Android apps can skip Firebase
The ntfy service is the only public one and serves both publishing and subscribing. Postgres holds cached messages, users, tokens, ACLs and Web Push subscriptions over private networking. The bucket holds attachment bodies, which ntfy streams back through its /file/ route, so it never needs to be public.
Why Deploy ntfy on Railway
One deploy replaces a VPS, a proxy and a certificate.
- No volume to provision — Postgres and object storage hold everything
- Managed TLS, a public HTTPS URL and custom domains
- Private networking to the database
- Access control closed by default; admin from your password
- Web Push keys generated on first boot
- One-click redeploys from Git as new releases land
Common Use Cases
- Cron and backup alerts — one appended
curltells you a nightly job ran, output included - CI and deploy notifications — a GitHub Actions step pings a topic with the commit and run link
- Monitoring sink — point Grafana, Alertmanager or Uptime Kuma at a topic and template it
- UnifiedPush backend — self-host push for Android apps like FluffyChat
Dependencies for ntfy
- ntfy server — gridalpha/ntfy-railway, built on
binwiederhier/ntfy:latest(upstream: binwiederhier/ntfy) - PostgreSQL — required. Holds the message cache, user database and Web Push subscriptions instead of three SQLite files, which is what makes the container stateless
- Object storage bucket — optional. Holds attachment bodies; without it attachments are disabled.
Environment Variables Reference
| Variable | Description | Required |
|---|---|---|
NTFY_ADMIN_PASSWORD | Password for the first admin | Yes |
NTFY_ADMIN_USER | Admin username, default admin | No |
NTFY_DATABASE_URL | PostgreSQL connection string | Yes |
NTFY_BASE_URL | Public URL, used for attachments and Web Push | Yes |
NTFY_AUTH_DEFAULT_ACCESS | deny-all / read-only / read-write | No |
NTFY_ENABLE_SIGNUP | Let visitors create accounts | No |
NTFY_REQUIRE_LOGIN | Force login before the web app loads | No |
NTFY_UPSTREAM_BASE_URL | iOS push relay; blank disables iOS | No |
Any other setting in ntfy's config reference works as an NTFY_* variable — NTFY_SMTP_SENDER_ADDR for email, NTFY_TWILIO_ACCOUNT for phone calls.
Deployment Dependencies
- Source repo: https://github.com/gridalpha/ntfy-railway
- Upstream: https://github.com/binwiederhier/ntfy
- Image: https://hub.docker.com/r/binwiederhier/ntfy
- Docs: https://docs.ntfy.sh
- Runtime: one static Go binary on Alpine; PostgreSQL 14+
Hardware Requirements for Self-Hosting ntfy
ntfy is unusually light — one Go process, no runtime, no build step.
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 0.5 vCPU | 1 vCPU |
| RAM | 128 MB | 512 MB |
| Storage | none on the app; ~1 GB Postgres | 5 GB Postgres + bucket |
| Runtime | ntfy 2.27+, PostgreSQL 14+ | ntfy latest, PostgreSQL 18 |
Memory scales with open subscriptions, not message volume — each subscriber holds a connection. Attachments stream rather than buffer.
How to Self-Host ntfy
Run the official image against your own Postgres — three variables are the whole configuration:
docker run -d --name ntfy -p 80:80 \
-e NTFY_BASE_URL=https://ntfy.example.com \
-e NTFY_DATABASE_URL=postgres://ntfy:secret@db:5432/ntfy \
-e NTFY_AUTH_DEFAULT_ACCESS=deny-all \
binwiederhier/ntfy:latest serve
Note the trailing serve: the entrypoint is ntfy with no default command, so without it the container prints help and exits. Then create an admin and generate Web Push keys:
docker exec -it ntfy ntfy user add --role=admin alice
docker exec -it ntfy ntfy access alice "*" rw
docker exec -it ntfy ntfy webpush keys
Set the printed keypair as NTFY_WEB_PUSH_PUBLIC_KEY/NTFY_WEB_PUSH_PRIVATE_KEY, plus NTFY_WEB_PUSH_EMAIL_ADDRESS. On Railway all three steps happen at boot.
How Much Does ntfy Cost to Self-Host?
ntfy is free and open source under Apache-2.0 / GPL-2.0, with no paid edition — a self-hosted server does everything the hosted one does. On Railway you pay only for resources used, and ntfy idles under 100 MB of RAM, so Postgres is usually the larger line item. The hosted ntfy.sh is free for basic use and sells plans from about $6/month for higher message limits; on your own instance those limits are yours to set.
ntfy vs Pushover vs Gotify
| ntfy | Pushover | Gotify | |
|---|---|---|---|
| Open source | Yes | No | Yes |
| Self-hostable | Yes | No | Yes |
| iOS app | Yes | Yes | No |
| Attachments | Disk or S3 | Images only | No |
| Web Push / UnifiedPush | Yes | No | No |
Pushover is the polished commercial option but cannot be self-hosted. Gotify is simpler, at the cost of iOS support, attachments and Web Push.
FAQ
What is ntfy?
An open source notification server. PUT or POST a message to a topic URL and anyone subscribed — phone, browser or script — gets it instantly. Topics are created on first use.
What does this Railway template deploy? The ntfy server on a public HTTPS URL, PostgreSQL for messages, users and Web Push subscriptions, and a bucket for attachments. Access control starts closed and an admin is created from your password.
Why does the template include a PostgreSQL database? ntfy 2.27 can keep its message cache, user database and Web Push subscriptions in PostgreSQL instead of local SQLite files, so the container carries no state and there is no volume to manage.
Can I receive notifications on my iPhone from a self-hosted ntfy server?
Yes. Apple requires push via APNs, so your server relays a content-free poll request through ntfy.sh and the iOS app fetches the message from you. NTFY_UPSTREAM_BASE_URL is set for this; clear it to opt out, losing iOS delivery.
How do I let other people publish without giving them the admin account?
ntfy user add bob, then ntfy access bob "alerts-*" rw. Patterns work, so one grant covers a family of topics. For scripts, ntfy token add bob.
Is this safe to run in production?
Yes, with one caveat: attachment URLs under /file/ are not covered by topic access control — the unguessable ID is the only protection. Keep sensitive payloads in the message body, which is ACL-protected.
Template Content
ntfy-attachments
Bucket
