← Back to gatus

How to Deploy & Use gatus

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 requests
  • TCP - TCP connection checks
  • UDP - UDP connection checks
  • ICMP - Ping checks
  • DNS - DNS query validation
  • TLS - TLS certificate validation
  • STARTTLS - STARTTLS protocol checks
  • GRPC - gRPC service checks
  • WEBSOCKET - WebSocket connections
  • SSH - 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.retention period
  • 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