Install Avon AI on Azure Platform
Deployment Type: Single Docker Container on Azure VM Version: 1.6.6
Overview
Avon AI is deployed as a single Docker container that bundles all required services internally (MongoDB, Redis, ChromaDB, Nginx, and all Avon microservices). This guide walks through deploying Avon version 1.6.6 on an Azure Virtual Machine (the Azure equivalent of an AWS EC2 instance).
The container exposes a single port to the outside world. All inter-service communication happens on localhost inside the container.
Prerequisites Checklist
Before starting, make sure you have the following ready:
- Azure VM provisioned with a supported Linux distribution and Docker installed
- Azure OpenAI resource created with three model deployments (
gpt-4o,gpt-4o-mini, andtext-embedding-3-small) - Avon AI Docker image file (version 1.6.6) provided by the Avon team (loaded via
docker load) - Domain / subdomain pointing to the Azure VM's public IP (e.g.,
avon.your-company.com) - SSL certificate and private key for the configured domain
- Microsoft Entra (Azure AD) App Registration for SSO
- Azure Blob Storage container for conversation ingestion
- Network Security Group (NSG) rules configured to allow inbound traffic on port 443
Resource Requirements
The following table provides sizing guidance based on the expected number of users:
| Environment | CPU | Memory | Storage (Disk) |
|---|---|---|---|
| Small team (< 20 users) | 2 cores | 4 GiB | 25 GiB |
| Production (20-100 users) | 4 cores | 8 GiB | 50 GiB |
| Enterprise (100+ users) | 4 cores | 16 GiB | 100 GiB |
Recommended Azure VM sizes:
| Tier | Azure VM Size | vCPUs | Memory |
|---|---|---|---|
| Small | Standard_D2s_v5 | 2 | 8 GiB |
| Production | Standard_D4s_v5 | 4 | 16 GiB |
| Enterprise | Standard_D4s_v5 or D8s_v5 | 4-8 | 16-32 GiB |
Storage refers to the persistent data volume, not the OS disk. Attach a separate Azure Managed Disk for the /data volume (see next section).
Data Volume (/data)
Avon uses a single persistent volume mounted at /data inside the container. This volume stores:
| Path Inside Container | Purpose |
|---|---|
/data/db | MongoDB database files (conversations, configurations, users, etc.) |
/data/chromadb | ChromaDB vector database (knowledge base embeddings) |
/data/nginx/ | Generated SSL certificate files (written at container startup) |
How to Configure
-
Create an Azure Managed Disk (or use a local directory on the VM):
- Recommended size: 50 GiB minimum for production, expandable as conversation volume grows.
- Use Premium SSD (
Premium_LRS) for best performance.
-
Mount the disk on the Azure VM (e.g., at
/mnt/avon-data):
# Example: format and mount a new disk
sudo mkfs.ext4 /dev/sdc
sudo mkdir -p /mnt/avon-data
sudo mount /dev/sdc /mnt/avon-data
- Pass it to Docker using the
-vflag:
-v /mnt/avon-data:/data
Alternatively, use a Docker named volume:
docker volume create avon-data
# Then use: -v avon-data:/data
Back up the /data volume regularly. It contains all your conversations, configurations, and knowledge base data.
Domain and Networking
Domain Configuration
Configure a domain or subdomain that points to the Azure VM's public IP address:
avon.your-company.com → A record → <Azure VM Public IP>
This domain will be used:
- As the URL users access to use Avon
- In the SSO redirect URI (
https://avon.your-company.com/callback) - In the SSL certificate (must match the domain)
Ports
| Port | Protocol | Direction | Purpose |
|---|---|---|---|
| 443 | HTTPS | Inbound | Primary access port (when SSL is configured) |
| 5173 | HTTP | Inbound | Fallback port (only if no SSL certificate is provided) |
For production, only port 443 needs to be open.
All internal services run inside the container on localhost and do NOT require any external port exposure:
| Internal Service | Internal Port | Notes |
|---|---|---|
| MongoDB | 27017 | Database - internal only |
| Redis | 6379 | Cache - internal only |
| BFF Service | 8000 | Backend API - proxied via Nginx |
| Registry Service | 8001 | Internal only |
| Database Service | 8002 | Internal only |
| Validation Job | 8003 | Internal only |
| KB Service | 8004 | Internal only |
| Ingestion Service | 8005 | Internal only |
| Test Runner Service | 8006 | Internal only |
| ChromaDB | 8070 | Vector DB - internal only |
Azure NSG Rule
In your Azure Network Security Group, add an inbound rule:
| Priority | Name | Port | Protocol | Source | Action |
|---|---|---|---|---|---|
| 100 | AllowHTTPS | 443 | TCP | Any (or your IP range) | Allow |
Model Deployments (Azure OpenAI)
Step 1: Create Azure OpenAI Deployments
In the Azure OpenAI Studio, create three model deployments:
| Deployment Name (example) | Model | Purpose |
|---|---|---|
gpt-4o | gpt-4o | Complex analysis, tier-1 tasks (topic extraction, alert summaries) |
gpt-4o-mini | gpt-4o-mini | Default model for general tasks (validators, standard operations) |
text-embedding-3-small | text-embedding-3-small | Knowledge base embeddings |
The deployment name is what you choose in Azure OpenAI Studio. The examples above use the model name as the deployment name — this is the recommended convention and avoids extra configuration.
Step 2: Azure OpenAI Connection Variables
All three deployments share the same Azure OpenAI resource credentials:
AZURE_API_KEY="<your-azure-openai-api-key>"
AZURE_API_BASE="<your-azure-openai-endpoint>" # e.g. "https://your-company-openai.openai.azure.com"
AZURE_API_VERSION="2024-08-01-preview"
You can find these values in the Azure Portal under your Azure OpenAI resource > Keys and Endpoint.
Step 3: Chat Model Configuration Variables
# Default model - used for most operations
DEFAULT_MODEL="azure/gpt-4o-mini"
# Tier 1 - complex/expensive tasks
GENERAL_TIER_1_MODEL="azure/gpt-4o"
# Optional: explicit tier 2 and 3 (fall back to DEFAULT_MODEL if not set)
# GENERAL_TIER_2_MODEL="azure/<your-deployment-name>"
# GENERAL_TIER_3_MODEL="azure/<your-deployment-name>"
Step 4: Embedding Model Configuration
When AZURE_API_KEY is set, Avon automatically registers an Azure OpenAI embedding connection in the database at startup (named "Default Azure OpenAI"). No additional env vars are needed — the API key is resolved automatically at call time.
When creating a Knowledge Base in the Avon UI, select the "Default Azure OpenAI" connection and enter your text-embedding-3-small deployment name as the model.
Step 5: Azure Content Filtering
Azure OpenAI applies content filters to every request by default, evaluating prompts and responses for hate, sexual content, self-harm, and violence at severity thresholds of low, medium, or high.
Conversations about sensitive business topics (account disputes, financial distress, etc.) can be misclassified by Azure's violence or self-harm filters, causing requests to be rejected with content_filter errors.
Content filtering is configured per deployment in Azure AI Studio — it is not a setting inside Avon.
To adjust filters:
- Go to Azure AI Studio → your resource → Deployments
- Select the deployment → Edit → Content filters tab
- Raise any category threshold to High or turn it off
| Option | How | When to use |
|---|---|---|
| Raise threshold to "High" | Edit deployment → set each filter to High | Quickest fix; still blocks clearly harmful content |
| Custom filter policy | Azure AI Studio → Content filters → New policy → assign to deployment | Per-category control |
| Modified content filtering | Request via Azure support | Full removal for regulated industries |
Additional Model Variables (Optional)
# TOPIC_DEFAULT_MODEL="azure/<your-deployment-name>" # Topic extraction
# REGISTRY_TIER_1_MODEL="azure/<your-deployment-name>" # Complex validators
# REGISTRY_TIER_2_MODEL="azure/<your-deployment-name>" # Standard validators
# ALERTS_SUMMARY_DEFAULT_MODEL="azure/<your-deployment-name>" # Alert summaries
Authentication and Service Keys
Avon uses internal service-to-service authentication keys. Each key must be a unique, randomly generated hex string.
Generate Keys
openssl rand -hex 32
Required Keys
SECRET_KEY=<generate-64-char-hex>
SUPER_ADMIN_API_KEY=<generate-64-char-hex>
TEST_RUNNER_SERVICE_KEY=<generate-64-char-hex>
ENTERPRISE_AI_AGENTS_SERVICE_KEY=<generate-64-char-hex>
REGISTRY_SERVICE_KEY=<generate-64-char-hex>
VALIDATION_JOB_SERVICE_KEY=<generate-64-char-hex>
INGESTION_SERVICE_KEY=<generate-64-char-hex>
REPORTS_SERVICE_KEY=<generate-64-char-hex>
Quick Generate All Keys
echo "SECRET_KEY=$(openssl rand -hex 32)"
echo "SUPER_ADMIN_API_KEY=$(openssl rand -hex 32)"
echo "TEST_RUNNER_SERVICE_KEY=$(openssl rand -hex 32)"
echo "ENTERPRISE_AI_AGENTS_SERVICE_KEY=$(openssl rand -hex 32)"
echo "REGISTRY_SERVICE_KEY=$(openssl rand -hex 32)"
echo "VALIDATION_JOB_SERVICE_KEY=$(openssl rand -hex 32)"
echo "INGESTION_SERVICE_KEY=$(openssl rand -hex 32)"
echo "REPORTS_SERVICE_KEY=$(openssl rand -hex 32)"
Generate each key separately. Do not reuse the same value for multiple keys. Store them securely (e.g., in Azure Key Vault).
SSO Configuration (Microsoft Entra / Azure AD)
Step 1: Register an Application
- Go to the Azure Portal > Microsoft Entra ID > App registrations > New registration
- Configure:
- Name:
Avon AI - Supported account types: Accounts in this organizational directory only (single tenant)
- Redirect URI: Platform Web, URI
https://avon.your-company.com/callback
- Name:
- Note the Application (client) ID →
SSO_CLIENT_IDand Directory (tenant) ID - Go to Certificates & secrets > New client secret →
SSO_CLIENT_SECRET
The application must be registered as a Web application (confidential client), not as a Single-Page Application (SPA).
Step 2: Environment Variables
SSO_PROVIDER="entra"
SSO_ISSUER="https://login.microsoftonline.com/<your-tenant-id>/v2.0"
SSO_CLIENT_ID="<your-application-client-id>"
SSO_CLIENT_SECRET="<your-client-secret>"
SSL / TLS Certificates
HTTPS Certificate (Required for Production)
HTTPS_CERTIFICATE="-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgI...
-----END CERTIFICATE-----"
HTTPS_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhki...
-----END PRIVATE KEY-----"
If HTTPS_CERTIFICATE is not set, the application defaults to HTTP on port 5173.
Internal CA Certificate (Optional)
If your Azure OpenAI endpoint uses a custom/internal CA:
SSL_CERT_FILE_CONTENTS="-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgI...
-----END CERTIFICATE-----"
Passing Certificates in Docker Run
-e HTTPS_CERTIFICATE="$(cat /path/to/cert.pem)" \
-e HTTPS_PRIVATE_KEY="$(cat /path/to/key.pem)" \
Conversation Ingestion (Azure Blob Storage)
Avon reads conversation files from an Azure Blob Storage container for automated ingestion.
How it works:
- Avon connects using an
az://URL scheme - Files are discovered, ingested, and validated automatically on a schedule
- Credentials: account key (recommended for Docker/VM) or Managed Identity (if key not set)
Step 1: Azure Blob Storage Setup
- In the Azure Portal, go to your Storage Account
- Create (or identify) the container where conversation files will be placed
- Note your Storage account name, account key (under Security + networking > Access keys), and container name
Step 2: Environment Variables
AZURE_STORAGE_ACCOUNT_NAME="<your-storage-account-name>"
# Required for Docker environments; omit to use Managed Identity
AZURE_STORAGE_ACCOUNT_KEY="<your-storage-account-key>"
# Use az:// prefix for Azure Blob Storage
S3_INGESTION_BUCKET="az://<your-container-name>"
Example:
AZURE_STORAGE_ACCOUNT_NAME="mycompanystorage"
AZURE_STORAGE_ACCOUNT_KEY="xxxxxx...=="
S3_INGESTION_BUCKET="az://conversations"
The S3_INGESTION_BUCKET variable name is kept for backward compatibility but fully supports Azure Blob Storage via the az:// prefix.
Authentication Options
| Scenario | Configuration |
|---|---|
| Docker / VM with account key | Set both AZURE_STORAGE_ACCOUNT_NAME and AZURE_STORAGE_ACCOUNT_KEY |
| Azure VM with Managed Identity | Set only AZURE_STORAGE_ACCOUNT_NAME; omit AZURE_STORAGE_ACCOUNT_KEY |
Additional Configuration
Environment and Logging
ENVIRONMENT="prod" # Options: development, staging, prod
LOG_LEVEL="INFO" # Options: DEBUG, INFO, WARNING, ERROR
Validation Job Tuning
MAX_CONCURRENT_VALIDATIONS=1
MAX_CONCURRENT_VALIDATORS_PER_CONVERSATION=3
SCHEDULE_INTERVAL_HOURS=1.0
VALIDATION_DELAY_MINUTES=30
Reports and LLM
REPORT_JOB_TIMEOUT_SECONDS=7200
MAX_CONVERSATIONS_PER_REPORT=25000
LLM_TIMEOUT=120
How to Run
Step 1: Load the Docker Image
docker load < avon-ai-1.6.6.tar
docker images | grep avon-ai
Step 2: Future Updates
To update to a newer version, the Avon team will provide a new image file. Pull the latest deployment scripts first:
git pull origin main
Then repeat the docker load step with the new image.
Step 3: Prepare avon.env
# ============================================================================
# ENVIRONMENT
# ============================================================================
ENVIRONMENT=prod
LOG_LEVEL=INFO
# ============================================================================
# AZURE OPENAI
# ============================================================================
AZURE_API_KEY=<your-azure-openai-api-key>
AZURE_API_BASE=https://<your-resource-name>.openai.azure.com
AZURE_API_VERSION=2024-08-01-preview
# ============================================================================
# MODEL CONFIGURATION
# ============================================================================
DEFAULT_MODEL=azure/gpt-4o-mini
GENERAL_TIER_1_MODEL=azure/gpt-4o
# ============================================================================
# SERVICE KEYS (generate each with: openssl rand -hex 32)
# ============================================================================
SECRET_KEY=<generated-hex>
SUPER_ADMIN_API_KEY=<generated-hex>
TEST_RUNNER_SERVICE_KEY=<generated-hex>
ENTERPRISE_AI_AGENTS_SERVICE_KEY=<generated-hex>
REGISTRY_SERVICE_KEY=<generated-hex>
VALIDATION_JOB_SERVICE_KEY=<generated-hex>
INGESTION_SERVICE_KEY=<generated-hex>
REPORTS_SERVICE_KEY=<generated-hex>
# ============================================================================
# SSO (Microsoft Entra / Azure AD)
# ============================================================================
SSO_PROVIDER=entra
SSO_ISSUER=https://login.microsoftonline.com/<your-tenant-id>/v2.0
SSO_CLIENT_ID=<your-application-client-id>
SSO_CLIENT_SECRET=<your-client-secret>
# ============================================================================
# SSL CERTIFICATES (pass via -e flag in docker run, not here)
# ============================================================================
# HTTPS_CERTIFICATE=<cert-content>
# HTTPS_PRIVATE_KEY=<key-content>
# ============================================================================
# CONVERSATION INGESTION (Azure Blob Storage)
# ============================================================================
AZURE_STORAGE_ACCOUNT_NAME=<your-storage-account-name>
AZURE_STORAGE_ACCOUNT_KEY=<your-storage-account-key>
S3_INGESTION_BUCKET=az://<your-container-name>
# ============================================================================
# OPTIONAL TUNING
# ============================================================================
LLM_TIMEOUT=120
MAX_CONCURRENT_VALIDATORS_PER_CONVERSATION=3
REPORT_JOB_TIMEOUT_SECONDS=7200
MAX_CONVERSATIONS_PER_REPORT=25000
Step 4: Run the Container
docker run -d \
--name avon-ai \
--restart unless-stopped \
-p 443:443 \
-v /mnt/avon-data:/data \
--env-file avon.env \
-e HTTPS_CERTIFICATE="$(cat /path/to/cert.pem)" \
-e HTTPS_PRIVATE_KEY="$(cat /path/to/key.pem)" \
avon-ai:1.6.6
| Flag | Purpose |
|---|---|
-d | Run in detached (background) mode |
--restart unless-stopped | Auto-restart on crash or VM reboot |
-p 443:443 | Expose HTTPS port |
-v /mnt/avon-data:/data | Mount persistent storage |
--env-file avon.env | Load environment variables from file |
-e HTTPS_CERTIFICATE=... | Pass certificate content (multi-line values) |
SSL certificate and private key are passed as -e flags separately because --env-file does not handle multi-line values well.
Useful Commands
docker logs -f avon-ai # View logs
docker stop avon-ai # Stop
docker start avon-ai # Start
docker restart avon-ai # Restart
docker exec -it avon-ai /bin/bash # Shell into container
docker rm avon-ai # Remove (data persists in volume)
Health Check and Verification
-
Check container status:
docker ps | grep avon-ai -
Check health endpoint:
curl -k https://avon.your-company.com/You should receive an HTML response (the Avon UI).
-
Check logs for errors:
docker logs avon-ai 2>&1 | grep -i error -
Verify SSO: Navigate to
https://avon.your-company.comin a browser — you should be redirected to the Microsoft login page.
Quick Reference: All Environment Variables
| Variable | Required | Description |
|---|---|---|
ENVIRONMENT | Yes | Set to prod |
AZURE_API_KEY | Yes | Azure OpenAI API key |
AZURE_API_BASE | Yes | Azure OpenAI endpoint URL |
AZURE_API_VERSION | Yes | Azure OpenAI API version |
DEFAULT_MODEL | Yes | Default model: azure/gpt-4o-mini |
GENERAL_TIER_1_MODEL | Recommended | Tier 1 model: azure/gpt-4o |
SECRET_KEY | Yes | JWT signing key (64-char hex) |
SUPER_ADMIN_API_KEY | Yes | Super admin API key (64-char hex) |
TEST_RUNNER_SERVICE_KEY | Yes | Service key (64-char hex) |
ENTERPRISE_AI_AGENTS_SERVICE_KEY | Yes | Service key (64-char hex) |
REGISTRY_SERVICE_KEY | Yes | Service key (64-char hex) |
VALIDATION_JOB_SERVICE_KEY | Yes | Service key (64-char hex) |
INGESTION_SERVICE_KEY | Yes | Service key (64-char hex) |
REPORTS_SERVICE_KEY | Yes | Service key (64-char hex) |
SSO_PROVIDER | Yes | Set to entra |
SSO_ISSUER | Yes | Entra issuer URL |
SSO_CLIENT_ID | Yes | Entra App client ID |
SSO_CLIENT_SECRET | Yes | Entra App client secret |
HTTPS_CERTIFICATE | Yes (prod) | PEM certificate content |
HTTPS_PRIVATE_KEY | Yes (prod) | PEM private key content |
SSL_CERT_FILE_CONTENTS | Optional | Internal CA bundle |
AZURE_STORAGE_ACCOUNT_NAME | Yes | Azure Blob Storage account name |
AZURE_STORAGE_ACCOUNT_KEY | Yes (Docker) | Azure Blob Storage account key |
S3_INGESTION_BUCKET | Yes | Set to az://<container-name> |
LLM_TIMEOUT | Optional | LLM call timeout (default: 60s) |
MAX_CONCURRENT_VALIDATORS_PER_CONVERSATION | Optional | Parallel validators (default: 3) |
LOG_LEVEL | Optional | Log level (default: INFO) |