Gatus on Ubuntu 24.04 on Azure User Guide
Overview
Gatus is an automated health and uptime monitoring dashboard and status page. You describe the services you want to watch as a short list of endpoints in a single YAML file, each with its own check interval and success conditions, and Gatus continuously probes them and renders a clear, real time status page that shows what is up, what is down and how each service has behaved over time. Conditions are expressive, covering HTTP status, response time, response body, DNS answers and TLS certificate expiry across HTTP, TCP, ICMP, DNS and other protocols, and the same results are available as a JSON API. It is a single Go binary with an embedded SQLite backend, so it stays lightweight and starts instantly.
The cloudimg image installs Gatus 5.36.0 and puts it behind an nginx reverse proxy that binds the server to loopback. The appliance is secure by default: the status dashboard is read only by design, so there is no web admin surface, no login to manage and no credential of any kind baked into the image. The Prometheus metrics endpoint is disabled so nothing beyond the intended dashboard and JSON API is exposed. A sensible default configuration monitors the instance's own web server and a couple of well known public endpoints, so the dashboard is populated on first boot and you can immediately replace the examples with your own services.
What is included:
- Gatus 5.36.0 single Go binary (
/usr/local/bin/gatus) - Embedded SQLite history database at
/var/lib/gatus/data.db(no separate database to maintain) gatus.servicerunning asgatus, bound to loopback127.0.0.1:8080nginx.servicereverse proxy on TCP 80, TLS readygatus-firstboot.serviceresolving this VM's URL into the MOTD and a root only info note on first boot- A read only status dashboard at
/plus a JSON status API at/api/v1/endpoints/statuses - Prometheus
/metricsdisabled by default, so only the dashboard and API are exposed - Ubuntu 24.04 LTS base, latest patches, unattended security upgrades enabled
- 24/7 cloudimg support, 24h response SLA
Prerequisites
An active Azure subscription, an SSH key, and a VNet with a subnet. Recommended VM size: Standard_B2s (Gatus is very light; 4 GB RAM is plenty).
Step 1: Deploy from the Azure Portal
Search the Azure Marketplace for Gatus, choose the plan, and create the VM. In the networking step attach an NSG that allows inbound TCP 22 (SSH) and TCP 80 (the dashboard) from your client networks only. Put a TLS reverse proxy in front of port 80 for production. Because the dashboard is read only, it is safe to publish as a status page, but you should still restrict who can reach it if the endpoint names or URLs are sensitive.
Step 2: Deploy from the Azure CLI
RG="gatus-prod"; LOCATION="eastus"; VM_NAME="gatus-01"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/gatus-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az network vnet create -g "$RG" --name gt-vnet --address-prefix 10.106.0.0/16 --subnet-name gt-subnet --subnet-prefix 10.106.1.0/24
az network nsg create -g "$RG" --name gt-nsg
az network nsg rule create -g "$RG" --nsg-name gt-nsg --name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp
az network nsg rule create -g "$RG" --nsg-name gt-nsg --name allow-web --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 80 --access Allow --protocol Tcp
az vm create -g "$RG" --name "$VM_NAME" --image "$GALLERY_IMAGE_ID" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username azureuser --ssh-key-values "$SSH_KEY" \
--vnet-name gt-vnet --subnet gt-subnet --nsg gt-nsg --public-ip-sku Standard
Step 3: Connect via SSH
ssh azureuser@<vm-ip>
gatus.service, nginx.service and gatus-firstboot.service all start automatically on first boot.
Step 4: Verify the Service
sudo systemctl is-active gatus nginx gatus-firstboot
sudo test -f /var/lib/cloudimg/gatus-firstboot.done && echo FIRSTBOOT_DONE
sudo ss -tlnp | grep -E ':80 |:8080 '
Expected output — all three services are active, nginx is bound to the public port 80 and Gatus is bound to loopback 127.0.0.1:8080 only:
active
active
active
FIRSTBOOT_DONE
LISTEN 0 4096 127.0.0.1:8080 0.0.0.0:* users:(("gatus",...))
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",...))

Step 5: Instance Info — Read Only, No Credential
Gatus has no login. On first boot a root only note is written with this VM's dashboard URL and API URL. There is no password to change and no credential baked into the image, and the Prometheus metrics endpoint is disabled:
sudo cat /root/gatus-info.txt
sudo ss -tlnp | grep 8080
grep -E 'address:|port:|metrics:' /etc/gatus/config.yaml
curl -s -o /dev/null -w 'GET /metrics -> HTTP %{http_code} (404 = not exposed)\n' http://127.0.0.1/metrics
The note points at the dashboard and API, Gatus is bound to loopback only, and /metrics is not served:
GATUS_URL=http://<vm-ip>/
GATUS_API_URL=http://<vm-ip>/api/v1/endpoints/statuses
CONFIG=/etc/gatus/config.yaml
LISTEN 127.0.0.1:8080
address: 127.0.0.1
port: 8080
metrics: false
GET /metrics -> HTTP 404 (404 = not exposed)

Step 6: Query the Status API
Every result the dashboard shows is also available as JSON at /api/v1/endpoints/statuses, so you can wire Gatus into your own tooling. Each object carries the endpoint name, group, the last HTTP status, whether it is healthy, and the conditions used to decide:
curl -s http://127.0.0.1/api/v1/endpoints/statuses \
| jq '[.[] | {name, group, healthy: (.results[-1].success), status: (.results[-1].status)}]'
Every configured endpoint reports healthy:
[
{ "name": "cloudflare", "group": "internet", "healthy": true, "status": 200 },
{ "name": "github-api", "group": "internet", "healthy": true, "status": 200 },
{ "name": "web-server", "group": "this-instance", "healthy": true, "status": 200 }
]

Step 7: Open the Status Dashboard
Open the dashboard in a browser. There is no login — it is a read only status page:
open http://<vm-ip>/
The dashboard lists every monitored endpoint, grouped, with a health pill and a sparkline of recent checks. The default configuration already shows the instance's own web server and two public endpoints, all healthy:

Step 8: Inspect an Endpoint Detail
Click any endpoint to open its detail page. It shows the current status, the average response time, the response time range and when it was last checked, along with a Recent Checks strip where each square is one probe result. Here is the local web-server endpoint, answering in about a millisecond:

Step 9: Monitor TLS Certificate Expiry
Gatus can assert on more than HTTP status. The shipped cloudflare endpoint also checks the TLS certificate expiry with a condition like [CERTIFICATE_EXPIRATION] > 240h, so the endpoint turns unhealthy well before a certificate lapses. Its detail page shows real response times to the public site:

Step 10: Monitor Your Own Services
Replace the example endpoints with your own. Edit /etc/gatus/config.yaml and add an entry under endpoints: — a name, a group, the URL to probe, an interval and the success conditions:
endpoints:
- name: my-app
group: production
url: "https://app.example.com/health"
interval: 60s
conditions:
- "[STATUS] == 200"
- "[RESPONSE_TIME] < 400"
- "[BODY].status == UP"
Apply the change with a restart — Gatus reloads the whole configuration in under a second:
sudo systemctl restart gatus.service
sleep 2
systemctl is-active gatus.service
The shipped configuration already includes a public API example (github-api), whose detail page shows a fast, healthy external dependency — the same view you get for your own services once you add them:

Step 11: Server Components
| Component | Path |
|---|---|
| Gatus binary | /usr/local/bin/gatus |
| Config file | /etc/gatus/config.yaml |
| SQLite history database | /var/lib/gatus/data.db |
| Systemd unit | /etc/systemd/system/gatus.service |
| Firstboot script | /usr/local/sbin/gatus-firstboot.sh |
| Per VM info note | /root/gatus-info.txt (mode 0600) |
| Sentinel | /var/lib/cloudimg/gatus-firstboot.done |
ls -1 /usr/local/bin/gatus /etc/gatus/config.yaml /etc/systemd/system/gatus.service /usr/local/sbin/gatus-firstboot.sh
echo "endpoints monitored: $(curl -s http://127.0.0.1/api/v1/endpoints/statuses | jq 'length')"
echo "healthy right now: $(curl -s http://127.0.0.1/api/v1/endpoints/statuses | jq '[.[]|select(.results[-1].success==true)]|length')"

Step 12: Managing the Service
sudo systemctl restart gatus.service
sudo journalctl -u gatus.service --no-pager -n 15
Gatus restarts in under a second because it is a single binary with a local SQLite database. The service is hardened with NoNewPrivileges, ProtectSystem=strict and ProtectHome, and only has write access to its own data directory.
Step 13: Configuration
Gatus is configured entirely through /etc/gatus/config.yaml. Useful keys already set by the image:
| Setting | Meaning | Image default |
|---|---|---|
web.address |
Bind address | 127.0.0.1 (loopback) |
web.port |
Bind port | 8080 |
storage.type |
History backend | sqlite |
storage.path |
SQLite database file | /var/lib/gatus/data.db |
metrics |
Expose Prometheus /metrics |
false |
ui.title |
Browser tab title | Service Status | cloudimg |
endpoints |
The services to monitor | web server + two public examples |
After editing the file, apply changes with sudo systemctl restart gatus.service.
Step 14: Add TLS (Optional)
For production, terminate TLS at nginx. Point a DNS record at the VM, then use the packaged nginx with a certificate from Let's Encrypt:
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>
certbot installs the certificate, rewrites the nginx server block to listen on 443 and sets up automatic renewal.
Step 15: Require a Viewer Password (Optional)
The dashboard is read only, so it is safe to expose without a login. If you would rather keep it private, Gatus supports HTTP basic authentication. Generate a bcrypt hash on the VM (never bake one into an image), base64 encode it, and add a security block to /etc/gatus/config.yaml:
security:
basic:
username: viewer
password-bcrypt-base64: "<base64-of-a-bcrypt-hash-generated-on-this-vm>"
Then restart Gatus. Because the hash is generated per VM and never shipped, no two instances share a viewer credential.
Step 16: Security Recommendations
- Restrict the NSG so ports 80 and 22 only reach trusted networks.
- Terminate TLS at nginx (Step 14) so the dashboard and API travel encrypted.
- Keep
/metricsdisabled unless you have a Prometheus scraper that needs it, and if you enable it, expose it only to that scraper. - Add a viewer password (Step 15) if the endpoint names or URLs you monitor are sensitive.
- Back up
/var/lib/gatus/data.dbto Azure Blob if you need your uptime history to survive a rebuild. - Patch the OS monthly with
sudo apt-get update && sudo apt-get upgrade; unattended security upgrades are already enabled.
Step 17: Support and Licensing
Gatus is licensed under the Apache License 2.0 — no per CPU or per user fee. cloudimg provides commercial support separately.
- Email: support@cloudimg.co.uk
- Website: www.cloudimg.co.uk
- Support hours: 24/7, 24h response SLA
Deploy on Azure
Launch Gatus on Ubuntu 24.04 with 24/7 support from cloudimg.
View on Marketplace
Need Help?
Our support team is available 24/7. support@cloudimg.co.uk