Gatus Service Monitoring: Deploy a Developer-Focused Status Page in Docker
Step-by-step tutorial to setting up Gatus using Docker Compose. Monitor your service health, response times, and configure alerts via Discord or Telegram.
Core Architecture and Prerequisites
Before deploying Gatus, ensure you have: * A VPS running a Linux distribution (e.g., Ubuntu 22.04 LTS/24.04 LTS). * Docker Engine (v20.10+) and Docker Compose (v2.0+) installed. * A domain name pointing to your VPS IP address (optional but recommended for SSL setup).
Gatus runs as a single binary inside a lightweight Alpine-based container. In a standard self-hosted environment, you will deploy: 1. Gatus: The core monitoring engine. 2. Reverse Proxy (Caddy/Nginx): To handle SSL termination (HTTPS). 3. Database (Optional): Gatus uses SQLite for persistent metrics.
The Docker Compose Configuration
Create a dedicated directory for your Gatus deployment and create a docker-compose.yml file:
version: '3.8'
services:
gatus:
image: twinproduction/gatus:latest
container_name: gatus
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./config:/config
- ./data:/data
environment:
- TZ=UTC
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
Ensure the configuration directory exists and set correct permissions:
mkdir -p config data
touch config/config.yaml
Configuring Gatus (config.yaml)
Gatus configuration uses a single YAML file. The configuration is divided into three primary blocks: 1. Web Server: Port, path, security, and UI customisation. 2. Alerting: Integrations for notifications. 3. Endpoints: The health checks themselves.
Below is a production-ready config.yaml using SQLite for persistence:
storage:
type: sqlite
path: /data/data.db
web:
port: 8080
ui:
title: "System Status"
header: "Service Health Dashboard"
buttons:
- name: "Homepage"
link: "https://example.com"
# Global alerting defaults
alerting:
telegram:
token: "${TELEGRAM_BOT_TOKEN}"
id: "${TELEGRAM_CHAT_ID}"
default-alert:
enabled: true
failure-threshold: 3
success-threshold: 2
send-on-resolved: true
discord:
webhook-url: "${DISCORD_WEBHOOK_URL}"
default-alert:
enabled: true
failure-threshold: 3
success-threshold: 2
send-on-resolved: true
# Monitoring target definitions
endpoints:
- name: API Gateway
group: Core Services
url: https://api.example.com/health
interval: 30s
conditions:
- "[STATUS] == 200"
- "[RESPONSE_TIME] < 500"
- "[BODY].status == up"
alerts:
- type: telegram
send-on-resolved: true
- name: Public Website
group: Websites
url: https://example.com
interval: 60s
conditions:
- "[STATUS] == 200"
- "[RESPONSE_TIME] < 1000"
alerts:
- type: discord
- name: Database Port (TCP)
group: Infrastructure
url: tcp://db.example.com:5432
interval: 30s
conditions:
- "[CONNECTED] == true"
- name: DNS Resolution Check
group: Infrastructure
url: dns://8.8.8.8:53/google.com?type=A
interval: 60s
conditions:
- "[DNS_RCODE] == NOERROR"
Detailed Endpoint Checking Syntax
Gatus supports a rich query language for validation checks. Here are standard patterns for different protocols.
1. HTTP/HTTPS Checks
Evaluate status codes, response latency, certificates, and JSON payload values:
endpoints:
- name: Secure Endpoint Check
url: https://api.example.com/v1/users
method: POST
body: '{"username": "gatus-monitor"}'
headers:
Content-Type: application/json
Authorization: Bearer my-secure-token
conditions:
- "[STATUS] == 201"
- "[RESPONSE_TIME] < 800"
- "[CERTIFICATE_EXPIRATION] > 48h"
- "[BODY].id != null"
2. TCP Port Checks
Verify that infrastructure daemons (e.g., SSH, PostgreSQL, Redis) are listening:
endpoints:
- name: SSH Server
url: tcp://10.0.0.5:22
interval: 10s
conditions:
- "[CONNECTED] == true"
3. DNS Verification
Query a name server and validate response records:
endpoints:
- name: Primary DNS Resolver
url: dns://1.1.1.1:53/example.com?type=A
interval: 30s
conditions:
- "[DNS_RCODE] == NOERROR"
- "[DNS_IP] == 93.184.216.34"
4. ICMP Ping Checks
Simple network accessibility tests:
endpoints:
- name: Router Gateway
url: icmp://192.168.1.1
interval: 15s
conditions:
- "[CONNECTED] == true"
- "[RESPONSE_TIME] < 50"
Configuring Notification Alerting
Integrate Gatus with Telegram and Discord to receive real-time notifications on failures and resolutions.
Telegram Alert Setup
- Message
@BotFatheron Telegram to create a new bot and retrieve the Bot Token. - Start a chat with your bot, then retrieve the Chat ID by querying updates:
bash curl -s https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates | jq . - Update
config.yaml:yaml alerting: telegram: token: "123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ" id: "987654321"
Discord Alert Setup
- In your Discord server, open Server Settings > Integrations > Webhooks.
- Click New Webhook, select the target channel, and copy the webhook URL.
- Update
config.yaml:yaml alerting: discord: webhook-url: "https://discord.com/api/webhooks/..."
Reverse Proxy configuration (Optional SSL Deployment)
To access your status page securely over HTTPS, configure Caddy as a reverse proxy in your docker-compose.yml:
version: '3.8'
services:
gatus:
image: twinproduction/gatus:latest
container_name: gatus
restart: unless-stopped
volumes:
- ./config:/config
- ./data:/data
environment:
- TZ=UTC
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- gatus
volumes:
caddy_data:
caddy_config:
Create a Caddyfile in the same directory:
status.yourdomain.com {
reverse_proxy gatus:8080
}
Run docker compose up -d to launch the stack with automatic SSL configuration.
Operational Validation and Maintenance
Checking Deployment Status
Verify container runtime health and check standard logs for initialization errors:
docker compose ps
docker compose logs gatus
Hot-Reloading Configuration
Gatus supports hot-reloading configurations without stopping the container. Trigger a reload by sending a SIGHUP signal to the process:
docker kill --signal=HUP gatus
Alternatively, if using the HTTP management server, execute:
curl -X POST http://localhost:8080/api/v1/config/reload