Skip to content

Deployment

OctoFHIR is distributed as a Docker image via GitHub Container Registry.

Terminal window
docker pull ghcr.io/octofhir/octofhir-server:latest

Create a docker-compose.yml:

services:
postgres:
image: postgres:16
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: octofhir
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
octofhir:
image: ghcr.io/octofhir/octofhir-server:latest
ports:
- "8888:8888"
environment:
# Database connection
OCTOFHIR__STORAGE__POSTGRES__HOST: postgres
OCTOFHIR__STORAGE__POSTGRES__PORT: 5432
OCTOFHIR__STORAGE__POSTGRES__USER: postgres
OCTOFHIR__STORAGE__POSTGRES__PASSWORD: postgres
OCTOFHIR__STORAGE__POSTGRES__DATABASE: octofhir
# Admin credentials (change in production!)
OCTOFHIR__BOOTSTRAP__ADMIN_USER__USERNAME: admin
OCTOFHIR__BOOTSTRAP__ADMIN_USER__PASSWORD: your-secure-password
OCTOFHIR__BOOTSTRAP__ADMIN_USER__EMAIL: admin@example.com
# Auth issuer (set to your public URL)
OCTOFHIR__AUTH__ISSUER: https://fhir.example.com
depends_on:
postgres:
condition: service_healthy
volumes:
- fhir_packages:/opt/octofhir/data/.fhir
volumes:
postgres_data:
fhir_packages:

Start the services:

Terminal window
docker compose up -d

The server will be available at http://localhost:8888.

All configuration options can be set via environment variables using the OCTOFHIR__ prefix with double underscores for nested keys:

Environment VariableDescriptionDefault
OCTOFHIR__SERVER__PORTServer port8888
OCTOFHIR__STORAGE__POSTGRES__HOSTPostgreSQL hostpostgres
OCTOFHIR__STORAGE__POSTGRES__PORTPostgreSQL port5432
OCTOFHIR__STORAGE__POSTGRES__USERPostgreSQL userpostgres
OCTOFHIR__STORAGE__POSTGRES__PASSWORDPostgreSQL passwordpostgres
OCTOFHIR__STORAGE__POSTGRES__DATABASEDatabase nameoctofhir
OCTOFHIR__STORAGE__POSTGRES__URLFull connection URL (overrides individual settings)-
OCTOFHIR__FHIR__VERSIONFHIR version (R4, R4B, R5, R6)R4
OCTOFHIR__AUTH__ISSUEROAuth issuer URLhttp://localhost:8888
OCTOFHIR__BOOTSTRAP__ADMIN_USER__USERNAMEInitial admin usernameadmin
OCTOFHIR__BOOTSTRAP__ADMIN_USER__PASSWORDInitial admin passwordadmin
OCTOFHIR__REDIS__ENABLEDEnable Redis cachefalse
OCTOFHIR__REDIS__URLRedis URLredis://redis:6379
RUST_LOGLog levelinfo

Mount a custom configuration file:

Terminal window
docker run -d \
-p 8888:8888 \
-v ./octofhir.toml:/opt/octofhir/config/octofhir.toml:ro \
-v octofhir-data:/opt/octofhir/data \
ghcr.io/octofhir/octofhir-server:latest
  1. Change default credentials immediately after deployment
  2. Use HTTPS via a reverse proxy (nginx, Traefik, Caddy)
  3. Set proper issuer URL matching your public domain
  4. Generate production JWT keys (see JWT Key Persistence)
  1. Use a managed PostgreSQL service or properly configured instance
  2. Enable connection pooling (PgBouncer) for high traffic
  3. Regular backups and point-in-time recovery

For horizontal scaling, enable Redis:

environment:
OCTOFHIR__REDIS__ENABLED: "true"
OCTOFHIR__REDIS__URL: redis://redis:6379

The server exposes a health check endpoint:

Terminal window
curl http://localhost:8888/healthz

If you need to build the image locally:

Terminal window
# Clone the repository
git clone https://github.com/octofhir/server-rs.git
cd server-rs
# Build the image
just docker-build
# Or manually
docker build -t octofhir-server .

Available just commands:

CommandDescription
just docker-buildBuild Docker image with git tag
just docker-build-freshBuild without cache
just docker-pushPush to GitHub Container Registry
just docker-releaseBuild and push
just docker-runRun locally with docker-compose postgres
just docker-loginLogin to GHCR

The repository includes GitHub Actions workflows for:

  • Running tests on PRs and main branch
  • Building and publishing Docker images on releases
  • Deploying documentation to GitHub Pages
Terminal window
# Login to GitHub Container Registry
export GITHUB_TOKEN=your_token
export GITHUB_ACTOR=your_username
just docker-login
# Build and push
just docker-release

Example deployment manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
name: octofhir
spec:
replicas: 2
selector:
matchLabels:
app: octofhir
template:
metadata:
labels:
app: octofhir
spec:
containers:
- name: octofhir
image: ghcr.io/octofhir/octofhir-server:latest
ports:
- containerPort: 8888
env:
- name: OCTOFHIR__STORAGE__POSTGRES__URL
valueFrom:
secretKeyRef:
name: octofhir-secrets
key: database-url
- name: OCTOFHIR__AUTH__ISSUER
value: "https://fhir.example.com"
- name: OCTOFHIR__REDIS__ENABLED
value: "true"
- name: OCTOFHIR__REDIS__URL
value: "redis://redis:6379"
livenessProbe:
httpGet:
path: /healthz
port: 8888
initialDelaySeconds: 60
periodSeconds: 30
readinessProbe:
httpGet:
path: /healthz
port: 8888
initialDelaySeconds: 10
periodSeconds: 5
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
---
apiVersion: v1
kind: Service
metadata:
name: octofhir
spec:
selector:
app: octofhir
ports:
- port: 80
targetPort: 8888