This path brings up the EDK enterprise services on a single machine using the stack under compose/. It suits evaluation and single-node development. For production, use the Helm chart and follow quickstart-kubernetes.md.
Use the files in the public Enterprise Development Kit Deployment repository: https://github.com/Sphereon-Opensource/Enterprise-Development-Kit-Deployment.
There are two run modes:
- Base Compose plus the gateway overlay. A Traefik reverse proxy fronts the services on a single TLS port and routes by host and path. This is the customer walkthrough model and matches the production single-port gateway model.
- Base Compose alone. Each service is published on its own host port over plain HTTP. Use this only as a local developer diagnostic mode; it is not a customer URL model.
The platform is the configuration authority for tenant workloads. A clean
first-run installation starts the platform and all workload containers together:
tenant AS, tenant KMS, DID, wallet unit, wallet interaction, issuer, and verifier
must already be present when
tenant registration later provisions signing material and tenant DID state
through east-west services. Before the license is imported those workload
health endpoints can report licenseStatus: MISSING; Docker Compose accepts
that only while the first-run setup gate is still open.
- Docker with Compose v2.
- Nexus credentials for the published
nexus.sphereon.com/edk-docker/enterprise-*andnexus.sphereon.com/edk-docker/admin-consoleimages for the selectedEDK_TAG. - Docker Compose starts two local PostgreSQL 16 containers for evaluation: one platform/control-plane database and one tenant workload database. For a real single-node deployment, replace them with managed or operator-run PostgreSQL databases and keep platform and tenant state in separate logical databases. Do not put platform tables and tenant schemas in one database.
- A protected license bundle ZIP, or access to the license issuer provided through your EDK distribution channel. The setup UI creates the license recipient key in the platform
licenseKMS when it generates the license request. Evaluation bundles can include the test root CA material when needed. - TLS certificates for the operator and tenant hosts when you use the gateway
overlay. For local gateway evaluation, use the included wildcard certificate
helper. For a real domain, use a publicly trusted wildcard certificate for
*.<base-domain>, or individual certificates for each host.
Sign in once so Compose can pull the enterprise images:
docker login nexus.sphereon.comThe Compose file pins enterprise image pulls to nexus.sphereon.com/edk-docker; set
EDK_TAG only. Do not reintroduce sphereon or docker.io/sphereon; those
values point Compose at public Docker Hub.
Confirm Docker can pull the published images for the tag you plan to deploy:
docker pull nexus.sphereon.com/edk-docker/enterprise-platform:0.25.0-SNAPSHOTCopy the example environment file in compose/ and edit it:
cd compose
cp .env.example .envSet, at minimum:
- The image tag for the enterprise images. The image repository is pinned to
nexus.sphereon.com/edk-dockerin the Compose file. - The platform and tenant database passwords. The default Compose file starts
platform-postgresandtenant-postgres; use external databases only when you intentionally replace those evaluation services. Keep the two databases separate. They may share a PostgreSQL server, but not a database name, credential, or authorization boundary. - The required secrets: keystore password, internal client secret, and the issuer pipeline keys.
- The installation base domain. The platform is published as
https://platform.<base-domain>. Tenant protocol URLs are created during onboarding from<tenant-slug>.<base-domain>.
When upgrading an older Compose environment, remove the legacy single-database
keys EDK_DB_NAME, EDK_DB_USERNAME, EDK_DB_PASSWORD, and
EDK_POSTGRES_HOST_PORT from .env. Replace them with EDK_PLATFORM_DB_* and
EDK_TENANT_DB_*.
For gateway runs, the default base domain saas.localtest.me resolves every
subdomain to 127.0.0.1 with no host-file edits and no local DNS server, so
https://platform.saas.localtest.me and
https://<tenant>.saas.localtest.me both reach your machine. For a real domain,
set EDK_PLATFORM_BASE_DOMAIN to the customer-controlled base domain, point DNS
for platform.<base-domain> and *.<base-domain> at the gateway host, and bind
the tenant endpoints to the tenant host during onboarding.
docker compose -f docker-compose.yml up -dCompose pulls the published images and starts the full backing stack over plain HTTP on local host ports. This mode is only for local diagnostics before placing a gateway in front of the stack. Check that the containers are running:
docker compose psThe stack also starts an OpenTelemetry Collector and Jaeger. The service
containers use the otlp-all telemetry preset by default, exporting traces and
metrics to otel-collector; traces are available at http://localhost:16686.
The base stack is for local diagnostics only. The administrative REST paths
(/api/.../v1) are not protected by the base stack, so keep them on host
loopback or a private network and do not use these ports in customer-facing
instructions, smoke tests, or integrations.
To run the services behind one TLS port, add the gateway overlay.
First, for local evaluation, generate a wildcard certificate for *.saas.localtest.me and the operator host:
../scripts/gen-local-wildcard-cert.shOn Windows:
..\scripts\gen-local-wildcard-cert.ps1The script writes to compose/gateway/certs/. Trust the generated local-ca.crt in your operating system or browser so TLS connections succeed. If mkcert is installed, run mkcert -install once and its CA is trusted automatically. For a real base domain, supply a publicly trusted wildcard certificate or individual host certificates instead and see tls-and-gateway.md.
For a public Let's Encrypt wildcard such as *.edk.example.com, use the
Let's Encrypt renderer instead of this local-certificate overlay. Set the EDK
base domain to edk.example.com and use DNS-01 validation. Provide DNS API
credentials when Traefik should automate issuance and renewal, or use the
manual DNS-01 path when you create the TXT record yourself. See
Subdomain wildcard with Let's Encrypt.
Then start the full enterprise stack behind the gateway.
With the local certificate overlay:
docker compose -f docker-compose.yml -f docker-compose.gateway.yml up -dWith the Let's Encrypt overlay:
docker compose -f docker-compose.yml -f docker-compose.letsencrypt.yml up -d --waitAll public traffic now goes through 443. Traefik terminates TLS, preserves the inbound Host header, and routes by host and path: the operator plane at https://platform.<base-domain> and each tenant at https://<tenant>.<base-domain>. Customers and operators call the gateway URLs, not the individual containers.
On a pristine deployment the setup gate is still open and non-platform
workloads have not received an activated license yet. They should nevertheless
be running. Direct workload /health probes may show 503 with
licenseStatus: MISSING until first-run setup imports the protected license
bundle and bootstraps the operator account.
The public surface is the gateway route table, not direct container ports. It is limited to the platform host and tenant hosts; Traefik maps paths on those hosts to the backing containers internally:
| Gateway host | Routed paths |
|---|---|
platform.<base-domain> |
Operator OAuth/OIDC metadata, /authorize, /token, /userinfo, /admin-console |
<tenant>.<base-domain> |
Public protocol/resolver paths such as /.well-known/did.json, tenant OAuth/OIDC metadata and auth paths, OID4VCI issuer paths, OID4VP verifier paths, plus authenticated operator/admin API paths if your gateway policy exposes them |
Runtime probes are internal Docker Compose or Kubernetes concerns. They are not routed as tenant public URLs.
The administrative REST paths (/api/.../v1) are controlled operator/admin
traffic, not public protocol endpoints. Keep them off the open public network
and reach them only through an authenticated gateway path or a private network
path protected by JWT and network policy.
The optional admin-console service is the Next.js operator admin UI. It comes up with the gateway overlay and is reachable at https://platform.<base-domain>/admin-console. The console listens on port 3000 and owns the /admin-console path prefix; the gateway routes /admin-console to it without stripping the prefix.
On a new installation, open https://platform.<base-domain>/setup-license,
or open https://platform.<base-domain>/admin-console and follow the setup
redirect. First-run setup generates the license request, imports the protected
license bundle, and creates the first platform operator account. Do not set the
operator email, license installation id, deployment id, or tenant slug in
.env just to start the stack; setup and tenant creation collect those values
when they are needed.
After setup closes the anonymous setup gate, open
https://platform.<base-domain>/admin-console and sign in with the operator
account. The console authenticates against the platform authorization server for
this host, then uses token exchange to act on tenant KMS and DID APIs. The
issuer/verifier testing console is available to external testers at
https://<instance-host>/testing-console/{kind}/{instanceId} when enabled for
that instance. Those hosts expose only the canonical page and narrowly scoped
protocol-BFF/static support paths;
the full admin console and platform admin APIs remain platform-host-only. For
details see configuration.md and
tls-and-gateway.md.
With first-run setup complete, create a tenant from the admin console or the platform admin REST API. Tenant registration requires tenant AS, tenant KMS, DID, issuer, and verifier to be running, because the platform seeds tenant signing material and tenant DID state through those east-west services.
The tenant workload services fetch their effective configuration from the
platform and serve the tenant endpoints registered during onboarding. If a
workload was not running when tenant registration starts, re-run the same
up -d command before registering the tenant.
The scripts/provision helper and Postman collection are optional validation
and automation tools. They call the same setup and tenant admin APIs against the
running platform, but they are not required for the normal customer setup path.
See onboarding.md.
docker compose -f docker-compose.yml down -vUse the same overlay file you used when starting the stack:
docker compose -f docker-compose.yml -f docker-compose.gateway.yml down -v
docker compose -f docker-compose.yml -f docker-compose.letsencrypt.yml down -vThe -v flag removes the stack volumes. Omit it to keep data between runs.