Gotify
Overview
Gotify is a popular open-source, self-hosted push notification server. You send messages from any script, server or application over a simple REST API. You receive them in real time in the bundled web app, the official Android client, or any websocket consumer. It is a privacy-respecting alternative to hosted push services, running on infrastructure you control.
This SecureAnyCloud image runs the Gotify server, a single Go binary that serves both the REST API and the web app, behind nginx on port 80, with PostgreSQL as the datastore. On the first boot of every VM, a one-shot service creates an empty database, rotates the PostgreSQL password and seeds a single administrator account with its own password. Open registration is disabled, and two VMs deployed from the same image never share credentials.
What you get:
- Gotify 2.9.1 server (single Go binary, bundles the web UI) at
/opt/gotify/gotify, listening on127.0.0.1:8080 - An nginx reverse proxy on
:80, with websocket upgrade support, in front of the Gotify server on loopback:8080 - A PostgreSQL datastore on
127.0.0.1:5432, bound to the loopback interface only, with its datadir on a dedicated Azure data disk at/var/lib/postgresql - A second dedicated Azure data disk at
/var/lib/gotifyfor uploaded application images and plugins. Both disks are separate from the OS disk and re-provisioned with every VM - A fresh empty database on first boot, which also yields a new per-instance session signing key
- Per-VM administrator and PostgreSQL passwords generated at first boot, with the login written to
/root/gotify-credentials.txtin a root-only file (mode 0600) gotify.service,postgresql.serviceandnginx.serviceas enabled, active systemd units- A fully patched Ubuntu 24.04 LTS security baseline at capture time, with unattended security updates enabled
- 24/7 SecureAnyCloud support
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.
Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting size, because Gotify is lightweight. Scale up for very large message volumes.
Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp from the networks that your users and senders will reach Gotify on. Also allow 443/tcp once you enable HTTPS.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Gotify by SecureAnyCloud, and select Create.
On the Basics tab, 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 two dedicated data disks on the Disks tab, then select Review + create and Create. First-boot initialisation takes approximately one minute after the VM starts.
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:gotify-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name gotify \
--image sac1647283583153:gotify-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 gotify --port 80 --priority 1010Step 3 - Connect to your VM
Connect to the VM over SSH:
ssh azureuser@<vm-public-ip>Step 4 - Verify the Gotify stack
Three systemd services make up the stack. Confirm that all three are active and that the open version endpoint answers through nginx:
systemctl is-active gotify postgresql nginx curl -s http://127.0.0.1/versionAll three lines read active, and the version endpoint returns JSON containing "version":"2.9.1".
Next, confirm that the Gotify server and PostgreSQL bind to loopback only, and that the two dedicated data disks are mounted:
ss -tln 2>/dev/null | grep -E ':(80|8080|5432) ' || sudo ss -tln | grep -E ':(80|8080|5432) ' df -h /var/lib/postgresql /var/lib/gotify | tail -2Port 80 (nginx) listens on all interfaces. Ports 8080 (Gotify) and 5432 (PostgreSQL) are bound to 127.0.0.1 only.
Step 5 - Retrieve your administrator login
The login for the admin account is generated on the first boot of your VM and stored in a root-only file. The file lists the Gotify URL, the administrator username (admin), the password and the PostgreSQL credentials:
sudo cat /root/gotify-credentials.txtStore the password in your password manager and treat the file as sensitive.
Step 6 - Verify authentication
The API rejects anonymous requests and accepts the generated administrator password. The first command reports 401 and the second reports 200:
curl -s -o /dev/null -w 'anonymous /current/user HTTP %{http_code}\n' http://127.0.0.1/current/user
PASS=$(sudo grep '^gotify.admin.pass=' /root/gotify-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'authenticated /current/user HTTP %{http_code}\n' -u admin:$PASS http://127.0.0.1/current/userStep 7 - Sign in to the web app
Open a web browser and go to http://<vm-public-ip>/. Sign in with the username admin and the password from /root/gotify-credentials.txt.
The web app shows the message stream: all notifications, grouped by application, arriving in real time.
Step 8 - Create an application and push your first message
Senders authenticate with an application token, not your administrator password. Create an application in the web app under Apps, or over the API as shown below. Then push a message with its token:
PASS=$(sudo grep '^gotify.admin.pass=' /root/gotify-credentials.txt | cut -d= -f2-)
APP_TOKEN=$(curl -s -u admin:$PASS -X POST http://127.0.0.1/application -F name=server-alerts -F description='Demo application' | jq -r .token)
echo "application token: $APP_TOKEN" curl -s -X POST "http://127.0.0.1/message?token=$APP_TOKEN" -F title='Backup finished' -F message='Nightly backup completed successfully' -F priority=5 | jq .The message appears instantly in the web app and on every connected client. Any script or application that can issue an HTTP POST can now push notifications. When you send from another host, replace 127.0.0.1 with your VM's address. You manage applications, clients and users in the web app.
Confirm that the message was stored by reading the stream back over the API:
PASS=$(sudo grep '^gotify.admin.pass=' /root/gotify-credentials.txt | cut -d= -f2-)
curl -s -u admin:$PASS http://127.0.0.1/message | jq '.messages[0] | {title, message, priority}'Step 9 - Receive messages in real time
The web app receives messages over a websocket the moment they arrive.
For your phone, install the official Gotify Android client from F-Droid or Google Play. Point it at http://<vm-public-ip>/ and sign in. The client registers itself and shows every push as a native Android notification.
Any other consumer can subscribe to the stream with a client token:
curl -s -N -H "X-Gotify-Key: <client-token>" "ws://<vm-public-ip>/stream"Because this is your own self-hosted VM, your notification traffic never leaves infrastructure you control.
Security baseline
The image is captured with the Ubuntu 24.04 security baseline fully applied, including phased updates. It ships with unattended security upgrades enabled, so your VM keeps patching itself after deployment:
cat /etc/apt/apt.conf.d/20auto-upgrades systemctl is-enabled unattended-upgradesEnabling HTTPS
For production, serve Gotify over HTTPS so that login credentials and message traffic are encrypted in transit. Point a DNS A record at the VM's public IP address, then install a certificate with Certbot. Replace the domain with your own:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.comAfter you enable HTTPS, open 443/tcp in the NSG and update the URL in your Android client and senders to https://. Then restrict or close inbound port 80.
Backup and maintenance
All Gotify state lives on the two dedicated Azure data disks. The PostgreSQL datadir at /var/lib/postgresql holds users, applications, clients and messages. Uploaded application images and plugins are at /var/lib/gotify.
Both disks are separate from the OS disk, so the simplest backup is an Azure disk snapshot:
az snapshot create --resource-group <your-rg> --name gotify-db-backup --source <data-disk-id>For a logical database backup, run sudo -u postgres pg_dump gotify instead and copy the dump to object storage on a schedule.
Apply operating system security updates with sudo apt update && sudo apt upgrade. The services restart cleanly, and Gotify resumes serving immediately because all state is on the persistent data disks. Restart the server at any time with sudo systemctl restart gotify.
Support
This image comes with 24/7 SecureAnyCloud support. Contact us by email or chat for deployment help, integrations, TLS termination and database administration.
Gotify itself is open-source software licensed under the MIT license.
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on Azure
Launch Gotify 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
Gotify is an open-source, self-hosted push notification server. You send messages from any script, server or application over a simple REST API. You receive them in real time in the web app, the official Android client, or any websocket consumer. It is a privacy-respecting alternative to hosted push services, and it deploys in your own VPC.
This SecureAnyCloud image runs Gotify as a single Go binary that serves both the REST API and the bundled web app. It runs behind nginx as a reverse proxy, and PostgreSQL is the datastore.
What you get:
- The Gotify server listening on
127.0.0.1:8080, reached through nginx on port 80 (and 443 once you add TLS) - The server and the database bound to the loopback interface only
- A one-shot service on the first boot of every deployed instance that recreates an empty database, which also yields a fresh per-instance session signing key
- A rotated PostgreSQL password and a single administrator account seeded with a per-instance password
- Open registration disabled
- The login written to
/root/gotify-credentials.txtwith mode 0600 - 24/7 SecureAnyCloud support
Prerequisites
Before you deploy this image you need:
- 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. It must also allow inbound ports 80 and 443 from the networks your users and senders use to reach Gotify
- 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 Gotify. Select the SecureAnyCloud listing and choose Select, then Continue on the subscription summary.
Pick an instance type of t3.small or larger. Gotify is lightweight. Choose your EC2 key pair under Key pair (login).
Under Network settings, select your VPC and subnet. 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 initialisation takes under a minute after the instance state becomes Running and the status checks pass.
Launch the Instance from the AWS CLI
The following command launches an instance from the SecureAnyCloud Gotify Marketplace AMI into an existing subnet and security group. Replace the values in angle brackets:
- Replace <ami-id> with the AMI ID shown on the Marketplace listing.
- Replace <key-name> with your EC2 key pair name.
- Replace <subnet-id> with your subnet ID.
- Replace <security-group-id> with a security group that opens ports 22, 80 and 443 as described in Prerequisites.
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=gotify-01}]'On success, the command prints a JSON document. Note the instance ID. Once the instance is running, retrieve its public address 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. For Gotify 2.9 on Ubuntu 24.04, the SSH login user is 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/gotify-credentials.txtThe plain text file contains the Gotify URL, the administrator username (admin) and the password.
From the same SSH session, confirm that the deployment is healthy. The version endpoint is open:
curl -fsS http://127.0.0.1/version{"version":"2.9.1","commit":"...","buildDate":"..."}A JSON response with a version confirms that the full stack is serving: nginx, the Gotify server and PostgreSQL.
First Sign-in
Open a web browser and navigate to http://<public-ip>/. Gotify presents its sign-in page. Enter the username admin and the password from /root/gotify-credentials.txt, then select Login.
The screenshot shows the Gotify sign-in page, served on first boot with a per-instance administrator login.
Create an Application and Push a Message
In Gotify, every sender is an application with its own token. Open APPS, select Create Application, give it a name, and copy its token.
Then push a message with a single HTTP call. It can come from a script, a cron job, a monitoring tool or anything else:
curl -X POST "http://<public-ip>/message?token=<app-token>" \
-F "title=Backup complete" \
-F "message=Database dump 4.2 GB written to S3" \
-F "priority=5"The message appears instantly in the web app and in any connected client.
The screenshot shows Gotify applications, each with its own token for pushing messages over the REST API.
Read Messages in Real Time
The Messages view streams notifications as they arrive, grouped by application. Priority indicators make the important alerts stand out, and higher-priority messages are highlighted. You can delete individual messages or clear them all.
The screenshot shows the Gotify message stream, with notifications grouped by application and priority indicators.
To receive push notifications on your phone, install the official Gotify Android client. Point it at http://<public-ip>/ (or your HTTPS domain) and sign in with a client token from CLIENTS.
Any websocket consumer can subscribe to /stream for real-time delivery.
Manage Users and Clients
As the administrator, open USERS to add users. Open registration is disabled by default, so you create accounts here.
Open CLIENTS to create client tokens for the mobile and desktop apps. Open PLUGINS to extend Gotify with compiled plugins.
Enable HTTPS with Let's Encrypt
For any production deployment, serve Gotify over HTTPS so that logins and tokens cannot be intercepted. The image ships with nginx, which certbot can configure automatically.
These commands assume that a DNS record 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 push.your-domain.example \
--non-interactive --agree-tos -m you@your-domain.example \
--redirectcertbot also configures the websocket upgrade headers that the real-time stream needs.
Backups and Maintenance
Gotify keeps all of its state (users, applications, clients and messages) in PostgreSQL. It keeps uploaded application images under /var/lib/gotify. Back up both regularly:
sudo -u postgres pg_dump gotify > <backup-dir>/gotify-db-$(date +%F).sql
sudo tar czf <backup-dir>/gotify-data-$(date +%F).tgz -C /var/lib/gotify images pluginsShip the archives to an Amazon S3 bucket or another object store. The database and the data directory are each on their own EBS volume, so you can also take coordinated EBS snapshots.
To upgrade Gotify, replace /opt/gotify/gotify with a newer release and restart. Database migrations run automatically on start. See https://gotify.net/docs/.
Scaling and Operations
- Move PostgreSQL to Amazon RDS for PostgreSQL and update the
databasesection of/etc/gotify/config.yml - Put the web tier behind an Application Load Balancer (with websocket support) if you need high availability
- Integrate Gotify with monitoring (Grafana, Prometheus Alertmanager), CI/CD and backup jobs by pushing to application tokens
The official Gotify documentation at https://gotify.net/docs/ covers each of these options.
Support
SecureAnyCloud provides 24/7/365 expert technical support for this image. Response is guaranteed within 24 hours, with a one-hour average for critical issues. Contact sales@secureanycloud.com.
For general Gotify questions, consult the documentation at https://gotify.net/docs/. Gotify is a trademark of its respective owner. Its use here is nominative and does not imply affiliation or endorsement.
Deploy on AWS
Launch Gotify on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com