Gatus Deployment and Usage Guide
1. Prerequisites
Required:
- Go 1.21+ - For building from source (optional)
- Docker - For containerized deployment (recommended)
- Kubernetes CLI (kubectl) - For Kubernetes deployment (optional)
- Helm - For Helm chart deployment (optional)
Optional for production:
- Persistent storage - For data persistence across restarts
- Reverse proxy (nginx, Traefik, etc.) - For TLS termination and load balancing
- Alerting service accounts - Slack, Discord, PagerDuty, etc. for alert integrations
2. Installation
Docker (Quick Start)
# Using GitHub Container Registry
docker run -p 8080:8080 --name gatus ghcr.io/twin/gatus:stable
# Using Docker Hub
docker run -p 8080:8080 --name gatus twinproduction/gatus:stable
From Source
# Clone the repository
git clone https://github.com/TwiN/gatus.git
cd gatus
# Build the binary
go build -o gatus .
# Or install globally
go install github.com/TwiN/gatus/v5@latest
Helm (Kubernetes)
# Add the Helm repository
helm repo add twin https://twin.github.io/helm-charts
helm repo update
# Install Gatus
helm install gatus twin/gatus
3. Configuration
Configuration File
Create config/config.yaml (or config/config.yml):
# Basic configuration
web:
address: "0.0.0.0:8080"
ui:
title: "Service Status"
logo-url: "https://example.com/logo.png"
logo-height: "40px"
logo-width: "40px"
favicon-url: "https://example.com/favicon.ico"
link: "https://example.com"
auto-refresh: true
hide-sections:
- "endpoint.url"
- "endpoint.interval"
- "endpoint.conditions"
security:
basic:
username: "admin"
password: "$2a$10$..." # bcrypt hash
oidc:
provider-url: "https://accounts.google.com"
client-id: "your-client-id"
client-secret: "your-client-secret"
redirect-url: "http://localhost:8080/auth/callback"
scopes:
- "openid"
- "profile"
- "email"
# Storage configuration (defaults to in-memory)
storage:
type: "sqlite" # or "postgres", "mysql"
path: "./data/gatus.db" # for sqlite
# For PostgreSQL/MySQL:
# host: "localhost"
# port: 5432
# username: "gatus"
# password: "password"
# database: "gatus"
# tls:
# skip-verify: false
# ca-cert: "/path/to/ca.crt"
# client-cert: "/path/to/client.crt"
# client-key: "/path/to/client.key"
retention: 8760h # 1 year
# Endpoint monitoring
endpoints:
- name: "Example API"
group: "APIs"
url: "https://api.example.com/health"
interval: 30s
conditions:
- "[STATUS] == 200"
- "[BODY].status == UP"
- "[RESPONSE_TIME] < 300"
alerts:
- type: "slack"
enabled: true
failure-threshold: 3
success-threshold: 2
send-on-resolved: true
description: "Health check failed for Example API"
slack:
webhook-url: "https://hooks.slack.com/services/..."
- name: "Database"
group: "Infrastructure"
url: "tcp://database.example.com:5432"
interval: 1m
conditions:
- "[CONNECTED] == true"
alerts:
- type: "pagerduty"
enabled: true
pagerduty:
integration-key: "your-integration-key"
# Alerting providers (global configuration)
alerting:
slack:
webhook-url: "https://hooks.slack.com/services/..."
default-alert: true
discord:
webhook-url: "https://discord.com/api/webhooks/..."
email:
from: "alerts@example.com"
to: "team@example.com"
smtp:
host: "smtp.example.com"
port: 587
username: "user"
password: "password"
tls:
skip-verify: false
ca-cert: "/path/to/ca.crt"
client-cert: "/path/to/client.crt"
client-key: "/path/to/client.key"
Environment Variables
# Configuration path (default: config/config.yaml)
export GATUS_CONFIG_PATH="/path/to/config.yaml"
# Security
export GATUS_SECURITY_BASIC_USERNAME="admin"
export GATUS_SECURITY_BASIC_PASSWORD="password" # Plain text, will be hashed
# Database
export GATUS_STORAGE_TYPE="postgres"
export GATUS_STORAGE_HOST="localhost"
export GATUS_STORAGE_PORT="5432"
export GATUS_STORAGE_USERNAME="gatus"
export GATUS_STORAGE_PASSWORD="secret"
# Web server
export GATUS_WEB_ADDRESS=":8080"
export GATUS_WEB_TLS_CERTIFICATE_FILE="/path/to/cert.pem"
export GATUS_WEB_TLS_KEY_FILE="/path/to/key.pem"
Supported Endpoint Types
HTTP- HTTP/HTTPS requestsTCP- TCP connection checksUDP- UDP connection checksICMP- Ping checksDNS- DNS query validationTLS- TLS certificate validationSTARTTLS- STARTTLS protocol checksGRPC- gRPC service checksWEBSOCKET- WebSocket connectionsSSH- SSH connection checks
Condition Examples
conditions:
# Status code checks
- "[STATUS] == 200"
- "[STATUS] < 300"
# Response time checks
- "[RESPONSE_TIME] < 500"
- "[RESPONSE_TIME] < [MAX_RESPONSE_TIME]"
# Body content checks
- "[BODY] == expected-value"
- "[BODY].status == UP"
- "[BODY].users[0].name == John"
# Certificate checks
- "[CERTIFICATE_EXPIRATION] > 72h"
# DNS checks
- "[DNS_RCODE] == NOERROR"
- "[BODY] == 8.8.8.8"
# Connection checks
- "[CONNECTED] == true"
- "[IP] == 192.168.1.1"
4. Build & Run
Local Development
# Clone and setup
git clone https://github.com/TwiN/gatus.git
cd gatus
# Create configuration
mkdir -p config
cat > config/config.yaml << 'EOF'
web:
address: "localhost:8080"
endpoints:
- name: "Local Test"
url: "http://localhost:8080/health"
interval: 10s
conditions:
- "[STATUS] == 200"
EOF
# Run with hot reload (using air)
go install github.com/cosmtrek/air@latest
air
# Or run directly
go run main.go
Production Build
# Build static binary
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o gatus .
# Build with Docker
docker build -t gatus:latest .
# Multi-architecture build
docker buildx build --platform linux/amd64,linux/arm64 -t your-registry/gatus:latest --push .
Running with Docker Compose
# docker-compose.yml
version: '3.8'
services:
gatus:
image: ghcr.io/twin/gatus:stable
ports:
- "8080:8080"
volumes:
- ./config:/config
- ./data:/data
environment:
- GATUS_CONFIG_PATH=/config/config.yaml
restart: unless-stopped
5. Deployment
Docker Deployment
# Basic deployment with mounted config
docker run -d \
--name gatus \
-p 8080:8080 \
-v $(pwd)/config:/config \
-v $(pwd)/data:/data \
-e GATUS_CONFIG_PATH=/config/config.yaml \
--restart unless-stopped \
ghcr.io/twin/gatus:stable
Kubernetes Deployment
# gatus-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gatus
spec:
replicas: 1
selector:
matchLabels:
app: gatus
template:
metadata:
labels:
app: gatus
spec:
containers:
- name: gatus
image: ghcr.io/twin/gatus:stable
ports:
- containerPort: 8080
volumeMounts:
- name: config
mountPath: /config
- name: data
mountPath: /data
env:
- name: GATUS_CONFIG_PATH
value: /config/config.yaml
volumes:
- name: config
configMap:
name: gatus-config
- name: data
persistentVolumeClaim:
claimName: gatus-data
---
apiVersion: v1
kind: ConfigMap
metadata:
name: gatus-config
data:
config.yaml: |
web:
address: ":8080"
endpoints:
- name: "Kubernetes API"
url: "https://kubernetes.default.svc.cluster.local"
interval: 30s
conditions:
- "[STATUS] == 200"
Helm Deployment
# Custom values file (values.yaml)
web:
address: ":8080"
ui:
title: "Production Status"
storage:
type: "postgres"
host: "postgres-service"
port: 5432
username: "gatus"
password: "changeme"
endpoints:
- name: "Production API"
url: "https://api.production.com/health"
interval: 30s
conditions:
- "[STATUS] == 200"
# Install with custom values
helm install gatus twin/gatus -f values.yaml
Cloud Platforms
- AWS ECS/EKS: Use Docker image with Fargate or EC2
- Google Cloud Run: Stateless deployment with Cloud SQL
- Azure Container Instances: Quick deployment with persistent volumes
- DigitalOcean App Platform: Managed app deployment
- Fly.io: Edge deployment with global regions
Reverse Proxy Setup (nginx)
# nginx.conf
server {
listen 80;
server_name status.example.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# For WebSocket support
location /ws {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
}
6. Troubleshooting
Common Issues
1. Configuration File Not Found
Error: configuration file not found
Solution:
# Set correct config path
export GATUS_CONFIG_PATH="/path/to/config.yaml"
# Or mount config directory
docker run -v $(pwd)/config:/config ...
2. Permission Denied for Storage
Error: unable to open database file: permission denied
Solution:
# Set correct permissions
chown -R 1000:1000 ./data # Docker user UID
# Or run with correct user
docker run -u $(id -u):$(id -g) ...
3. Alerting Not Working
# Check logs for alert errors
docker logs gatus
Solution:
- Verify alert provider configuration
- Check network connectivity to alert service
- Validate API keys/webhook URLs
- Enable debug logging:
export GATUS_LOG_LEVEL=debug
4. High Memory Usage
# Monitor memory usage
docker stats gatus
Solution:
- Reduce
storage.retentionperiod - Increase monitoring interval
- Limit number of endpoints
- Use external database instead of in-memory
5. TLS Certificate Errors
Error: x509: certificate signed by unknown authority
Solution:
client:
tls:
skip-verify: true # Not recommended for production
# OR specify custom CA
ca-cert: "/path/to/ca.crt"
6. DNS Resolution Issues
Error: dial tcp: lookup hostname: no such host
Solution:
# Specify DNS servers
client:
dns:
- "8.8.8.8"
- "1.1.1.1"
7. Web UI Not Loading
# Check if service is running
curl http://localhost:8080/health
Solution:
- Verify port binding:
netstat -tulpn | grep 8080 - Check firewall rules
- Ensure no other service is using port 8080
8. Condition Evaluation Failures
# Enable condition debugging
export GATUS_LOG_LEVEL=debug
Solution:
- Check condition syntax
- Verify response format matches condition expectations
- Use
[BODY]placeholder for raw body inspection - Test conditions individually
Debug Mode
# Run with debug logging
docker run -e GATUS_LOG_LEVEL=debug ...
# Or from source
go run main.go --log-level debug
# Check detailed metrics
curl http://localhost:8080/metrics
Health Check Endpoint
# Verify Gatus is running
curl http://localhost:8080/health
# Get version info
curl http://localhost:8080/api/v1/info
Logging Configuration
# config.yaml
log:
level: "info" # debug, info, warn, error
file: "/var/log/gatus.log"
max-size: 100 # MB
max-backups: 3
max-age: 28 # days