CommunityRAPP

Deployment Guide

Complete guide for deploying CommunityRAPP to production environments.

Table of Contents

Overview

This guide covers production deployment strategies for CommunityRAPP, including:

Deployment Checklist

Prerequisites

Azure Requirements

Subscriptions & Permissions:

Services:

Development Requirements

Local Tools:

Install Azure CLI:

# Windows (PowerShell)
winget install Microsoft.AzureCLI

# Mac
brew install azure-cli

# Linux
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

Install Functions Core Tools:

npm install -g azure-functions-core-tools@4

Deployment Options

Deploy all resources with a single click:

Deploy to Azure

What Gets Deployed:

Option 2: Manual Azure Portal Deployment

Step-by-step manual deployment for customization.

Option 3: Azure CLI Deployment

Automated deployment via command line.

Option 4: Terraform/Bicep (Infrastructure as Code)

For enterprise environments requiring version control.

Azure Deployment

Step 1: Deploy Infrastructure

Using ARM Template

# Login to Azure
az login

# Set variables
RESOURCE_GROUP="rg-contoso-rapp-prod"
LOCATION="eastus"
PROJECT_NAME="contoso-rapp-prod"

# Create resource group
az group create \
  --name $RESOURCE_GROUP \
  --location $LOCATION

# Deploy ARM template
az deployment group create \
  --resource-group $RESOURCE_GROUP \
  --template-file azuredeploy.json \
  --parameters projectName=$PROJECT_NAME

Using Azure CLI (Manual)

Create Resource Group:

az group create \
  --name rg-contoso-rapp-prod \
  --location eastus

Create Storage Account:

az storage account create \
  --name contoserappstorage \
  --resource-group rg-contoso-rapp-prod \
  --location eastus \
  --sku Standard_LRS \
  --kind StorageV2

Create File Shares:

# Get connection string
CONNECTION_STRING=$(az storage account show-connection-string \
  --name contoserappstorage \
  --resource-group rg-contoso-rapp-prod \
  --output tsv)

# Create file shares
az storage share create --name agents --connection-string $CONNECTION_STRING
az storage share create --name memory --connection-string $CONNECTION_STRING
az storage share create --name multi_agents --connection-string $CONNECTION_STRING

Create Application Insights:

az monitor app-insights component create \
  --app contoso-rapp-insights \
  --location eastus \
  --resource-group rg-contoso-rapp-prod \
  --application-type web

Create Function App:

az functionapp create \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --consumption-plan-location eastus \
  --runtime python \
  --runtime-version 3.11 \
  --functions-version 4 \
  --storage-account contoserappstorage \
  --app-insights contoso-rapp-insights \
  --os-type Linux

Create Azure OpenAI:

az cognitiveservices account create \
  --name contoso-rapp-openai \
  --resource-group rg-contoso-rapp-prod \
  --location eastus \
  --kind OpenAI \
  --sku S0

# Deploy model
az cognitiveservices account deployment create \
  --name contoso-rapp-openai \
  --resource-group rg-contoso-rapp-prod \
  --deployment-name gpt-4o \
  --model-name gpt-4o \
  --model-version "2024-08-06" \
  --model-format OpenAI \
  --sku-capacity 50 \
  --sku-name Standard

Step 2: Configure Application Settings

Get service keys and endpoints:

# Storage connection string
STORAGE_CONN=$(az storage account show-connection-string \
  --name contoserappstorage \
  --resource-group rg-contoso-rapp-prod \
  --output tsv)

# OpenAI key and endpoint
OPENAI_KEY=$(az cognitiveservices account keys list \
  --name contoso-rapp-openai \
  --resource-group rg-contoso-rapp-prod \
  --query key1 --output tsv)

OPENAI_ENDPOINT=$(az cognitiveservices account show \
  --name contoso-rapp-openai \
  --resource-group rg-contoso-rapp-prod \
  --query properties.endpoint --output tsv)

# Application Insights key
APP_INSIGHTS_KEY=$(az monitor app-insights component show \
  --app contoso-rapp-insights \
  --resource-group rg-contoso-rapp-prod \
  --query instrumentationKey --output tsv)

Configure Function App settings:

az functionapp config appsettings set \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --settings \
    "AzureWebJobsStorage=$STORAGE_CONN" \
    "AZURE_OPENAI_API_KEY=$OPENAI_KEY" \
    "AZURE_OPENAI_ENDPOINT=$OPENAI_ENDPOINT" \
    "AZURE_OPENAI_DEPLOYMENT_NAME=gpt-4o" \
    "AZURE_OPENAI_API_VERSION=2025-01-01-preview" \
    "APPINSIGHTS_INSTRUMENTATIONKEY=$APP_INSIGHTS_KEY" \
    "ASSISTANT_NAME=CommunityRAPP" \
    "CHARACTERISTIC_DESCRIPTION=Professional AI assistant with enterprise capabilities"

Step 3: Deploy Function Code

# Navigate to project directory
cd CommunityRAPP

# Deploy to Azure
func azure functionapp publish contoso-rapp-function-prod

Step 4: Verify Deployment

# Test function endpoint
FUNCTION_URL="https://contoso-rapp-function-prod.azurewebsites.net/api/businessinsightbot_function"
FUNCTION_KEY=$(az functionapp keys list \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --query functionKeys.default --output tsv)

curl -X POST "$FUNCTION_URL?code=$FUNCTION_KEY" \
  -H "Content-Type: application/json" \
  -d '{"user_input": "Hello", "conversation_history": []}'

Production Best Practices

1. Use Premium or Dedicated Hosting Plan

For production workloads, upgrade from Consumption plan:

Premium Plan Benefits:

# Create Premium plan
az functionapp plan create \
  --name contoso-rapp-plan-premium \
  --resource-group rg-contoso-rapp-prod \
  --location eastus \
  --sku EP1 \
  --is-linux

# Update function app to use Premium plan
az functionapp update \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --plan contoso-rapp-plan-premium

2. Enable Managed Identity

Use managed identity instead of connection strings:

# Enable system-assigned identity
az functionapp identity assign \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod

# Get identity principal ID
PRINCIPAL_ID=$(az functionapp identity show \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --query principalId --output tsv)

# Grant Storage Blob Data Contributor role
az role assignment create \
  --assignee $PRINCIPAL_ID \
  --role "Storage Blob Data Contributor" \
  --scope "/subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/rg-contoso-rapp-prod/providers/Microsoft.Storage/storageAccounts/contoserappstorage"

3. Use Azure Key Vault for Secrets

Store sensitive configuration in Key Vault:

# Create Key Vault
az keyvault create \
  --name contoso-rapp-keyvault \
  --resource-group rg-contoso-rapp-prod \
  --location eastus

# Add secrets
az keyvault secret set \
  --vault-name contoso-rapp-keyvault \
  --name OpenAI-API-Key \
  --value $OPENAI_KEY

# Grant function app access
az keyvault set-policy \
  --name contoso-rapp-keyvault \
  --object-id $PRINCIPAL_ID \
  --secret-permissions get list

# Update function app settings to reference Key Vault
az functionapp config appsettings set \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --settings \
    "AZURE_OPENAI_API_KEY=@Microsoft.KeyVault(SecretUri=https://contoso-rapp-keyvault.vault.azure.net/secrets/OpenAI-API-Key/)"

4. Configure Custom Domain & SSL

# Add custom domain
az functionapp config hostname add \
  --webapp-name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --hostname copilot.yourcompany.com

# Bind SSL certificate (assumes certificate uploaded)
az functionapp config ssl bind \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --certificate-thumbprint YOUR_CERT_THUMBPRINT \
  --ssl-type SNI

5. Enable Application Insights Profiler

az monitor app-insights component update \
  --app contoso-rapp-insights \
  --resource-group rg-contoso-rapp-prod \
  --query-access Enabled

6. Set Up Deployment Slots

For blue-green deployments:

# Create staging slot
az functionapp deployment slot create \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --slot staging

# Deploy to staging
func azure functionapp publish contoso-rapp-function-prod --slot staging

# Test staging slot
# https://contoso-rapp-function-prod-staging.azurewebsites.net

# Swap to production
az functionapp deployment slot swap \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --slot staging

Scaling Strategies

Horizontal Scaling

Consumption Plan:

Premium/Dedicated Plan:

# Set minimum and maximum instances
az functionapp plan update \
  --name contoso-rapp-plan-premium \
  --resource-group rg-contoso-rapp-prod \
  --min-instances 2 \
  --max-burst 10

Vertical Scaling

Upgrade Function App SKU:

# Scale up to EP2 (more CPU/memory)
az functionapp plan update \
  --name contoso-rapp-plan-premium \
  --resource-group rg-contoso-rapp-prod \
  --sku EP2

OpenAI Scaling

Increase TPM (Tokens Per Minute) quota:

  1. Azure Portal → OpenAI Service → Quotas
  2. Request quota increase
  3. Update deployment capacity
az cognitiveservices account deployment update \
  --name contoso-rapp-openai \
  --resource-group rg-contoso-rapp-prod \
  --deployment-name gpt-4o \
  --sku-capacity 100

Monitoring & Logging

Application Insights Queries

Request Volume:

requests
| where name == "businessinsightbot_function"
| summarize Count=count() by bin(timestamp, 5m)
| render timechart

Error Rate:

requests
| where name == "businessinsightbot_function"
| summarize
    Total=count(),
    Errors=countif(success==false),
    ErrorRate=100.0*countif(success==false)/count()
    by bin(timestamp, 5m)
| render timechart

Performance:

requests
| where name == "businessinsightbot_function"
| summarize
    AvgDuration=avg(duration),
    P50=percentile(duration, 50),
    P95=percentile(duration, 95),
    P99=percentile(duration, 99)
    by bin(timestamp, 1h)
| render timechart

Alerts

Create availability alert:

az monitor metrics alert create \
  --name "Function App Down" \
  --resource-group rg-contoso-rapp-prod \
  --scopes "/subscriptions/YOUR_SUB/resourceGroups/rg-contoso-rapp-prod/providers/Microsoft.Web/sites/contoso-rapp-function-prod" \
  --condition "avg Percentage CPU > 80" \
  --window-size 5m \
  --evaluation-frequency 1m \
  --action email YOUR_EMAIL@company.com

Create error rate alert:

az monitor metrics alert create \
  --name "High Error Rate" \
  --resource-group rg-contoso-rapp-prod \
  --scopes "/subscriptions/YOUR_SUB/resourceGroups/rg-contoso-rapp-prod/providers/Microsoft.Web/sites/contoso-rapp-function-prod" \
  --condition "total Http5xx > 10" \
  --window-size 5m

Backup & Recovery

Backup Strategy

1. Code & Configuration:

2. Memory/Data:

# Backup Azure File Shares
az storage file download-batch \
  --destination ./backup \
  --source agents \
  --account-name contoserappstorage

az storage file download-batch \
  --destination ./backup \
  --source memory \
  --account-name contoserappstorage

3. Automated Backup Script:

#!/bin/bash
# backup.sh

BACKUP_DIR="./backups/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

# Backup file shares
az storage file download-batch \
  --destination "$BACKUP_DIR/agents" \
  --source agents \
  --account-name contoserappstorage

az storage file download-batch \
  --destination "$BACKUP_DIR/memory" \
  --source memory \
  --account-name contoserappstorage

echo "Backup completed: $BACKUP_DIR"

Schedule with cron:

# Run daily at 2 AM
0 2 * * * /path/to/backup.sh

Disaster Recovery

1. Export ARM Template:

az group export \
  --name rg-contoso-rapp-prod \
  --output json > infrastructure-backup.json

2. Document Recovery Procedure:

Recovery Time Objective (RTO): < 1 hour Recovery Point Objective (RPO): < 24 hours

CI/CD Pipeline

GitHub Actions

Create .github/workflows/deploy.yml:

name: Deploy to Azure Functions

on:
  push:
    branches: [ main ]

env:
  AZURE_FUNCTIONAPP_NAME: contoso-rapp-function-prod
  AZURE_FUNCTIONAPP_PACKAGE_PATH: '.'
  PYTHON_VERSION: '3.11'

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - name: 'Checkout GitHub Action'
      uses: actions/checkout@v3

    - name: Setup Python $
      uses: actions/setup-python@v4
      with:
        python-version: $

    - name: 'Install dependencies'
      shell: bash
      run: |
        pushd './$'
        python -m pip install --upgrade pip
        pip install -r requirements.txt --target=".python_packages/lib/site-packages"
        popd

    - name: 'Run tests'
      shell: bash
      run: |
        pip install pytest
        pytest tests/

    - name: 'Deploy to Azure Functions'
      uses: Azure/functions-action@v1
      with:
        app-name: $
        package: $
        publish-profile: $
        scm-do-build-during-deployment: true
        enable-oryx-build: true

Get publish profile:

az functionapp deployment list-publishing-profiles \
  --name contoso-rapp-function-prod \
  --resource-group rg-contoso-rapp-prod \
  --xml

Add to GitHub Secrets as AZURE_FUNCTIONAPP_PUBLISH_PROFILE.

Azure DevOps

Create azure-pipelines.yml:

trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

variables:
  azureSubscription: 'YOUR_SERVICE_CONNECTION'
  functionAppName: 'contoso-rapp-function-prod'
  pythonVersion: '3.11'

stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - task: UsePythonVersion@0
      inputs:
        versionSpec: '$(pythonVersion)'

    - script: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt --target=".python_packages/lib/site-packages"
      displayName: 'Install dependencies'

    - script: |
        pip install pytest
        pytest tests/
      displayName: 'Run tests'

    - task: ArchiveFiles@2
      inputs:
        rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
        includeRootFolder: false
        archiveType: 'zip'
        archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'

    - publish: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
      artifact: drop

- stage: Deploy
  dependsOn: Build
  jobs:
  - job: DeployJob
    steps:
    - download: current
      artifact: drop

    - task: AzureFunctionApp@1
      inputs:
        azureSubscription: '$(azureSubscription)'
        appType: 'functionAppLinux'
        appName: '$(functionAppName)'
        package: '$(Pipeline.Workspace)/drop/*.zip'
        deploymentMethod: 'auto'

Next Steps


Need help? Open an issue