Get started
Requirements
Host sizing, storage, network egress and what the hospital PACS must allow.
Accounts and tools
- Docker Engine 24.0 or newer with Docker Compose (the README states v2.24.7 or newer; check with
docker compose version). - A Docker Hub account (to pull
heartwisehubimages; credentials go inDOCKER_USERNAME/DOCKER_PASSWORDwhen images are private). For a private registry,docker login <registry>first, thendocker compose pull; skipgit checkoutwhen shipping images only. - A Google Cloud Platform project with Identity Platform and Firebase (one account; they are linked). The free tier is sufficient but a billing account must be attached.
- A Mailgun account and a verified sending domain for transactional email (verification, invites, password resets).
- A TLS certificate for nginx: customer-provided, ACME (Let's Encrypt) or an internal CA. Self-signed certificates are generated if none are supplied and browsers will warn.
-
makeon the host (apt-get install makeordnf install make),jqanddockerfor the model deployment script, anddcmtk(echoscu,findscu,movescu) for connectivity checks.
Host sizing tiers
| Component | Minimum | Recommended | Production |
|---|---|---|---|
| OS | RHEL 9 or Ubuntu 22.04 | RHEL 9 or Ubuntu 22.04 | RHEL 9 or Ubuntu 22.04 |
| GPU | NVIDIA RTX 3090 (24 GB) | NVIDIA RTX 4090 (24 GB) | NVIDIA A6000 (48 GB) or multi-GPU |
| GPU VRAM | 16 GB | 24 GB | 48 GB or more |
| System RAM | 64 GB | 128 GB | 256 GB |
| CPU | 8 cores | 16 cores | 32 or more cores |
| System storage | 256 GB SSD | 500 GB NVMe | 1 TB or more NVMe RAID |
| Network | 1 Gbps | 1 Gbps | 10 Gbps |
| CUDA / driver | 12.1 or newer, driver 525.x or newer | same | same |
The GPU tier applies only to hosts that run model containers. If inference runs on a separate GPU host, the api-pacs, Orthanc and data-store host can use the minimum CPU and RAM column without a GPU (see the no-GPU compose override in Configuration).
DICOM storage sizing
Orthanc is a rolling 24-hour cache, not an archive. Storage only needs to cover the working set in flight. Plan disk as average study size x studies per day x 1.3 (the 1.3 covers in-flight overlap at the cleanup boundary plus index overhead), then recalibrate on a two-week sample after the first install. The cache lifetime is ORTHANC_LOCAL_CACHE_EXPIRATION_IN_HOURS (default 24); if a customer needs a longer working window, for example for retries after a model failure, increase it and redo the disk math, because usage scales linearly with the window.
| Modality | Typical range | Planning value | Notes |
|---|---|---|---|
| Echo (US, TTE) | 100 to 500 MB | 300 MB | Cine-loop heavy; stress or pediatric echo can reach 1 GB |
| XA (coronary angiography) | 200 to 800 MB | 500 MB | Multiple cine runs at 15 to 30 fps |
| CT (cardiac, CTA) | 300 MB to 1.5 GB | 800 MB | Thin-slice CCTA can reach 2 GB; chest-only CT closer to 200 MB |
Outbound network access (HTTPS, port 443)
| Destination | Purpose | Required |
|---|---|---|
*.googleapis.com, securetoken.google.com | Firebase authentication | Yes |
hub.docker.com, registry-1.docker.io, *.cloudflare.docker.com | Pull PACS-AI images from heartwisehub | Yes |
huggingface.co, cdn-lfs.huggingface.co | Model weights on first run or image build | Yes |
api.mailgun.net | Transactional email | Yes |
*.api.mailchimp.com | Marketing list sync | Optional |
*.docusign.net, *.docusign.com | DocuSign e-signature | Optional |
challenges.cloudflare.com | Cloudflare Turnstile bot challenge | Optional (required when public registration or adaptive login is enabled) |
DICOM connectivity with the hospital PACS
| Direction | Protocol | Port | Purpose |
|---|---|---|---|
| api-pacs to remote PACS | DICOM DIMSE | customer-defined (104, 11112 or a hospital-assigned high port are common) | C-FIND, C-MOVE |
| remote PACS to Orthanc | DICOM DIMSE | ORTHANC_DICOM_PORT (4242 in the development compose and the deployment guide) | C-STORE study transfer |
The customer must whitelist the api-pacs host, its AE title and IP on the source PACS. A static IP and resolvable hostname for the API endpoint are required (api.<customer-domain> A record to the host, optionally orthanc.<customer-domain> if Orthanc is exposed).
Port matrix (as shipped in the compose files)
| Service | Container port | Host binding | Consumer |
|---|---|---|---|
| nginx | 80 / 443 | 80 / 443, public | Browsers, API clients |
| pacs-ai viewer | 80 | not published (nginx only) | nginx |
| api-pacs | 8000 | 127.0.0.1:8000 only | nginx, local diagnostics |
| Orthanc REST | 8042 | 8042 on all interfaces, with Orthanc authentication disabled | api-pacs, study-service, smoke tests |
| Orthanc DIMSE | ORTHANC_DICOM_PORT | same port on all interfaces | Remote PACS C-STORE |
| study-service | 8600 | not published | api-pacs |
| PostgreSQL control | 5432 | 5433 on all interfaces | api-pacs |
| PostgreSQL cardio | 5432 | 5434 on all interfaces | study-service, Celery |
| Redis | 6379 | not published | study-service, Celery, api-pacs |
| Elasticsearch | 9200 | not published | api-pacs |
| Kibana | 5601 | 5601 on all interfaces | Operators |
| Ollama, orchestrator | 11434, 8585 | not published, optional | orchestrator, api-pacs |
ss -tlnp after install and block those ports at the host firewall or rebind them to 127.0.0.1 in a compose override. Never publish port 8000 externally as plain HTTP; the login endpoint carries passwords and must only be reached through the nginx TLS listener.