Deployment Guide
Deployment Guide¶
First Time Deploying?
For your first deployment, use the Quickstart Guide — it covers azd up in detail.
This guide covers advanced deployment scenarios and production considerations.
Deployment Options¶
| Scenario | Method | Guide |
|---|---|---|
| First deployment | azd up |
Quickstart |
| Production deployment | azd + custom config | Production Guide |
| CI/CD pipeline | GitHub Actions | CI/CD Guide |
| Direct Terraform | terraform apply |
This page |
Infrastructure Overview¶
All deployments create these Azure resources:
- Azure OpenAI — GPT-4o for conversations
- Azure Speech Services — STT/TTS with VoiceLive API
- Azure Communication Services — Voice calls, telephony
- Cosmos DB — MongoDB API for conversation history
- Redis Enterprise — Session caching
- Blob Storage — Audio files, media
- Key Vault — Secrets management
- Container Apps — Frontend + backend hosting
- Container Registry — Image storage
- App Configuration — Centralized settings
- Application Insights — Telemetry, traces
- Log Analytics — Centralized logging
Prerequisites¶
Permissions Required
| Permission | Purpose |
|---|---|
| Contributor | Create resources |
| User Access Administrator | Assign managed identity roles |
See Prerequisites for tool installation.
Direct Terraform Deployment¶
For advanced users who prefer direct Terraform control:
Step 1: Configure Backend¶
cd infra/terraform
# Set subscription
export ARM_SUBSCRIPTION_ID=$(az account show --query id -o tsv)
Step 2: Configure Variables¶
Create terraform.tfvars:
environment_name = "prod"
location = "eastus"
principal_id = "<your-principal-id>"
# Customize SKUs for production
redis_sku = "Enterprise_E10"
Step 3: Deploy¶
Phone Number Setup¶
Phone numbers enable PSTN (telephone) calls. Not required for browser-based voice.
See Phone Number Setup for:
- Purchasing numbers via Portal or CLI
- Configuring Event Grid webhooks
- Testing inbound calls
Deployment Hooks & Configuration¶
The azd up command runs automated pre-provisioning and post-provisioning hooks that handle environment validation, setup, and configuration.
Pre-Provisioning Hook¶
The pre-provisioning script (devops/scripts/azd/preprovision.sh) runs before Terraform and performs:
| Task | Description |
|---|---|
| Tool Validation | Checks az, azd, jq, docker are installed |
| CLI Extensions | Auto-installs quota, redisenterprise, cosmosdb-preview extensions |
| Azure Auth | Validates Azure CLI and azd authentication |
| Subscription Config | Sets ARM_SUBSCRIPTION_ID for Terraform |
| Provider Registration | Registers required Azure resource providers |
| Regional Availability | Checks if services are available in target region |
| Quota Checks | Validates OpenAI TPM quotas (opt-in for others) |
| Remote State Setup | Creates Azure Storage for Terraform state |
Post-Provisioning Hook¶
The post-provisioning script (devops/scripts/azd/postprovision.sh) runs after Terraform and handles:
| Task | Description |
|---|---|
| Cosmos DB Init | Seeds database with initial data |
| Phone Number Config | Interactive prompt for ACS phone number |
| URL Updates | Configures backend/WebSocket URLs in App Configuration |
| Settings Sync | Syncs config/appconfig.json to Azure App Configuration |
| Local Dev Setup | Generates .env.local for local development |
Environment Variables & Flags¶
Control deployment behavior with these environment variables:
Preflight Check Flags¶
| Variable | Default | Description |
|---|---|---|
PREFLIGHT_DEEP_CHECKS |
false |
Enable slow quota checks for Cosmos DB, Redis, Container Apps |
PREFLIGHT_LIVE_CHECKS |
true |
Enable live Azure API checks (set false in CI for faster runs) |
CI |
- | Auto-detected; affects interactive prompts and default behaviors |
Example: Enable deep quota checks
Terraform State Flags¶
| Variable | Default | Description |
|---|---|---|
LOCAL_STATE |
false |
Use local Terraform state instead of Azure Storage |
RS_STORAGE_ACCOUNT |
- | Existing storage account for remote state |
RS_RESOURCE_GROUP |
- | Resource group for remote state storage |
RS_CONTAINER_NAME |
- | Blob container for state files |
RS_STATE_KEY |
- | State file key (auto-set to <env>.tfstate) |
TF_INIT_SKIP_INTERACTIVE |
- | Skip interactive prompts during Terraform init |
Example: Use local state for development
Example: Use existing remote state
azd env set RS_STORAGE_ACCOUNT "mystorageaccount"
azd env set RS_RESOURCE_GROUP "rg-tfstate"
azd env set RS_CONTAINER_NAME "tfstate"
azd env set RS_STATE_KEY "myenv.tfstate"
azd up
CI/CD Flags¶
| Variable | Default | Description |
|---|---|---|
CI |
- | Set to true for CI/CD pipelines |
GITHUB_ACTIONS |
- | Auto-set in GitHub Actions |
AZD_SKIP_INTERACTIVE |
- | Skip all interactive prompts |
ACS_SOURCE_PHONE_NUMBER |
- | Pre-configure phone number (E.164 format) |
Example: CI/CD deployment
export CI=true
export TF_INIT_SKIP_INTERACTIVE=true
export ACS_SOURCE_PHONE_NUMBER="+18001234567"
azd up --no-prompt
Next Steps¶
| Topic | Guide |
|---|---|
| Production hardening | Production Guide |
| CI/CD pipelines | CI/CD Guide |
| Phone configuration | Phone Number Setup |
| Monitoring setup | Monitoring Guide |
| Security | Authentication |
Advanced: Direct Terraform Deployment¶
For users who need more control over the deployment process, you can use Terraform directly instead of azd.
Terraform Variables¶
Configure your terraform.tfvars:
# Environment configuration
environment_name = "dev"
name = "rtaudioagent"
location = "eastus"
# Principal configuration (replace with your user ID)
principal_id = "your-user-principal-id-here"
principal_type = "User"
# Azure Communication Services data location
acs_data_location = "United States"
# Authentication settings
disable_local_auth = true
# Redis Enterprise SKU (adjust based on your needs and regional availability)
redis_sku = "MemoryOptimized_M10"
# OpenAI model deployments with latest models
model_deployments = [
{
name = "gpt-4-1-mini"
version = "2024-11-20"
sku_name = "DataZoneStandard"
capacity = 50
},
{
name = "o3-mini"
version = "2025-01-31"
sku_name = "DataZoneStandard"
capacity = 30
}
]
Deploy with Terraform¶
📖 For full Terraform details including module structure, all variables, and outputs, see the Infrastructure README.
Building Container Images¶
For custom image builds or manual deployments, build and push containers to Azure Container Registry:
# From repo root
ACR_NAME=$(terraform output -raw container_registry_name) # or azd env get-value
ACR_LOGIN_SERVER="$ACR_NAME.azurecr.io"
az acr login --name $ACR_NAME
# Backend image
docker build \
-f apps/artagent/backend/Dockerfile \
-t $ACR_LOGIN_SERVER/voice-agent-backend:$(git rev-parse --short HEAD) \
apps/artagent/backend
docker push $ACR_LOGIN_SERVER/voice-agent-backend:$(git rev-parse --short HEAD)
# Frontend image
docker build \
-f apps/artagent/frontend/Dockerfile \
-t $ACR_LOGIN_SERVER/voice-agent-frontend:$(git rev-parse --short HEAD) \
apps/artagent/frontend
docker push $ACR_LOGIN_SERVER/voice-agent-frontend:$(git rev-parse --short HEAD)
Update your Terraform variables (backend_image_tag, frontend_image_tag) to match the tags you pushed.
Connectivity Testing¶
Test your deployed application to ensure everything works correctly:
Health Check¶
# Get backend URL
BACKEND_URL=$(azd env get-value BACKEND_CONTAINER_APP_URL)
# Test health endpoint
curl -I $BACKEND_URL/health
WebSocket Testing¶
# Install wscat for WebSocket testing
npm install -g wscat
# Test WebSocket connection with the media endpoint
BACKEND_FQDN=$(azd env get-value BACKEND_CONTAINER_APP_FQDN)
wscat -c wss://$BACKEND_FQDN/api/v1/media/stream
# Test real-time communication endpoint
wscat -c wss://$BACKEND_FQDN/api/v1/stream
Expected Behavior:
- Health endpoint returns 200 OK with service status information
- WebSocket connection establishes successfully without errors
- Receives connection confirmation message with session details
- Use
Ctrl+Cto disconnect gracefully
Need help? See our Monitoring and Troubleshooting section below.
Environment Management¶
Switch Between Environments¶
# List all environments
azd env list
# Switch environment
azd env select <environment-name>
# View current variables
azd env get-values
Update Configurations¶
# View all environment variables
azd env get-values
# Update location
azd env set AZURE_LOCATION <azure-region>
# Update phone number
azd env set ACS_SOURCE_PHONE_NUMBER <phone-number>
# Apply changes
azd deploy
Environment Files for Local Development¶
Generate environment files from deployed infrastructure:
# Generate .env file from Terraform outputs
make generate_env_from_terraform
# Update with Key Vault secrets
make update_env_with_secrets
# View current environment file
make show_env_file
Terraform State Configuration¶
For Azure Developer CLI¶
Remote state is automatically configured by azd pre-provision hooks. No manual setup required.
For Direct Terraform¶
See the Infrastructure README for detailed state configuration options:
- BYOS: Bring your own storage account via environment variables
- Local State: Set
LOCAL_STATE=truefor development/testing - Manual backend.tf: Configure your own backend settings
Monitoring and Troubleshooting¶
Deployment Monitoring¶
Azure Developer CLI¶
# Check deployment status
azd show
# View environment details
azd env get-values
# View deployment logs
azd deploy --debug
Direct Terraform¶
# Check Terraform state
terraform show
# View outputs
terraform output
# Monitor deployment
make monitor_backend_deployment
make monitor_frontend_deployment
Container App Logs¶
# Real-time logs
az containerapp logs show \
--name ca-voice-agent-backend \
--resource-group $(azd env get-value AZURE_RESOURCE_GROUP) \
--follow
# Recent logs (last 100 lines)
az containerapp logs show \
--name ca-voice-agent-backend \
--resource-group $(azd env get-value AZURE_RESOURCE_GROUP) \
--tail 100
Common Issues & Solutions¶
| Issue | Symptoms | Solution |
|---|---|---|
| Terraform Init Fails | Backend configuration errors, state lock issues | Check storage account permissions, verify backend.tf configuration, ensure unique state key |
| Container Won't Start | App unavailable, startup errors, health check failures | Check environment variables, verify managed identity permissions, review container logs |
| Redis Connection Issues | Cache connection timeouts, authentication failures | Verify Redis Enterprise configuration, check firewall rules, validate access policies |
| Phone Number Issues | ACS calling fails, webhook errors | Verify phone number is purchased and configured correctly, check webhook endpoints |
| OpenAI Rate Limits | API quota exceeded, throttling errors | Check deployment capacity, monitor usage in Azure Portal, consider scaling up |
| WebSocket Connection Fails | Connection refused, handshake errors, timeout issues | Check Container App ingress settings, test health endpoint, verify CORS configuration |
| Live Voice API Issues | Audio streaming problems, voice quality issues | Verify Azure Speech Live Voice API configuration, check network connectivity, review audio codecs |
| Agent Routing Problems | Incorrect model selection, tool call failures | Check agent configuration, verify model deployments, validate tool registry setup |
Health Check Commands¶
# Basic health check with detailed output
BACKEND_URL=$(azd env get-value BACKEND_CONTAINER_APP_URL)
curl -v $BACKEND_URL/health
# Test specific agent endpoints
curl $BACKEND_URL/api/v1/agents/health
curl $BACKEND_URL/api/v1/media/health
# Test WebSocket connection with timeout
BACKEND_FQDN=$(azd env get-value BACKEND_CONTAINER_APP_FQDN)
timeout 10s wscat -c wss://$BACKEND_FQDN/api/v1/stream
# Check all service endpoints with status
echo "Backend: https://$BACKEND_FQDN"
echo "Frontend: https://$(azd env get-value FRONTEND_CONTAINER_APP_FQDN)"
echo "Health: $BACKEND_URL/health"
echo "API Docs: $BACKEND_URL/docs"
Advanced Debugging¶
Enable Debug Logging¶
# Deploy with debug logging
azd deploy --debug
# Check container environment variables
az containerapp show \
--name $(azd env get-value BACKEND_CONTAINER_APP_NAME) \
--resource-group $(azd env get-value AZURE_RESOURCE_GROUP) \
--query "properties.template.containers[0].env"
Verify RBAC Assignments¶
# Check managed identity assignments
az role assignment list \
--assignee $(azd env get-value BACKEND_UAI_PRINCIPAL_ID) \
--all \
--output table
# Verify Key Vault access
az keyvault show \
--name $(azd env get-value AZURE_KEY_VAULT_NAME) \
--query "properties.accessPolicies"
Need more help? For detailed troubleshooting steps, diagnostic commands, and solutions to common issues, see the comprehensive Troubleshooting Guide.
Cleanup¶
Remove all deployed resources:
# Delete all resources (recommended)
azd down
# Delete specific environment
azd env delete <environment-name>
# Direct Terraform cleanup
cd infra/terraform
terraform destroy
Advanced Configuration¶
Container Apps Scaling Configuration¶
Update container app scaling in your terraform.tfvars:
# Adjust based on expected load
container_apps_configuration = {
backend = {
min_replicas = 1
max_replicas = 10
cpu_limit = "1.0"
memory_limit = "2Gi"
}
frontend = {
min_replicas = 1
max_replicas = 5
cpu_limit = "0.5"
memory_limit = "1Gi"
}
}
Model Configuration¶
Customize OpenAI model deployments for the latest supported models:
model_deployments = [
{
name = "gpt-4-1-mini"
version = "2024-11-20"
sku_name = "DataZoneStandard"
capacity = 100 # Increase for higher throughput
},
{
name = "o3-mini"
version = "2025-01-31"
sku_name = "DataZoneStandard"
capacity = 50 # Adjust based on reasoning workload
}
]
Security Hardening¶
For production deployments, consider:
# Enhanced security settings
disable_local_auth = true
enable_redis_ha = true
principal_type = "ServicePrincipal" # For CI/CD deployments
# Use higher Redis SKU for production
redis_sku = "Enterprise_E20"
Multi-Region Deployment¶
Configure secondary regions for OpenAI and Cosmos DB:
# Primary location
location = "eastus"
# Secondary locations for specific services
openai_location = "westus2"
cosmosdb_location = "westus"
Support & Next Steps¶
Additional Resources & Best Practices
Always test locally first to isolate issues before deploying to Azure. Use the comprehensive load testing framework in tests/load/ to validate performance under realistic conditions.
- Local Development Guide - Set up and test on your local machine
- Troubleshooting Guide - Comprehensive problem-solving guide
- Repository Structure - Understand the codebase layout
- Utilities & Services - Core infrastructure components
- Terraform Infrastructure README - Detailed infrastructure documentation