Skip to main content

Daily Operations

Monitoring Container Health

Regularly check that all services are running:
# Check container status
docker compose ps

# Expected output: All services should be "Up" or "healthy"
docker compose logs plausible --tail=100 --follow
Watch for:
  • Application startup messages
  • Error logs
  • Request timeouts
  • Database connection issues

Health Check Endpoints

Plausible provides health check endpoints:
# Liveness probe - is the application running?
curl http://localhost:8000/api/system/health/live

# Readiness probe - is the application ready to serve traffic?
curl http://localhost:8000/api/system/health/ready

# Legacy health check (soft-deprecated)
curl http://localhost:8000/api/health
Use /api/system/health/live and /api/system/health/ready for Kubernetes probes and load balancers.

Backup Strategy

PostgreSQL Backups

1

Manual Backup

Create a full database dump:
docker compose exec plausible_db pg_dump -U postgres plausible_db > backup_$(date +%Y%m%d_%H%M%S).sql
2

Compressed Backup

For large databases:
docker compose exec plausible_db pg_dump -U postgres plausible_db | gzip > backup_$(date +%Y%m%d_%H%M%S).sql.gz
3

Automated Backups

Add a cron job:
# Edit crontab
crontab -e

# Add daily backup at 2 AM
0 2 * * * cd /path/to/community-edition && docker compose exec -T plausible_db pg_dump -U postgres plausible_db | gzip > /backups/postgres/backup_$(date +\%Y\%m\%d).sql.gz

ClickHouse Backups

ClickHouse data is the largest component:
# Create backup using ClickHouse's native backup system
docker compose exec plausible_events_db clickhouse-client --query \
  "BACKUP DATABASE plausible_events_db TO Disk('backups', 'backup_$(date +%Y%m%d).zip')"
ClickHouse backups can be very large. Ensure you have sufficient disk space and consider backup retention policies.

Restore Procedures

# Stop services
docker compose down

# Start only PostgreSQL
docker compose up -d plausible_db

# Wait for database to be ready
sleep 5

# Drop and recreate database
docker compose exec plausible_db psql -U postgres -c "DROP DATABASE IF EXISTS plausible_db;"
docker compose exec plausible_db psql -U postgres -c "CREATE DATABASE plausible_db;"

# Restore from backup
gunzip -c backup_20240115.sql.gz | docker compose exec -T plausible_db psql -U postgres plausible_db

# Start all services
docker compose up -d

Database Maintenance

PostgreSQL Maintenance

Reclaim storage and update statistics:
# Regular vacuum (doesn't lock tables)
docker compose exec plausible_db psql -U postgres plausible_db -c "VACUUM ANALYZE;"

# Full vacuum (locks tables, schedule during low traffic)
docker compose exec plausible_db psql -U postgres plausible_db -c "VACUUM FULL ANALYZE;"
Schedule monthly with cron:
0 3 1 * * cd /path/to/community-edition && docker compose exec -T plausible_db psql -U postgres plausible_db -c "VACUUM ANALYZE;"
docker compose exec plausible_db psql -U postgres plausible_db -c \
  "SELECT pg_size_pretty(pg_database_size('plausible_db'));"
docker compose exec plausible_db psql -U postgres -c \
  "SELECT count(*) FROM pg_stat_activity;"

ClickHouse Maintenance

Manually trigger merges for better performance:
# Optimize events table
docker compose exec plausible_events_db clickhouse-client --query \
  "OPTIMIZE TABLE plausible_events_db.events_v2 FINAL"

# Optimize sessions table
docker compose exec plausible_events_db clickhouse-client --query \
  "OPTIMIZE TABLE plausible_events_db.sessions_v2 FINAL"
OPTIMIZE FINAL can be resource-intensive. Run during low-traffic periods.
docker compose exec plausible_events_db clickhouse-client --query \
  "SELECT table, formatReadableSize(sum(bytes)) as size FROM system.parts WHERE database = 'plausible_events_db' AND active GROUP BY table ORDER BY sum(bytes) DESC"
docker compose exec plausible_events_db clickhouse-client --query \
  "SELECT * FROM system.merges"
For data retention (e.g., keep only 2 years):
# List partitions
docker compose exec plausible_events_db clickhouse-client --query \
  "SELECT partition, table FROM system.parts WHERE database = 'plausible_events_db' GROUP BY partition, table ORDER BY partition"

# Drop specific partition (CAUTION: This deletes data!)
docker compose exec plausible_events_db clickhouse-client --query \
  "ALTER TABLE plausible_events_db.events_v2 DROP PARTITION '202201'"
Dropping partitions permanently deletes data. Always backup first!

Log Management

View Logs

# All services
docker compose logs --tail=100 --follow

# Specific service
docker compose logs plausible --tail=100 --follow

# Since specific time
docker compose logs --since="2024-01-15T10:00:00" plausible

# Filter by pattern
docker compose logs plausible | grep ERROR

Log Rotation

Configure Docker logging driver in docker-compose.yml:
services:
  plausible:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

Export Logs

# Export to file
docker compose logs --no-color > plausible_logs_$(date +%Y%m%d).log

# Export with timestamps
docker compose logs --timestamps --no-color > plausible_logs_$(date +%Y%m%d).log

Performance Monitoring

Resource Usage

# Real-time resource monitoring
docker stats

# Specific container
docker stats community-edition-plausible-1

Query Performance

# Slow queries
docker compose exec plausible_db psql -U postgres plausible_db -c \
  "SELECT query, calls, mean_exec_time FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 10;"

Cleanup and Optimization

Docker Cleanup

# Remove unused images
docker image prune -a

# Remove unused volumes (CAUTION: Can delete data!)
docker volume prune

# Remove all unused data
docker system prune -a --volumes
docker volume prune will delete all unused volumes, including database volumes if containers are stopped. Always verify volumes before pruning.

Clean Old Data

1

Session Cleanup

Plausible automatically cleans old user sessions every 2 hours via cron jobs.
2

Invitation Cleanup

Old invitations are cleaned daily at 1 AM.
3

Analytics Data

Manually archive or delete old analytics data:
# Export old data before deletion
docker compose exec plausible_events_db clickhouse-client --query \
  "SELECT * FROM plausible_events_db.events_v2 WHERE timestamp < '2022-01-01' FORMAT Native" > old_events.native

# Delete old data
docker compose exec plausible_events_db clickhouse-client --query \
  "ALTER TABLE plausible_events_db.events_v2 DELETE WHERE timestamp < '2022-01-01'"

Security Maintenance

Update Docker Images

Regularly update base images for security patches:
# Pull latest images
docker compose pull

# Recreate containers
docker compose up -d

Review Access Logs

# Check for suspicious activity
docker compose logs plausible | grep "401\|403\|404"

# Failed login attempts (if LOG_FAILED_LOGIN_ATTEMPTS=true)
docker compose logs plausible | grep "Failed login"

Rotate Secrets

Rotating SECRET_KEY_BASE will invalidate all user sessions. Plan accordingly.
1

Generate New Secret

openssl rand -base64 64
2

Update Configuration

Edit plausible-conf.env with the new secret
3

Restart Services

docker compose down
docker compose up -d
4

Notify Users

All users will need to log in again

Troubleshooting

Symptoms: Containers consuming excessive RAMSolutions:
  1. Check ClickHouse memory settings
  2. Reduce CLICKHOUSE_INGEST_POOL_SIZE
  3. Optimize queries
  4. Add more RAM or enable swap
  5. Review max_memory_usage in ClickHouse config
Symptoms: “No space left on device” errorsSolutions:
  1. Check disk usage: df -h
  2. Clean Docker: docker system prune -a
  3. Clean old logs
  4. Archive old analytics data
  5. Optimize ClickHouse tables
  6. Add more storage
Symptoms: Cannot connect to PostgreSQL or ClickHouseSolutions:
  1. Check database container status
  2. Verify DATABASE_URL and CLICKHOUSE_DATABASE_URL
  3. Check network connectivity
  4. Review database logs
  5. Restart database containers
  6. Verify credentials
Symptoms: Dashboard takes long to loadSolutions:
  1. Optimize ClickHouse tables: OPTIMIZE TABLE ... FINAL
  2. Check for slow queries in ClickHouse logs
  3. Increase ClickHouse memory allocation
  4. Review and optimize custom goals
  5. Consider archiving very old data
  6. Check server resources (CPU, RAM, disk I/O)
Symptoms: Invites and reports not deliveredSolutions:
  1. Check MAILER_ADAPTER configuration
  2. Verify SMTP credentials
  3. Test email configuration:
    docker compose exec plausible sh -c "/app/bin/plausible eval 'Plausible.Mailer.send_test_email(\"[email protected]\")'"
    
  4. Review mailer logs
  5. Check firewall rules for SMTP ports
  6. Verify DNS records (SPF, DKIM)

Monitoring Setup

Prometheus Metrics (Optional)

PromEx is disabled by default in Community Edition. Enable it for Prometheus monitoring.
# In plausible-conf.env
PROMEX_DISABLED=false
Metrics will be available at http://localhost:8000/metrics.

External Monitoring

Set up external monitoring for production:

Uptime Monitoring

Use services like UptimeRobot or Pingdom to monitor /api/system/health/live

Log Aggregation

Forward logs to services like Loki, ELK, or Datadog

Error Tracking

Configure Sentry for application error tracking with SENTRY_DSN

Metrics

Use Prometheus + Grafana for detailed metrics and dashboards

Maintenance Checklist

Getting Help

GitHub Discussions

Community support forum for self-hosting issues

Documentation

Official Community Edition documentation

Issue Tracker

Report bugs and feature requests

Changelog

Review changes and known issues

Next Steps

Configuration

Review and optimize your configuration

Upgrade Guide

Plan your next upgrade

Build docs developers (and LLMs) love