Files
cmdb-insight/docs/Setup and configuration/AZURE-NEW-SUBSCRIPTION-SETUP.md
Bert Hausmans 57e4adc69c Remove JIRA_SCHEMA_ID from entire application
- Remove JIRA_SCHEMA_ID from all documentation, config files, and scripts
- Update generate-schema.ts to always auto-discover schemas dynamically
- Runtime application already discovers schemas via /objectschema/list API
- Build script now automatically selects schema with most objects
- Remove JIRA_SCHEMA_ID from docker-compose.yml, Azure setup scripts, and all docs
- Application is now fully schema-agnostic and discovers schemas automatically
2026-01-22 22:56:29 +01:00

937 lines
26 KiB
Markdown

# 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
1. **Resource Group** - Container for all resources
2. **Azure Container Registry (ACR)** - Store Docker images
3. **Azure Database for PostgreSQL** - Production database (recommended)
4. **Azure Key Vault** - Secure storage for secrets
5. **Azure App Service Plan** - Hosting plan for web apps
6. **Azure App Service (Backend)** - Backend API service
7. **Azure App Service (Frontend)** - Frontend web application
8. **Application Insights** - Monitoring and logging
9. **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)
```bash
# macOS
brew install azure-cli
# Linux
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Windows
# Download from: https://aka.ms/installazurecliwindows
```
### Login to Azure
```bash
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:
```bash
# 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:
```bash
# 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:
```bash
# 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
```bash
# 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)
```bash
# 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):
```bash
# 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.
```bash
# 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
```bash
# 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"
# 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"
# 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.
```bash
# 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.
```bash
# 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
```bash
# 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" \
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
```bash
# 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)
```bash
# 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
```bash
# 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
```bash
# 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)**
```bash
# 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**
```bash
# 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:
```bash
az webapp show --name $FRONTEND_APP_NAME --resource-group $RESOURCE_GROUP --query defaultHostName
```
---
## ✅ Step 10: Verify Deployment
### Check App Status
```bash
# 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
```bash
# Backend health check
curl https://${BACKEND_APP_NAME}.azurewebsites.net/api/health
# Frontend
curl https://${FRONTEND_APP_NAME}.azurewebsites.net
```
### View Logs
```bash
# 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:
```bash
# 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:
```bash
# 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.
1. **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)
2. **Configure Pipeline Variables**:
Update `azure-pipelines.yml` with your values:
```yaml
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'
```
3. **Create Environment**:
- Go to **Pipelines** → **Environments**
- Create environment: `production`
- (Optional) Add approvals for manual deployment control
4. **Run Pipeline**:
- Push to `main` branch → **Automatically builds AND deploys**
- Pipeline will:
- Build Docker images
- Push to ACR
- Deploy to App Services
- Verify deployment
### Zero-Downtime Deployment (Optional)
For production with zero downtime, use deployment slots:
1. **Create Staging Slots**:
```bash
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
```
2. **Use Advanced Pipeline**:
- Use `azure-pipelines-slots.yml` instead
- Deploys to staging first
- Swaps to production after verification
**See `docs/AZURE-PIPELINES.md` for complete setup guide.**
---
## 🛠️ Troubleshooting
### App Service Won't Start
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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
1. Go to Azure Portal → Application Insights → Your app
2. View:
- **Live Metrics**: Real-time performance
- **Application Map**: Service dependencies
- **Logs**: Query application logs
- **Metrics**: Performance metrics
### Set Up Alerts
```bash
# 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
1. **Use Basic tier ACR** for development (€5 vs €20)
2. **Application Insights Basic** is free up to 5GB/month
3. **Stop App Services** when not in use (dev/test environments)
4. **Use SQLite** instead of PostgreSQL (saves €20-30/month, but less scalable)
---
## 📚 Next Steps
1. **Configure DNS**: Point your domain to App Service
2. **Set up SSL**: Configure HTTPS certificate
3. **Test Application**: Verify all features work
4. **Set up Monitoring**: Configure alerts
5. **Document Access**: Share URLs and credentials with team
6. **Backup Strategy**: Plan for database backups (if needed)
---
## 🔗 Useful Commands Reference
```bash
# 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](https://docs.microsoft.com/azure/app-service/)
- [Azure Container Registry Documentation](https://docs.microsoft.com/azure/container-registry/)
- [Azure Database for PostgreSQL Documentation](https://docs.microsoft.com/azure/postgresql/)
- [Azure Key Vault Documentation](https://docs.microsoft.com/azure/key-vault/)
- [Application Insights Documentation](https://docs.microsoft.com/azure/azure-monitor/app/app-insights-overview)
---
## ✅ 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 guide
- `AZURE-ACR-SETUP.md` - ACR setup and usage
- `PRODUCTION-DEPLOYMENT.md` - General production deployment guide