Deployment guide

Blaze

Overview

Blaze is a lean, fast, self-contained FHIR R4 server with an embedded CQL evaluation engine, built by Data Sharing Framework / Kiel University's biomedical informatics group. It exposes a complete FHIR REST API (FHIR R4) for storing, searching and retrieving clinical resources such as Patient, Observation and Encounter. There is no external database to install or manage, because all data is stored on disk with RocksDB inside the Blaze process itself.

The SecureAnyCloud image runs the pinned official Blaze container (samply/blaze:1.10.1, Apache-2.0) bound to loopback. An nginx reverse proxy on port 80 fronts it and adds a per-VM HTTP Basic Auth gate over the FHIR API. The RocksDB data directories are persisted to a dedicated Azure data disk, so your data survives restarts.

Blaze itself ships open by design, with no built-in accounts. The nginx Basic Auth credential is the access gate, and a unique password is generated on the first boot of every VM.

Blaze is a pure JSON REST API. The pinned standalone-backend container has no browser page or dashboard of its own. Blaze's separate web frontend component requires its own Node.js container, Keycloak and roughly 16 GiB RAM, so it is out of scope for this lean single-VM image. Use curl, a FHIR client library, or a tool such as Postman to talk to it.

What you get:

  • Blaze 1.10.1 (FHIR R4, embedded CQL) running as a Docker container under docker.service, pinned by image digest
  • The FHIR REST API at /fhir on port 80, with no separate web UI
  • An nginx reverse proxy with per-VM HTTP Basic Auth (user admin) protecting the API, and a unique password generated on first boot
  • RocksDB storage (index, transaction and resource directories) on a dedicated Azure data disk at /var/lib/blaze, which is durable, unlike an in-memory store
  • docker.service and nginx.service as systemd units, enabled and active
  • An unauthenticated /healthz endpoint, proxied to Blaze's own /health, for Azure Load Balancer health probes
  • 24/7 SecureAnyCloud support

Prerequisites

  • An active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.
  • Standard_B2ms (2 vCPU, 8 GiB RAM) is a comfortable starting size. Blaze is a JVM application and benefits from the extra memory over a smaller size.
  • NSG inbound rules that allow 22/tcp from your management network and 80/tcp for the FHIR API.

The image serves plain HTTP on port 80. For production and any use with real patient data, terminate TLS in front of it with your own domain (see Maintenance and the Compliance section below).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Blaze by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).

Review the dedicated data disk on the Disks tab, then choose Review + create and Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:blaze-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name blaze \
  --image sac1647283583153:blaze-ubuntu-24-04:default:latest \
  --size Standard_B2ms \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name blaze --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

systemctl is-active docker.service nginx.service
sudo docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'

Both services report active, and docker ps shows the blaze container Up and bound to loopback:

active active NAMES IMAGE STATUS PORTS blaze samply/blaze@sha256:c43a6af3c3b3309170219cdb281cf2ec12188399fbf89e140fb8677deca7d144 Up 5 minutes 127.0.0.1:8080->8080/tcp

Blaze listens on the loopback connector 127.0.0.1:8080. nginx fronts the FHIR API on port 80, adds the per-VM HTTP Basic Auth gate, and serves an unauthenticated /healthz. RocksDB data is persisted on the dedicated Azure data disk mounted at /var/lib/blaze.

Step 5 - Retrieve your password

nginx protects the FHIR API with HTTP Basic Auth. The username is admin and a unique password is generated on the first boot of your VM and written to a root-only file:

sudo cat /root/blaze-credentials.txt

This file contains BLAZE_USERNAME, BLAZE_PASSWORD, the BLAZE_URL and the BLAZE_FHIR_BASE REST endpoint. The password is stored on disk only as a bcrypt hash in /var/lib/blaze/.htpasswd, so no plaintext password ships in the image.

Store the password somewhere safe. In the commands below, <BLAZE_PASSWORD> stands for the value of BLAZE_PASSWORD.

Step 6 - Confirm the health endpoint

nginx serves an unauthenticated health endpoint, proxied straight through to Blaze's own /health, for load balancers and probes:

curl -s http://localhost/healthz

It returns OK. This endpoint never requires authentication, so you can use it for an Azure Load Balancer health probe.

Step 7 - Confirm authentication and run a FHIR round-trip

A password is set on first boot, so an unauthenticated request to the FHIR API returns HTTP 401. Nobody reaches your FHIR server without the password.

The following commands read the per-VM password from the credentials file and prove the round-trip. An unauthenticated request is rejected, a wrong password is rejected, and the correct password returns HTTP 200. They then create and read back a Patient resource:

PW=$(sudo grep '^BLAZE_PASSWORD=' /root/blaze-credentials.txt | cut -d= -f2-)
echo "unauth : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/fhir/metadata)" echo "wrong pw : $(curl -s -o /dev/null -w '%{http_code}' -u admin:wrong http://127.0.0.1/fhir/metadata)" echo "authed : $(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW http://127.0.0.1/fhir/metadata)"
ID=$(curl -s -u admin:$PW -H 'Content-Type: application/fhir+json' -X POST http://127.0.0.1/fhir/Patient \
  -d '{"resourceType":"Patient","name":[{"family":"Smith","given":["Ada"]}]}' | grep -oP '"id"\s*:\s*"\K[^"]+' | head -1)
echo "created : Patient/$ID"
echo "read back: $(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW http://127.0.0.1/fhir/Patient/$ID)"
unauth : 401 wrong pw : 401 authed : 200 created : Patient/DH2HF3L5MQ23SVGN read back: 200

The /fhir/metadata endpoint returns the server's FHIR CapabilityStatement. The Patient you created is now stored in RocksDB on the data disk.

Blaze resolves absolute FHIR URLs (Bundle.link and resource fullUrl) from the actual Host header of each request, and nginx forwards that header unchanged. The URLs you get back therefore always match how you reached the server, whether by its public IP address or by a domain name you put in front of it later.

Step 8 - Confirm RocksDB persistence survives a restart

Blaze's storage variant creates its own index, transaction and resource directories under the data disk mount on first start. This is durable RocksDB storage, not an in-memory database:

sudo ls -la /var/lib/blaze
drwxr-xr-x 8 1001 1001 4096 Jul 9 13:54 . drwxr-xr-x 51 root root 4096 Jul 9 13:53 .. -rw-r----- 1 root www-data 68 Jul 9 13:54 .htpasswd drwxr-xr-x 2 1001 root 4096 Jul 9 13:55 admin-index drwxr-xr-x 2 1001 root 4096 Jul 9 13:55 admin-transaction drwxr-xr-x 2 1001 root 4096 Jul 9 14:01 index drwxr-xr-x 2 1001 root 4096 Jul 9 13:55 resource drwxr-xr-x 2 1001 root 4096 Jul 9 13:55 transaction

Create one more Patient resource, restart the container, and confirm that the same resource is still there afterward. This proves that the storage is persistent rather than reset on every start:

PW=$(sudo grep '^BLAZE_PASSWORD=' /root/blaze-credentials.txt | cut -d= -f2-)
PID=$(curl -s -u admin:$PW -H 'Content-Type: application/fhir+json' -X POST http://127.0.0.1/fhir/Patient \
  -d '{"resourceType":"Patient","name":[{"family":"Persistence","given":["Test"]}]}' | grep -oP '"id"\s*:\s*"\K[^"]+' | head -1)
echo "created before restart: Patient/$PID"
sudo docker restart blaze for i in $(seq 1 30); do
C=$(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW http://127.0.0.1/fhir/metadata) [ "$C" = "200" ] && break sleep 2 done echo "post-restart metadata : $C" echo "post-restart Patient/$PID : $(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW http://127.0.0.1/fhir/Patient/$PID)"
created before restart: Patient/DH2HGCJI63DH2JOM post-restart metadata : 200 post-restart Patient/DH2HGCJI63DH2JOM : 200

Both return 200, so the Patient resource created before the restart survived it. The RocksDB directories on the dedicated Azure data disk make this possible. The disk is captured into the image and re-provisioned on every VM, independent of the OS disk.

Maintenance

  • Password: the password is set on first boot and stored as a bcrypt entry in /var/lib/blaze/.htpasswd. To change it, run sudo htpasswd -B /var/lib/blaze/.htpasswd admin and then sudo systemctl reload nginx.
  • Authentication model: the nginx Basic Auth credential is a single shared gate in front of the whole server. Blaze itself ships with no authorization by default. For production, consider Blaze's built-in OpenID Connect authentication (see the Blaze documentation) so that access is scoped per client rather than a single shared password.
  • The FHIR API: the REST base is http://<vm-public-ip>/fhir. Point your FHIR client at it with the admin Basic Auth credential. /fhir/metadata returns the CapabilityStatement. Blaze supports FHIR R4.
  • Persistence and storage: FHIR data is stored with RocksDB under /var/lib/blaze on the data disk, in the index, transaction and resource subdirectories that Blaze creates itself. Snapshot or back up that volume to protect your data.
  • Memory: the container is started with -Xmx3g. Increase it, and the VM size, if you load large datasets or run CQL evaluations over big cohorts.
  • TLS: the server is plain HTTP on port 80. For production, front it with TLS (for example, certbot with your own domain) and proxy / over :443.
  • Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.

Compliance

This image ships as infrastructure: a self-hosted Blaze FHIR server behind a per-VM password. It is not a certified or HIPAA-compliant healthcare product, and nothing here implies certified compliance.

If you store, process or transmit protected health information (PHI), you are solely responsible for implementing and operating the required controls. These include encryption in transit and at rest, FHIR-level authentication and authorization, audit logging, access management, backups and any applicable regulatory obligations (HIPAA, GDPR and others).

Deploy the image inside your own secured, compliant environment, and add TLS and stronger authentication before using it with real patient data.

Support

SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.

Blaze is developed by the Data Sharing Framework project. This image is provided by SecureAnyCloud and is not affiliated with or endorsed by the Blaze project maintainers.

Deploy on Azure

Launch Blaze FHIR Server R4 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure