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