← Back to Guides

End-to-End Azure Deployment with IaC

AdvancedBicep & Terraform2026-03-14

Architecture Overview

This guide walks through deploying a production-ready Azure environment:

  • Virtual Network with subnets for application, data, and management tiers
  • API Management instance for API gateway
  • Logic App (Standard) with VNET integration
  • Key Vault for secrets management
  • Application Insights for monitoring

Project Structure

infra/
├── main.bicep          # or main.tf
├── parameters/
│   ├── dev.json        # Dev environment parameters
│   └── prod.json       # Prod environment parameters
├── modules/
│   ├── networking/     # VNET, subnets, NSGs
│   ├── apim/           # API Management
│   ├── logic-app/      # Logic App Standard
│   ├── key-vault/      # Key Vault
│   └── monitoring/     # App Insights + Log Analytics
└── pipeline.yml        # Azure DevOps pipeline

Networking Module (Bicep)

param location string
param environment string
param vnetAddressPrefix string = '10.0.0.0/16'

resource vnet 'Microsoft.Network/virtualNetworks@2023-05-01' = {
  name: 'vnet-${environment}'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        vnetAddressPrefix
      ]
    }
    subnets: [
      {
        name: 'snet-app'
        properties: {
          addressPrefix: '10.0.1.0/24'
          delegations: [
            {
              name: 'delegation'
              properties: {
                serviceName: 'Microsoft.Web/serverFarms'
              }
            }
          ]
        }
      }
      {
        name: 'snet-apim'
        properties: {
          addressPrefix: '10.0.2.0/24'
        }
      }
      {
        name: 'snet-data'
        properties: {
          addressPrefix: '10.0.3.0/24'
          serviceEndpoints: [
            { service: 'Microsoft.Storage' }
            { service: 'Microsoft.KeyVault' }
          ]
        }
      }
    ]
  }
}

output vnetId string = vnet.id
output appSubnetId string = vnet.properties.subnets[0].id
output apimSubnetId string = vnet.properties.subnets[1].id

Deployment Pipeline

trigger:
  branches:
    include:
      - main
  paths:
    include:
      - infra/*

parameters:
  - name: environment
    displayName: 'Environment'
    type: string
    default: 'dev'
    values:
      - dev
      - prod

stages:
  - stage: Validate
    jobs:
      - job: ValidateTemplate
        steps:
          - task: AzureCLI@2
            displayName: 'Validate Bicep'
            inputs:
              azureSubscription: 'service-connection'
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                az deployment group validate \
                  --resource-group rg-${{ parameters.environment }} \
                  --template-file infra/main.bicep \
                  --parameters @infra/parameters/${{ parameters.environment }}.json

  - stage: Deploy
    dependsOn: Validate
    jobs:
      - deployment: DeployInfra
        environment: 'infra-${{ parameters.environment }}'
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
                - task: AzureCLI@2
                  displayName: 'Deploy Infrastructure'
                  inputs:
                    azureSubscription: 'service-connection'
                    scriptType: 'bash'
                    scriptLocation: 'inlineScript'
                    inlineScript: |
                      az deployment group create \
                        --resource-group rg-${{ parameters.environment }} \
                        --template-file infra/main.bicep \
                        --parameters @infra/parameters/${{ parameters.environment }}.json

Environment Separation

🔧

Dev

Development environment — cost-optimised
APIM TierDeveloper
Logic App PlanWS1
Key VaultSoft delete
VNETBasic NSGs
MonitoringBasic
🛡

Prod

Production environment — fully hardened
APIM TierStandard
Logic App PlanWS2
Key VaultSoft delete + Purge protection
VNETFull NSG rules + DDoS protection
MonitoringFull diagnostics + alerts

Deployment Order

Resources must be deployed in dependency order:

  1. Resource Groups (if not pre-existing)
  2. Networking — VNET, subnets, NSGs
  3. Monitoring — Log Analytics workspace, Application Insights
  4. Key Vault — With access policies for other services
  5. APIM — With VNET integration
  6. Logic App — With VNET integration and Key Vault references

Best Practices

  1. Use What-If / Plan before every deployment
  2. Parameterise per environment — never hardcode environment-specific values
  3. Enable diagnostic settings on all resources
  4. Use Managed Identities between services
  5. Implement naming conventions consistently (e.g., {type}-{workload}-{environment}-{region})
  6. Store secrets in Key Vault and reference via Bicep/Terraform