Skip to main content
Version: 1.13.0-dev

Docker Compose Setup

All DVARA Docker Compose stacks live in the public dvara-examples repo. Each variant is a self-contained directory — cd in, set your .env, and run docker compose up -d. For the 5-minute first-run experience, see Quickstart.

These stacks run the Enterprise platform and include PostgreSQL for Flightdeck. From 1.8.2 the gateway has no database: it enrols with Flightdeck using DVARA_ENROLMENT_SECRET, reads its configuration from Flightdeck as a signed bundle, and spools its audit and usage records to the gateway-data volume, which it ships to Flightdeck. See How the gateway runs without a database. The separate Open Source distribution does not use these Compose files and needs no database; follow the Open Source distribution quickstart.

Pre-built images​

ImageWhat it isAccess
ghcr.io/dvarahq/dvara-gateway:1.12.0Data plane (:8080) — serves /v1/*, /mcp/* and /a2a/*Public
ghcr.io/dvarahq/dvara-flightdeck:1.12.0Role-aware control plane (:8090)Public

Two images, both public. There is one artifact per app. The license decides the posture and the limits, not which image you pull — see Container images & license posture.

Do not pull these

dvara-llm-gateway (renamed to dvara-gateway), dvara-mcp-gateway and dvara-a2a-gateway (retired — all three planes now run in the gateway process, so ports 8070 and 8075 no longer exist), and the -ee variants (there is no separate Enterprise build). Some of these still resolve to old pre-release images.

Tags: latest (current release) or a version tag (e.g. 1.12.0). The dvara-examples stacks pin 1.12.0.

One Enterprise image set, two postures

The public dvara-gateway and dvara-flightdeck images run the Enterprise platform. Without a licence key they start in the non-production Development posture, which serves every feature, including the MCP and A2A paths, within 3 workspaces and 100,000 governed calls a month. A valid licence selects Production and removes those limits in the same images. There are no private MCP, A2A, Community, or -ee images.

The Open Source distribution is a separate Java distribution, not a mode of these images. See capability availability.

Topologies​

StackServicesUse for
quick-start/postgres + dvara-gateway + dvara-flightdeckFastest path to a running gateway. OpenAI only.
mcp-quickstart/postgres + dvara-flightdeck + dvara-gateway + a JBang MCP serverGoverned MCP tool calls in one command: allowed, PII-redacted and policy-denied. No licence or provider key.
multi-provider/postgres + dvara-gateway + dvara-flightdeckOpenAI + Anthropic out of the box. Add Gemini, Mistral, Cohere, Groq or Azure OpenAI by uncommenting env vars.
ollama/postgres + dvara-gateway + dvara-flightdeck + ollamaLocal models, no external LLM calls.
with-email/postgres + dvara-gateway + dvara-flightdeckThe same shape as quick-start/, with transactional email (log / resend / smtp) and the delivery durability layer surfaced for tuning.
There is no full/ stack any more

It ran the MCP and A2A planes as their own containers. Since 1.7.0 those planes run inside the gateway process, so full/ was the same three services as quick-start/ plus a licence key — a directory naming a topology that no longer exists.

To get what it gave you: run quick-start/. From 1.8.2 the /mcp and /a2a paths serve on :8080 with or without a licence.

Clone once, then switch between stacks by cd-ing into a different directory:

git clone https://github.com/dvarahq/dvara-examples.git
cd dvara-examples/docker-compose

Quick-start stack​

The fastest path to a running gateway — PostgreSQL + dvara-gateway + DVARA Flightdeck with OpenAI as the only provider. This is what Quickstart walks through.

cd quick-start
cp .env.example .env
# edit .env — every uncommented variable is required; the file's
# inline comments explain each one and how to generate the random
# secrets (openssl rand -base64 32)
docker compose up -d

Want more than one provider? Use multi-provider/ below.

Two kinds of credentials

DVARA uses two separate credential layers:

  • Provider keys (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) — infrastructure secrets the gateway uses to call upstream LLM providers. Set as env vars, or manage them through the DVARA Flightdeck's BYOK credential store, or integrate with vault.
  • Workspace API keys (gw_...) — application credentials your SDK uses to authenticate with the gateway. Create them in the DVARA Flightdeck after setting up a workspace.

In production, provider keys are managed by your ops/security team; workspace API keys are managed by platform admins through the dashboard or by workspace admins in Flightdeck.

Multi-provider stack​

Same topology as quick-start/ but with OpenAI + Anthropic wired up out of the box, plus commented-out slots for every other supported provider. Providers register automatically at startup whenever their API key env var is set and non-empty — so adding Gemini, Mistral, Cohere, Groq or Azure OpenAI is just a matter of uncommenting a line in docker-compose.yml and setting the matching value in .env. The stack has no slots for Bedrock or Ollama: add BEDROCK_ENABLED=true with AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_REGION, or OLLAMA_ENABLED with OLLAMA_BASE_URL, to the gateway's environment by hand, or use the ollama/ stack.

cd multi-provider
cp .env.example .env
# set OPENAI_API_KEY and/or ANTHROPIC_API_KEY
docker compose up -d

# with a workspace API key created in Flightdeck
curl -s http://localhost:8080/v1/models \
-H "Authorization: Bearer $DVARA_API_KEY" | jq '.data[].id'
"gpt-4o"
"gpt-4o-mini"
"o3-mini"
"claude-sonnet-4-5"
"claude-opus-4-5"
...

/v1/models queries each registered provider live on a best-effort basis, so the list is not a catalogue DVARA maintains. A provider that fails discovery is omitted from the otherwise successful response. If data is empty, check that the key variables reached the container with docker compose exec dvara-gateway env | grep API_KEY. See Provider Setup for the full discovery contract.

The call requires a workspace API key. Create a workspace and a key in Flightdeck first (see First-run setup), and export it as DVARA_API_KEY.

To enable additional providers, open docker-compose.yml and uncomment the env vars under dvara-gateway.environment:

dvara-gateway:
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
GEMINI_API_KEY: ${GEMINI_API_KEY:-}
MISTRAL_API_KEY: ${MISTRAL_API_KEY:-}
COHERE_API_KEY: ${COHERE_API_KEY:-}
GROQ_API_KEY: ${GROQ_API_KEY:-}
AZURE_OPENAI_API_KEY: ${AZURE_OPENAI_API_KEY:-}
AZURE_OPENAI_BASE_URL: ${AZURE_OPENAI_BASE_URL:-}

Then set the matching values in .env. For Azure OpenAI you must set both AZURE_OPENAI_API_KEY and AZURE_OPENAI_BASE_URL. See Providers for the complete list and per-provider setup.

Local models with Ollama​

Run the Enterprise platform entirely locally with no provider API keys or outbound LLM calls. Add a licence only for production rights and support; see Licensing.

cd ollama
cp .env.example .env # fill in every uncommented variable per the inline comments
docker compose up -d

# Pull a model
docker compose exec ollama ollama pull llama3.2

# Use it, with a workspace API key created in Flightdeck
curl -s -X POST http://localhost:8080/v1/chat/completions \
-H "Authorization: Bearer $DVARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "ollama/llama3.2",
"messages": [{"role": "user", "content": "Hello!"}]
}' | jq .

Every /v1 call needs a workspace API key. Create a workspace and a key in Flightdeck first (see First-run setup), and export it as DVARA_API_KEY.

The stack includes a GPU-passthrough block in docker-compose.yml, commented out under the ollama service — uncomment it if you have an NVIDIA GPU and the NVIDIA Container Toolkit installed.

All three planes, one container​

There is no separate stack to run for MCP or A2A. Since 1.7.0 the gateway serves all three governed planes in one process on port 8080:

planepathwhat it governs
LLM/v1model traffic
MCP/mcpthe tools your agents call
A2A/a2athe other agents your agents call

From 1.8.2 the MCP and A2A planes serve with or without a licence: same container, same port, same health probe. Neither plane is included in the Open Source distribution.

curl http://localhost:8080/actuator/health
Upgrading from 1.6.0 or earlier

Earlier releases ran two more containers, dvara-mcp-gateway on 8070 and dvara-a2a-gateway on 8075. Both images are retired. Remove those services from your compose file and repoint anything addressing :8070 or :8075 at the gateway on :8080 — the paths are unchanged, so only the host and port move.

See Agentic Governance for the MCP plane and A2A Governance Plane for the A2A plane.

First-run setup​

Open the DVARA Flightdeck at http://localhost:8090 — you'll be redirected to /setup to create the initial owner account. Full walkthrough in Setup & Login. For self-service portal access (workspace admin / developer / viewer roles), see Workspace Flightdeck.

Disable authentication for local development

If you prefer to skip authentication entirely during local development, add this to the dvara-flightdeck service environment section of any stack:

dvara-flightdeck:
environment:
DVARA_FLIGHTDECK_SECURITY_ENABLED: "false"
# ... other env vars

Never use this in production.

What the platform secrets do​

The .env.example in each stack carries the DVARA-specific secrets below in addition to provider keys + DB_PASSWORD (Flightdeck's database password; the gateway has no database). The stacks already wire each one into the right service — .env.example lists what to set; the compose files reference them. The summary below is for understanding what each one is for, not for hand-editing your compose YAML.

Env varWhat it doesFailure mode if unset
DVARA_LICENSE_KEYOptional. From 1.8.2 Flightdeck copies it into its licence store once, when none is stored; Gateway containers ignore it. Prefer the License page in Flightdeck.Missing starts Development. A value that does not verify is not stored.
DVARA_ENROLMENT_SECRETFrom 1.8.2. The shared secret the gateway enrols with Flightdeck by, to get its certificate for Flightdeck's /internal channel and the key that verifies config bundles. The same value on both services, at least 32 characters (openssl rand -base64 32).Compose refuses to start the stack
DVARA_ENCRYPTION_MASTER_PASSWORDAES-256-GCM key for ENCRYPTED-mode credentials stored per-workspace in PostgreSQL (the BYOK Credentials store in the Flightdeck)ENCRYPTED-mode credential persistence fails; REFERENCE-mode (vault pointer) still works
DVARA_ACTUATOR_API_KEYOperator Bearer for /actuator/gateway-status, Enterprise /actuator/license, and every authenticated actuator path except prometheusEvery authenticated actuator request returns 401
DVARA_ACTUATOR_METRICS_API_KEYDistinct Bearer for /actuator/prometheus onlyPrometheus scrape 401s on every poll; dashboard's live-metrics card stays empty. Must differ from DVARA_ACTUATOR_API_KEY — principle of least privilege
DVARA_PII_TOKEN_ENCRYPTION_MASTER_PASSWORDFlightdeck only. Seals each workspace's PII token key; the gateway fetches keys from Flightdeck and needs no copyOnly pii.action=TOKENIZE is affected. Losing the value makes every PII token unreadable
DVARA_AUDIT_HMAC_SECRETHMAC-SHA256 key for the tamper-evident audit chainRequired from 1.8.0. DVARA no longer generates it. Set your own value (openssl rand -base64 32), the same on every gateway and on Flightdeck. On a production Spring profile a process refuses to start without it; on the default profile it starts with only a warning. Never use a published placeholder value or one under 32 characters: on the default profile the process only logs a warning, and on a production profile it refuses to start.

Set the A2A push callback URL​

From 1.8.5 A2A push notifications go through the gateway. The gateway needs its own URL, as peer agents reach it, in A2A_PUSH_CALLBACK_BASE_URL. While it is empty, every A2A push config is refused with 503 A2A_PUSH_NOT_AVAILABLE, except in a workspace that keeps direct delivery. The LLM path does not need it.

The dvara-examples stacks default it to http://dvara-gateway:8080, which only a peer on the same Compose network can reach. For a peer anywhere else, set it to the gateway's public URL, in .env or in your docker-compose.override.yml:

services:
dvara-gateway:
environment:
A2A_PUSH_CALLBACK_BASE_URL: https://gateway.example.com

See Receive push notifications through DVARA.

The probe paths (/actuator/health, /actuator/health/liveness, /actuator/health/readiness, /actuator/info) stay anonymous so container health checks don't need credentials.

BYOK: credentials via the DVARA Flightdeck​

Provider credentials can be managed through the DVARA Flightdeck under Credentials instead of (or in addition to) env vars. Keys are encrypted with AES-256-GCM and stored per-workspace in PostgreSQL — recommended for multi-tenant setups where each workspace brings their own provider keys (BYOK). The stacks already wire DVARA_ENCRYPTION_MASTER_PASSWORD into both the Flightdeck and gateway services; setting a non-default value in .env is all that's required.

Authentication modes​

By default, the DVARA Flightdeck uses built-in email/password authentication. For production, DVARA supports three modes:

ModeWhen to useConfig required
Built-in (default)Local dev, small teams, no existing IdPNone — works out of the box
OIDCExisting Keycloak, Okta, or Azure ADDVARA_FLIGHTDECK_SECURITY_OIDC_ISSUER_URI
SAML 2.0Enterprise SSO (ADFS, Okta SAML, Azure AD)DVARA_FLIGHTDECK_SECURITY_SAML_METADATA_URL

Example — enabling OIDC on the DVARA Flightdeck by adding env vars to the dvara-flightdeck service:

dvara-flightdeck:
environment:
DVARA_FLIGHTDECK_SECURITY_OIDC_ISSUER_URI: https://keycloak.example.com/realms/dvara
DVARA_FLIGHTDECK_SECURITY_OIDC_AUDIENCE: dvara-admin
DVARA_FLIGHTDECK_SECURITY_OIDC_ROLE_CLAIM: realm_access.roles
# ... other env vars

OIDC and SAML are mutually exclusive — configuring both causes a startup error. The full property reference for OIDC + SAML lives in Setup & Login and Configuration.

Viewing logs​

docker compose logs -f # all services
docker compose logs -f dvara-gateway # single service

Logs use structured JSON format by default. Switch to plain text with SPRING_PROFILES_ACTIVE=default,log-plain on the example stacks. log-plain alone replaces the default profile, so the process counts as production-class, and it then refuses placeholder secrets.

Health probes​

The DVARA Flightdeck exposes standard health endpoints for Docker health checks:

curl http://localhost:8090/actuator/health/liveness # liveness
curl http://localhost:8090/actuator/health/readiness # readiness (application state and PostgreSQL)

Gateway connectivity is deliberately excluded from Flightdeck readiness. Check it in System Status.

Stopping​

docker compose down # stop, keep data
docker compose down -v # stop and delete the volumes: PostgreSQL and the gateway's spool

Stop with docker compose down (or stop), not by killing containers. On a normal stop the gateway flushes its spool to Flightdeck first; deleting the gateway-data volume discards any records it has not shipped yet.

Troubleshooting​

Port already in use​

Edit the stack's docker-compose.yml directly, or replace the port list in a docker-compose.override.yml beside it (Compose 2.24 or later). A plain ports entry in an override file is added to the stack's "8080:8080", so the conflict stays; !override replaces the list:

services:
dvara-gateway:
ports: !override
- "9080:8080" # maps host 9080 → container 8080

Gateway starts but providers are not registered​

Check that environment variables are being passed through:

docker compose exec dvara-gateway env | grep -i api_key

Keys must be non-empty for providers to register.

The gateway refuses to start and names a setting​

From 1.8.2 the gateway has no database, and it checks its settings at startup. It refuses to start, and names the setting, when:

  • it has no DVARA_DATA_PLANE_CONTROL_PLANE_BASE_URL (Flightdeck's /internal address) or no DVARA_LLM_GATEWAY_LOCAL_STORE_PATH (its spool);
  • it is given SPRING_DATASOURCE_URL or a bootstrap file. Database settings and DVARA_BOOTSTRAP_FILE belong on dvara-flightdeck only.

A compose file written for 1.8.1 or earlier gives the gateway a database. Start again from one of the dvara-examples stacks rather than editing it by hand.

The gateway cannot enrol​

The gateway enrols with Flightdeck when it starts, so Flightdeck has to be healthy first. Check that DVARA_ENROLMENT_SECRET is set to the same value for both services, and that the gateway's base URL uses a name in Flightdeck's DVARA_INTERNAL_ENROLMENT_SERVER_NAMES:

docker compose logs dvara-gateway | grep -i enrol

Health check keeps failing​

docker compose logs dvara-gateway | head -50

Flightdeck runs its database migrations on first boot, and the gateway starts only after Flightdeck is healthy and the gateway has enrolled, so allow a minute on the first run. If it consistently fails, check for port conflicts.

Cannot log in to the DVARA Flightdeck​

First-time users must create the initial owner account at http://localhost:8090/setup. If you've set up an account and forgotten the password, use Forgot password? on the login page. With the default log transport Flightdeck sends no email, and the logged email hides the link. An owner can give the user a reset link instead: Users, then Reset password on the user. Configure SMTP with dvara.flightdeck.email.transport=smtp (or =resend for the Resend transactional API) for email delivery.