Objectives

Before you begin

  • You must have an active Azure subscription.
  • Your account must have permissions to create Resource Groups, Virtual Networks, Private DNS Zones, PostgreSQL Flexible Servers, and Container Apps. The Contributor role includes all required permissions.
  • Install Azure CLI and sign in with az login.

Set up environment variables

First, define the variables that will be used throughout this tutorial:

export RESOURCE_GROUP="aidbox-rg"
export LOCATION="westeurope"
export VNET_NAME="aidbox-vnet"
export PG_SUBNET="pg-subnet"
export CONTAINER_SUBNET="container-subnet"
export PG_SERVER="aidbox-pg-server"
export PG_USER="aidbox"
export PG_PASSWORD="<your-secure-password>"
export PG_DATABASE="aidbox"
export CONTAINER_ENV="aidbox-env"
export CONTAINER_APP="aidbox-app"

Replace <your-secure-password> with a strong password. Azure requires passwords to be at least 8 characters with uppercase, lowercase, numbers, and special characters.

Create a Resource Group (optional)

If you don't have an existing resource group, create one:

az group create \
  --name $RESOURCE_GROUP \
  --location $LOCATION

Create a Virtual Network

Create a VNet with two subnets — one for PostgreSQL and one for Container Apps:

az network vnet create \
  --resource-group $RESOURCE_GROUP \
  --name $VNET_NAME \
  --location $LOCATION \
  --address-prefix 10.0.0.0/16

az network vnet subnet create \
  --resource-group $RESOURCE_GROUP \
  --vnet-name $VNET_NAME \
  --name $PG_SUBNET \
  --address-prefix 10.0.1.0/24 \
  --delegations Microsoft.DBforPostgreSQL/flexibleServers

az network vnet subnet create \
  --resource-group $RESOURCE_GROUP \
  --vnet-name $VNET_NAME \
  --name $CONTAINER_SUBNET \
  --address-prefix 10.0.2.0/23

Container Apps requires a subnet with at least /23 CIDR block (512 IP addresses). This is an Azure policy requirement .

Create a private DNS zone for PostgreSQL

az network private-dns zone create \
  --resource-group $RESOURCE_GROUP \
  --name "privatelink.postgres.database.azure.com"

az network private-dns link vnet create \
  --resource-group $RESOURCE_GROUP \
  --zone-name "privatelink.postgres.database.azure.com" \
  --name "postgres-dns-link" \
  --virtual-network $VNET_NAME \
  --registration-enabled false

Create a PostgreSQL Flexible Server

Create the PostgreSQL server with private access (no public endpoint):

PG_SUBNET_ID=$(az network vnet subnet show \
  --resource-group $RESOURCE_GROUP \
  --vnet-name $VNET_NAME \
  --name $PG_SUBNET \
  --query id -o tsv)

az postgres flexible-server create \
  --resource-group $RESOURCE_GROUP \
  --name $PG_SERVER \
  --location $LOCATION \
  --admin-user $PG_USER \
  --admin-password "$PG_PASSWORD" \
  --sku-name Standard_B1ms \
  --tier Burstable \
  --storage-size 32 \
  --version 15 \
  --subnet $PG_SUBNET_ID \
  --private-dns-zone "privatelink.postgres.database.azure.com" \
  --yes

Create the database

az postgres flexible-server db create \
  --resource-group $RESOURCE_GROUP \
  --server-name $PG_SERVER \
  --database-name $PG_DATABASE

Configure PostgreSQL extensions

During initialization, Aidbox creates certain database extensions. You can find more details here. Azure PostgreSQL requires extensions to be allowlisted before they can be created.

Allowlist the required extensions:

az postgres flexible-server parameter set \
  --resource-group $RESOURCE_GROUP \
  --server-name $PG_SERVER \
  --name azure.extensions \
  --value "PG_STAT_STATEMENTS,UNACCENT,PG_TRGM"

Aidbox will automatically create these extensions on startup.

Create a Container Apps Environment

Create the environment with VNet integration:

CONTAINER_SUBNET_ID=$(az network vnet subnet show \
  --resource-group $RESOURCE_GROUP \
  --vnet-name $VNET_NAME \
  --name $CONTAINER_SUBNET \
  --query id -o tsv)

az containerapp env create \
  --name $CONTAINER_ENV \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --infrastructure-subnet-resource-id $CONTAINER_SUBNET_ID

Deploy Aidbox Container App

Deploy Aidbox with the required environment variables:

az containerapp create \
  --name $CONTAINER_APP \
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINER_ENV \
  --image healthsamurai/aidboxone:latest \
  --target-port 8888 \
  --ingress external \
  --cpu 1.5 \
  --memory 3Gi \
  --min-replicas 1 \
  --max-replicas 1 \
  --env-vars \
    BOX_ADMIN_PASSWORD=<your-admin-password> \
    BOX_BOOTSTRAP_FHIR_PACKAGES=hl7.fhir.r4.core#4.0.1 \
    "BOX_COMPATIBILITY_VALIDATION_JSON__SCHEMA_REGEX=#{:fhir-datetime}" \
    BOX_DB_DATABASE=$PG_DATABASE \
    BOX_DB_HOST=${PG_SERVER}.postgres.database.azure.com \
    BOX_DB_PASSWORD=$PG_PASSWORD \
    BOX_DB_PORT=5432 \
    BOX_DB_USER=$PG_USER \
    BOX_FHIR_BUNDLE_EXECUTION_VALIDATION_MODE=limited \
    BOX_FHIR_COMPLIANT_MODE=true \
    BOX_FHIR_CORRECT_AIDBOX_FORMAT=true \
    BOX_FHIR_CREATEDAT_URL=https://aidbox.app/ex/createdAt \
    BOX_FHIR_SCHEMA_VALIDATION=true \
    BOX_FHIR_SEARCH_AUTHORIZE_INLINE_REQUESTS=true \
    BOX_FHIR_SEARCH_CHAIN_SUBSELECT=true \
    BOX_FHIR_SEARCH_COMPARISONS=true \
    BOX_FHIR_TERMINOLOGY_ENGINE=hybrid \
    BOX_FHIR_TERMINOLOGY_ENGINE_HYBRID_EXTERNAL_TX_SERVER=https://tx.health-samurai.io/fhir \
    BOX_FHIR_TERMINOLOGY_SERVICE_BASE_URL=https://tx.health-samurai.io/fhir \
    BOX_MODULE_SDC_STRICT_ACCESS_CONTROL=true \
    BOX_ROOT_CLIENT_SECRET=<your-client-secret> \
    BOX_SEARCH_INCLUDE_CONFORMANT=true \
    BOX_SECURITY_AUDIT_LOG_ENABLED=true \
    BOX_SECURITY_DEV_MODE=true \
    BOX_SETTINGS_MODE=read-write \
    BOX_WEB_BASE_URL=<your-base-url> \
    BOX_WEB_PORT=8888

Replace <your-admin-password>, <your-client-secret>, and <your-base-url> with your values. The base URL will be available after deployment (see "Verify deployment" section).

See more about recommended Aidbox environment variables.

Verify deployment

  1. 1.
    Check the container logs:
az containerapp logs show \
  --name $CONTAINER_APP \
  --resource-group $RESOURCE_GROUP \
  --tail 100
  1. 2.
    Get the application URL:
az containerapp show \
  --name $CONTAINER_APP \
  --resource-group $RESOURCE_GROUP \
  --query "properties.configuration.ingress.fqdn" \
  --output tsv
  1. 3.
    Open the URL in your browser and activate your Aidbox instance.

What's next

See more about different options for running Aidbox:

Last updated: