Overview
An installation has two sides, as the architecture page shows:
| Side | What runs there |
|---|---|
| Centre | the central service with its database, and the Train a model interface |
| Clinic | the clinic node with worker, trainer, inference service, model sync and dataset catalogue, and the Assess risk interface |
The clinic opens every connection itself: the worker and the model sync connect to the central service, and the centre never calls into the clinic. Both sides can also run within the same institution.
Project members receive the source code. Every image is built from it; the paths on this page refer to the repository.
Requirements
- Docker Engine 24 or later with Docker Compose v2.
- Processors are enough; no graphics card is needed. In the clinic's reference stack, the trainer is limited to 2 processor cores and 2 GB of memory.
- A few gigabytes of disk space for the images, and internet access while building: the builds fetch pinned base images and packages.
- For the centre's installation script, Python and openssl on the host.
- For the multi-site installation, a Bash shell; on Windows, Git Bash.
- To build without Docker, Node.js 24 or later and Python 3.10 or later.
The services and their connections:
| Port | Service | Who connects |
|---|---|---|
| 8794 | central service | the worker and model sync of each clinic, outbound from the clinic |
| 8080 | Train a model | browsers at the centre |
| 8081 | Assess risk | browsers on the clinic's network |
| 8795 | inference service | only Assess risk in the same clinic |
The platform needs no connection into the clinic. Restrict access to both interfaces through the institution's network.
Trying it out
The interfaces in demo mode
In the directory platform/software/frontend, with the two uvicorn commands in separate terminals:
cd web
npm ci
npm run build
cd ..
pip install -r requirements-demo.txt
HDP_DEMO=1 uvicorn app.main:app --port 8080
HDP_DEMO=1 uvicorn inference_app.main:app --port 8081
With Docker, no local packages are needed; one Dockerfile builds both interfaces:
docker build --target training -t hdp-training .
docker run --rm -p 8080:8080 -e HDP_DEMO=1 hdp-training
docker build --target inference -t hdp-inference .
docker run --rm -p 8081:8081 -e HDP_DEMO=1 hdp-inference
Train a model is then available at http://127.0.0.1:8080, and Assess risk at http://127.0.0.1:8081. The tutorial walks through both.
One centre and three clinics on one computer
In the directory platform/deploy/sites:
./sites.sh build
./sites.sh up
./sites.sh status
build builds the five images; up starts the centre and then clinics A, B and C, each on its own sealed network. Each clinic registers a dataset in its catalogue at start-up and fetches its model from the centre.
| Address | What runs there |
|---|---|
http://127.0.0.1:8080 | Train a model |
http://127.0.0.1:8794/docs | the central service's interfaces |
http://127.0.0.1:8181, :8182, :8183 | Assess risk of clinics A, B and C |
./sites.sh logs clinic-a shows a clinic's logs, and ./sites.sh cohort clinic-a evaluates its dataset. ./sites.sh down stops everything; ./sites.sh down -v also removes the database, catalogues and model registries. A further clinic comes from a copy of clinics/clinic-a.env with its own id, port and subnets.
Setting up the centre
The centre's operations package is in platform/software/backend/deploy:
./install.sh
docker compose up -d --build
install.sh writes a .env with a newly generated access token (HDP_API_TOKEN) and database password, without printing either, and sets up the model registry. The package starts the database and the central service; the database migrations run at start-up. The service listens on port 8794 at 127.0.0.1 (BACKEND_BIND). Make it available to the clinics through a TLS reverse proxy.
Build the Train a model interface in platform/software/frontend and connect it to the central service:
docker build --target training -t hdp-training .
docker run -d -p 8080:8080 \
-e HDP_BACKEND_URL=<address of the central service> \
-e HDP_BACKEND_TOKEN=<HDP_API_TOKEN from the .env> \
hdp-training
If the service presents a certificate from your own certificate authority, pass that authority to the interface with HDP_BACKEND_CA_FILE.
The clinics fetch their model from the centre's model registry. Put a model there with node-client registry push --backend-url <address> --job-id <id> --artifact <model file>; the model-publish service in platform/deploy/sites/central/compose.yaml shows the call for the seed model.
Setting up a clinic
Set up the clinic node as a container stack, modelled on platform/deploy/sites/clinic/compose.yaml: worker, trainer, inference service, model sync and the Assess risk interface, with volumes for the dataset catalogue, model registry, exchange files and journal. The trainer runs without a network and on a read-only file system. Start the worker and the trainer together: the worker takes a job only while the trainer is ready.
| Variable | Service | Meaning |
|---|---|---|
HD_BACKEND_URL | worker, model sync | address of the central service |
HD_API_TOKEN | worker, model sync | the centre's access token (HDP_API_TOKEN from its .env) |
HD_CA_FILE | worker, model sync | trust anchor for the connection to the centre; with it, the node connects over HTTPS only |
HD_NODE_NAME | worker | the node's name |
HD_SPOOL_DIR, HD_CATALOGUE_DIR, HD_EGRESS_JOURNAL_DIR | worker, trainer | directories for exchange files, the dataset catalogue and the journal |
HDP_REGISTRY | inference service | the clinic's model registry |
HDP_INFERENCE_URL | Assess risk | address of the inference service, such as http://inference:8795 |
HDP_CLINIC_NAME | Assess risk | the clinic's name, as the interface shows it as the location |
Data. Data enters the node through the dataset catalogue. node-client dataset register --from <directory> --label <name> --kind site --uses cohort-inference takes an export in the platform's data format, one CSV file per entity, as an immutable snapshot. The catalogue accepts the hospital's data only pseudonymised: the node's data connector writes the export with the key from node-client pseudonym-key init and adds a source-manifest.json. The data owner then approves the snapshot for its purpose with node-client dataset approve.
Model. The model sync fetches the model from the centre and checks it against pinned SHA-256 checksums for the model and its operating point (node-client registry sync). The values for the seed model are in platform/deploy/sites/sites.env.
Checking the installation
- Centre:
curl -s http://127.0.0.1:8794/healthreports"status":"ok"and the database as its store.docker compose exec backend python -m app.hdpctl statussums up the state;jobs,nodesandmodelslist jobs, participating nodes and models. - Interfaces:
/api/healthreports for each connected service whether it can be reached. - Node:
node-client healthchecks the connection to the centre,node-client registry verify --root <model registry>the model registry, andnode-client egress verifythe journal of every message that left. - First training run: start a job in Train a model. Its status moves from submitted through accepted and running to completed, and the node shown is the clinic that ran it.
- First assessment: calculate a single case in Assess risk.
Detailed guides
| Topic | In the repository |
|---|---|
| Multi-site installation | platform/deploy/sites/README.md |
| The centre's operations package | platform/software/backend/deploy/README-Betrieb.md |
| Credentials and certificates | platform/software/backend/docs/credentials-and-enrolment.md |
| Interfaces | platform/software/frontend/README.md |
| Clinic node, trainer and egress gate | platform/software/node-client/README.md, docs/training-sandbox.md, docs/export-contract.en.md |