-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
534 lines (503 loc) · 22.4 KB
/
Copy pathdocker-compose.yml
File metadata and controls
534 lines (503 loc) · 22.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
services:
knooppunt:
build: .
ports:
- "8080:8080"
- "8081:8081"
environment:
KNPT_MCSDADMIN_FHIRBASEURL: http://hapi-fhir:7050/fhir/knpt-mcsd-admin
KNPT_MCSD_QUERY_FHIRBASEURL: http://hapi-fhir:7050/fhir/knpt-mcsd-query
# The seeded LRZa tenant, NOT the external test LRZa. The seed registers the
# demo organizations (De Plataan, Zonnebloem, Care2Cure) here, and the mCSD
# sync walks this directory to populate the query directory. Pointing this
# at the external LRZa instead yields a query directory full of unrelated
# organizations and none of the demo ones — so the seeded patient would be
# findable but not addressable.
KNPT_MCSD_ADMIN_LRZA_FHIRBASEURL: http://hapi-fhir:7050/fhir/lrza-mcsd-admin
KNPT_NVI_BASEURL: http://hapi-fhir:7050/fhir/nvi
KNPT_TRACING_OTLPENDPOINT: ${KNPT_TRACING_OTLPENDPOINT:-aspire-dashboard:18890}
# The PDP's Policy Information Point resolves Patient/<id> to a BSN, which
# the BGZ policy needs before it will ask Mitz for consent. It must point at
# the tenant that actually holds the data being protected — the seeded pool
# patients live in sunflower-patients, not in the generic PIP tenant. With
# the wrong tenant the lookup 404s, no BSN is derived, MitzConsent stays
# false and every request is denied with an opaque 403.
#
# NOTE: this makes the composed PDP single-data-holder. It is correct while
# Zonnebloem is the only organization serving data through a PEP here; once
# both demo organizations hold data, the PIP has to become per-tenant.
KNPT_PDP_PIP_URL: http://hapi-fhir:7050/fhir/sunflower-patients
# Trust the test CA that issues the demo X509Credentials. Go reads
# SSL_CERT_FILE once at process start, so it has to be an environment
# variable rather than config.
#
# ⚠️ This REPLACES the system trust store: any outbound HTTPS from the
# knooppunt will fail verification. That is why the external LRZa sync is
# disabled below — otherwise its TLS errors fill the logs and mask real
# failures in the authorization chain.
SSL_CERT_FILE: /app/certs/ca.pem
# Empty disables the LRZa sync client (see lrza.Config.Enabled).
KNPT_LRZA_LRZABASEURL: ""
KNPT_MITZ_MITZBASE: http://mitzmock:8080
volumes:
- ./config:/app/config:ro
- ./test/e2e/pep/certs/ca.pem:/app/certs/ca.pem:ro
# Seeds FHIR test data, creates a Nuts subject per demo organization and writes
# each subject's DID to the shared scratch volume for the credential issuers.
init:
image: golang:1.24.4-alpine
depends_on:
hapi-fhir-healthcheck:
condition: service_completed_successfully
knooppunt-healthcheck:
condition: service_completed_successfully
environment:
# Publish the mCSD Endpoints (and the discovery registrations) at each
# organization's PEP rather than straight at HAPI, so a resolved address
# leads through the authorization chain instead of bypassing it.
#
# ⚠️ These hostnames resolve only INSIDE the compose network. From the host,
# use http://localhost:9080/fhir (Zonnebloem) and :9081 (De Plataan).
SEED_ZONNEBLOEM_ENDPOINT_ADDRESS: http://pep-zonnebloem:8080/fhir
SEED_PLATAAN_ENDPOINT_ADDRESS: http://pep-plataan:8080/fhir
# Where to write the created DIDs for the credential-issuer services.
SEED_DID_DIR: /shared
volumes:
- ./test/testdata:/app/:ro
- seed-shared:/shared
command: /bin/sh -c "cd /app && go run main.go http://knooppunt:8081 http://hapi-fhir:7050/fhir"
nutsadmin:
image: nutsfoundation/nuts-admin:6.2.1
volumes:
- "./config/nuts-admin.yml:/app/config.yml:ro"
ports:
- "1305:1305"
environment:
NUTS_NODE_ADDRESS: http://knooppunt:8081/nuts
NUTS_CONFIGFILE: /app/config.yml
# PostgreSQL Database
# postgres:
# image: postgres:14
# container_name: hapi-postgres
# environment:
# POSTGRES_DB: hapi
# POSTGRES_USER: admin
# POSTGRES_PASSWORD: admin
# ports:
# - "5432:5432"
# volumes:
# - postgres-data:/var/lib/postgresql/data
# healthcheck:
# test: ["CMD-SHELL", "pg_isready -U admin -d hapi"]
# interval: 10s
# timeout: 5s
# retries: 5
# start_period: 10s
# restart: unless-stopped
# HAPI FHIR Server
hapi-fhir:
# :main, not :latest. The e2e harness pins :main (test/e2e/harness/hapi.go), and :latest
# lags it far enough to reject the "subject:identifier" modifier the NVI component sends,
# which fails the seed at boot with a transient error and leaves `docker compose up`
# without a dataset. Two tags for one component is how that went unnoticed: the e2e
# suite passed on :main while compose was broken on :latest.
image: ghcr.io/nuts-foundation/fake-nvi:main # hapi with our NVI specifics
container_name: hapi-fhir-server
ports:
- "7050:7050"
# depends_on:
# postgres:
# condition: service_healthy
environment:
# For a full list of options, see https://github.com/nuts-foundation/nuts-knooppunt/blob/8463b719caca0a3dd8623a36188a4e1423faa8bb/config/hapi.application.dev.yml
#
# Properties that should be enabled when deploying to test/production/etc
#
# spring.datasource.url: jdbc:postgresql://postgres:5432/hapi
# spring.datasource.username: admin
# spring.datasource.password: admin
# spring.datasource.driverClassName: org.postgresql.Driver
# spring.jpa.properties.hibernate.dialect: "ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect"
hapi.fhir.server_address: http://localhost:7050/fhir
hapi.fhir.version: R4
# Prevents encoding of the pipe char in queries
server.tomcat.relaxed-query-chars: "|"
server.port: 7050
# should be an ADR? How does this behave?
hapi.fhir.allow_cascading_deletes: true
# Lets the server generate UUIDs for resources instead of integers
hapi.fhir.server_id_strategy: UUID
# Allow storing of meta.source as provided by the client (used by mCSD to reference the originating resource)
hapi.fhir.store_meta_source_information: SOURCE_URI
NVI_AUDIENCE: nvi
NVI_TENANT: nvi
# OpenTelemetry - enables full trace/log visibility into HAPI FHIR
JAVA_TOOL_OPTIONS: "-javaagent:/app/opentelemetry-javaagent.jar"
OTEL_SERVICE_NAME: "hapi-fhir"
OTEL_EXPORTER_OTLP_ENDPOINT: "http://aspire-dashboard:18890"
OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf"
OTEL_PROPAGATORS: "tracecontext,baggage"
OTEL_LOGS_EXPORTER: "otlp"
#
# Local development properties (not to be used when deploying to test/production)
#
# Allows clients to set UUID on resources, is this needed?
hapi.fhir.client_id_strategy: ANY
# Allows for expung operations, handy during development
hapi.fhir.delete_expunge_enabled: true
hapi.fhir.allow_multiple_delete: true # to allow $expunge on system-level
# Adds some default configs to the HAPI web UI for development
hapi.fhir.tester.admin.name: Local Administration Directory
hapi.fhir.tester.admin.server_address: http://localhost:7050/fhir/knpt-mcsd-admin
hapi.fhir.tester.admin.refuse_to_fetch_third_party_urls: false
hapi.fhir.tester.admin.fhir_version: R4
hapi.fhir.tester.query.name: Local Query Directory
hapi.fhir.tester.query.server_address: http://localhost:7050/fhir/knpt-mcsd-query
hapi.fhir.tester.query.refuse_to_fetch_third_party_urls: false
hapi.fhir.tester.query.fhir_version: R4
hapi.fhir.tester.lrza.name: Local LRZA
hapi.fhir.tester.lrza.server_address: http://localhost:7050/fhir/lrza-mcsd-admin
hapi.fhir.tester.lrza.refuse_to_fetch_third_party_urls: false
hapi.fhir.tester.lrza.fhir_version: R4
hapi.fhir.tester.care2cure.name: Care2Cure Admin Directory
hapi.fhir.tester.care2cure.server_address: http://localhost:7050/fhir/care2cure-admin
hapi.fhir.tester.care2cure.refuse_to_fetch_third_party_urls: false
hapi.fhir.tester.care2cure.fhir_version: R4
hapi.fhir.tester.sunflower.name: Sunflower Admin Directory
hapi.fhir.tester.sunflower.server_address: http://localhost:7050/fhir/sunflower-admin
hapi.fhir.tester.sunflower.refuse_to_fetch_third_party_urls: false
hapi.fhir.tester.sunflower.fhir_version: R4
hapi.fhir.tester.sunflowerpatients.name: Sunflower Patients Directory
hapi.fhir.tester.sunflowerpatients.server_address: http://localhost:7050/fhir/sunflower-patients
hapi.fhir.tester.sunflowerpatients.refuse_to_fetch_third_party_urls: false
hapi.fhir.tester.sunflowerpatients.fhir_version: R4
hapi.fhir.tester.plataan.name: Plataan Admin Directory
hapi.fhir.tester.plataan.server_address: http://localhost:7050/fhir/plataan-admin
hapi.fhir.tester.plataan.refuse_to_fetch_third_party_urls: false
hapi.fhir.tester.plataan.fhir_version: R4
hapi.fhir.tester.plataanpatients.name: Plataan Patients Directory
hapi.fhir.tester.plataanpatients.server_address: http://localhost:7050/fhir/plataan-patients
hapi.fhir.tester.plataanpatients.refuse_to_fetch_third_party_urls: false
hapi.fhir.tester.plataanpatients.fhir_version: R4
hapi.fhir.tester.nvi.name: NVI
hapi.fhir.tester.nvi.server_address: http://localhost:7050/fhir/nvi
hapi.fhir.tester.nvi.refuse_to_fetch_third_party_urls: false
hapi.fhir.tester.nvi.fhir_version: R4
hapi.fhir.tester.pip.name: PIP
hapi.fhir.tester.pip.server_address: http://localhost:7050/fhir/policy-information-point
hapi.fhir.tester.pip.refuse_to_fetch_third_party_urls: false
hapi.fhir.tester.pip.fhir_version: R4
# Enable partitioning and allow string tenant identifiers
hapi.fhir.partitioning.allow_references_across_partitions: false
restart: unless-stopped
hapi-fhir-healthcheck:
image: curlimages/curl:7.87.0
depends_on:
- hapi-fhir
entrypoint:
[
"sh",
"-c",
"echo 'Starting fhirstore healthcheck...'; while ! curl -s -f http://hapi-fhir:7050/fhir/DEFAULT/Task > /dev/null; do echo 'Waiting for HAPI FHIR to be ready...'; sleep 5; done; echo 'HAPI FHIR is up and running.'",
]
# Ensure the container exits successfully after the check
restart: "no"
# The init service seeds NVI Lists through the Knooppunt's internal API, so it
# must wait for the Knooppunt to accept requests — not just for HAPI.
knooppunt-healthcheck:
image: curlimages/curl:7.87.0
depends_on:
- knooppunt
entrypoint:
[
"sh",
"-c",
"echo 'Starting knooppunt healthcheck...'; while ! curl -s -f http://knooppunt:8081/status > /dev/null; do echo 'Waiting for Knooppunt to be ready...'; sleep 5; done; echo 'Knooppunt is up and running.'",
]
# Ensure the container exits successfully after the check
restart: "no"
# Mock MITZ closed-question (consent) service. The real Mitz is a national
# service that is not reachable from a local deployment, but the BGZ policy
# will not permit a retrieval without a consent decision — so AC1 needs one
# locally. Answers Permit by default; see test/mitzmock/cmd/main.go.
mitzmock:
build:
context: .
dockerfile: test/mitzmock/Dockerfile
container_name: knooppunt-mitzmock
ports:
- "8087:8080"
# ---------------------------------------------------------------------------
# Credential issuance
#
# did:web subject DIDs contain a fresh UUID per subject creation, so an
# X509Credential — which binds credentialSubject.id to that DID — cannot be
# generated ahead of time and committed. It has to be issued after the subject
# exists, which is why this runs as compose services rather than as fixtures.
#
# Ordering: init (creates subjects, writes DIDs) → credential-issuer-* (mint
# the JWT VCs) → init-credentials (store them in the wallets, register on
# discovery, seed the NVI).
# ---------------------------------------------------------------------------
credential-issuer-plataan:
image: nutsfoundation/go-didx509-toolkit:main
depends_on:
init:
condition: service_completed_successfully
volumes:
- ./test/e2e/pep/certs:/certs:ro
- seed-shared:/shared
entrypoint: ["/bin/sh", "-c"]
command:
- |
set -e
/usr/bin/didx509-toolkit vc /certs/plataan-chain.pem /certs/plataan.key "CN=Fake UZI Root CA" "$$(cat /shared/plataan.did)" > /shared/plataan.jwt
echo "issued X509Credential for plataan"
credential-issuer-zonnebloem:
image: nutsfoundation/go-didx509-toolkit:main
depends_on:
init:
condition: service_completed_successfully
volumes:
- ./test/e2e/pep/certs:/certs:ro
- seed-shared:/shared
entrypoint: ["/bin/sh", "-c"]
command:
- |
set -e
/usr/bin/didx509-toolkit vc /certs/zonnebloem-chain.pem /certs/zonnebloem.key "CN=Fake UZI Root CA" "$$(cat /shared/zonnebloem.did)" > /shared/zonnebloem.jwt
echo "issued X509Credential for zonnebloem"
# Stores the issued credentials in each subject's wallet, registers both on the
# discovery service, then seeds the NVI localization records. NVI seeding runs
# last so a failure to authorize is not masked by a half-seeded index.
init-credentials:
image: golang:1.24.4-alpine
depends_on:
credential-issuer-plataan:
condition: service_completed_successfully
credential-issuer-zonnebloem:
condition: service_completed_successfully
environment:
SEED_DID_DIR: /shared
SEED_ZONNEBLOEM_ENDPOINT_ADDRESS: http://pep-zonnebloem:8080/fhir
SEED_PLATAAN_ENDPOINT_ADDRESS: http://pep-plataan:8080/fhir
volumes:
- ./test/testdata:/app/:ro
- seed-shared:/shared
command: /bin/sh -c "cd /app && go run ./cmd/credentials http://knooppunt:8081"
vektis-issuer:
image: ghcr.io/nuts-foundation/mock-vc-issuer:latest
build:
context: ./mock-components/vc-issuer
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
DATABASE_URL: file:vc-issuer.db
NEXT_PUBLIC_BASE_URL: http://localhost:3000
ISSUER_HOSTNAME: localhost:3000
NUTS_NODE_INTERNAL_URL: http://knooppunt:8081/nuts
NUTS_ISSUER_DID: TODO
# ---------------------------------------------------------------------------
# Policy Enforcement Points (NGINX-based reference implementation)
#
# The PEP is single-tenant by design (pep/README.md), so each demo organization
# gets its own container. Both run the SAME image and differ only by
# environment, so there is no per-tenant build.
#
# These are deliberately NOT behind a `profiles:` key. AC1 requires a fresh
# `docker compose up` to yield a retrievable patient, and requiring
# `--profile pep` would make that a manual step.
#
# ⚠️ FHIR_BASE_PATH must stay identical on both: authorize.js reads it via
# process.env, and nginx.conf only exports the variables it declares with
# `env`. Per-organization routing is done with FHIR_UPSTREAM_PATH, which is
# consumed by envsubst when the config is rendered.
# ---------------------------------------------------------------------------
# Zonnebloem is the data holder on the AC1 path: the seeded pool patients live
# in its tenant, and its mCSD Endpoint resolves here.
pep-zonnebloem:
build:
context: ./pep/nginx
dockerfile: Dockerfile
container_name: knooppunt-pep-zonnebloem
ports:
- "9080:8080"
volumes:
- ./pep/logs/zonnebloem:/var/log/nginx
environment:
# Backend connections
- FHIR_BACKEND_HOST=hapi-fhir
- FHIR_BACKEND_PORT=7050
- FHIR_BASE_PATH=/fhir
- FHIR_UPSTREAM_PATH=/fhir/sunflower-patients
- KNOOPPUNT_PDP_HOST=knooppunt
- KNOOPPUNT_PDP_PORT=8081
# Nuts node connection (Authorization Server)
- NUTS_NODE_HOST=knooppunt
- NUTS_NODE_INTERNAL_PORT=8081
# Data holder (this organization): Zorgcentrum De Zonnebloem
- DATA_HOLDER_ORGANIZATION_URA=00000020
- DATA_HOLDER_FACILITY_TYPE=Z3
depends_on:
hapi-fhir-healthcheck:
condition: service_completed_successfully
knooppunt-healthcheck:
condition: service_completed_successfully
healthcheck:
# Must be 127.0.0.1, not localhost: nginx.conf uses `listen 8080` (IPv4
# only), while wget resolves "localhost" to ::1 first via /etc/hosts and
# gets connection refused, leaving the container permanently unhealthy.
test:
["CMD", "wget", "--spider", "--quiet", "http://127.0.0.1:8080/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
# De Plataan is the requester on the AC1 path and holds no data that AC1
# retrieves, but its seeded Endpoint must resolve to a PEP for the same reason
# Zonnebloem's does (DESIGN §5.4) — otherwise the addressing story is only half
# true.
pep-plataan:
build:
context: ./pep/nginx
dockerfile: Dockerfile
container_name: knooppunt-pep-plataan
ports:
- "9081:8080"
volumes:
- ./pep/logs/plataan:/var/log/nginx
environment:
- FHIR_BACKEND_HOST=hapi-fhir
- FHIR_BACKEND_PORT=7050
- FHIR_BASE_PATH=/fhir
- FHIR_UPSTREAM_PATH=/fhir/plataan-patients
- KNOOPPUNT_PDP_HOST=knooppunt
- KNOOPPUNT_PDP_PORT=8081
- NUTS_NODE_HOST=knooppunt
- NUTS_NODE_INTERNAL_PORT=8081
# Data holder (this organization): Ziekenhuis De Plataan
- DATA_HOLDER_ORGANIZATION_URA=00000010
- DATA_HOLDER_FACILITY_TYPE=Z3
depends_on:
hapi-fhir-healthcheck:
condition: service_completed_successfully
knooppunt-healthcheck:
condition: service_completed_successfully
healthcheck:
test:
["CMD", "wget", "--spider", "--quiet", "http://127.0.0.1:8080/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
demo-dezi-client:
image: ghcr.io/nuts-foundation/demo-dezi-client:latest
build:
context: ./mock-components/demo-dezi-client
dockerfile: Dockerfile
profiles:
- demoehr
container_name: demo-dezi-client
ports:
- "8090:8090"
environment:
DEZI_AUTHORITY: https://acceptatie.auth.dezi.nl
DEZI_CLIENT_ID: cb96e3fb-394c-4d12-b2b2-7a1a7bbe0b02
DEZI_REDIRECT_URI: http://localhost:8090/callback
SERVER_PORT: 8090
FRONTEND_BASE_URL: http://localhost:8091
demo-ehr:
build:
context: ./mock-components/demo-ehr
dockerfile: Dockerfile.dev
profiles:
- demoehr
container_name: demo-ehr
ports:
- "8091:3000"
volumes:
- ./mock-components/demo-ehr/src:/app/src
- ./mock-components/demo-ehr/public:/app/public
environment:
- CHOKIDAR_USEPOLLING=true # For hot reload on some systems
- REACT_APP_DEV_LOGIN=1 # Enables a "Dev login" button that bypasses Dezi auth; never set in deployed envs
- REACT_APP_AUTH_BASE_URL=http://localhost:8090
- REACT_APP_FHIR_BASE_URL=https://server.fire.ly/R4 # adjust this to a local FHIR server or a different one if needed
- REACT_APP_FHIR_STU3_BASE_URL=https://server.fire.ly/R3 # adjust this to a local FHIR server or a different one if needed
- REACT_APP_FHIR_MCSD_QUERY_BASE_URL=http://hapi-fhir:7050/fhir/knpt-mcsd-query
- REACT_APP_ORGANIZATION_URA=
stdin_open: true
tty: true
gf-sandbox:
build:
context: .
dockerfile: sandbox/app/Dockerfile
ports:
- "8091:8091" # same host port as demo-ehr maps; don't combine --profile demoehr with --profile sandbox (split lands with E7)
environment:
DEZI_PUBLIC_AUTHORIZE_URL: http://localhost:8092/authorize
DEZI_INTERNAL_BASE_URL: http://mock-dezi:8092
SANDBOX_PUBLIC_URL: http://localhost:8091
# Enable the reset/recycle actions: the sandbox backend calls the
# Knooppunt internal /nvi endpoint and HAPI to restore the seeded dataset.
KNOOPPUNT_INTERNAL_URL: http://knooppunt:8081
HAPI_BASE_URL: http://hapi-fhir:7050/fhir
# The ordering that makes the authorization route work lives in
# docker-compose.sandbox.yml: it depends on a service only that file defines.
# Spelled in mapping form to match the override there. Compose 5.3.0 merges
# list and mapping notation additively either way, but matching notation
# means this dependency's survival does not rest on that.
depends_on:
mock-dezi:
condition: service_started
knooppunt:
condition: service_started
hapi-fhir:
condition: service_started
profiles:
- sandbox
mock-dezi:
build:
context: .
dockerfile: mock-components/dezi/Dockerfile
ports:
- "8092:8092"
- "8443:8443"
environment:
TLS_CERT_FILE: /certs/mock-dezi.pem
TLS_KEY_FILE: /certs/mock-dezi.key
DEZI_SIGNING_KEY_FILE: /certs/dezi-signing.key
DEZI_JKU: https://mock-dezi:8443/dezi/jwks.json
# The only callback /authorize will bind. Matched exactly; without it the
# mock redirects a browser wherever a link asks. Keep in step with the
# sandbox service's SANDBOX_PUBLIC_URL above.
DEZI_ALLOWED_REDIRECT_URIS: http://localhost:8091/demo/auth/callback
volumes:
# Generated by sandbox/generate-demo-certs.sh; gitignored, never committed.
# Mounted per file rather than the whole directory: mock-dezi only ever
# reads TLS_CERT_FILE, TLS_KEY_FILE and DEZI_SIGNING_KEY_FILE below.
# ca.key (the demo CA's private key) is deliberately not mounted here;
# it can mint further certificates and mock-dezi has no use for it.
- ./sandbox/.certs/mock-dezi.pem:/certs/mock-dezi.pem:ro
- ./sandbox/.certs/mock-dezi.key:/certs/mock-dezi.key:ro
- ./sandbox/.certs/dezi-signing.key:/certs/dezi-signing.key:ro
profiles:
- sandbox
# Aspire Dashboard - unified observability for traces, logs, and metrics
# UI available at http://localhost:18888
aspire-dashboard:
image: mcr.microsoft.com/dotnet/aspire-dashboard:latest
container_name: aspire-dashboard
ports:
- "18888:18888" # Dashboard UI
- "4317:18889" # OTLP gRPC endpoint
- "4318:18890" # OTLP HTTP endpoint
environment:
DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS: "true"
volumes:
#postgres-data:
hapi-data:
# Scratch space shared by the seed pipeline: init writes <org>.did, the
# credential issuers write <org>.jwt, init-credentials consumes both.
seed-shared: