Status pages communicate system health and incident information to users and stakeholders. While SaaS options like Statuspage.io exist, self-hosted solutions give you full control and eliminate subscription costs. This guide covers deploying Cachet and alternative self-hosted status page solutions.
Cachet Installation (Docker)
# docker-compose.yml
services:
cachet:
image: cachethq/docker:latest
ports:
- "8000:8000"
environment:
- DB_DRIVER=pgsql
- DB_HOST=postgres
- DB_DATABASE=cachet
- DB_USERNAME=cachet
- DB_PASSWORD=CachetDBPass!
- APP_KEY=base64:your_app_key
- APP_URL=https://status.example.com
- MAIL_DRIVER=smtp
- MAIL_HOST=smtp.example.com
- MAIL_PORT=587
- MAIL_USERNAME=status@example.com
- MAIL_PASSWORD=MailPass
- MAIL_ADDRESS=status@example.com
depends_on:
- postgres
postgres:
image: postgres:16
environment:
- POSTGRES_DB=cachet
- POSTGRES_USER=cachet
- POSTGRES_PASSWORD=CachetDBPass!
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Alternative: Gatus as a Status Page
# Gatus doubles as both monitoring and status page
# config.yaml
ui:
title: "Service Status"
description: "Current status of our services"
endpoints:
- name: Website
group: core
url: "https://example.com"
interval: 30s
conditions:
- "[STATUS] == 200"
- "[RESPONSE_TIME] < 1000"
- name: API
group: core
url: "https://api.example.com/health"
interval: 30s
conditions:
- "[STATUS] == 200"
Alternative: Upptime (GitHub-Based)
# Upptime uses GitHub Actions for monitoring and GitHub Pages for the status page
# No server required — fully GitHub-hosted
# 1. Use the Upptime template: github.com/upptime/upptime
# 2. Configure .upptimerc.yml:
sites:
- name: Website
url: https://example.com
- name: API
url: https://api.example.com/health
status-website:
cname: status.example.com
name: "Service Status"
Configuring Components
# In Cachet, create components representing your services:
# Dashboard → Components → Create Component
# Example components:
# - Website (Group: Core Services)
# - API (Group: Core Services)
# - Database (Group: Infrastructure)
# - Email (Group: Communication)
# - CDN (Group: Infrastructure)
# Component statuses:
# 1 = Operational (green)
# 2 = Performance Issues (yellow)
# 3 = Partial Outage (orange)
# 4 = Major Outage (red)
Creating Incidents
# Via API
curl -X POST https://status.example.com/api/v1/incidents \
-H "X-Cachet-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"name": "API Performance Degradation",
"message": "We are investigating reports of slow API response times.",
"status": 1,
"component_id": 2,
"component_status": 2,
"notify": true
}'
# Incident statuses:
# 1 = Investigating
# 2 = Identified
# 3 = Watching
# 4 = Fixed
Automated Status Updates
#!/bin/bash
# /usr/local/bin/update-status.sh
# Automatically update Cachet based on health checks
API_TOKEN="your-cachet-api-token"
STATUS_URL="https://status.example.com/api/v1/components"
check_service() {
local url=$1
local component_id=$2
local status
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 10 "$url")
if [ "$HTTP_CODE" = "200" ]; then
status=1 # Operational
else
status=4 # Major Outage
fi
curl -s -X PUT "$STATUS_URL/$component_id" \
-H "X-Cachet-Token: $API_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"status\": $status}"
}
check_service "https://example.com" 1
check_service "https://api.example.com/health" 2
Subscriber Notifications
Cachet supports email notifications for status updates:
- Users can subscribe on the status page
- Incident creation and updates trigger email notifications
- Component status changes notify subscribers
Best Practices
- Keep the status page simple — show only customer-facing services
- Update incident status promptly — users check status pages during outages
- Use scheduled maintenance to inform users of planned downtime
- Automate component status updates with health checks
- Host the status page on separate infrastructure from your main services
- Provide an email subscription option for proactive notifications