Gatus
Overview
Gatus is an open source health dashboard and status page. You describe the services you want to watch in one YAML file. Each endpoint has a URL (HTTP, HTTPS, TCP, ICMP, DNS, SSH, STARTTLS, WebSocket or gRPC), a check interval and a list of conditions such as [STATUS] == 200, [RESPONSE_TIME] < 300, [BODY].status == UP or [CERTIFICATE_EXPIRATION] > 720h. Gatus runs the checks, keeps the history, and shows a live dashboard with uptime and response-time charts, a JSON API and status badges. It can alert you through Slack, Microsoft Teams, email, PagerDuty, Discord, Telegram, ntfy and many other providers.
The SecureAnyCloud image runs Gatus 5.36.0, compiled by SecureAnyCloud from the official 5.36.0 source with Go 1.27.3 and patched golang.org/x/net, golang.org/x/crypto and gRPC modules. Gatus publishes no release binary of its own, only container images. The 5.36.0 source does not build with the current Go release until gRPC is updated.
The build is reproducible, and its record ships with the image. The base is Ubuntu 24.04 LTS, patched at build time, and unattended security upgrades stay on for your VM.
What you get:
- Gatus 5.36.0 (
gatus.service) running as the unprivilegedgatususer, listening on127.0.0.1:8080only - nginx publishing the dashboard over HTTPS on port 443 with a certificate created on your VM's first boot, behind HTTP Basic Auth with a password unique to your VM; port 80 redirects to HTTPS
- A starter configuration at
/etc/gatus/config.yamlthat monitors this VM only (its HTTPS front end and certificate expiry, Gatus itself, and SSH), so the dashboard is green on first boot. Nothing on the internet is probed until you add it. gatus-set-hostname, a helper to serve the dashboard under your own DNS name- The build record (
BUILD-INFO.txt),go.mod,go.sum, thegovulncheckresults and the Apache 2.0 licence in/usr/share/doc/gatus/ - 24/7 SecureAnyCloud support
Security posture
- Password on everything. Gatus has no login by default, and its own optional login leaves the badge, uptime and history routes open. nginx therefore protects every path (the dashboard, the JSON API, the badges and Gatus' health route) with HTTP Basic Auth for the user
admin. The password is generated on each VM's first boot, stored only as a bcrypt hash in/etc/nginx/.gatus.htpasswd, and written in plain text to/root/gatus-credentials.txt(mode 0600, root only). No password or hash ships in the image. - Fails closed. nginx refuses to start until first boot has created the certificate and the password, so the dashboard is never reachable without a login.
- Loopback only. Gatus listens on
127.0.0.1only. nginx on 443 is the only way in. - HTTPS on first boot. nginx serves the dashboard with a TLS key and self-signed certificate created on your VM (TLS 1.2 and 1.3 only). Port 80 only redirects to HTTPS.
- Fixed host name. The dashboard is served under your VM's public IP address, read from the Azure Instance Metadata Service at first boot (or a name you set), never from the request. Requests for any other host name are dropped, and cross-site form posts and WebSocket connections are refused.
- Real client addresses. nginx passes the connecting address to Gatus and ignores any
X-Forwarded-Forheader a client sends. - No metadata access for the checks. Gatus fetches whatever URLs you configure, so
gatus.serviceandnginx.serviceare blocked from reaching the Azure Instance Metadata Service (169.254.169.254) and the Azure wire server (168.63.129.16). A check pointed at either fails instead of leaking it. Name resolution keeps working through Ubuntu's local resolver. - Least privilege.
gatus.serviceruns with no Linux capabilities, a read-only system (ProtectSystem=strict) except/var/lib/gatus, and its own private/tmp. - No surprise traffic. The starter configuration checks only the VM itself, and the Prometheus
/metricsendpoint is off. - Per-VM identity. SSH host keys and the machine ID are generated fresh on every VM.
Known advisory in a bundled library
govulncheck reports one advisory against the binary, GO-2026-5932: the golang.org/x/crypto/openpgp package is deprecated and described by the Go team as unsafe by design, and it has no fixed version. It is compiled in only because the GitHub library behind Gatus' GitHub-issue alerting provider imports it for signing commits, which Gatus never does. Every call path govulncheck finds reaches it only through package initialisation, and the build fails if that ever changes. Every other finding was fixed by the module updates. The full output ships in /usr/share/doc/gatus/govulncheck-binary.txt and govulncheck-source.txt.
Prerequisites
You need an active Azure subscription, an SSH key, and a virtual network with a subnet.
The recommended VM size is Standard_B2s. Gatus is a single small Go process with an embedded SQLite database. The VM needs outbound access to the services you want to monitor.
Deploy from the Azure Portal
Search the Azure Marketplace for Gatus, choose the plan and create the VM.
In the networking step, attach a network security group. Allow inbound TCP 22 (SSH) from your management address. Allow TCP 443 (the dashboard) and TCP 80 (redirect only) from the people who need the status page.
Deploy from the Azure CLI
RG="gatus-prod"; LOCATION="eastus"; VM_NAME="gatus-01" IMAGE_URN="sac1647283583153:gatus-ubuntu-24-04:default:latest" 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 443 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:gatus-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
--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 StandardConnect and read your login
Connect as the admin user you chose (here azureuser):
ssh azureuser@<vm-ip>First boot finishes within a minute of the VM starting. It reads the VM's public IP address from the Azure Instance Metadata Service, creates the HTTPS certificate, generates the password and starts nginx. Then Gatus starts its checks. Your login is in a root-only file:
sudo cat /root/gatus-credentials.txt# Gatus - generated on first boot by gatus-firstboot.service
# These credentials are unique to this VM. Store them somewhere safe. GATUS_URL=https://20.121.0.141/ GATUS_USERNAME=admin GATUS_PASSWORD=<GATUS_PASSWORD>
#
# Open GATUS_URL in a browser (self-signed certificate minted on this VM's first boot; port 80 # redirects to https) and sign in with the username and password above. The same credentials protect # the JSON API (/api/v1/endpoints/statuses) and the status badges. # Change the name it is served as:
sudo gatus-set-hostname <your-dns-name>
#
# The default endpoints monitor this VM only. Add your own services to /etc/gatus/config.yaml
# (Gatus reloads it automatically). Restrict 80/443 in the network security group to the people who need the page.
# Full deployment guide: https://secureanycloud.com/stacks/gatus/GATUS_URL holds your VM's public IP address and GATUS_PASSWORD your VM's own password.
Confirm the services are running
Check that first boot, Gatus and nginx are active, that Gatus runs as the unprivileged gatus user, and that the open health endpoint answers:
systemctl is-active gatus-firstboot.service gatus.service nginx.service ps -o user= -C gatus test "$(curl -sk https://localhost/healthz)" = ok && echo "healthz ok"active active active gatus healthz oknginx serves /healthz without a login, so you can use it for an Azure Load Balancer or Application Gateway health probe over HTTPS. Everything else needs the password.
List the ports the VM listens on. These are the only ones:
sudo ss -Hltnu | awk '{print $1, $5}' | sort -utcp 0.0.0.0:22 tcp 0.0.0.0:443 tcp 0.0.0.0:80 tcp 127.0.0.1:8080 tcp 127.0.0.53%lo:53 tcp 127.0.0.54:53 tcp [::]:22 tcp [::]:443 tcp [::]:80 udp 10.0.0.10%eth0:68 udp 127.0.0.1:323 udp 127.0.0.53%lo:53 udp 127.0.0.54:53 udp [::1]:323Gatus (8080) listens on loopback only, and nginx publishes it on 443. The loopback port 53 entries are Ubuntu's local stub resolver (systemd-resolved), 323 is chrony's local control socket and 68 is the DHCP client.
The binary is the reproducible SecureAnyCloud build of the 5.36.0 source. Its record ships with the image. Check it:
sha256sum /usr/local/bin/gatus grep -E '^(source|toolchain |binary|govulncheck)' /usr/share/doc/gatus/BUILD-INFO.txt07676fb59df06f69deb9d1c155c21eff7da6d0bb4e32585ed82d06cc7f982a66 /usr/local/bin/gatus source https://github.com/TwiN/gatus/archive/refs/tags/v5.36.0.tar.gz source sha256 b5543af591e602281406049ee2f822a6529a8f14be0cd54df5a31c210520159a (tag commit ed1107b41a30e22047eecfb6dbc3be5e39829d5a) toolchain go1.27.3 linux/amd64, official tarball https://go.dev/dl/go1.27.3.linux-amd64.tar.gz toolchain sha256 65efbc80fdc1fa2cd2631cad5b481777a68e8725f34e89f50fc6ac714e379b40 binary sha256 07676fb59df06f69deb9d1c155c21eff7da6d0bb4e32585ed82d06cc7f982a66 (reproducible) govulncheck v1.9.0 -mode=binary and source mode: only GO-2026-5932 (DB updated: 2026-10-21 00:27:29 +0000 UTC)Sign in to the dashboard
Browse to the GATUS_URL from Step 3, for example https://20.121.0.141/. The certificate is self-signed, so your browser warns once. Accept it, or install your own certificate (Step 9). Without a login, nginx answers 401 and your browser asks for a username and password:
Sign in as admin with the password from Step 3. The Gatus health dashboard lists the three starter endpoints, each with its latest result and a bar per check:
Select an endpoint to open its detail page. It shows the current status, the average and range of response times, the recent checks and a response-time chart:
Port 80 only redirects to the HTTPS address. A request for any host name that is not this VM's is dropped without an answer (000):
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' http://localhost/
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: not-this-vm.example' http://127.0.0.1/ || true301 https://20.121.0.141/ 000You can also check the login from the command line. These requests go to nginx on the VM itself. The API refuses a request with no password or a wrong one. The VM's own password returns the endpoint statuses. The block reads the password from the credentials file and passes it to curl on standard input, never on the command line. It stops with an error if any answer is not the expected one:
H=$(sudo sed -n 's/^set $gatus_host "\(.*\)";$/\1/p' /etc/nginx/gatus-host.conf) AUTH() {
sudo sed -n 's/^GATUS_PASSWORD=\(.*\)$/user = "admin:\1"/p' /root/gatus-credentials.txt; }
U=$(curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}' "https://$H/api/v1/endpoints/statuses")
W=$(printf 'user = "admin:not-the-password"\n' | curl -K - -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}' "https://$H/api/v1/endpoints/statuses")
A=$(AUTH | curl -K - -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}' "https://$H/api/v1/endpoints/statuses")
echo "unauth : $U";
echo "wrongpw : $W";
echo "authed : $A" [ "$U" = 401 ] && [ "$W" = 401 ] && [ "$A" = 200 ]unauth : 401 wrongpw : 401 authed : 200Read the results from the API
The dashboard is built on a JSON API that you can use from scripts. This block lists every endpoint with how many results Gatus holds and whether the latest check passed. It fails unless all three starter endpoints are healthy:
H=$(sudo sed -n 's/^set $gatus_host "\(.*\)";$/\1/p' /etc/nginx/gatus-host.conf) AUTH() {
sudo sed -n 's/^GATUS_PASSWORD=\(.*\)$/user = "admin:\1"/p' /root/gatus-credentials.txt; }
J=$(AUTH | curl -K - -sk --resolve "$H:443:127.0.0.1" "https://$H/api/v1/endpoints/statuses")
echo "$J" | jq -r '.[] | "\(.key) results=\(.results|length) last_success=\(.results[-1].success)"' test "$(echo "$J" | jq -r '[.[] | select(.results[-1].success == true) | .name] | sort | join(",")')" = "gatus,nginx-https,ssh"this-instance_gatus results=5 last_success=true this-instance_nginx-https results=5 last_success=true this-instance_ssh results=5 last_success=trueEach endpoint's key is <group>_<name>. The detail of one check shows each condition and its result:
H=$(sudo sed -n 's/^set $gatus_host "\(.*\)";$/\1/p' /etc/nginx/gatus-host.conf) AUTH() {
sudo sed -n 's/^GATUS_PASSWORD=\(.*\)$/user = "admin:\1"/p' /root/gatus-credentials.txt; } AUTH | curl -K - -sk --resolve "$H:443:127.0.0.1" "https://$H/api/v1/endpoints/this-instance_nginx-https/statuses" \
| jq -e '.results[-1] | {status, success, conditionResults}'{ "status": 200, "success": true, "conditionResults": [ { "condition": "[STATUS] == 200", "success": true }, { "condition": "[BODY] == pat(ok*)", "success": true }, { "condition": "[CERTIFICATE_EXPIRATION] > 720h", "success": true } ] }Status badges live under the same API, for example https://<your-host>/api/v1/endpoints/this-instance_ssh/health/badge.svg, and they also need the password.
Add your own endpoints
The configuration is /etc/gatus/config.yaml. Only root and the gatus service account can read it, because the alerting tokens you add will live there. This is the starter file:
sudo stat -c '%a %U:%G %n' /etc/gatus/config.yaml
sudo grep -vE '^\s*#|^$' /etc/gatus/config.yaml640 root:gatus /etc/gatus/config.yaml storage: type: sqlite path: /var/lib/gatus/data.db web: address: 127.0.0.1 port: 8080 metrics: false ui: title: "Status | Gatus" header: "Service Health" description: "Live health and uptime of the services monitored by this instance." endpoints: - name: nginx-https group: this-instance url: "https://127.0.0.1/healthz" interval: 60s client: insecure: true conditions: - "[STATUS] == 200" - "[BODY] == pat(ok*)" - "[CERTIFICATE_EXPIRATION] > 720h" - name: gatus group: this-instance url: "http://127.0.0.1:8080/health" interval: 60s conditions: - "[STATUS] == 200" - "[BODY].status == UP" - name: ssh group: this-instance url: "tcp://127.0.0.1:22" interval: 60s conditions: - "[CONNECTED] == true"Edit it with sudoedit (or your editor of choice through sudo) and append your services under endpoints:. This example adds a website with a response-time and certificate check, a database port, and a DNS record:
sudoedit /etc/gatus/config.yaml- name: website group: production url: "https://www.example.com/" interval: 60s conditions: - "[STATUS] == 200" - "[RESPONSE_TIME] < 800" - "[CERTIFICATE_EXPIRATION] > 336h" - name: postgres group: production url: "tcp://10.0.1.20:5432" interval: 30s conditions: - "[CONNECTED] == true" - name: dns-www group: production url: "1.1.1.1" dns: query-name: "www.example.com" query-type: "A" conditions: - "[DNS_RCODE] == NOERROR"Gatus checks the file for changes every 30 seconds and reloads it on its own. You do not need to restart it.
If an edit does not parse, Gatus logs the error and exits. systemd keeps restarting it every few seconds, so the dashboard is down until you correct the file. It then comes back by itself. Check the service and the log after each change:
systemctl is-active gatus
sudo journalctl -u gatus -n 20 --no-pager -o catTo be notified when a check fails, add an alerting: block (for example Slack, email or PagerDuty) and an alerts: list on each endpoint. The Gatus alerting documentation has an example for every provider. Keep the file 0640 root:gatus.
The Gatus log shows each check as it runs:
sudo journalctl -u gatus -n 3 --no-pager -o cat | grep -E 'success=(true|false)'2026/10/21 16:08:29 [watchdog.executeEndpoint] Monitored group=this-instance; endpoint=nginx-https; key=this-instance_nginx-https; success=true; errors=0; duration=4ms 2026/10/21 16:08:29 [watchdog.executeEndpoint] Monitored group=this-instance; endpoint=gatus; key=this-instance_gatus; success=true; errors=0; duration=1ms 2026/10/21 16:08:29 [watchdog.executeEndpoint] Monitored group=this-instance; endpoint=ssh; key=this-instance_ssh; success=true; errors=0; duration=0sMonitoring private services
Gatus checks run from this VM, so Gatus can watch services that are not on the internet at all. Examples are databases, internal APIs and load balancers in the same virtual network or in peered networks. Make sure the network security groups of those services allow traffic from this VM.
ICMP (icmp://) checks work too, without giving Gatus any capability. The image allows unprivileged ICMP sockets for the gatus group only (/etc/sysctl.d/60-sac-gatus-ping.conf).
HTTPS certificate and host name
The certificate was created on your VM's first boot for the VM's public IP address, its private IP address and localhost. Only root can read the key and the credentials file. The password hash is readable by root and nginx's group:
sudo openssl x509 -in /etc/ssl/gatus/gatus.crt -noout -subject -dates -ext subjectAltName
sudo stat -c '%a %U:%G %n' /etc/ssl/gatus/gatus.key /etc/ssl/gatus/gatus.crt /etc/nginx/.gatus.htpasswd /root/gatus-credentials.txtsubject=CN = 20.121.0.141, O = sac notBefore=Oct 21 16:07:30 2026 GMT notAfter=Jan 23 16:07:30 2029 GMT X509v3 Subject Alternative Name: IP Address:20.121.0.141, IP Address:10.0.0.10, IP Address:127.0.0.1, DNS:localhost 600 root:root /etc/ssl/gatus/gatus.key 644 root:root /etc/ssl/gatus/gatus.crt 640 root:www-data /etc/nginx/.gatus.htpasswd 600 root:root /root/gatus-credentials.txtTo serve the dashboard under your own DNS name, point the name at this VM and run the helper. The name can be, for example, status.example.com, or the DNS name label of the VM's public IP such as gatus-01.eastus.cloudapp.azure.com. The helper records the name, creates a new self-signed certificate for it, updates nginx and rewrites the URL in the credentials file:
sudo gatus-set-hostname status.example.comIf the VM's public IP address changes (for example a dynamic address after a deallocation), run the helper again so that the certificate names the new address too.
To use a certificate from your own certificate authority, replace /etc/ssl/gatus/gatus.key (keep it 0600 root) and /etc/ssl/gatus/gatus.crt. Then run sudo systemctl reload nginx.
Metadata access is blocked for Gatus
gatus.service and nginx.service carry a systemd IPAddressDeny rule for the Azure Instance Metadata Service and the Azure wire server. No check can reach them, even if an endpoint's URL points at one. First boot, which reads the public IP address, runs outside both services. DNS names still resolve for your checks, because Gatus asks Ubuntu's local resolver (127.0.0.53), which forwards on its own:
systemctl show -p IPAddressDeny gatus.service nginx.serviceIPAddressDeny=169.254.169.254/32 168.63.129.16/32 IPAddressDeny=169.254.169.254/32 168.63.129.16/32A Gatus dns endpoint that names 168.63.129.16 as its server is blocked by the same rule. Use another resolver address in such checks.
Maintenance
- Password: the per-VM password is in
/root/gatus-credentials.txtand its bcrypt hash in/etc/nginx/.gatus.htpasswd. To change it, runsudo htpasswd -B /etc/nginx/.gatus.htpasswd admin, which prompts for the new password. Then runsudo systemctl reload nginxand update the credentials file. To add more viewers, run the same command with a different user name. - A public status page: the image keeps the whole page behind the password. If you want a page anyone can read, decide which paths to open. Add an nginx
locationwithauth_basic off;for them in/etc/nginx/sites-available/sac-gatus, then runsudo nginx -t && sudo systemctl reload nginx. The API and the badges then show your endpoint names and history to anyone. - Keep Gatus on loopback: leave
web.address: 127.0.0.1in the configuration. Gatus has no password of its own, so binding it to a public address would publish your dashboard and API to anyone. - History: results are kept in the SQLite database
/var/lib/gatus/data.db. Back up that file together with/etc/gatus/config.yaml, for example to Azure Blob Storage. Stop Gatus first, or usesqlite3 .backup. - Upgrades: to move to a newer Gatus release, deploy the newer image version when it is published, and copy your
config.yamlacross. - Security patches: unattended-upgrades remains enabled, so the OS keeps receiving security updates.
Security recommendations
- Keep the network security group tight. Open 22 only to your management address, and 80/443 only to the people who need the dashboard.
- Keep alerting tokens in the config file only. Keep its
0640 root:gatuspermissions, and rotate the tokens if the VM is ever shared. - Use your own certificate for the dashboard if other people sign in to it. Browsers then trust it without a warning.
Support and licensing
Gatus is developed by TwiN and contributors and distributed under the Apache License 2.0. This image ships a binary that SecureAnyCloud compiled from the unmodified 5.36.0 source with Go 1.27.3 and updated Go modules. The build record and licence are in /usr/share/doc/gatus/. SecureAnyCloud provides the packaging, the hardening, first-boot HTTPS and per-VM credentials, and 24/7 support.
SecureAnyCloud is not affiliated with or endorsed by the Gatus project. Product names are marks of their owners and are used here only to identify the software.
- Email: sales@secureanycloud.com
- Website: secureanycloud.com
- Support hours: 24/7, with a 24-hour response SLA
Deploy on Azure
Launch Gatus 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
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. Gatus probes them continuously 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 cover HTTP status, response time, response body, DNS answers and TLS certificate expiry across HTTP, TCP, ICMP, DNS and other protocols. The same results are available as a JSON API. Gatus is a single Go binary with an embedded SQLite backend, so it stays lightweight and starts instantly.
The SecureAnyCloud image installs Gatus behind an nginx reverse proxy that binds the server to loopback. 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 default configuration monitors the instance's own web server and a couple of well known public endpoints. The dashboard is populated on first boot, and you can replace the examples with your own services.
What you get:
- Gatus single Go binary (
/usr/local/bin/gatus) - Embedded SQLite history database at
/var/lib/gatus/data.db(no separate database to maintain) gatus.servicerunning as thegatususer, bound to loopback127.0.0.1:8080nginx.servicereverse proxy on TCP 80, TLS readygatus-firstboot.service, which resolves this instance'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 SecureAnyCloud support
Prerequisites
Before you deploy this image, make sure you have:
- 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 and inbound ports 80 and 443 from the networks your users will reach the dashboard on
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Connecting to your instance
Connect over SSH on port 22 as the default login user for the operating system variant you launched. This listing currently ships Ubuntu 24.04 LTS, and the SSH login user is ubuntu.
nginx serves the dashboard on port 80. Gatus itself listens only on 127.0.0.1:8080.
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 Gatus. Select the SecureAnyCloud listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger. Gatus is very light, but m5.large is the tested recommendation. Choose your EC2 key pair under Key pair (login). Under Network settings, select your VPC and subnet. Then 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 block launches an instance from the SecureAnyCloud Gatus Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing and <key-name> with your EC2 key pair name. Replace <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens ports 22, 80 and 443 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--metadata-options "HttpTokens=required,HttpEndpoint=enabled" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=gatus}]'On first boot, the image resolves this instance's public address using the EC2 Instance Metadata Service (IMDSv2), so it works with HttpTokens=required enabled.
Connect via SSH
Connect as the ubuntu user:
ssh ubuntu@<public-ip>As soon as you log in, the message of the day prints the dashboard URL, the status API URL and the key operational commands.
View the per-instance info note
Gatus has no login and no credential to retrieve. For convenience, the first boot service writes a root-only note with the resolved dashboard URL:
sudo cat /root/gatus-info.txtConfirm the services are running
Gatus and nginx start automatically. Confirm that both are active:
systemctl is-active gatus nginxOpen the status dashboard
Browse to http://<public-ip>/ to see the live status page. It refreshes automatically and shows each configured endpoint with its current health, recent checks and average response time.
The dashboard is read-only and has no login, so it is safe to publish as a status page. Still, restrict who can reach it if the endpoint names or URLs are sensitive.
Verify that the dashboard is answering. Run this from the instance itself, through nginx:
for i in $(seq 1 30); do code=$(curl -s -o /dev/null -w '%{http_code}' -m 5 http://127.0.0.1/) [ "$code" = "200" ] && break sleep 2 done echo "dashboard HTTP $code"Each endpoint links to a detail view with its current status, average response time, response-time range, recent check history and a response-time trend chart.
The dashboard also has a built-in dark mode.
Query the JSON status API
The same results are available as JSON. Use the API for scripting and for wiring Gatus into your own tooling:
curl -s http://127.0.0.1/api/v1/endpoints/statuses | jq '[.[] | {name, group, healthy: ([.results[]?|select(.success==true)]|length>0)}]'Edit the monitored endpoints
The whole configuration lives in one declarative YAML file. Add or edit the services you want to watch under endpoints:, then restart Gatus to apply the change. Each endpoint has a url, an interval, and one or more conditions such as [STATUS] == 200, [RESPONSE_TIME] < 300, or [CERTIFICATE_EXPIRATION] > 240h.
sudo nano /etc/gatus/config.yaml
sudo systemctl restart gatusThe default configuration monitors this instance's own web server (an always available local nginx health target) plus two well known public endpoints, including a TLS certificate expiry check. The dashboard is populated the moment the instance boots. Replace those examples with your own services.
Optional viewer password (basic authentication)
The dashboard ships open and read-only by design. To require a viewer password, use Gatus' HTTP basic authentication. Install apache2-utils for the htpasswd tool, generate a bcrypt hash on this instance, and add a security.basic block to the configuration. Never bake a hash into an image, and do not reuse a hash across instances.
# Install the htpasswd tool, then generate a bcrypt hash for your chosen
# password on THIS instance (replace <viewer-password> with your own):
sudo apt-get install -y apache2-utils htpasswd -bnBC 10 "" "<viewer-password>" | tr -d ':\n'Add the resulting hash under a security block in /etc/gatus/config.yaml (see the Gatus documentation for the exact security.basic schema), then restart Gatus with sudo systemctl restart gatus.
Enable HTTPS
For production, terminate TLS at nginx. Point a DNS record at the instance, open port 443, and obtain a certificate with certbot. Replace <your-domain> with your host name.
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>certbot installs and renews the certificate, and it updates the nginx server block automatically.
Maintenance
- Service management:
systemctl status gatus nginx,sudo systemctl restart gatusafter a config change. - Logs:
journalctl -u gatus -n 100 --no-pagerfor the monitor,journalctl -u nginxfor the proxy. - History database: the SQLite history lives at
/var/lib/gatus/data.db. It is captured empty in the image and grows on your instance as checks run. It needs no separate maintenance. - Patching: the base ships with unattended security upgrades enabled. Reboot after kernel updates, during a maintenance window.
Support
SecureAnyCloud provides 24/7 technical support for this image via email at sales@secureanycloud.com and live chat. We help with deployment, upgrades, authoring and tuning the YAML endpoint configuration, enabling an optional viewer password, TLS termination and troubleshooting.
Deploy on AWS
Launch Gatus on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com