Application Infrastructure Azure

Prometheus Alertmanager on Ubuntu 24.04 on Azure User Guide

| Product: Prometheus Alertmanager on Ubuntu 24.04 LTS on Azure

Overview

Prometheus Alertmanager is the open source alerting hub of the Prometheus monitoring stack. It receives alerts from Prometheus (and any Alertmanager compatible client), then dedupes, groups, routes, silences and inhibits them before dispatching notifications to receivers such as email, Slack, PagerDuty, OpsGenie and generic webhooks. It ships a built-in web UI and a v2 REST API. The cloudimg image installs the pinned Alertmanager 0.33.1 single Go binary running under systemd, then locks it down for a marketplace appliance: Alertmanager is bound to loopback 127.0.0.1:9093 so its UI and API are never exposed directly, HA clustering is disabled so nothing binds the public gossip port, and an nginx reverse proxy on port 80 adds a per-VM HTTP Basic Auth gate in front of it. Alertmanager has no user accounts of its own, so the nginx Basic Auth credential (user admin, unique password generated on first boot) is the gate. Alertmanager's durable state - silences, the notification log and peer state - lives on a dedicated Azure data disk mounted at /var/lib/alertmanager. Backed by 24/7 cloudimg support.

What is included:

  • Prometheus Alertmanager 0.33.1 installed as a single Go binary and running as the alertmanager systemd service
  • The Alertmanager web UI and v2 REST API on :80, fronted by nginx with the binary bound to loopback only
  • Per-VM HTTP Basic Auth (user admin) protecting the UI and API, with a unique password generated on first boot
  • Alertmanager bound to 127.0.0.1:9093 with HA clustering disabled - nothing is exposed to the network directly
  • A minimal valid default /etc/alertmanager/alertmanager.yml so the service starts cleanly and you edit in your own receivers and routes
  • --web.external-url templated from the VM's public IP on first boot so UI links and silence URLs are correct
  • A dedicated Azure data disk at /var/lib/alertmanager holding silences, the notification log and peer state
  • alertmanager.service + nginx.service as systemd units, enabled and active
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 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 comfortable starting point; Alertmanager is light on resources. NSG inbound: allow 22/tcp from your management network, 80/tcp for the UI and API, and 443/tcp if you add TLS. Alertmanager serves plain HTTP on port 80; for production use, terminate TLS in front of it with your own domain and restrict access to trusted IP ranges (see Maintenance).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Prometheus Alertmanager 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 alertmanager \
  --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 alertmanager --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

systemctl is-active alertmanager.service nginx.service

Both report active. Alertmanager serves its web UI and v2 API on the loopback address 127.0.0.1:9093; nginx fronts it on port 80 and adds the per-VM HTTP Basic Auth gate. Clustering is disabled, so nothing binds the public :9094 gossip port. Alertmanager's state lives on the dedicated Azure data disk mounted at /var/lib/alertmanager.

The alertmanager and nginx services active, Alertmanager listening on loopback 127.0.0.1:9093, nginx on port 80 with no public 9094, and the dedicated data disk mounted at /var/lib/alertmanager

Step 5 - Retrieve your web UI password

nginx protects the Alertmanager UI and API with HTTP Basic Auth. The username is admin and a unique password is generated on the first boot of your VM and written to a root-only file:

sudo cat /root/alertmanager-credentials.txt

This file contains ALERTMANAGER_USERNAME, ALERTMANAGER_PASSWORD and the ALERTMANAGER_URL to open in a browser. The password is stored on disk only as a bcrypt hash in /etc/nginx/.alertmanager.htpasswd, so no plaintext password ships in the image. Store the password somewhere safe.

The Alertmanager version, the systemd ExecStart flags binding to loopback with clustering disabled, the default config passing amtool check-config, and the per-VM credentials file with the generated admin password

Step 6 - Confirm the health endpoint

nginx serves an unauthenticated health endpoint for load balancers and probes:

curl -s http://localhost/healthz

It returns ok. This endpoint never requires authentication, so it is safe for an Azure Load Balancer health probe.

Step 7 - Confirm authentication and the status API

Because a password is set on first boot, an unauthenticated request to the UI returns HTTP 401, so nobody reaches Alertmanager without the password. The following reads the per-VM password from the credentials file and proves the round-trip - unauthenticated is rejected, a wrong password is rejected, the correct password authenticates, and an authenticated call to the v2 status API returns JSON:

PW=$(sudo grep '^ALERTMANAGER_PASSWORD=' /root/alertmanager-credentials.txt | cut -d= -f2-)
echo "unauth  : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/)"
echo "wrongpw : $(curl -s -o /dev/null -w '%{http_code}' -u admin:wrong-pw http://127.0.0.1/)"
echo "authed  : $(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW http://127.0.0.1/)"
curl -s -u admin:$PW http://127.0.0.1/api/v2/status | python3 -c 'import sys,json;d=json.load(sys.stdin);print("version :",d["versionInfo"]["version"]);print("cluster :",d["cluster"]["status"])'

It prints unauth : 401, wrongpw : 401, authed : 200, then the Alertmanager version and a cluster status of disabled. The /api/v2/status endpoint, like the whole UI, is only reachable with the per-VM password because Alertmanager itself is bound to loopback and nginx is the only way in.

The HTTP Basic Auth round-trip returning 401 unauthenticated, 401 for a wrong password, 200 with the per-VM password, and the authenticated v2 status API returning Alertmanager 0.33.1 with clustering disabled

Step 8 - Post a test alert through the v2 API

Alertmanager receives alerts on POST /api/v2/alerts. In production your Prometheus servers push here; you can also post one by hand to confirm the pipeline. The following posts a test alert and reads it back:

PW=$(sudo grep '^ALERTMANAGER_PASSWORD=' /root/alertmanager-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'POST /api/v2/alerts -> %{http_code}\n' -u admin:$PW \
  -H 'Content-Type: application/json' \
  -d '[{"labels":{"alertname":"HighRequestLatency","severity":"warning","job":"api"}}]' \
  http://127.0.0.1/api/v2/alerts
curl -s -u admin:$PW http://127.0.0.1/api/v2/alerts | python3 -c 'import sys,json;a=json.load(sys.stdin);print("active alerts:",len(a));[print("  -",x["labels"]["alertname"]) for x in a]'

The POST returns 200 and the alert appears in the active list. To point a real Prometheus at this VM, set alerting.alertmanagers[].static_configs[].targets to <vm-public-ip>:80 and supply the admin Basic Auth credentials.

Posting a test alert to the v2 API returning HTTP 200, the active alert list read back through the API, and Alertmanager durable state on the dedicated data disk mounted at /var/lib/alertmanager

Step 9 - Sign in and read the Alerts view

Browse to http://<vm-public-ip>/. Your browser prompts for a username and password: enter admin and the password from Step 5. Alertmanager opens on the Alerts view, which shows active alerts grouped according to your routing tree (by alertname in the default config). Each group can be expanded, filtered with a label matcher, or silenced directly from the list.

The Alertmanager Alerts view showing active alerts grouped by alertname, with filter and group tabs and a New Silence action

Step 10 - Create and manage silences

Open the Silences page from the top navigation. A silence mutes notifications for alerts that match a set of label matchers for a chosen window - useful during maintenance. Click New Silence, add matchers (for example severity="warning"), set a duration and a comment, and create it; the Silences page then lists active, pending and expired silences and lets you expire or recreate them.

The Alertmanager Silences page for muting notifications by label matcher over a chosen window, with the New Silence action

Step 11 - Check status, version and cluster

Open the Status page from the top navigation. It shows the process uptime, the cluster status (disabled on this single-node appliance), and the full version information - branch, build date, Go version, revision and the Alertmanager version (0.33.1). Below that it displays the currently loaded configuration.

The Alertmanager Status page showing uptime, cluster status disabled, and version information reporting Alertmanager 0.33.1

Step 12 - Configure your receivers and routes

The Status page also renders the loaded alertmanager.yml - the global defaults, the routing tree and the receivers. The image ships a minimal valid default with a single default-null no-op receiver so the service starts cleanly with no external credentials. To send real notifications, edit the config, then validate and reload:

sudo nano /etc/alertmanager/alertmanager.yml
amtool check-config /etc/alertmanager/alertmanager.yml
sudo systemctl reload alertmanager

Add a receiver (for example an email_configs, slack_configs or webhook_configs block) under receivers: and route alerts to it in the route: tree. amtool check-config validates the file before you reload, so a typo never takes the service down.

The Alertmanager Status page scrolled to the loaded configuration showing the global receiver URLs, the route tree with the default-null receiver, the inhibit rules and the receivers list

Maintenance

  • Password: the UI password is set on first boot and stored as a bcrypt entry in /etc/nginx/.alertmanager.htpasswd. To change it, run sudo htpasswd -B /etc/nginx/.alertmanager.htpasswd admin and then sudo systemctl reload nginx.
  • Configuration: edit /etc/alertmanager/alertmanager.yml to define your receivers and routing tree, validate with amtool check-config /etc/alertmanager/alertmanager.yml, then sudo systemctl reload alertmanager. The reload applies changes without dropping in-flight state.
  • Restrict access: Alertmanager serves plain HTTP on port 80. For production, restrict access to trusted IP ranges in your Network Security Group, and front it with TLS (for example certbot with your own domain) terminating on :443.
  • Loopback binding: Alertmanager is bound to 127.0.0.1:9093 and clustering is disabled (--cluster.listen-address= empty) in /etc/systemd/system/alertmanager.service, so nginx is the only path in and no gossip port is exposed. Keep it that way - do not change the listen address to a public interface.
  • External URL: --web.external-url is templated from the VM's public IP on first boot (via /etc/alertmanager/external-url.env) so UI links and silence URLs resolve correctly. If you put Alertmanager behind a domain, set AM_EXTERNAL_URL=https://alerts.example.com/ in that file and sudo systemctl restart alertmanager.
  • Connect Prometheus: point your Prometheus alerting.alertmanagers block at <vm-public-ip>:80 with the admin Basic Auth credentials so it delivers alerts to this hub.
  • Storage: all Alertmanager state (silences, the notification log and peer state) lives under /var/lib/alertmanager on the dedicated data disk; back up that volume to protect your silences and notification history.
  • Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.

Support

cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.