ntfy
Overview
This SecureAnyCloud 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 other subscriber. It is a privacy-respecting alternative to hosted push services that you can deploy in your own virtual network.
The ntfy server is a single Go binary that serves both the REST API and the bundled web app, and it runs behind nginx as a reverse proxy. The datastore is an embedded SQLite database for accounts and the message cache. It is held on a dedicated Azure data disk at /var/lib/ntfy, which is 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 you get:
- 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 - A per-VM administrator password generated at first boot, in a root-only file
ntfy.serviceandnginx.serviceas systemd units, enabled and active- 24/7 SecureAnyCloud support
Prerequisites
Before you deploy, make sure you have an active Azure subscription, an SSH key pair, and a VNet and subnet in the target region.
Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point, because ntfy is lightweight.
In the NSG, allow inbound 22/tcp from your management network. Also allow 80/tcp (and 443/tcp once you enable TLS) from the networks your users and publishers 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 SecureAnyCloud, 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 choose Review + create and Create.
Step 2 - Deploy from the Azure CLI
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:ntfy-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name ntfy \
--image sac1647283583153:ntfy-ubuntu-24-04:default:latest \
--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 1010Step 3 - Connect to your VM
First boot initialization 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/healthBoth services report active and the health endpoint returns:
{"healthy":true}A "healthy":true response confirms that 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.txtThe plain text file contains 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 go 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, where you 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 command 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/alertsFrom any other machine, make the same call with your VM's address. Replace the password and IP:
curl -u admin:<password> -H "Title: Hello" -d "Message body" http://<vm-public-ip>/alertsSubscribe 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.
To receive push notifications on your phone, 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.
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 are 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
With these commands you can 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
Check the ntfy binary version and the dedicated data disk that holds the accounts database, message cache and attachments:
ntfy --version findmnt -no SOURCE,SIZE,FSTYPE,TARGET /var/lib/ntfyThe 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. Browser push notifications also 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 run:
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 \
--redirectAfter 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 ntfyBackup and maintenance
ntfy keeps its accounts, access control and message cache under /var/lib/ntfy (SQLite databases) on the dedicated data disk. Back up this directory 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.tgzShip 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 SecureAnyCloud support, with a guaranteed response within 24 hours and a one-hour average for critical issues. Contact sales@secureanycloud.com 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. It is named here only to identify the software and does not imply affiliation or endorsement.
Deploy on Azure
Launch ntfy on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
This SecureAnyCloud 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 other subscriber. It is a privacy-respecting alternative to hosted push services that you can deploy in your own VPC.
The ntfy server is a single Go binary that serves both the REST API and the bundled web app, and it runs behind nginx as a reverse proxy. The datastore is an embedded SQLite database for accounts and the message cache. 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 instance, a one-shot service recreates an empty authentication database and creates a single administrator account with a per-instance password. The login is written to /root/ntfy-credentials.txt with mode 0600.
Prerequisites
Before you deploy this image, make sure you have:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network and inbound ports 80 and 443 from the networks your users and publishers reach ntfy on
- The AWS CLI (version 2) installed locally, if you plan to deploy from the command line
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for ntfy. Select the SecureAnyCloud listing and choose Select, then Continue on the subscription summary.
Pick an instance type of t3.small or larger, because ntfy is lightweight. Choose your EC2 key pair under Key pair (login). Under Network settings, select your VPC and subnet, and either create or select a security group that allows inbound port 22 from your management network and inbound ports 80 and 443 from the networks your users use. Leave the root volume at the default size or larger.
Select Launch instance. First boot initialization takes under a minute after the instance state becomes Running and the status checks pass.
Launch the Instance from the AWS CLI
Run the following command to launch an instance from the SecureAnyCloud ntfy Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens ports 22, 80 and 443 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type t3.small \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":30,"VolumeType":"gp3"}}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=ntfy-01}]'On success, the command prints a JSON document. Note the instance ID, then retrieve the public address once the instance is running with aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].PublicIpAddress" --output text.
Connect and Retrieve the Administrator Login
Connect over SSH with the key pair you selected and the public IP address from Step 2. The SSH login user depends on the operating system of the AMI variant you launched:
AMI variant SSH login user
ntfy 2.24 on Ubuntu 24.04 ubuntu
The first-boot service runs before the SSH daemon becomes ready, so the credentials file is always in place when you log in for the first time.
ssh <login-user>@<public-ip>
sudo cat /root/ntfy-credentials.txtThe plain text file contains the ntfy URL, the administrator username (admin) and the password. From the same SSH session, confirm the deployment is healthy. The health endpoint is open:
curl -fsS http://127.0.0.1/v1/health{"healthy":true}A "healthy":true response confirms that the full stack, nginx and the ntfy server, is serving.
First Sign-in
Open a web browser and go to http://<public-ip>/. ntfy presents its web app. Select Sign in (top right) and enter the username admin and the password from /root/ntfy-credentials.txt.
The ntfy web app, where you subscribe to topics and read notifications in the browser.
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). Publish a message with a single HTTP call from a script, a cron job, a monitoring tool or anything else:
curl -u admin:<password> \
-H "Title: Backup complete" \
-H "Priority: high" \
-H "Tags: white_check_mark" \
-d "Database dump 4.2 GB written to S3 successfully" \
http://<public-ip>/alertsSubscribe 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.
Settings, Tokens and Mobile Apps
Open Settings to manage your account, notification preferences and subscriptions. Create access tokens (under your account) so scripts can publish without your password.
To receive push notifications on your phone, install the official ntfy Android or iOS app. Add your server http://<public-ip>/ (or your HTTPS domain), sign in, and subscribe to topics.
ntfy settings: account, notification preferences and subscriptions.
Access Control
Access defaults to deny-all. Manage users and per-topic access from the command line, over SSH on the instance:
- List users:
sudo ntfy user list - Add a user (you are 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
With these commands you can 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.
Enable HTTPS with Let's Encrypt
For any production deployment, serve ntfy over HTTPS so logins and tokens cannot be intercepted. Browser push notifications also require HTTPS. The image ships with nginx, which certbot can configure automatically.
The following commands assume you have a DNS record that points your fully qualified domain name at the instance's public IP address.
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 \
--redirectAfter 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 ntfyBackups and Maintenance
ntfy keeps its accounts, access control and message cache under /var/lib/ntfy (SQLite databases). Back up this directory regularly:
sudo systemctl stop ntfy
sudo tar czf <backup-dir>/ntfy-data-$(date +%F).tgz -C /var/lib/ntfy .
sudo systemctl start ntfyShip the archive to an Amazon S3 bucket or another object store. Because the data directory is on its own EBS volume, you can also take coordinated EBS snapshots. 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 an Application Load Balancer (with websocket support) if you need high availability.
Each of these is documented in the official ntfy documentation at https://docs.ntfy.sh/.
Support
SecureAnyCloud provides 24/7/365 expert technical support for this image, with a guaranteed response within 24 hours and a one-hour average for critical issues. Contact sales@secureanycloud.com.
For general ntfy questions, consult the documentation at https://docs.ntfy.sh/. ntfy is a trademark of its respective owner. It is named here only to identify the software and does not imply affiliation or endorsement.
Deploy on AWS
Launch ntfy on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com