Skip to content

Deployment

CM Box runs as a small set of cooperating containers: four application services built from the container images provided with your license, plus two Redis instances and a text-extraction service. This page describes what each service does, how they connect, and the three supported ways to deploy them.

  • Docker — all deployment options run CM Box as containers. On Windows or macOS use Docker Desktop; on Linux the Docker engine is sufficient.
  • Node.js 22.x+ — only needed if you run the application from source rather than from the provided images. The app and graphql images are built on Node 22; the process image on Node 24.
  • Container images — the four CM Box images (app, graphql, process, web) provided with your license, pulled into your own container registry or environment.
  • A product license — required from version 1.5.0 onward; see Instance setup and licensing.
Service Image Port Role
app CM Box app image 4321 The application server: web UI, REST API, authentication middleware, and the /api/graphql/ proxy.
graphql CM Box graphql image 4000 (internal) Apollo GraphQL server with one endpoint per repository (/graphql/:repo). Only the app service needs to reach it.
process CM Box process image BullMQ queue workers: media renditions, webhook delivery, and scheduled tasks. The image bundles conversion tooling (Ghostscript, GraphicsMagick, ImageMagick, FFmpeg, LibreOffice).
web CM Box web image 80 An nginx reverse proxy in front of app: gzip compression and a 1000 MB upload limit (client_max_body_size).
db redis:latest 6379 The primary database. CM Box requires Redis 8.0+ with the Search and JSON modules. Runs with --appendonly yes --save 60 1 — append-only-file persistence plus a snapshot every 60 seconds.
queue redis:latest 6410 A second Redis instance dedicated to the BullMQ job queues, run with --maxmemory-policy noeviction so queued jobs are never evicted.
extraction apache/tika:latest-full 9998 (internal) Apache Tika text extraction, used during content processing (default endpoint http://extraction:9998/tika/text, overridable with EXTRACTION_URL). Included in the Kubernetes manifest and the development stack; the single-host Compose file does not define it, so add it there (or point EXTRACTION_URL at an external Tika) if you need document text extraction.

Request flow: clients reach web (port 80), which proxies to app (port 4321). The app proxies GraphQL calls to graphql (port 4000) via GRAPHQL_SERVER_ENDPOINT. All application services connect to db via REDIS_URL; the app and process services also connect to queue via BULLMQ_REDIS_HOST/BULLMQ_REDIS_PORT. Every service is configured through environment variables — see the environment variable reference.

Both Redis instances hold state and must have persistent volumes: db is the system of record for all content, configuration, and security objects, and queue holds in-flight background jobs.

Two Compose files ship with the product:

  • local-full-deploy-compose.yml — the full stack: db, queue, app, graphql, process, and web, with named volumes (redis_data, queue_data) for the two Redis instances. Use this as the starting point for a single-host deployment. The file ships with development values for JWT_SECRET_KEY, WORKOS_ORGANIZATION_ID, and WORKOS_DIRECTORY_ID — replace all three with your own before starting the stack.
  • docker-compose.yml — a development dependency stack only (redis, queue, extraction, process) for running the app and GraphQL servers from source with npm run dev and npm run graphql.

cmbox-kubernetes.yaml is a reference manifest for a cluster deployment:

  • StatefulSets cmbox-db and cmbox-queue run the two Redis instances, each with a 40 Gi volumeClaimTemplate and the same persistence flags as the Compose files.
  • Deployment cmbox-app runs the app container with the web nginx container as a sidecar in the same pod, so nginx proxies to localhost:4321.
  • Deployments cmbox-graphql and cmbox-process run the GraphQL server and queue workers; the Tika extraction container runs as a sidecar in the process pod.
  • Services: cmbox-app-svc is a LoadBalancer on port 80 targeting the nginx sidecar (the manifest includes OCI flexible load-balancer annotations); cmbox-graphql-svc (4000), cmbox-db-svc (6379), and cmbox-queue-svc (6410) are internal.
  • An imagePullSecrets entry authenticates to the registry that hosts your licensed images.

Adjust image references, hostnames (AUTH_REDIRECT_URI, GRAPHQL_ENDPOINT), JWT_SECRET_KEY, and WorkOS IDs in the manifest’s env blocks for your environment.

The OCI Marketplace image ships with the stack preinstalled at /opt/apps/cmbox/docker-compose.yml (the contents of oci-marketplace-compose.yml — the full stack with restart: always). On a new instance, run the provided cmbox-oci-new-instance.sh script, which:

  1. Generates a fresh 256-bit base64 key with openssl rand -base64 32.
  2. Replaces the ****DYNAMIC_KEY**** placeholder for JWT_SECRET_KEY in the Compose file (keeping a .bak backup).
  3. Restarts the stack with docker-compose down && docker-compose up -d.

This ensures every instance gets a unique JWT signing key before first use.

  • The app service answers GET /healthcheck with Ok (HTTP 200) once it can reach both Redis instances; it returns HTTP 503 otherwise.
  • The GraphQL service exposes its own /healthcheck on port 4000 that verifies its primary Redis connection.
  • Browsing to the instance for the first time redirects to the instance setup screen — continue with Instance setup and licensing.