Skip to content

Docker Deployment

The workflow engine is distributed as a Docker image and can be deployed standalone or as part of the full neops stack.

Docker Image

docker pull quay.io/zebbra/neops-workflow-engine:latest

The image also carries the Monitor App sources together with a generated engine API client (built in the Dockerfile’s client-gen stage), so the app can be served directly from the image — neops-lab runs it this way with npm install && npm run dev inside /app/rest/monitor-app.

Tags follow the branch/release naming:

Tag Source
latest Latest stable release
develop Latest development build
main Latest main branch build
x.y.z Specific release version

Docker Compose

The repository includes a ready-to-use docker-compose.yml that starts the development dependency stack (PostgreSQL + Monitor App):

make gen-fetch-client   # the Monitor App image builds from the generated API client
docker compose up -d

Run the engine locally with npm run start:dev (see Setup). The base compose file only starts supporting services — the engine is not included.

Service URL Purpose
PostgreSQL localhost:5434 Database (mapped from container port 5432)
Monitor App http://localhost:5173 Web UI for workflow management

Configuration

All settings can be overridden via environment variables or a .env file:

Variable Default Description
POSTGRES_PASSWORD unsafe Database password
POSTGRES_PORT 5434 Host port for PostgreSQL
MONITOR_PORT 5173 Host port for the Monitor App

CMS dependency

Workflows that use acquire clauses or operate on specific entities (devices, interfaces, groups) require a running CMS. Set NEOPS_CMS_URL to point to an existing instance — as a host environment variable when running the engine locally via npm, or as a service environment variable when you run the engine as a container of your own.

Building the Image

The Makefile helper builds either flavor with the right build args:

make build-docker                 # enterprise        -> neops-workflow-engine:latest
make build-docker flavor=preview  # developer-preview -> neops-workflow-engine-preview:latest

NPM_TOKEN is expected to already be exported in your environment; the target aborts with a clear message if it is not. It runs the run-ci stage first, then builds the image itself.

To build by hand instead:

export NPM_TOKEN=ghp_xxx

DOCKER_BUILDKIT=1 docker build \
  --secret id=npm_token,env=NPM_TOKEN \
  --build-arg LICENSE_FLAVOR=enterprise \
  --build-arg NEOPS_VERSION=1.4.0 \
  -t quay.io/zebbra/neops-workflow-engine:latest .

The build uses BuildKit secrets so the npm token is never written to image layers.

Build-time variables

These are properties of the image, fixed when it is built. They are not runtime settings – see Configuration for the variables you set when deploying.

Build arg Required Purpose
LICENSE_FLAVOR Yes enterprise or developer-preview. Selects the license compiled into the image
NEOPS_VERSION No (develop) Version string the image reports at GET /version/

LICENSE_FLAVOR has no default

Omitting it fails the build. This is deliberate: defaulting would risk shipping the enterprise flavor unintentionally.

The chosen flavor is both compiled in and stamped into the image’s NEOPS_LICENSE_FLAVOR environment variable. On startup the engine compares the two and refuses to boot if they disagree, treating the image as corrupt. Do not override NEOPS_LICENSE_FLAVOR when running a container – it is an integrity check, not a switch.

Running from source

When you run the engine from source rather than from an image (npm run start:dev), there is no compiled flavor. NEOPS_LICENSE=developer-preview selects that flavor for local development and tests; anything else yields enterprise. This variable has no effect on a built image.

Authorization

The image runs NODE_ENV=production, so logs are JSON, the Swagger UI is not mounted at /api, and every gate that opens only in a declared development environment stays closed.

Variable What a deployment sets it to
NEOPS_AUTHZ_MODE enforce (the default), permissive, or disabled
NEOPS_JWT_PUBLIC_KEY / NEOPS_JWT_PUBLIC_KEY_PATH / NEOPS_JWKS_URL The CMS’s RS256 verification key, inline, as a file path, or as a key-set URL. One of the three is required outside disabled
NEOPS_CMS_TOKEN The token the engine calls the CMS with
NEOPS_CORS_ORIGINS The exact browser origins allowed to call the API, comma-separated. Unset serves same-origin callers only

The engine refuses to start, names the variable to set, and exits non-zero when:

  • no verification key is configured and NEOPS_AUTHZ_MODE is not disabled
  • NEOPS_AUTHZ_MODE=disabled is set without NEOPS_ALLOW_DISABLED_AUTHZ=true
  • NEOPS_CMS_TOKEN is still the built-in placeholder unsafe
  • NEOPS_JWKS_URL is plaintext HTTP without both NODE_ENV=development and NEOPS_ALLOW_INSECURE_JWKS=true

See Configuration for the full list, the token claims the engine reads, and the permission strings each route requires.

Running Migrations

The engine runs pending migrations automatically on startup.

Networking

The engine needs to reach:

  • PostgreSQL – for state persistence
  • CMS – for entity data and locking (GraphQL over HTTP)

Workers need to reach the engine’s REST API (port 3030) for:

  • Worker registration and heartbeat
  • Function block registration
  • Job polling and result pushing

The Monitor App runs client-side in the browser and connects to the engine API directly (default: http://localhost:3030, configurable in the Monitor App’s Settings page).

Health Check

The engine exposes a health endpoint:

curl http://localhost:3030/health/

For custom deployments that run the engine as a compose service, configure a health check like this:

services:
  engine:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3030/health/"]
      interval: 15s
      timeout: 5s
      retries: 5
      start_period: 30s

See also: Configuration Reference for all environment variables, Setup for local development.