Appearance
Runbook: Add a New Azure Environment
Estimated time: 4–8 hours (first environment), 2–3 hours (subsequent)
Audience: DevOps engineers
Prerequisites: Azure Owner access on the ERP subscription, Azure DevOps Project Administrator, Bicep CLI installed
Overview
This runbook provisions a new Azure environment for the Microtec ERP platform from scratch. Follow all steps in order — later steps depend on earlier ones.
services-config.json → Bicep params → Azure provision → Pipeline variables → TestStep 1 — Define the Environment Name
Choose a short lowercase identifier for the new environment. Existing environments:
| Name | CIDR | Purpose |
|---|---|---|
dev | 10.0.0.0/16 | Development |
stage | 10.1.0.0/16 | Staging / integration |
preprod | 10.6.0.0/16 | Pre-production |
uat | 10.5.0.0/16 | User acceptance testing |
production | 10.2.0.0/16 | Production |
Pick the next available CIDR block. For this example, the new environment is named qa with CIDR 10.3.0.0/16.
Step 2 — Update services-config.json
File: Devops/azure/config/container-backend/services-config.json
Each service entry has an environments object with per-environment overrides. Add a qa entry for every service:
jsonc
{
"services": [
{
"name": "gateway",
"image": "gateway-api",
"environments": {
"dev": { "minReplicas": 1, "maxReplicas": 3 },
"stage": { "minReplicas": 1, "maxReplicas": 5 },
"preprod": { "minReplicas": 1, "maxReplicas": 5 },
"uat": { "minReplicas": 1, "maxReplicas": 3 },
"production": { "minReplicas": 2, "maxReplicas": 10 },
"qa": { "minReplicas": 1, "maxReplicas": 3 } // ← ADD THIS
}
}
// Repeat for every service entry
]
}Add the new environment to ALL service entries
The pipeline reads environments.{env} for every service. If any service is missing the new environment key, the pipeline will fail during deployment with a key-not-found error.
Step 3 — Create the Bicep Parameter File
File: Devops/azure/infrastructure/parameters/qa.bicepparam
Start by copying the closest existing environment's param file:
bash
cp Devops/azure/infrastructure/parameters/uat.bicepparam \
Devops/azure/infrastructure/parameters/qa.bicepparamEdit the new file:
bicep
// qa.bicepparam
using '../main.bicep'
param environment = 'qa'
param location = 'uksouth'
// Networking
param vnetAddressPrefix = '10.3.0.0/16'
param acaSubnetPrefix = '10.3.0.0/23'
param infraSubnetPrefix = '10.3.2.0/27'
// Resource naming (follows mic-erp-be-{env}-{resource} convention)
param resourcePrefix = 'mic-erp-be'
// SQL
param sqlServerResourceGroup = 'mic-backend-shared-sql-rg'
param sqlServerName = 'mic-backend-shared-sql'
// Key Vault name (must be globally unique, max 24 chars)
param keyVaultName = 'mic-erp-be-qa-skv'
// Container Apps
param minReplicas = 1
param maxReplicas = 5Resource naming the Bicep will create
The main.bicep template generates these resource groups based on the environment parameter:
| Resource Group | Contains |
|---|---|
mic-erp-be-qa-network-rg | VNet, subnets, NSG, NAT GW |
mic-erp-be-qa-containers-rg | Public CAE, Private CAE, container apps |
mic-erp-be-qa-storage-rg | Blob storage (attachments) |
mic-erp-be-fr-qa-storage-rg | Frontend SWA storage |
mic-erp-be-qa-monitoring-rg | Log Analytics, App Insights |
mic-erp-be-qa-shared-rg | ACR, Key Vault, managed identity |
mic-backend-shared-sql-rg | Shared SQL (unchanged — do not create new) |
Step 4 — Run the Bicep Deployment
bash
# Login and set subscription
az login
az account set --subscription "<ERP Subscription ID>"
# Validate first (dry run)
az deployment sub what-if \
--location uksouth \
--template-file Devops/azure/infrastructure/main.bicep \
--parameters Devops/azure/infrastructure/parameters/qa.bicepparam
# Review what-if output carefully, then deploy
az deployment sub create \
--location uksouth \
--template-file Devops/azure/infrastructure/main.bicep \
--parameters Devops/azure/infrastructure/parameters/qa.bicepparam \
--name "mic-erp-qa-$(date +%Y%m%d)"Expected deployment time: 15–25 minutes.
Monitor progress
Use the Azure Portal → Subscriptions → Deployments to see real-time provisioning status. Each module (network, containerApps, acr) appears as a nested deployment.
Step 5 — Verify Created Resources
After deployment completes, verify the key resources exist:
bash
ENV=qa
SUBSCRIPTION="<ERP Subscription ID>"
# Verify VNet
az network vnet show \
--resource-group "mic-erp-be-${ENV}-network-rg" \
--name "mic-erp-be-${ENV}-vnet" \
--query "addressSpace.addressPrefixes" -o tsv
# Verify ACR
az acr show \
--resource-group "mic-erp-be-${ENV}-shared-rg" \
--name "micerpbe${ENV}acr" \
--query "loginServer" -o tsv
# Verify Key Vault
az keyvault show \
--resource-group "mic-erp-be-${ENV}-shared-rg" \
--name "mic-erp-be-${ENV}-skv" \
--query "properties.vaultUri" -o tsv
# Verify Public CAE
az containerapp env show \
--resource-group "mic-erp-be-${ENV}-apps-public-rg" \
--name "mic-erp-be-${ENV}-cae-public" \
--query "properties.provisioningState" -o tsvAll outputs should be non-empty and provisioningState should be Succeeded.
Step 6 — Populate Key Vault Secrets
Secrets must be added to the new environment's Key Vault before any services can start. The minimum required secrets are:
bash
KV="mic-erp-be-qa-skv"
# SQL connection strings (one per service that uses SQL)
az keyvault secret set --vault-name $KV \
--name "DefaultConnection" \
--value "Server=mic-backend-shared-sql.database.windows.net;Database=mic_erp_qa;..."
# Redis
az keyvault secret set --vault-name $KV \
--name "RedisConfiguration--Password" \
--value "<redis-password>"
# RabbitMQ / Service Bus
az keyvault secret set --vault-name $KV \
--name "ServiceBus--ConnectionString" \
--value "<service-bus-connection-string>"Key Vault naming convention
Use -- (double dash) in secret names, not __ (double underscore). Azure Key Vault does not allow double underscores. The hosting package translates -- back to : when loading configuration.
Step 7 — Update Pipeline Variables in Azure DevOps
In Azure DevOps, navigate to Pipelines → Library → Variable Groups and create a new variable group named microtec-erp-qa:
| Variable | Value | Secret? |
|---|---|---|
environment | qa | No |
acr_name | micerpbeqaacr | No |
resource_group_containers | mic-erp-be-qa-containers-rg | No |
keyvault_name | mic-erp-be-qa-skv | No |
azure_subscription_connection | microtec-erp-qa-serviceconnection | No |
nuget_pat | <PAT> | Yes |
Then add qa to the environment allowlist in the pipeline template:
yaml
# Devops/azure/templates/devsecops/pipeline-template.yml
parameters:
- name: environment
type: string
values: [dev, stage, preprod, uat, production, qa] # ← add qaStep 8 — Add Branch Mapping
The pipeline auto-detects the target environment from the triggering branch. Add the qa branch mapping:
yaml
# Devops/azure/templates/devsecops/stages/11-deploy-dev.yml
# (and the equivalent deploy-stage.yml)
variables:
targetEnv: ${{
eq(variables['Build.SourceBranch'], 'refs/heads/main') == 'true' ? 'dev' :
eq(variables['Build.SourceBranch'], 'refs/heads/stage') == 'true' ? 'stage' :
eq(variables['Build.SourceBranch'], 'refs/heads/qa') == 'true' ? 'qa' : # ← add
'dev' }}Step 9 — Deploy All Services to the New Environment
Trigger the first full deployment by running the pipeline manually for each service with environment=qa, or merge to the qa branch if branch mapping is configured.
bash
# Trigger via Azure DevOps CLI (example for gateway service)
az pipelines run \
--name "deploy-gateway" \
--parameters "environment=qa" \
--branch mainStep 10 — Verify Deployment
bash
ENV=qa
RG="mic-erp-be-${ENV}-containers-rg"
# Check all container apps are running
az containerapp list \
--resource-group $RG \
--query "[].{name:name, status:properties.runningStatus}" \
-o table
# Hit the gateway health endpoint
GATEWAY_FQDN=$(az containerapp show \
--name "mic-erp-be-${ENV}-gateway" \
--resource-group $RG \
--query "properties.configuration.ingress.fqdn" -o tsv)
curl -s "https://${GATEWAY_FQDN}/health" | jq .Checklist
- [ ] Environment name chosen; CIDR block selected (no overlap with existing environments)
- [ ]
services-config.jsonupdated for ALL services - [ ] Bicep parameter file created (
qa.bicepparam) - [ ]
what-ifreviewed and deployment executed - [ ] All resource groups verified in Azure Portal
- [ ] Key Vault secrets populated
- [ ] Azure DevOps variable group created (
microtec-erp-qa) - [ ] Branch mapping updated in pipeline template
- [ ] Pipeline environment gate added in Azure DevOps
- [ ] All services deployed and health-checked
- [ ] DNS configured for new environment (if public-facing)