Skip to main content
Skip to main content

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

ItemDevProduction
ModeNON_HAHA (must recreate)
BackupsOptionalEnabled
ConnectionSingle primaryPrimary + read replicas

HA is immutable — cannot switch after creation. Delete and recreate with mode: HA.

Application Services

ItemDevProduction
minContainers12+
Health checksOptionalEnabled
LoggingConsole/debugStructured (syslog)
Debug modeEnabledDisabled
# Production app service
- hostname: app
type: nodejs@22
minContainers: 2
maxContainers: 4

Dev Services to Remove

Mailpit → Production SMTP

# REMOVE for production:
- hostname: mailpit
type: go@1
buildFromGit: https://github.com/zeropsio/recipe-mailpit

# REPLACE with production SMTP env vars:
envVariables:
SMTP_HOST: smtp.sendgrid.net
SMTP_PORT: "587"
envSecrets:
SMTP_PASSWORD: your-production-key

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 caseSolution
User uploadsObject Storage (S3)
Media filesObject Storage (S3)
Temp filesContainer disk (OK)
Build artifactsDeploy via zerops.yaml
# Add Object Storage for persistent files
- hostname: storage
type: object-storage
objectStorageSize: 2
objectStoragePolicy: public-read

Sessions & Cache

File-based sessions break with multiple containers and are lost on deploy.

Use caseSolution
PHP sessionsRedis/Valkey
Laravel sessionsRedis driver
Django sessionsRedis backend
Express sessionsRedis store
# Add Valkey for sessions/cache
- hostname: cache
type: valkey@7.2
mode: NON_HA # HA for production

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: prod
  • TRUSTED_PROXIES: 127.0.0.1,10.0.0.0/8
  • Logging via Monolog SyslogHandler

Python/Django

  • DEBUG: "false"
  • CSRF_TRUSTED_ORIGINS: https://your-domain.com
  • ALLOWED_HOSTS: .zerops.app,your-domain.com
  • Static files via collectstatic

Node.js

  • NODE_ENV: production
  • HOST: 0.0.0.0
  • Health check endpoint at /status or /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_BASE generated via preprocessor
  • PHX_HOST set to domain

HA Checklist

ItemRecommendation
Core packageSerious Core for production (better SLA, dedicated resources)
CPU modecpuMode: DEDICATED for consistent performance under load
Environment separationSeparate projects for dev/staging/prod
Stateless designSessions in Valkey, uploads in Object Storage — no local state
Database modemode: HA for all managed services (immutable — plan before creation)
Min containersminContainers: 2 on all app services for zero-downtime deploys

Health Check Pattern

Combined readiness + runtime health check for production services:

zerops:
- setup: app
deploy:
readinessCheck:
httpGet:
port: 3000
path: /health
run:
healthCheck:
httpGet:
port: 3000
path: /health
start: node server.js

Readiness check gates traffic during deploy. Health check runs continuously — unhealthy containers are restarted after 5-minute retry window.

Gotchas

  1. HA is immutable: Must delete and recreate service to switch modes
  2. Container filesystem survives restarts but is replaced on every deploy: use external storage for persistent data
  3. File sessions break with scaling: Multiple containers don't share filesystem
  4. Mailpit is not production SMTP: Only for dev — no delivery guarantees
  5. Debug mode leaks secrets: Disable APP_DEBUG in production
  6. 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