Consolidate documentation and update backend services
- 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
This commit is contained in:
943
docs/Setup and configuration/AZURE-NEW-SUBSCRIPTION-SETUP.md
Normal file
943
docs/Setup and configuration/AZURE-NEW-SUBSCRIPTION-SETUP.md
Normal file
@@ -0,0 +1,943 @@
|
||||
# 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"
|
||||
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.
|
||||
|
||||
```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" \
|
||||
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
|
||||
|
||||
```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
|
||||
Reference in New Issue
Block a user