ntfy on Ubuntu 24.04 on Azure User Guide
Overview
This image runs ntfy (pronounced notify), the open source, self-hosted pub/sub notification service - publish a message to a topic with a single HTTP POST from any script, server or application, and receive it in real time in the web app, the Android and iOS apps, or any subscriber. A privacy-respecting alternative to hosted push services, deployable in your own virtual network.
The ntfy server is a single Go binary that serves both the REST API and the bundled web app. It runs behind nginx as a reverse proxy. The datastore is an embedded SQLite database for accounts and the message cache, held on a dedicated Azure data disk at /var/lib/ntfy - separate from the OS disk and re-provisioned with every VM. The server listens on 127.0.0.1:2586 and is reached through nginx on port 80 (and 443 once you add TLS).
Access control defaults to deny-all, so only authenticated users can read or publish. On the first boot of every deployed VM, a one-shot service recreates an empty authentication database and creates a single administrator account with a per-VM password. The login is written to /root/ntfy-credentials.txt with mode 0600.
What is included:
- ntfy 2.24 server (single Go binary at
/usr/local/bin/ntfy) serving the REST API and the web app - nginx reverse proxy on
:80in front of the ntfy server (bound to loopback:2586) - A dedicated Azure data disk at
/var/lib/ntfyholding the authentication database, message cache and attachments - Per-VM administrator password generated at first boot, in a root-only file
ntfy.service+nginx.serviceas systemd units, enabled and active- 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point - ntfy is lightweight. NSG inbound: allow 22/tcp from your management network and 80/tcp (and 443/tcp once you enable TLS) from the networks your users and publishers will reach ntfy on.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for ntfy by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Review the dedicated data disk on the Disks tab, then Review + create → Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name ntfy \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name ntfy --port 80 --priority 1010
Step 3 - Connect to your VM
First boot initialisation takes under a minute after the VM starts. Connect over SSH:
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the services are running
systemctl is-active ntfy.service nginx.service
curl -fsS http://127.0.0.1/v1/health
Both services report active and the health endpoint returns:
{"healthy":true}
A "healthy":true response confirms the full stack - nginx and the ntfy server - is serving.

Service status, the open health endpoint and the loopback-only ntfy listener behind nginx.
Step 5 - Retrieve your administrator login
The administrator password is generated uniquely on the first boot of your VM and written to a root-only file:
sudo cat /root/ntfy-credentials.txt
You will see a plain text file containing the ntfy URL, the administrator username (admin) and the password.

The per-VM administrator login and the deny-all access control round-trip.
Step 6 - First sign-in
Open a web browser and navigate to http://<vm-public-ip>/. ntfy presents its web app. Select Sign in and enter the username admin and the password from /root/ntfy-credentials.txt.

The ntfy web app sign-in - subscribe to topics and read notifications in the browser.
Step 7 - Publish to a topic
In ntfy, a topic is just a name - publish to it and any subscriber receives the message. Because access control is deny-all, authenticate with your administrator credentials (or an access token). The following publishes a message from the VM itself, reading the password from the credentials file:
PASS=$(sudo grep '^ntfy.admin.pass=' /root/ntfy-credentials.txt | cut -d= -f2-)
curl -fsS -u "admin:$PASS" \
-H "Title: Backup complete" \
-H "Priority: high" \
-H "Tags: white_check_mark" \
-d "Database dump written to object storage successfully" \
http://127.0.0.1/alerts
From any other machine the call is the same with your VM's address - replace the password and IP:
curl -u admin:<password> -H "Title: Hello" -d "Message body" http://<vm-public-ip>/alerts
Subscribe to the alerts topic in the web app and the message appears instantly, with its title, tags and priority.

A ntfy topic receiving messages published over the REST API, with titles, tags and priorities.
Step 8 - Settings, tokens and mobile apps
Open Settings in the web app to manage your account, notification preferences and subscriptions. Create access tokens (under your account) so scripts can publish without your password. Install the official ntfy Android or iOS app, add your server http://<vm-public-ip>/ (or your HTTPS domain), sign in, and subscribe to topics to receive push notifications on your phone.

ntfy settings - account, notification preferences and subscriptions.
Step 9 - Access control
Access defaults to deny-all. Manage users and per-topic access from the command line over SSH on the VM. The ntfy user add command prompts for a password interactively:
- List users:
sudo ntfy user list - Add a user (you will be prompted for a password):
sudo ntfy user add <username> - Grant read/write on a topic:
sudo ntfy access <username> <topic> rw - Make one topic publicly readable:
sudo ntfy access everyone <public-topic> ro
This lets you keep most topics private while exposing selected ones, or give each team its own credentials. See https://docs.ntfy.sh/config/#access-control for the full model.
Step 10 - Verify the runtime and the data disk
The ntfy binary version and the dedicated data disk holding the accounts database, message cache and attachments:
ntfy --version
findmnt -no SOURCE,SIZE,FSTYPE,TARGET /var/lib/ntfy

The dedicated Azure data disk at /var/lib/ntfy holding the accounts database, message cache and attachments, with deny-all access control configured.
Enabling HTTPS with Let's Encrypt
For any production deployment serve ntfy over HTTPS so logins and tokens cannot be intercepted (and browser push notifications work, which require HTTPS). The image ships with nginx, which certbot can configure automatically. Open 443/tcp in your NSG and point a DNS record for your fully qualified domain name at the VM's public IP address, then:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d ntfy.your-domain.example \
--non-interactive --agree-tos -m you@your-domain.example \
--redirect
After certbot finishes, set the base URL so generated links are correct, then restart ntfy:
sudo sed -i 's|^base-url: .*|base-url: "https://ntfy.your-domain.example"|' /etc/ntfy/server.yml
sudo systemctl restart ntfy
Backup and maintenance
ntfy keeps its accounts, access control and message cache under /var/lib/ntfy (SQLite databases) on the dedicated data disk. Back it up regularly:
sudo systemctl stop ntfy
sudo tar czf /tmp/ntfy-data-backup.tgz -C /var/lib/ntfy .
sudo systemctl start ntfy
ls -lh /tmp/ntfy-data-backup.tgz
Ship the archive to Azure Blob Storage or another object store. Because the data directory is on its own Azure data disk, you can also take coordinated disk snapshots in Azure. Keep the OS patched with sudo apt update && sudo apt upgrade. To upgrade ntfy, replace /usr/local/bin/ntfy with a newer release and restart. See https://docs.ntfy.sh/.
Scaling and operations
- Use access tokens for scripts and CI rather than the admin password
- Integrate ntfy with monitoring (Grafana, Prometheus Alertmanager), backups and cron jobs by publishing to topics
- Put the web tier behind Azure Application Gateway (with websocket support) if you need high availability
Each of these is documented in the official ntfy documentation at https://docs.ntfy.sh/.
Support
This image is backed by 24/7 cloudimg support. Guaranteed response within 24 hours, one hour average for critical issues. Contact support@cloudimg.co.uk for help with deployment, upgrades, integrations, TLS termination and access control.
For general ntfy questions consult the documentation at https://docs.ntfy.sh/. ntfy is a trademark of its respective owner; use here is nominative and does not imply affiliation or endorsement.