- Reorganize docs into 'Core deployment guides' and 'Setup and configuration' subdirectories - Consolidate redundant documentation files (ACR, pipelines, deployment guides) - Add documentation consolidation plan - Update backend database factory and logger services - Update migration script and docker-compose configurations - Add PostgreSQL setup script
27 KiB
Azure New Subscription Setup Guide
Complete guide for setting up all required Azure resources for CMDB Insight in a new Azure subscription.
📋 Overview
This guide will help you create and configure all necessary Azure resources to deploy the CMDB Insight application. The setup includes:
Required Resources
- Resource Group - Container for all resources
- Azure Container Registry (ACR) - Store Docker images
- Azure Database for PostgreSQL - Production database (recommended)
- Azure Key Vault - Secure storage for secrets
- Azure App Service Plan - Hosting plan for web apps
- Azure App Service (Backend) - Backend API service
- Azure App Service (Frontend) - Frontend web application
- Application Insights - Monitoring and logging
- DNS & SSL - Custom domain and HTTPS certificate
Estimated Costs
- Basic Setup (SQLite): €17-35/month
- Recommended Setup (PostgreSQL): €36-62/month
🚀 Prerequisites
Before starting, ensure you have:
- Azure CLI installed (
az --version) - Azure subscription with appropriate permissions
- Docker installed (for local testing)
- Access to Azure Portal
- Jira credentials (OAuth client ID/secret or Personal Access Token)
Install Azure CLI (if needed)
# macOS
brew install azure-cli
# Linux
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Windows
# Download from: https://aka.ms/installazurecliwindows
Login to Azure
az login
az account list --output table
az account set --subscription "<subscription-id-or-name>"
📦 Step 1: Create Resource Group
Create a resource group to organize all resources:
# Set variables (customize as needed)
RESOURCE_GROUP="rg-cmdb-insight-prod"
LOCATION="westeurope" # or your preferred region
# Create resource group
az group create \
--name $RESOURCE_GROUP \
--location $LOCATION
# Verify
az group show --name $RESOURCE_GROUP
Note: Choose a location close to your users. Common options:
westeurope(Netherlands, Germany)northeurope(Ireland, UK)eastus(US East)
🐳 Step 2: Create or Use Existing Azure Container Registry (ACR)
Important: Azure Container Registry can be shared across multiple applications. The repository name (cmdb-insight) is what separates this application from others in the same ACR.
Option A: Use Existing ACR (Recommended if you have one)
If you already have an ACR for other applications, you can reuse it:
# Set variables - use your existing ACR name
ACR_NAME="your-existing-acr" # Your existing ACR name
ACR_RESOURCE_GROUP="rg-shared-services" # Resource group where ACR exists
# Verify ACR exists
az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP
# Get ACR login server
ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query loginServer --output tsv)
echo "ACR Login Server: $ACR_LOGIN_SERVER"
Benefits of reusing ACR:
- ✅ Cost savings (one ACR for all apps)
- ✅ Centralized image management
- ✅ Easier to share images across teams
- ✅ Better resource utilization
Option B: Create New ACR
If you don't have an ACR yet, create one:
# Set variables
ACR_NAME="yourcompanyacr" # Must be globally unique, lowercase, 5-50 chars, alphanumeric only
ACR_RESOURCE_GROUP="rg-shared-services" # Or use your app resource group
SKU="Standard" # Options: Basic, Standard, Premium
# Create resource group for shared services (if needed)
az group create --name $ACR_RESOURCE_GROUP --location westeurope
# Create ACR
az acr create \
--resource-group $ACR_RESOURCE_GROUP \
--name $ACR_NAME \
--sku $SKU \
--admin-enabled true
# Get ACR login server
ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query loginServer --output tsv)
echo "ACR Login Server: $ACR_LOGIN_SERVER"
# Get admin credentials (save these securely)
az acr credential show --name $ACR_NAME
ACR SKU Comparison:
- Basic: €5/month - Development/test, 10GB storage
- Standard: €20/month - Production, 100GB storage, geo-replication (recommended)
- Premium: €50/month - Enterprise, 500GB storage, advanced security
Repository Structure in ACR:
yourcompanyacr.azurecr.io/
├── cmdb-insight/ ← This application
│ ├── backend:latest
│ └── frontend:latest
├── other-app/ ← Other applications
│ ├── api:latest
│ └── web:latest
└── shared-services/ ← Shared images
└── nginx:latest
Test ACR Connection
# Login to ACR
az acr login --name $ACR_NAME
# Verify
az acr repository list --name $ACR_NAME
# List repositories (you'll see cmdb-insight after first push)
az acr repository list --name $ACR_NAME --output table
🗄️ Step 3: Create Azure Database for PostgreSQL
PostgreSQL is recommended for production. Alternatively, you can use SQLite with Azure Storage (see Step 3B).
Step 3A: PostgreSQL (Recommended)
# Set variables
DB_SERVER_NAME="cmdb-postgres-prod" # Must be globally unique
RESOURCE_GROUP="rg-cmdb-insight-prod"
DB_ADMIN_USER="cmdbadmin"
DB_ADMIN_PASSWORD="<generate-secure-password>" # Use a strong password!
DB_NAME="cmdb"
SKU="Standard_B1ms" # Burstable tier, 1 vCore, 2GB RAM
# Generate secure password (save this!)
DB_ADMIN_PASSWORD=$(openssl rand -base64 32)
echo "Database Password: $DB_ADMIN_PASSWORD"
# Create PostgreSQL Flexible Server
az postgres flexible-server create \
--resource-group $RESOURCE_GROUP \
--name $DB_SERVER_NAME \
--location westeurope \
--admin-user $DB_ADMIN_USER \
--admin-password $DB_ADMIN_PASSWORD \
--sku-name $SKU \
--tier Burstable \
--storage-size 32 \
--version 15 \
--public-access 0.0.0.0 # Allow Azure services (restrict later if needed)
# Create database
az postgres flexible-server db create \
--resource-group $RESOURCE_GROUP \
--server-name $DB_SERVER_NAME \
--database-name $DB_NAME
# Get connection string
DB_CONNECTION_STRING="postgresql://${DB_ADMIN_USER}:${DB_ADMIN_PASSWORD}@${DB_SERVER_NAME}.postgres.database.azure.com:5432/${DB_NAME}?sslmode=require"
echo "Database Connection String: $DB_CONNECTION_STRING"
# Save connection details securely
echo "DB_HOST=${DB_SERVER_NAME}.postgres.database.azure.com" > .env.azure
echo "DB_USER=${DB_ADMIN_USER}" >> .env.azure
echo "DB_PASSWORD=${DB_ADMIN_PASSWORD}" >> .env.azure
echo "DB_NAME=${DB_NAME}" >> .env.azure
PostgreSQL SKU Options:
- Standard_B1ms: €20-30/month - 1 vCore, 2GB RAM (recommended for 20 users)
- Standard_B2s: €40-50/month - 2 vCores, 4GB RAM (for growth)
- Standard_D2s_v3: €100+/month - 2 vCores, 8GB RAM (high performance)
Step 3B: SQLite with Azure Storage (Alternative)
If you prefer to use SQLite (simpler, but less scalable):
# Set variables
STORAGE_ACCOUNT_NAME="cmdbstorage$(openssl rand -hex 4)" # Must be globally unique, lowercase
RESOURCE_GROUP="rg-cmdb-insight-prod"
# Create storage account
az storage account create \
--resource-group $RESOURCE_GROUP \
--name $STORAGE_ACCOUNT_NAME \
--location westeurope \
--sku Standard_LRS
# Get storage account key
STORAGE_KEY=$(az storage account keys list \
--resource-group $RESOURCE_GROUP \
--account-name $STORAGE_ACCOUNT_NAME \
--query "[0].value" --output tsv)
echo "Storage Account: $STORAGE_ACCOUNT_NAME"
echo "Storage Key: $STORAGE_KEY"
Note: SQLite works but has limitations with concurrent users. PostgreSQL is recommended for production.
🔐 Step 4: Create Azure Key Vault
Key Vault securely stores secrets like API keys, passwords, and tokens.
# Set variables
KEY_VAULT_NAME="kv-cmdb-insight-prod" # Must be globally unique
RESOURCE_GROUP="rg-cmdb-insight-prod"
# Create Key Vault
az keyvault create \
--name $KEY_VAULT_NAME \
--resource-group $RESOURCE_GROUP \
--location westeurope \
--sku standard
# Verify
az keyvault show --name $KEY_VAULT_NAME --resource-group $RESOURCE_GROUP
Add Secrets to Key Vault
# Set your actual values
JIRA_PAT="your-jira-personal-access-token"
SESSION_SECRET=$(openssl rand -hex 32)
JIRA_OAUTH_CLIENT_ID="your-oauth-client-id"
JIRA_OAUTH_CLIENT_SECRET="your-oauth-client-secret"
JIRA_SCHEMA_ID="your-schema-id"
# Add secrets
az keyvault secret set \
--vault-name $KEY_VAULT_NAME \
--name "JiraPat" \
--value "$JIRA_PAT"
az keyvault secret set \
--vault-name $KEY_VAULT_NAME \
--name "SessionSecret" \
--value "$SESSION_SECRET"
az keyvault secret set \
--vault-name $KEY_VAULT_NAME \
--name "JiraOAuthClientId" \
--value "$JIRA_OAUTH_CLIENT_ID"
az keyvault secret set \
--vault-name $KEY_VAULT_NAME \
--name "JiraOAuthClientSecret" \
--value "$JIRA_OAUTH_CLIENT_SECRET"
az keyvault secret set \
--vault-name $KEY_VAULT_NAME \
--name "JiraSchemaId" \
--value "$JIRA_SCHEMA_ID"
# If using PostgreSQL, add database password
az keyvault secret set \
--vault-name $KEY_VAULT_NAME \
--name "DatabasePassword" \
--value "$DB_ADMIN_PASSWORD"
📊 Step 5: Create Application Insights
Application Insights provides monitoring, logging, and performance metrics.
# Set variables
APP_INSIGHTS_NAME="appi-cmdb-insight-prod"
RESOURCE_GROUP="rg-cmdb-insight-prod"
# Create Application Insights
az monitor app-insights component create \
--app $APP_INSIGHTS_NAME \
--location westeurope \
--resource-group $RESOURCE_GROUP \
--application-type web
# Get Instrumentation Key
INSTRUMENTATION_KEY=$(az monitor app-insights component show \
--app $APP_INSIGHTS_NAME \
--resource-group $RESOURCE_GROUP \
--query instrumentationKey --output tsv)
echo "Instrumentation Key: $INSTRUMENTATION_KEY"
Note: Application Insights Basic tier is free up to 5GB/month, which is sufficient for most small applications.
🖥️ Step 6: Create App Service Plan
App Service Plan defines the compute resources for your web apps.
# Set variables
APP_SERVICE_PLAN_NAME="plan-cmdb-insight-prod"
RESOURCE_GROUP="rg-cmdb-insight-prod"
SKU="B1" # Basic tier, 1 vCore, 1.75GB RAM
# Create App Service Plan (Linux)
az appservice plan create \
--name $APP_SERVICE_PLAN_NAME \
--resource-group $RESOURCE_GROUP \
--sku $SKU \
--is-linux
# Verify
az appservice plan show --name $APP_SERVICE_PLAN_NAME --resource-group $RESOURCE_GROUP
App Service Plan SKU Options:
- B1: €15-25/month - 1 vCore, 1.75GB RAM (recommended for 20 users)
- B2: €30-40/month - 2 vCores, 3.5GB RAM
- S1: €50-70/month - 1 vCore, 1.75GB RAM (Standard tier, better performance)
🚀 Step 7: Create App Services (Backend & Frontend)
Create two web apps: one for backend API and one for frontend.
Step 7A: Create Backend App Service
# Set variables
BACKEND_APP_NAME="cmdb-backend-prod" # Must be globally unique
RESOURCE_GROUP="rg-cmdb-insight-prod"
APP_SERVICE_PLAN_NAME="plan-cmdb-insight-prod"
ACR_NAME="cmdbinsightacr" # From Step 2
# Create backend web app
az webapp create \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--plan $APP_SERVICE_PLAN_NAME \
--deployment-container-image-name "${ACR_NAME}.azurecr.io/cmdb-insight/backend:latest"
# Enable Managed Identity (for ACR access)
az webapp identity assign \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP
# Get Managed Identity Principal ID
BACKEND_PRINCIPAL_ID=$(az webapp identity show \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--query principalId --output tsv)
# Grant ACR pull permissions
ACR_ID=$(az acr show --name $ACR_NAME --resource-group $RESOURCE_GROUP --query id --output tsv)
az role assignment create \
--assignee $BACKEND_PRINCIPAL_ID \
--role AcrPull \
--scope $ACR_ID
# Configure container settings
az webapp config container set \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--docker-custom-image-name "${ACR_NAME}.azurecr.io/cmdb-insight/backend:latest" \
--docker-registry-server-url "https://${ACR_NAME}.azurecr.io"
# Set environment variables
az webapp config appsettings set \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--settings \
NODE_ENV=production \
PORT=3001 \
DATABASE_TYPE=postgres \
DATABASE_URL="@Microsoft.KeyVault(SecretUri=https://${KEY_VAULT_NAME}.vault.azure.net/secrets/DatabasePassword/)" \
JIRA_HOST=https://jira.zuyderland.nl \
JIRA_AUTH_METHOD=oauth \
JIRA_OAUTH_CLIENT_ID="@Microsoft.KeyVault(SecretUri=https://${KEY_VAULT_NAME}.vault.azure.net/secrets/JiraOAuthClientId/)" \
JIRA_OAUTH_CLIENT_SECRET="@Microsoft.KeyVault(SecretUri=https://${KEY_VAULT_NAME}.vault.azure.net/secrets/JiraOAuthClientSecret/)" \
JIRA_OAUTH_CALLBACK_URL="https://${BACKEND_APP_NAME}.azurewebsites.net/api/auth/callback" \
JIRA_SCHEMA_ID="@Microsoft.KeyVault(SecretUri=https://${KEY_VAULT_NAME}.vault.azure.net/secrets/JiraSchemaId/)" \
SESSION_SECRET="@Microsoft.KeyVault(SecretUri=https://${KEY_VAULT_NAME}.vault.azure.net/secrets/SessionSecret/)" \
FRONTEND_URL="https://${FRONTEND_APP_NAME}.azurewebsites.net" \
APPINSIGHTS_INSTRUMENTATIONKEY="${INSTRUMENTATION_KEY}"
# Grant Key Vault access to backend
az keyvault set-policy \
--name $KEY_VAULT_NAME \
--object-id $BACKEND_PRINCIPAL_ID \
--secret-permissions get list
# Enable HTTPS only
az webapp update \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--https-only true
Step 7B: Create Frontend App Service
# Set variables
FRONTEND_APP_NAME="cmdb-frontend-prod" # Must be globally unique
RESOURCE_GROUP="rg-cmdb-insight-prod"
APP_SERVICE_PLAN_NAME="plan-cmdb-insight-prod"
ACR_NAME="cmdbinsightacr" # From Step 2
# Create frontend web app
az webapp create \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--plan $APP_SERVICE_PLAN_NAME \
--deployment-container-image-name "${ACR_NAME}.azurecr.io/cmdb-insight/frontend:latest"
# Enable Managed Identity
az webapp identity assign \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP
# Get Managed Identity Principal ID
FRONTEND_PRINCIPAL_ID=$(az webapp identity show \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--query principalId --output tsv)
# Grant ACR pull permissions
az role assignment create \
--assignee $FRONTEND_PRINCIPAL_ID \
--role AcrPull \
--scope $ACR_ID
# Configure container settings
az webapp config container set \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--docker-custom-image-name "${ACR_NAME}.azurecr.io/cmdb-insight/frontend:latest" \
--docker-registry-server-url "https://${ACR_NAME}.azurecr.io"
# Set environment variables
az webapp config appsettings set \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--settings \
VITE_API_URL="https://${BACKEND_APP_NAME}.azurewebsites.net/api"
# Enable HTTPS only
az webapp update \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--https-only true
🔄 Step 8: Build and Push Docker Images
Before the apps can run, you need to build and push Docker images to ACR.
Option A: Using Script (Recommended)
# Navigate to project root
cd /path/to/cmdb-insight
# Set environment variables
export ACR_NAME="cmdbinsightacr" # Your ACR name
export REPO_NAME="cmdb-insight"
# Build and push
./scripts/build-and-push-azure.sh
Option B: Manual Build and Push
# Set variables
ACR_NAME="cmdbinsightacr"
REGISTRY="${ACR_NAME}.azurecr.io"
REPO_NAME="cmdb-insight"
# Login to ACR
az acr login --name $ACR_NAME
# Build backend
docker build -t ${REGISTRY}/${REPO_NAME}/backend:latest \
-f backend/Dockerfile.prod ./backend
# Build frontend
docker build -t ${REGISTRY}/${REPO_NAME}/frontend:latest \
-f frontend/Dockerfile.prod ./frontend
# Push images
docker push ${REGISTRY}/${REPO_NAME}/backend:latest
docker push ${REGISTRY}/${REPO_NAME}/frontend:latest
# Verify
az acr repository list --name $ACR_NAME
az acr repository show-tags --name $ACR_NAME --repository ${REPO_NAME}/backend
az acr repository show-tags --name $ACR_NAME --repository ${REPO_NAME}/frontend
🌐 Step 9: Configure Custom Domain and SSL (Optional)
If you have a custom domain (e.g., cmdb.yourcompany.com):
Step 9A: Add Custom Domain
# Set variables
FRONTEND_APP_NAME="cmdb-frontend-prod"
BACKEND_APP_NAME="cmdb-backend-prod"
CUSTOM_DOMAIN="cmdb.yourcompany.com"
RESOURCE_GROUP="rg-cmdb-insight-prod"
# Add custom domain to frontend
az webapp config hostname add \
--webapp-name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--hostname $CUSTOM_DOMAIN
# Add custom domain to backend (if needed)
az webapp config hostname add \
--webapp-name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--hostname "api.${CUSTOM_DOMAIN}"
Step 9B: Configure SSL Certificate
Option 1: App Service Managed Certificate (Free, Recommended)
# Create managed certificate for frontend
az webapp config ssl create \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--hostname $CUSTOM_DOMAIN
# Bind certificate
az webapp config ssl bind \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--certificate-thumbprint <thumbprint> \
--ssl-type SNI
Option 2: Import Existing Certificate
# Upload certificate
az webapp config ssl upload \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--certificate-file /path/to/certificate.pfx \
--certificate-password <password>
Note: You'll need to update DNS records to point to your App Service. Get the IP address:
az webapp show --name $FRONTEND_APP_NAME --resource-group $RESOURCE_GROUP --query defaultHostName
✅ Step 10: Verify Deployment
Check App Status
# Check backend
az webapp show --name $BACKEND_APP_NAME --resource-group $RESOURCE_GROUP --query state
# Check frontend
az webapp show --name $FRONTEND_APP_NAME --resource-group $RESOURCE_GROUP --query state
# Start apps if needed
az webapp start --name $BACKEND_APP_NAME --resource-group $RESOURCE_GROUP
az webapp start --name $FRONTEND_APP_NAME --resource-group $RESOURCE_GROUP
Test Health Endpoints
# Backend health check
curl https://${BACKEND_APP_NAME}.azurewebsites.net/api/health
# Frontend
curl https://${FRONTEND_APP_NAME}.azurewebsites.net
View Logs
# Backend logs
az webapp log tail --name $BACKEND_APP_NAME --resource-group $RESOURCE_GROUP
# Frontend logs
az webapp log tail --name $FRONTEND_APP_NAME --resource-group $RESOURCE_GROUP
🔧 Step 11: Configure Database Schema
If using PostgreSQL, you need to initialize the database schema:
# Connect to database and run schema initialization
# Option 1: Using psql
psql "postgresql://${DB_ADMIN_USER}:${DB_ADMIN_PASSWORD}@${DB_SERVER_NAME}.postgres.database.azure.com:5432/${DB_NAME}?sslmode=require"
# Option 2: Using Azure Cloud Shell or local script
# The application will create tables automatically on first run
# Or use the migration scripts in backend/scripts/
Note: The application will automatically create the required database schema on first startup if it doesn't exist.
📝 Step 12: Update Environment Variables (If Needed)
If you need to update any configuration:
# Update backend settings
az webapp config appsettings set \
--name $BACKEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--settings \
NEW_SETTING=value
# Update frontend settings
az webapp config appsettings set \
--name $FRONTEND_APP_NAME \
--resource-group $RESOURCE_GROUP \
--settings \
VITE_API_URL="https://${BACKEND_APP_NAME}.azurewebsites.net/api"
# Restart apps to apply changes
az webapp restart --name $BACKEND_APP_NAME --resource-group $RESOURCE_GROUP
az webapp restart --name $FRONTEND_APP_NAME --resource-group $RESOURCE_GROUP
🔄 Step 13: Set Up CI/CD with Automated Deployment
Azure DevOps Pipeline Setup
The project includes an automated pipeline that builds, pushes, and deploys your application.
-
Create Service Connections:
A) Docker Registry Connection (for building images):
- Go to Azure DevOps → Project Settings → Service connections
- Create new Docker Registry connection
- Select Azure Container Registry
- Choose your subscription and ACR
- Name:
zuyderland-cmdb-acr-connection(or match your variable)
B) Azure Resource Manager Connection (for deployment):
- Create new Azure Resource Manager connection
- Select your subscription
- Name:
zuyderland-cmdb-subscription(or match your variable)
-
Configure Pipeline Variables:
Update
azure-pipelines.ymlwith your values:variables: acrName: 'cmdbinsightacr' # Your ACR name resourceGroup: 'rg-cmdb-insight-prod' # Your resource group backendAppName: 'cmdb-backend-prod' # Your backend app name frontendAppName: 'cmdb-frontend-prod' # Your frontend app name azureSubscription: 'zuyderland-cmdb-subscription' # Azure service connection dockerRegistryServiceConnection: 'zuyderland-cmdb-acr-connection' -
Create Environment:
- Go to Pipelines → Environments
- Create environment:
production - (Optional) Add approvals for manual deployment control
-
Run Pipeline:
- Push to
mainbranch → Automatically builds AND deploys - Pipeline will:
- Build Docker images
- Push to ACR
- Deploy to App Services
- Verify deployment
- Push to
Zero-Downtime Deployment (Optional)
For production with zero downtime, use deployment slots:
-
Create Staging Slots:
az webapp deployment slot create \ --name $BACKEND_APP_NAME \ --resource-group $RESOURCE_GROUP \ --slot staging az webapp deployment slot create \ --name $FRONTEND_APP_NAME \ --resource-group $RESOURCE_GROUP \ --slot staging -
Use Advanced Pipeline:
- Use
azure-pipelines-slots.ymlinstead - Deploys to staging first
- Swaps to production after verification
- Use
See docs/AZURE-PIPELINES.md for complete setup guide.
🛠️ Troubleshooting
App Service Won't Start
# Check logs
az webapp log tail --name $BACKEND_APP_NAME --resource-group $RESOURCE_GROUP
# Check container logs
az webapp log show --name $BACKEND_APP_NAME --resource-group $RESOURCE_GROUP
# Check app status
az webapp show --name $BACKEND_APP_NAME --resource-group $RESOURCE_GROUP --query state
ACR Authentication Issues
# Re-authenticate
az acr login --name $ACR_NAME
# Check Managed Identity permissions
az role assignment list --assignee $BACKEND_PRINCIPAL_ID --scope $ACR_ID
Database Connection Issues
# Test database connection
psql "postgresql://${DB_ADMIN_USER}:${DB_ADMIN_PASSWORD}@${DB_SERVER_NAME}.postgres.database.azure.com:5432/${DB_NAME}?sslmode=require"
# Check firewall rules
az postgres flexible-server firewall-rule list \
--resource-group $RESOURCE_GROUP \
--name $DB_SERVER_NAME
Key Vault Access Issues
# Check Key Vault policies
az keyvault show --name $KEY_VAULT_NAME --resource-group $RESOURCE_GROUP
# Verify Managed Identity has access
az keyvault show-policy --name $KEY_VAULT_NAME
📊 Monitoring
Application Insights
- Go to Azure Portal → Application Insights → Your app
- View:
- Live Metrics: Real-time performance
- Application Map: Service dependencies
- Logs: Query application logs
- Metrics: Performance metrics
Set Up Alerts
# Create alert for app downtime
az monitor metrics alert create \
--name "Backend-Down" \
--resource-group $RESOURCE_GROUP \
--scopes "/subscriptions/<subscription-id>/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Web/sites/${BACKEND_APP_NAME}" \
--condition "avg AvailabilityPercentage < 99" \
--window-size 5m \
--evaluation-frequency 1m
💰 Cost Optimization
Current Setup Costs
| Resource | SKU | Estimated Monthly Cost |
|---|---|---|
| App Service Plan | B1 | €15-25 |
| PostgreSQL | Standard_B1ms | €20-30 |
| Container Registry | Basic | €5 |
| Key Vault | Standard | €1-2 |
| Application Insights | Basic | €0-5 (free tier) |
| Total | €41-67/month |
Cost Saving Tips
- Use Basic tier ACR for development (€5 vs €20)
- Application Insights Basic is free up to 5GB/month
- Stop App Services when not in use (dev/test environments)
- Use SQLite instead of PostgreSQL (saves €20-30/month, but less scalable)
📚 Next Steps
- Configure DNS: Point your domain to App Service
- Set up SSL: Configure HTTPS certificate
- Test Application: Verify all features work
- Set up Monitoring: Configure alerts
- Document Access: Share URLs and credentials with team
- Backup Strategy: Plan for database backups (if needed)
🔗 Useful Commands Reference
# List all resources
az resource list --resource-group $RESOURCE_GROUP --output table
# Get resource IDs
az acr show --name $ACR_NAME --resource-group $RESOURCE_GROUP --query id
az postgres flexible-server show --name $DB_SERVER_NAME --resource-group $RESOURCE_GROUP --query id
# Export resource configuration
az group export --name $RESOURCE_GROUP --output-file resources.json
# Delete all resources (careful!)
az group delete --name $RESOURCE_GROUP --yes --no-wait
📖 Additional Resources
- Azure App Service Documentation
- Azure Container Registry Documentation
- Azure Database for PostgreSQL Documentation
- Azure Key Vault Documentation
- Application Insights Documentation
✅ Deployment Checklist
- Resource Group created
- Azure Container Registry created and accessible
- PostgreSQL database created (or SQLite storage configured)
- Key Vault created with all secrets
- Application Insights created
- App Service Plan created
- Backend App Service created and configured
- Frontend App Service created and configured
- Docker images built and pushed to ACR
- Apps started and running
- Health checks passing
- Custom domain configured (if applicable)
- SSL certificate configured (if applicable)
- Monitoring and alerts configured
- Team access configured
- Documentation updated
🎉 Congratulations! Your CMDB Insight application is now deployed to Azure!
For questions or issues, refer to:
AZURE-APP-SERVICE-DEPLOYMENT.md- Detailed App Service deployment guideAZURE-ACR-SETUP.md- ACR setup and usagePRODUCTION-DEPLOYMENT.md- General production deployment guide