Skip to content

calServer v2 — Deployment

Building Docker Images

# Laravel API v2
docker build -f Dockerfile.laravel -t calhelp/calserver-api-v2:local .

# Frontend v2
docker build -f Dockerfile.frontend -t calhelp/calserver-frontend:local .

Docker Compose (Development + Production)

v1 Only (existing customers — no changes)

cd docker
docker compose up -d

v1 + v2 in Parallel

cd docker
docker compose -f docker-compose.yml -f docker-compose.v2.yml up -d

Restart Only v2 Services

cd docker
docker compose -f docker-compose.yml -f docker-compose.v2.yml restart calserver-api-v2 calserver-frontend

Additional Environment Variables (.env)

The following variables must be added to the existing .env:

# Laravel API v2
LARAVEL_APP_KEY=base64:... # generate with: php artisan key:generate --show
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com
DB_PREFIX=                 # table prefix of the V1 database, if any

# Redis (new)
# No separate password needed within the internal Docker network

Health Checks

# API v2
curl http://localhost:8081/api/v2/health
# → {"status":"healthy","services":{"database":"up",…},…}

# Frontend v2
curl http://localhost:3000/
# → HTML response (200)

# Redis
docker exec calserver-redis redis-cli ping
# → PONG

Kubernetes / Helm

v2 is fully integrated into the maintained Helm chart (k8s/charts/calserver) as a coexistence deployment. Setting

v2:
  enabled: true

creates:

  1. Deployment + Service -api-v2 — Laravel API (port 8081, probes on /up)
  2. Deployment + Service -frontend — Nuxt frontend (port 3000, probes on /v2/_health — Nitro serves every route under the Nuxt baseURL)
  3. Ingress routes for /api/v2 and /v2 (prefix, before the v1 catch-all)
  4. A release secret with a generated, upgrade-stable Laravel APP_KEY (or v2.existingSecret)

The v2 database is picked with a single value: v2.postgresql.enabled=true deploys a PostgreSQL of its own (ADR-008) and overrides v2.api.database.*; leaving it off keeps v2 on the v1 MySQL (transition mode); setting v2.api.database.host points v2 at an externally operated database. With v2.enabled=false (default) the chart renders byte-identically to before — existing installations are unaffected. All parameters are documented in the chart README; the API container migrates on startup, and with its own PostgreSQL the data is copied over once with php artisan v1:sync.

OpenShift

Two extras matter on OpenShift, both wired up in k8s/values-oc.yml:

  • Security context. Leave v2.*.podSecurityContext / v2.*.containerSecurityContext disabled and set v2.api.volumePermissions.enabled=false. The images run under any UID from the SCC range (storage, caches and the nginx runtime directories are owned by www-data:root and group-writable), while the chown init container would need runAsUser: 0 — which restricted-v2 rejects.
  • Routing. Clusters without an ingress-nginx controller use route.enabled=true instead of the Ingress; the chart then creates OpenShift Routes for /, /v2 and /api/v2 on the same host.

The chart must be >= 0.1.26 — earlier packaged releases contain no v2 templates at all. Step-by-step guide: k8s/INSTALL-ON-OPENSHIFT.md, section 7.

CI/CD Pipeline

The build pipeline must produce three images:

calhelp/calwebapp_bootstrap:$TAG  → Yii 1 (unchanged)
calhelp/calserver-api-v2:$TAG     → Laravel API
calhelp/calserver-frontend:$TAG   → Nuxt Frontend

Rollback

If there are problems with v2, the overlay Compose file can simply be omitted. v1 then continues to run on its own:

docker compose down calserver-api-v2 calserver-frontend redis
docker compose up -d  # v1 only