Skip to content

Production Checklist

Use this checklist to verify your Mantis deployment is ready for production.

  • Changed default admin password
  • JWT secret is cryptographically random (32+ characters)
  • JWT private key is secured (file permissions 400)
  • Session tokens have appropriate expiry
  • Valid TLS certificates installed (not self-signed)
  • mTLS enabled for client authentication
  • Registration tokens created with auto_approve disabled (new clients reviewed before approval)
  • Certificate expiration monitoring configured
  • CA private key stored securely (HSM or secrets manager)
  • MANTIS_ENCRYPTION_KEY is a secure 32-byte base64 value
  • Encryption key stored in secrets manager (not in .env)
  • Key rotation procedure documented
  • RBAC roles configured appropriately
  • Principle of least privilege applied
  • Admin accounts limited and audited
  • SSO/OIDC configured (if applicable)
  • Log level set to info for all services (not debug/trace): RUST_LOG=info for Mandible, MANTIS_LOG_LEVEL=info for Thorax, TARSUS__LOG_LEVEL=info for Tarsus
  • Lens production build served (no dev server, source maps disabled)
  • CORS origins restricted to actual domains
  • All default passwords changed
  • External/managed PostgreSQL 16
  • Migration role can CREATE ROLE and owns the audit tables — migrations create the mantis_audit_* roles and apply FORCE ROW LEVEL SECURITY, and fail outright on a managed instance that grants neither
  • Connection pooling configured appropriately (database.max_connections defaults to 10 per Mandible replica)
  • SSL/TLS enabled for database connections
  • Database credentials in secrets manager

RabbitMQ is off by default — Mantis falls back to database polling. Skip this section unless you set queue.enabled = true.

  • External/managed RabbitMQ (not containerized)
  • TLS enabled for all connections (port 5671)
  • Queue credentials secured
  • External/managed Redis (not containerized)
  • AUTH password configured
  • TLS enabled (if supported)
  • Only Lens, Mandible, and Thorax exposed externally
  • Database/RabbitMQ/Redis on internal network only
  • Firewall rules configured
  • Rate limiting enabled
  • TLS termination configured
  • X-Forwarded headers passed correctly
  • DDoS protection enabled
  • Request size limits configured
  • Multiple Thorax instances for HA (if needed)
  • Load balancer configured
  • Health checks configured
  • Health endpoints monitored
  • Prometheus metrics collected — Thorax only. It exposes /metrics on THORAX_METRICS_BIND_ADDR (default 0.0.0.0:9090); Mandible collects metrics in-process but exposes no endpoint, and Tarsus exports none
  • Alerting configured for critical issues
  • Certificate expiration alerts
  • Centralized logging configured
  • Deployment-log retention configured at PUT /api/v1/admin/log-retention — off by default, so logs accumulate indefinitely until it is set
  • If archiving deployment-log output, a destination is configured and POST /api/v1/admin/log-retention/verify-archives returns every archive intact
  • Audit logs enabled and monitored
  • No sensitive data in logs
  • Database backup schedule configured
  • Backup restoration tested
  • CA certificate/key backed up securely
  • Disaster recovery plan documented
  • Audit logging enabled
  • Audit retention is never automatic — there is no schedule or purge job. Entries are immutable and the triggers block row deletion; ageing data out means archiving a completed quarterly partition and dropping it, which an administrator invokes deliberately. The chain is verified and the archive read back first, and the operation refuses if either fails
  • Audit chain verification run periodically, and its recorded history reviewed at GET /api/v1/audit/integrity/{tenant_id}/history
  • Runbooks for common operations
  • Incident response procedures
  • Contact information documented

./docker.sh health is a local docker-compose helper: it runs pg_isready and rabbitmq-diagnostics inside compose containers, so it cannot reach the external PostgreSQL and RabbitMQ this checklist mandates, and it checks neither Thorax, Tarsus nor Redis. Verify the services individually instead:

Terminal window
# Mandible: database connectivity only -- this endpoint performs no
# security checks, despite the name suggesting otherwise
curl -s https://your-domain/api/v1/health | jq
# Readiness and the gRPC dependency
curl -s https://your-domain/api/v1/health/ready | jq
curl -s https://your-domain/api/v1/health/grpc | jq
# Thorax
curl -s http://thorax-host:9090/metrics | head