Prometheus Alertmanager on Ubuntu 24.04 on Azure User Guide
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
alertmanagersystemd 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:9093with HA clustering disabled - nothing is exposed to the network directly - A minimal valid default
/etc/alertmanager/alertmanager.ymlso the service starts cleanly and you edit in your own receivers and routes --web.external-urltemplated 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/alertmanagerholding silences, the notification log and peer state alertmanager.service+nginx.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 + 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.

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.

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.

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.

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.

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.

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.

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.

Maintenance
- Password: the UI password is set on first boot and stored as a bcrypt entry in
/etc/nginx/.alertmanager.htpasswd. To change it, runsudo htpasswd -B /etc/nginx/.alertmanager.htpasswd adminand thensudo systemctl reload nginx. - Configuration: edit
/etc/alertmanager/alertmanager.ymlto define your receivers and routing tree, validate withamtool check-config /etc/alertmanager/alertmanager.yml, thensudo 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:9093and 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-urlis 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, setAM_EXTERNAL_URL=https://alerts.example.com/in that file andsudo systemctl restart alertmanager. - Connect Prometheus: point your Prometheus
alerting.alertmanagersblock at<vm-public-ip>:80with theadminBasic Auth credentials so it delivers alerts to this hub. - Storage: all Alertmanager state (silences, the notification log and peer state) lives under
/var/lib/alertmanageron 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.