GoAlert on Ubuntu 24.04 on Azure User Guide
Overview
This image runs GoAlert 0.34.1, the open source on-call scheduling and alerting platform maintained by Target, on Ubuntu 24.04 LTS. GoAlert routes incidents to the right responder at the right time through on-call schedules, rotations and escalation policies, and delivers notifications by SMS, voice call, email and Slack once you connect a delivery provider. It ships as a single self-contained Go binary, run by an unprivileged goalert system account under a systemd service that starts it on boot and restarts it on failure, backed by a local PostgreSQL 16 database.
GoAlert listens on the loopback address 127.0.0.1:8081 by design and is never exposed directly. nginx is installed as a reverse proxy on port 80 that forwards every request to GoAlert, including the WebSocket connections the UI uses for live updates. PostgreSQL is bound to loopback only.
What is included:
- GoAlert 0.34.1 (official release binary), run by systemd as the unprivileged
goalertuser - The GoAlert web UI and API on
:80(nginx reverse proxy to127.0.0.1:8081) - A per-VM
adminaccount created on first boot and recorded in a root-only file - A per-VM data encryption key and a per-VM PostgreSQL password, both generated on first boot
- PostgreSQL 16, bound to loopback, holding schedules, escalation policies, services and users
postgresql.service,goalert.serviceandnginx.serviceas systemd units, enabled and active- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes - 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point; size up for larger teams. NSG inbound: allow 22/tcp from your management network and 80/tcp for the web UI. GoAlert serves plain HTTP on port 80; for production, terminate TLS in front of it with your own domain and set the Public URL accordingly (see Step 8).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for GoAlert 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). Then Review + create then Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name goalert \
--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 goalert --port 80 --priority 1010
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the services are running
GoAlert is served by nginx on port 80, which reverse-proxies to the Go binary on 127.0.0.1:8081, which in turn talks to PostgreSQL on 127.0.0.1:5432. Confirm all three services are active, and note that only nginx listens on a public address - GoAlert and PostgreSQL are bound to loopback:
systemctl is-active postgresql goalert nginx goalert-firstboot
sudo ss -tlnp | grep -E ':80 |:8081 |:5432 '
Expected output:
active
active
active
active
LISTEN 0 4096 127.0.0.1:8081 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 200 127.0.0.1:5432 0.0.0.0:*
LISTEN 0 511 [::]:80 [::]:*

Step 5 - Retrieve your admin password
On the first boot of every VM, goalert-firstboot.service generates a unique administrator password, a PostgreSQL password and a data encryption key, runs the database migrations, then creates the single admin account with goalert add-user. It writes the admin username, password and dashboard URL into a root-only file. Read it with:
sudo cat /root/goalert-credentials.txt
There is no default or shared credential in the image: the admin account does not exist until first boot creates it with a password unique to this VM. Store the password somewhere safe.

Step 6 - Confirm the version and health endpoint
nginx serves an unauthenticated /healthz endpoint for load balancer probes. Confirm the GoAlert and PostgreSQL versions and that the UI responds:
goalert version | head -4
psql --version
curl -sI http://127.0.0.1/healthz | head -1
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/
Expected output:
Version: v0.34.1
GitCommit: 0918387... (clean)
BuildDate: 2025-10-06T20:20:57Z
GoVersion: go1.25.1 (gc)
psql (PostgreSQL) 16.14 (Ubuntu 16.14-0ubuntu0.24.04.1)
HTTP/1.1 200 OK
200

Step 7 - The local PostgreSQL backend
Everything GoAlert stores - schedules, rotations, escalation policies, services, users and alerts - lives in the local goalert PostgreSQL database, owned by the goalert role and reachable only over loopback. The image ships with the schema migrated and exactly one account (the per-VM admin):
sudo -u postgres psql -l | grep goalert
sudo -u postgres psql -d goalert -tAc "SELECT count(*) FROM information_schema.tables WHERE table_schema='public'"
sudo -u postgres psql -d goalert -tAc "SELECT count(*) FROM users"

Step 8 - Sign in to the web UI
Browse to http://<vm-public-ip>/. Enter admin and the password from Step 5.

GoAlert validates that your browser's address matches its configured Public URL when you sign in. On this image goalert-configure.service sets the Public URL to the VM's detected public IP on every boot, so signing in over the Azure public IP works out of the box. If you reach GoAlert through a different hostname (a DNS name, a load balancer or your own TLS proxy), set the correct URL once: edit GOALERT_PUBLIC_URL in /etc/goalert/goalert.env and run sudo systemctl restart goalert, or set it from the Admin page after signing in.
Step 9 - Build your on-call schedules
Open Schedules from the left navigation and click Create Schedule. Give the schedule a name and time zone, then add rotations and assign users to define who is on call and when. Schedules are the foundation of GoAlert: escalation policies notify whoever a schedule says is on call at the moment an alert fires.

Step 10 - Define escalation policies
Open Escalation Policies and click Create Escalation Policy. An escalation policy is an ordered set of steps - notify this schedule, wait N minutes, then notify the next - with an optional repeat count, so an unacknowledged alert is escalated automatically until someone responds.

Step 11 - Register your services
Open Services and click Create Service, attaching it to an escalation policy. A service represents something you want alerts for (an API, a website, a job). Each service gets integration keys - a generic API endpoint, plus Grafana, Prometheus Alertmanager, email and other formats - that your monitoring tools call to raise an alert, which GoAlert then routes through the service's escalation policy.

Step 12 - Enable alert delivery (SMS, voice, email, Slack)
The image ships the fully functional UI, schedules, escalation policies and services. To actually deliver notifications you connect a provider from the Admin -> Config page after signing in:
- Twilio for SMS and voice calls (Account SID, Auth Token, From Number)
- SMTP for email notifications to responders
- Slack to notify channels as part of an escalation policy
- Mailgun or the built-in SMTP ingress to create alerts from inbound email
Each provider is toggled on and configured in its own section of the Admin Config page. See the GoAlert documentation for provider-specific setup.
Maintenance
- Back up your data: everything GoAlert stores lives in the local
goalertPostgreSQL database. Snapshot the OS disk, or usepg_dump goalertfor logical backups. - Public URL: the Public URL is set to the detected public IP on each boot. For a stable hostname or HTTPS, set
GOALERT_PUBLIC_URLin/etc/goalert/goalert.envandsudo systemctl restart goalert. - Security updates: unattended security upgrades are enabled, so the OS keeps itself patched. Reboot when a new kernel is installed.
- TLS: for production, front GoAlert with your own domain and a TLS-terminating reverse proxy or Azure Application Gateway, and set the Public URL to the
https://address. - Add responders: open Users to manage accounts, and enable GitHub or OIDC single sign-on from Admin -> Config for larger teams.
Support
cloudimg provides 24/7/365 expert technical support for this image. Contact support@cloudimg.co.uk. GoAlert is licensed under the Apache License 2.0. This image is provided by cloudimg; additional charges apply for build, maintenance and 24/7 support.