Deploy on Azure
Run Elixium on your own Azure infrastructure. Start with a single Linux VM via Terraform in minutes, then scale to managed services as your team grows.
Prerequisites
- Azure subscription with a configured
az loginsession - Terraform 1.5+ installed (
brew install terraformor download) - Elixium enterprise license key (from your Command Center → Deployment tab)
Getting Started with Terraform
The fastest path to a running Elixium instance. Download a pre-configured Terraform bundle from your Command Center — no Azure CLI required beyond initial authentication.
# 1. Download your deployment bundle from the Command Center
Go to Command Center → Deployment → Docker Compose → Download Bundle
# 2. Extract and navigate to the Azure Terraform directory
$ unzip elixium-docker-compose-bundle-*.zip
$ cd terraform/deployments/azure/docker-compose
# 3. Add your SSH public key and GHCR credentials to terraform.tfvars
$ nano terraform.tfvars
ssh_public_key = "ssh-rsa AAAA..." # must be RSA (Azure does not support ed25519)
ghcr_user = "your-github-user"
ghcr_token = "your-ghcr-pat"
# 4. Deploy
$ terraform init
$ terraform plan
$ terraform apply
# 5. Validate (~5 minutes after apply)
$ ./scripts/validate-deployment.sh $(terraform output -raw public_ip)
What Terraform Creates
| Resource | Details |
|---|---|
| Resource Group | Dedicated RG for all Elixium resources |
| VNet + Subnet | Isolated network with public subnet |
| Network Security Group | SSH + HTTPS only (configurable deployer CIDR) |
| Linux VM | Standard_B2ms (2 vCPU, 8GB) with Docker Compose via cloud-init |
| TLS | Auto-generated via nginx on port 443 |
Supports FIPS 140-2 for Azure Government and FedRAMP environments. Passwords are auto-generated if not provided. Air-gapped mode disables egress.
Estimated Monthly Cost
| Service | Configuration | Est. Cost |
|---|---|---|
| Azure VM | Standard_B2ms (2 vCPU, 8GB RAM) | ~$35 |
| OS Disk | 100GB Standard SSD | ~$8 |
| Public IP | Standard static IP | ~$4 |
| Total | ~$47/mo | |
Troubleshooting
SkuNotAvailable: VM size is not available in location
Azure free trial and new pay-as-you-go subscriptions have zero vCPU quota for most VM sizes. B-series burstable VMs (Standard_B2ms) also have frequent capacity constraints in US East regions.
Fix: Request a vCPU quota increase in the Azure Portal under Subscriptions → Usage + quotas, or try a different region (westus3, northcentralus, canadacentral tend to have better availability). You can also switch to Standard_D2s_v3 or Standard_D2as_v5 in your terraform.tfvars.
Azure requires RSA SSH keys
Azure VMs do not support ed25519 SSH keys. If you see an error about unsupported key types, generate an RSA key:
"Root object was present, but now absent"
This is a known bug in the azurerm Terraform provider (v3.x). Azure creates the resource but the provider loses track of it.
Fix: Run terraform apply again. Terraform will detect the existing resource and continue. If it says "already exists", import it: terraform import <resource_address> <azure_resource_id>
Production Architecture: Managed Services
For larger teams or high-availability requirements, deploy Elixium using managed Azure services. This architecture uses Container Apps, Azure Database for PostgreSQL, and Blob Storage — replacing the single-VM Docker Compose setup with auto-scaling and managed backups.
Requires Azure CLI
The managed services setup below uses az CLI commands. Install it with brew install azure-cli or from the Azure CLI docs. If you're just getting started, use the Terraform approach above instead.
Architecture Overview
| Component | Azure Service | Notes |
|---|---|---|
| Frontend + API | Azure Container Apps | Serverless containers, scales to zero |
| Database | Azure Database for PostgreSQL (Flexible Server) | Managed backups, HA optional |
| File Storage | Azure Blob Storage | S3-compatible via gateway |
| Authentication | Azure Container Apps (Keycloak) | Backed by PostgreSQL |
| AI Inference | Gemini (default), OpenAI, Azure OpenAI, or Ollama | Cloud AI or self-hosted Ollama (external GPU) |
| Container Registry | Azure Container Registry (ACR) | Mirror images from GHCR |
Step 1: Create Resource Group & Container Registry
# Create resource group az group create --name elixium-rg --location <region> # Create ACR and mirror images from GHCR az acr create --resource-group elixium-rg --name elixiumacr --sku Basic az acr login --name elixiumacr docker login ghcr.io docker pull ghcr.io/indirecttek/elixium-app:latest docker pull ghcr.io/indirecttek/elixium-api:latest docker tag ghcr.io/indirecttek/elixium-app:latest elixiumacr.azurecr.io/elixium-app:latest docker tag ghcr.io/indirecttek/elixium-api:latest elixiumacr.azurecr.io/elixium-api:latest docker push elixiumacr.azurecr.io/elixium-app:latest docker push elixiumacr.azurecr.io/elixium-api:latest
Step 2: Provision Database & Storage
# PostgreSQL Flexible Server az postgres flexible-server create \ --resource-group elixium-rg --name elixium-db \ --location <region> --admin-user elixium \ --admin-password <your-secure-password> \ --sku-name Standard_B1ms --version 16 --storage-size 32 az postgres flexible-server db create \ --resource-group elixium-rg --server-name elixium-db --database-name elixium # Blob Storage az storage account create --resource-group elixium-rg \ --name elixiumuploads --location <region> --sku Standard_LRS
Step 3: Deploy Container Apps
# Create Container Apps environment
az containerapp env create --resource-group elixium-rg \
--name elixium-env --location <region>
# Deploy Elixium API
az containerapp create --resource-group elixium-rg \
--environment elixium-env --name elixium-api \
--image elixiumacr.azurecr.io/elixium-api:latest \
--registry-server elixiumacr.azurecr.io \
--target-port 3001 --ingress external \
--cpu 1.0 --memory 2.0Gi --min-replicas 1 \
--env-vars ELIXIUM_MODE=local NODE_ENV=production \
AI_PROVIDER=gemini ELIXIUM_LICENSE_KEY=<your-license-key>
# Deploy Elixium App (Frontend)
az containerapp create --resource-group elixium-rg \
--environment elixium-env --name elixium-app \
--image elixiumacr.azurecr.io/elixium-app:latest \
--registry-server elixiumacr.azurecr.io \
--target-port 3000 --ingress external \
--cpu 0.5 --memory 1.0Gi --min-replicas 1Step 4: Custom Domain & TLS
az containerapp hostname add --resource-group elixium-rg \ --name elixium-app --hostname elixium.yourcompany.com az containerapp hostname bind --resource-group elixium-rg \ --name elixium-app --hostname elixium.yourcompany.com \ --environment elixium-env --validation-method CNAME
Estimated Monthly Cost (Managed)
| Service | Configuration | Est. Cost |
|---|---|---|
| Container Apps (3 apps) | App + API + Keycloak, min 1 replica | ~$80 |
| PostgreSQL Flexible Server | Standard_B1ms, 32GB storage | ~$50 |
| Blob Storage | Standard LRS, minimal usage | <$1 |
| AI Provider (optional GPU) | Gemini API or Ollama on NC-series VM | $0–$350 |
| Total (without GPU) | ~$160/mo | |
Need help with your Azure deployment? Contact [email protected] or back to self-hosted docs.
