Skip to content

Bicep Deployment

Bicep Status: Tested Run on: Mgmt Workstation CI/CD: Examples Available

Overview

Subscription-scope Bicep deployment that creates all Azure-side resources for the SOFS guest cluster using Azure Verified Modules (AVM) from the public Bicep registry for the resource group and cloud witness storage account.

Microsoft references used for this implementation:

  • Bicep docs: https://learn.microsoft.com/azure/azure-resource-manager/bicep/
  • AVM overview: https://azure.github.io/Azure-Verified-Modules/
  • AVM Bicep quickstart: https://azure.github.io/Azure-Verified-Modules/usage/quickstart/bicep/

Capability

Capability Supported
Azure resource provisioning
Domain join (JsonADDomainExtension)
Per-VM storage path mapping
Guest OS configuration Delegates to PS/Ansible
AVM modules (RG + Storage)

Phase Ownership

Phase Group Ownership
Phase 0 (decision tree) Parameter validation only
Phases 1-2 (Azure/Host plane) Implemented in Bicep modules
Phases 3-11 (Guest OS plane) Delegated to PowerShell or Ansible

Resources Created

Resource Module
Resource Group AVM br/public:avm/res/resources/resource-group
Cloud Witness Storage Account AVM br/public:avm/res/storage/storage-account
Arc Machine Placeholders sofs-resources.bicep
NICs (compute logical network) sofs-resources.bicep
Data Disks (S2D pool) sofs-resources.bicep
VM Instances (with per-VM storage paths) sofs-resources.bicep
Domain Join Extensions sofs-resources.bicep

Prerequisites


File Inventory

File Purpose
main.bicep Subscription-scope wrapper — AVM RG + storage, calls sofs-resources module
sofs-resources.bicep Resource-group-scope module — VMs, NICs, data disks, domain join extensions
main.bicepparam Bicep parameters file (reference only — never commit secrets)
Deploy-SOFS-Azure.ps1 Orchestrator script — reads config, resolves KV, deploys

Architecture

main.bicep (subscription scope)
├── AVM: avm/res/resources/resource-group
├── AVM: avm/res/storage/storage-account (cloud witness)
└── sofs-resources.bicep (resource-group scope)
    ├── Microsoft.HybridCompute/machines[]               — Arc placeholders
    ├── Microsoft.AzureStackHCI/networkInterfaces[]       — NICs
    ├── Microsoft.AzureStackHCI/virtualHardDisks[]        — Data disks
    ├── Microsoft.AzureStackHCI/VirtualMachineInstances[] — VMs (per-VM storage paths)
    └── Microsoft.HybridCompute/machines/extensions[]     — Domain join

Setup

1. Configure Parameters

cd src/bicep
cp main.bicepparam.example main.bicepparam

Edit main.bicepparam with values from your config/variables.yml.

2. Set Secrets

The Deploy-SOFS-Azure.ps1 wrapper resolves Key Vault secrets automatically. If deploying manually, pass secrets as secure parameters:

az deployment sub create `
    --location eastus `
    --template-file main.bicep `
    --parameters main.bicepparam `
    --parameters adminPassword="$(az keyvault secret show --vault-name kv-platform-prod --name sofs-vm-admin-password --query value -o tsv)"

Deployment

# Dry run (validate templates):
.\Deploy-SOFS-Azure.ps1 -WhatIf

# Full deployment:
.\Deploy-SOFS-Azure.ps1

The script reads config/variables.yml, resolves Key Vault secrets, and runs az deployment sub create.

Manual: Azure CLI

az deployment sub create `
    --location eastus `
    --template-file main.bicep `
    --parameters main.bicepparam

Manual: Az PowerShell

New-AzSubscriptionDeployment `
    -Location "eastus" `
    -TemplateFile "main.bicep" `
    -TemplateParameterFile "main.bicepparam"

Post-Deployment

After Bicep deploys the Azure resources:

  1. Verify VMs are running in Azure portal
  2. Verify domain join — the JsonADDomainExtension is deployed automatically
  3. Run guest configuration:
.\src\powershell\deploy\Configure-SOFS-Cluster.ps1 -ConfigPath "config\variables.yml"

Next Steps

  • PowerShell — Guest OS configuration (Phases 3–11)
  • Ansible — Alternative guest configuration via Ansible
  • Validation — Verify the deployment