Overview

HAPI FHIR R4 starter backed by PostgreSQL with SMART-on-FHIR auth. This is a HIPAA-aware baseline - add your specific Business Associate Agreement requirements on top.

application.yaml

spring:
  datasource:
    url:      jdbc:postgresql://localhost:5432/hapifhir
    username: ${DB_USER}
    password: ${DB_PASS}
    driver-class-name: org.postgresql.Driver
    hikari:
      maximum-pool-size:   20
      minimum-idle:        5
      connection-timeout:  30000
      idle-timeout:        600000
      max-lifetime:        1800000
  jpa:
    properties:
      hibernate:
        dialect:               org.hibernate.dialect.PostgreSQLDialect
        search.enabled:        false   # use Elasticsearch separately
        hbm2ddl.auto:         validate  # never 'create-drop' in production
        jdbc.batch_size:       20
        order_inserts:         true

hapi:
  fhir:
    fhir_version: R4
    server_address: https://fhir.example.com/fhir

    cors:
      allow_Credentials: true
      allowed_origin:
        - https://app.example.com

    # SMART-on-FHIR OAuth2
    smart_capabilities_list:
      - LAUNCH_STANDALONE
      - CLIENT_PUBLIC
      - PERMISSION_PATIENT
      - PERMISSION_USER

    openid_connect:
      issuer:                 https://auth.example.com
      jwks_uri:               https://auth.example.com/.well-known/jwks.json
      userinfo_endpoint:      https://auth.example.com/userinfo
      authorization_endpoint: https://auth.example.com/authorize
      token_endpoint:         https://auth.example.com/token

    # Subscriptions (push notifications on resource changes)
    subscription:
      resthook_enabled: true
      websocket_enabled: false

    # Binary resource storage (S3 recommended for production)
    binary_storage_enabled: true

    # Audit logging - required for HIPAA
    audit_enabled: true
    audit_log_path: /var/log/hapi-fhir/audit.log

    validation:
      requests_enabled:  true
      responses_enabled: false   # enable for debugging only

    default_page_size:   20
    max_page_size:       200

Docker Compose snippet

services:
  fhir:
    image: hapiproject/hapi:latest
    ports:
      - "8080:8080"
    environment:
      spring.config.location: file:///app/config/application.yaml
      DB_USER: ${DB_USER}
      DB_PASS: ${DB_PASS}
    volumes:
      - ./application.yaml:/app/config/application.yaml
    depends_on:
      db:
        condition: service_healthy

HIPAA checklist

  • TLS 1.2+ termination at load balancer
  • Audit log shipped to immutable store (CloudTrail / S3 with Object Lock)
  • Database encryption at rest (PostgreSQL TDE or disk-level)
  • Secrets via Vault or AWS Secrets Manager - not env vars in compose
  • Access tokens expire in ≤ 1 hour