Production Checklist for Zerops
Keywords
production, checklist, ha, high availability, minContainers, mailpit, smtp, adminer, volatile, sessions, object storage, deploy production, go-live, launch
TL;DR
Before going to production: (1) databases to HA mode, (2) minContainers: 2 on app services, (3) replace Mailpit with real SMTP, (4) remove Adminer, (5) use Object Storage for uploads, (6) use Redis/Valkey for sessions.
Database
| Item | Dev | Production |
|---|---|---|
| Mode | NON_HA | HA (must recreate) |
| Backups | Optional | Enabled |
| Connection | Single primary | Primary + read replicas |
HA is immutable — cannot switch after creation. Delete and recreate with mode: HA.
Application Services
| Item | Dev | Production |
|---|---|---|
| minContainers | 1 | 2+ |
| Health checks | Optional | Enabled |
| Logging | Console/debug | Structured (syslog) |
| Debug mode | Enabled | Disabled |
Dev Services to Remove
Mailpit → Production SMTP
Adminer → Remove or Restrict
Remove entirely or disable enableSubdomainAccess. Use VPN + pgAdmin/DBeaver locally.
File Storage
Container filesystem survives restarts but is replaced on every deploy — files stored on disk persist through reload/restart/stop+start but are lost on deploy or container replacement (scale-up/down).
| Use case | Solution |
|---|---|
| User uploads | Object Storage (S3) |
| Media files | Object Storage (S3) |
| Temp files | Container disk (OK) |
| Build artifacts | Deploy via zerops.yaml |
Sessions & Cache
File-based sessions break with multiple containers and are lost on deploy.
| Use case | Solution |
|---|---|
| PHP sessions | Redis/Valkey |
| Laravel sessions | Redis driver |
| Django sessions | Redis backend |
| Express sessions | Redis store |
Framework-Specific Production Settings
PHP/Laravel
APP_ENV: production,APP_DEBUG: "false"- Trusted proxies:
TRUSTED_PROXIES: 127.0.0.1,10.0.0.0/8 - Sessions in Redis, not files
- Optimize:
php artisan config:cache && route:cache && view:cache
PHP/Symfony
APP_ENV: prodTRUSTED_PROXIES: 127.0.0.1,10.0.0.0/8- Logging via Monolog SyslogHandler
Python/Django
DEBUG: "false"CSRF_TRUSTED_ORIGINS: https://your-domain.comALLOWED_HOSTS: .zerops.app,your-domain.com- Static files via
collectstatic
Node.js
NODE_ENV: productionHOST: 0.0.0.0- Health check endpoint at
/statusor/health
Java/Spring
server.address: 0.0.0.0(required — default binds localhost)- Actuator health endpoints enabled
- JVM memory flags:
-Xmx512m(match container limits)
Elixir/Phoenix
PHX_SERVER: "true"(required to start server in releases)SECRET_KEY_BASEgenerated via preprocessorPHX_HOSTset to domain
HA Checklist
| Item | Recommendation |
|---|---|
| Core package | Serious Core for production (better SLA, dedicated resources) |
| CPU mode | cpuMode: DEDICATED for consistent performance under load |
| Environment separation | Separate projects for dev/staging/prod |
| Stateless design | Sessions in Valkey, uploads in Object Storage — no local state |
| Database mode | mode: HA for all managed services (immutable — plan before creation) |
| Min containers | minContainers: 2 on all app services for zero-downtime deploys |
Health Check Pattern
Combined readiness + runtime health check for production services:
Readiness check gates traffic during deploy. Health check runs continuously — unhealthy containers are restarted after 5-minute retry window.
Gotchas
- HA is immutable: Must delete and recreate service to switch modes
- Container filesystem survives restarts but is replaced on every deploy: use external storage for persistent data
- File sessions break with scaling: Multiple containers don't share filesystem
- Mailpit is not production SMTP: Only for dev — no delivery guarantees
- Debug mode leaks secrets: Disable APP_DEBUG in production
- Missing health checks: Load balancer can't route around unhealthy containers
See Also
- zerops://themes/core — import.yml patterns
- zerops://guides/scaling
- zerops://guides/backup