
Deploy ntfy — Self-Hosted Push Notification Server
Self-host ntfy — send push notifications via simple HTTP calls
Just deployed
Deploy and Host ntfy on Railway
ntfy (pronounced "notify") is an open-source push notification service that turns any HTTP request into a push notification on your phone, desktop, or browser — no SDK, no API keys, no accounts. Send an alert with a single curl command from a script, cron job, server, or CI pipeline, and it appears instantly on every subscribed device. This template deploys your own private ntfy server with a persistent volume for message history and users — so you own your notification infrastructure, with no rate limits and no data on a third party, in minutes.
What This Template Deploys
| Service | Purpose |
|---|---|
| ntfy | The notification server, web UI, and HTTP API on port 80 |
A single, remarkably light service — a ~15MB Go binary with embedded SQLite, no external database required. A persistent volume at /var/lib/ntfy holds the message cache, user authentication, and attachments, so your history and accounts survive redeploys. Railway provides automatic HTTPS and a public domain.
About Hosting
ntfy is trivially light to run, and one security default is the thing everyone must get right — this template makes it clear.
ntfy is open by default — lock it down for a private server. This is the critical point: out of the box, anyone who knows your URL can publish and subscribe to any topic. That's fine for public use, but for a private notification server you must set NTFY_AUTH_DEFAULT_ACCESS=deny-all and NTFY_ENABLE_LOGIN=true, then create an admin user by opening a Railway shell and running ntfy user add --role=admin. After that, all publishing and subscribing requires authentication. Do this first, or your notification server is open to anyone who finds the URL.
All three data paths persist on one volume. ntfy writes three things under /var/lib/ntfy: the message cache (NTFY_CACHE_FILE), user authentication (NTFY_AUTH_FILE), and attachments (NTFY_ATTACHMENT_CACHE_DIR). This template mounts the volume there, so your message history and your user accounts survive redeploys — miss the volume and you'd lose both. No external database is needed.
NTFY_BASE_URL must be your domain, and proxy mode is set. NTFY_BASE_URL is set to your Railway domain, which the mobile and desktop apps need to subscribe correctly and to build links. NTFY_BEHIND_PROXY=true is set so ntfy reads the real client IP behind Railway's edge proxy, which matters for rate limiting and access rules.
Send a notification with one HTTP call. The whole appeal is simplicity: curl -d "Backup complete" https://your-domain/mytopic sends a push to everyone subscribed to mytopic. Add a title, priority, tags (emojis), and click actions with simple headers. Beyond plain messages, ntfy supports file attachments, delayed/scheduled delivery, priority levels, action buttons, and email publishing — all through HTTP headers, with attachments persisting on the volume.
Typical cost: ~$2–5/month on Railway — ntfy is one of the lightest services you can run, handling thousands of subscribers on minimal resources. It's dual-licensed Apache-2.0 / GPLv2 and free.
How It Compares
| ntfy (self-hosted) | Pushover | Firebase (FCM) | Twilio SMS | |
|---|---|---|---|---|
| Setup to send | One HTTP call | API + app | SDK + config | API + number |
| API keys / SDK | None needed | API key | SDK required | API + auth |
| Cost model | Flat infra | Paid | Usage (Google) | Per message |
| Self-hostable | Yes | No | No | No |
| Data ownership | Full — your infra | Vendor | Vendor | |
| Open source | Yes | No | No | No |
Pushover is popular but closed-source and paid. Firebase is powerful but ties you to Google's infrastructure and needs an SDK. Twilio SMS bills per message. ntfy's edge is radical simplicity and ownership — any HTTP request becomes a push notification, with no SDK, keys, or accounts — self-hosted at negligible cost, with your topics and message data entirely on infrastructure you own.
Deploy in Under 5 Minutes
- Click Deploy on Railway — ntfy builds with a persistent volume (~2 minutes)
- Confirm
NTFY_BASE_URLis your Railway domain and the volume is mounted at/var/lib/ntfy - To make it private, set
NTFY_AUTH_DEFAULT_ACCESS=deny-allandNTFY_ENABLE_LOGIN=true - Open a Railway shell and run
ntfy user add --role=adminto create your admin account - Send a test:
curl -d "Hello" https://your-domain/mytopic, and subscribe from the app
Install the ntfy Android or iOS app, point it at your domain, and subscribe to your topics.
Common Use Cases
- Server and cron alerts — notify yourself when a backup, cron job, or health check fails
- CI/CD notifications — push build success or failure from GitHub Actions, GitLab, or Jenkins
- Script and app events — add a one-line push to any script or app with a single HTTP call
- Self-hosted media — get notified when Sonarr/Radarr finish or a container updates
Configuration
| Variable | Required | Description |
|---|---|---|
NTFY_BASE_URL | Required | Your Railway domain — needed by the apps and for links |
NTFY_BEHIND_PROXY | Pre-set | true — reads real client IP behind Railway's proxy |
NTFY_CACHE_FILE | Pre-set | /var/lib/ntfy/cache.db — message history on the volume |
NTFY_AUTH_FILE | Pre-set | /var/lib/ntfy/auth.db — user accounts on the volume |
NTFY_AUTH_DEFAULT_ACCESS | Recommended | deny-all to make the instance private |
NTFY_ENABLE_LOGIN | Recommended | true to require authentication |
Lock it down — ntfy is public by default. Set
NTFY_AUTH_DEFAULT_ACCESS=deny-allandNTFY_ENABLE_LOGIN=true, then create an admin viantfy user add --role=adminin a Railway shell. Otherwise anyone with the URL can publish and subscribe.
One volume holds everything. Cache, auth, and attachments all live under
/var/lib/ntfy— mounted here so message history and user accounts survive redeploys. No external database needed.
Dependencies for ntfy Hosting
- Railway account — ~$2–5/month for the lightweight service
- A persistent volume at
/var/lib/ntfyfor cache, auth, and attachments (included) - Nothing else — no external database, and no SDK or API keys to send messages
- The ntfy mobile app (Android/iOS), web UI, or any HTTP client to subscribe
Deployment Dependencies
- ntfy GitHub Repository
- ntfy Documentation
- ntfy Configuration Reference
- Railway Volumes Documentation
Implementation Details
The template runs the official binwiederhier/ntfy image (a ~15MB Go binary) with the serve command on port 80, using embedded SQLite rather than an external database. A persistent volume mounted at /var/lib/ntfy holds the three data paths ntfy writes: the message cache (NTFY_CACHE_FILE), the user authentication database (NTFY_AUTH_FILE), and the attachment cache (NTFY_ATTACHMENT_CACHE_DIR) — so message history and user accounts persist across redeploys. NTFY_BASE_URL is set to the Railway domain (required for the apps to subscribe and for link generation), and NTFY_BEHIND_PROXY=true ensures ntfy reads the real client IP behind Railway's edge proxy.
By default ntfy allows anyone with a topic URL to publish and subscribe, which is intended for public use; for a private instance, NTFY_AUTH_DEFAULT_ACCESS=deny-all and NTFY_ENABLE_LOGIN=true should be set, followed by creating an admin user via ntfy user add --role=admin in a Railway shell, after which all access requires authentication. Publishing is done with plain HTTP requests, with titles, priorities, tags, action buttons, attachments, and scheduled delivery controlled through headers. ntfy is extremely lightweight, handling thousands of concurrent subscribers on minimal resources, and can scale horizontally with additional replicas if notification volume grows.
Frequently Asked Questions
Is my ntfy server private? Only if you make it so — by default, anyone with a topic URL can publish and subscribe. Set NTFY_AUTH_DEFAULT_ACCESS=deny-all and NTFY_ENABLE_LOGIN=true, then create an admin user with ntfy user add --role=admin in a Railway shell.
How do I send a notification? With a plain HTTP request — curl -d "message" https://your-domain/topic sends a push to everyone subscribed to that topic. Add titles, priorities, and tags via headers. No SDK or API key needed.
Do I need an SDK or account? No — that's the point. ntfy turns any HTTP call into a push notification, so any language or tool that can make an HTTP request can send one. Subscribe from the mobile app, web UI, or HTTP client.
How do subscribers get notifications? Install the ntfy Android or iOS app (or use the web UI), point it at your domain, and subscribe to topics. Messages arrive as push notifications instantly.
Can I send file attachments? Yes — ntfy supports attachments, which persist in the attachment cache on the volume, along with scheduled delivery, priorities, and action buttons, all set via HTTP headers.
Why Deploy ntfy on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying ntfy on Railway you get your own push notification server with the essentials handled — a persistent volume for history and users, proxy mode set, the base URL configured, and automatic HTTPS. Turn any HTTP request into a push notification, self-hosted on infrastructure you own.
Template Content
