Self-Hosting Cachet with Docker Compose

What Is Cachet?

Cachet is a self-hosted status page system for communicating service availability to your users. It provides a public dashboard showing component status, scheduled maintenance windows, and incident history with subscriber notifications. Think StatusPage.io or Atlassian Statuspage, but running on your own infrastructure with no monthly fees. Used by teams who need to communicate downtime professionally without paying $29-$99/month for a SaaS status page.

Official site: cachethq.io | GitHub

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 1 GB of free disk space
  • 512 MB of RAM minimum
  • A domain name (recommended — status pages need a public URL)

Docker Compose Configuration

services:
  cachet:
    image: cachethq/docker:2.3.18
    container_name: cachet
    restart: unless-stopped
    ports:
      - "8000:8000"
    environment:
      - APP_KEY=base64:changeme_generate_with_artisan
      - APP_ENV=production
      - APP_DEBUG=false
      - APP_URL=http://localhost:8000
      - DB_DRIVER=pgsql
      - DB_HOST=cachet-db
      - DB_PORT=5432
      - DB_DATABASE=cachet
      - DB_USERNAME=cachet
      - DB_PASSWORD=changeme_db
      - DB_PREFIX=chq_
      - CACHE_DRIVER=redis
      - SESSION_DRIVER=redis
      - QUEUE_DRIVER=redis
      - REDIS_HOST=cachet-redis
      - REDIS_PORT=6379
      - MAIL_DRIVER=smtp
      - MAIL_HOST=smtp.example.com
      - MAIL_PORT=587
      - MAIL_USERNAME=null
      - MAIL_PASSWORD=null
      - [email protected]
      - MAIL_NAME="Status Page"
      - MAIL_ENCRYPTION=tls
    depends_on:
      - cachet-db
      - cachet-redis
    networks:
      - cachet-net

  cachet-db:
    image: postgres:16-alpine
    container_name: cachet-db
    restart: unless-stopped
    environment:
      - POSTGRES_USER=cachet
      - POSTGRES_PASSWORD=changeme_db
      - POSTGRES_DB=cachet
    volumes:
      - cachet-pgdata:/var/lib/postgresql/data
    networks:
      - cachet-net

  cachet-redis:
    image: redis:7-alpine
    container_name: cachet-redis
    restart: unless-stopped
    volumes:
      - cachet-redis:/data
    networks:
      - cachet-net

volumes:
  cachet-pgdata:
  cachet-redis:

networks:
  cachet-net:

Generate the APP_KEY before starting:

docker compose run --rm cachet php artisan key:generate --show

Copy the output and set it as APP_KEY in the Compose file.

Start the stack:

docker compose up -d

Run the database migrations:

docker compose exec cachet php artisan cachet:install

Initial Setup

Open http://your-server-ip:8000/setup in your browser. The setup wizard walks you through:

  1. Environment setup — verify database and cache connections
  2. Status page setup — name, domain, timezone, language
  3. Admin account — create your administrator login
  4. Done — status page is live

Managing Your Status Page

Components

Components represent individual services you want to track (Website, API, Database, Email, etc.):

  1. Go to Dashboard → Components → Add Component
  2. Set a name, description, status, and optional link
  3. Group components into Component Groups for organization

Status levels: Operational, Performance Issues, Partial Outage, Major Outage.

Incidents

When something breaks:

  1. Dashboard → Incidents → Report Incident
  2. Set the incident name, message, status, and affected components
  3. Choose visibility (public or internal)
  4. Post updates as the situation evolves

Incident statuses: Investigating, Identified, Watching, Fixed.

Scheduled Maintenance

Communicate planned downtime:

  1. Dashboard → Incidents → Schedule Maintenance
  2. Set the maintenance window, affected components, and message
  3. Subscribers are notified before and after the window

Subscriber Notifications

Users can subscribe to status updates via email. Enable this in Settings → App Setup. When incidents are created or updated, subscribers receive email notifications.

Configuration

SettingEnvironment VariableDescription
App URLAPP_URLPublic URL for the status page
DatabaseDB_DRIVERpgsql, mysql, or sqlite
CacheCACHE_DRIVERredis, file, or database
QueueQUEUE_DRIVERredis, sync, or database
MailMAIL_DRIVERsmtp, sendmail, or log
BeaconCACHET_BEACONAnonymous usage stats (set false to disable)

API Access

Cachet provides a full REST API for automation:

# Get component status
curl -s http://localhost:8000/api/v1/components | jq

# Report an incident via API
curl -X POST http://localhost:8000/api/v1/incidents \
  -H "X-Cachet-Token: your-api-token" \
  -d "name=Service Disruption" \
  -d "message=Investigating elevated error rates" \
  -d "status=1" \
  -d "component_id=1" \
  -d "component_status=3"

API tokens are generated in Dashboard → Team → API Tokens.

Reverse Proxy

Set APP_URL to your public domain:

APP_URL=https://status.example.com

For proxy configuration, see Reverse Proxy Setup.

Backup

Back up the PostgreSQL database:

docker compose exec cachet-db pg_dump -U cachet cachet > cachet-backup-$(date +%Y%m%d).sql

For a full backup strategy, see Backup Strategy.

Troubleshooting

”500 Server Error” After Setup

Symptom: Status page shows a 500 error after completing the setup wizard.

Fix: Verify APP_KEY is set correctly. Run migrations again:

docker compose exec cachet php artisan migrate --force

Emails Not Sending

Symptom: Subscriber notifications and incident emails don’t arrive.

Fix: Check SMTP settings. Test with:

docker compose exec cachet php artisan tinker --execute="Mail::raw('test', function(\$m) { \$m->to('[email protected]')->subject('Test'); });"

Redis Connection Refused

Symptom: “Connection refused” errors in the logs.

Fix: Ensure the Redis container is running and the REDIS_HOST matches the container name in the Compose file.

Resource Requirements

  • RAM: ~150 MB (PHP-FPM + PostgreSQL + Redis)
  • CPU: Low — status pages have minimal traffic
  • Disk: ~200 MB for application, database grows slowly

Verdict

Cachet is the most established self-hosted status page with a solid feature set — components, incidents, maintenance windows, and subscriber notifications cover the essentials. The main concern is maintenance velocity — the v3 rewrite has been in progress for a while. For a simpler, more actively maintained alternative, Gatus offers monitoring + status page in one tool with better alerting. Uptime Kuma is better if you need monitoring with a status page as a secondary feature. Cachet wins when you need a dedicated, professional-looking incident communication platform.