Skip to content

Add Azure VM + Network Bicep IaC with modular structure#11

Open
Claude wants to merge 2 commits intomainfrom
claude/add-demo-iac-azure-vm
Open

Add Azure VM + Network Bicep IaC with modular structure#11
Claude wants to merge 2 commits intomainfrom
claude/add-demo-iac-azure-vm

Conversation

@Claude
Copy link
Copy Markdown

@Claude Claude AI commented Feb 6, 2026

Implements demo infrastructure for deploying a Windows Server VM with networking components in Azure using Bicep at subscription scope.

Structure

  • main.bicep: Subscription-level orchestration (creates resource group, invokes modules)
  • modules/network.bicep: VNet (10.0.0.0/16), subnet, NSG with RDP/HTTP/HTTPS rules
  • modules/vm.bicep: Windows Server 2022 VM, public IP with DNS, NIC, managed disk
  • main.bicepparam: Parameter file using readEnvironmentVariable() for secure password handling

Key Decisions

  • Subscription scope deployment: Creates resource group as part of deployment rather than requiring pre-existing RG
  • Standard_B2s VM size: Low-cost burstable instance (~$40/month) suitable for demos
  • StandardSSD_LRS disk: Cost-optimized storage tier
  • Sweden Central region: Default location per requirements
  • Modular design: Network and compute resources separated for reusability

Deployment Example

az deployment sub create \
  --location swedencentral \
  --template-file main.bicep \
  --parameters main.bicepparam \
  --parameters adminPassword='SecurePassword123!'

Comprehensive deployment instructions, cost breakdown, and security notes added to infra/bicep/README.md. Bicep build artifacts (*.json) excluded from version control via .gitignore.

Original prompt

This section details on the original issue you should resolve

<issue_title>Demo IaC Generator: Azure VM + Network</issue_title>
<issue_description>You are generating demo IaC for Azure for infrastructure engineers/DevOps personas.

Parameters

IaC Language: Bicep

Requirements

  • Use Azure Bicep for the IaC
  • Create a virtual machine and associated resources:
    • Azure region: Sweden Central
    • Operating System: Windows Server
    • Virtual Network + Subnet: Use default address spaces
    • VM Size: Use a common, low-cost size suitable for demo
    • Network Security Group (NSG) with default rules
    • Network Interface (NIC)
    • Managed OS Disk
    • Public IP (for demo access)
  • Keep defaults low-cost and demo-friendly.
  • Do not output secrets or keys.
  • Assume deployment scope is subscription (include resource group creation).
  • Update the README.md in the IaC language folder to document how to deploy the generated IaC code.
  • Create a .bicepparam file with example parameter values (no secrets).
  • Ensure the IaC is deployable by verifying lint errors are resolved, and validation passes.</issue_description>

Comments on the Issue (you are @claude[agent] in this section)

Co-authored-by: robpitcher <13648061+robpitcher@users.noreply.github.com>
@Claude Claude AI changed the title [WIP] Add demo IaC generator for Azure VM and network Add Azure VM + Network Bicep IaC with modular structure Feb 6, 2026
@Claude Claude AI requested a review from robpitcher February 6, 2026 21:59
@robpitcher robpitcher marked this pull request as ready for review February 7, 2026 03:42
Copilot AI review requested due to automatic review settings February 7, 2026 03:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a demo Azure Bicep infrastructure stack under infra/bicep/ to deploy a Windows Server VM with supporting network resources using a subscription-scope entrypoint template.

Changes:

  • Introduces subscription-scope main.bicep that creates a resource group and deploys network + VM modules.
  • Adds modules/network.bicep (VNet/Subnet/NSG) and modules/vm.bicep (Public IP/NIC/Windows VM) with outputs.
  • Adds deployment/validation documentation plus parameter and .gitignore updates to support local Bicep builds.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
infra/bicep/main.bicep Subscription-scope orchestration that creates the RG and calls the network/VM modules.
infra/bicep/main.bicepparam Example parameter values for demo deployment.
infra/bicep/modules/network.bicep Creates VNet + subnet and an NSG with inbound allow rules; outputs subnet/NSG IDs.
infra/bicep/modules/vm.bicep Creates Public IP + NIC + Windows VM and outputs VM name/IP/FQDN.
infra/bicep/README.md Deployment, validation, usage, cost, and security documentation for the demo stack.
.gitignore Ignores generated ARM JSON artifacts under infra/bicep/.

Comment on lines +87 to +90
osProfile: {
computerName: vmName
adminUsername: adminUsername
adminPassword: adminPassword
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Windows VMs, osProfile.computerName must be <= 15 characters. vmName includes the prefix + "-vm-" + uniqueSuffix (13 chars), so it will typically exceed 15 and cause deployment failure. Use a shorter computerName (e.g., separate var truncated to 15) instead of vmName.

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +102
subnets: [
{
name: subnetName
properties: {
addressPrefix: subnetAddressPrefix
networkSecurityGroup: {
id: networkSecurityGroup.id
}
}
}
]
}
}

// Outputs
@description('Virtual network name')
output vnetName string = virtualNetwork.name

@description('Subnet resource ID')
output subnetId string = virtualNetwork.properties.subnets[0].id
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The subnetId output relies on virtualNetwork.properties.subnets[0], which is brittle if the subnet list changes (ordering, additional subnets). Prefer defining the subnet as an explicit child resource (or otherwise selecting by subnetName) and outputting that resource's .id.

Suggested change
subnets: [
{
name: subnetName
properties: {
addressPrefix: subnetAddressPrefix
networkSecurityGroup: {
id: networkSecurityGroup.id
}
}
}
]
}
}
// Outputs
@description('Virtual network name')
output vnetName string = virtualNetwork.name
@description('Subnet resource ID')
output subnetId string = virtualNetwork.properties.subnets[0].id
}
}
// Subnet as explicit child resource
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2024-05-01' = {
name: subnetName
parent: virtualNetwork
properties: {
addressPrefix: subnetAddressPrefix
networkSecurityGroup: {
id: networkSecurityGroup.id
}
}
}
// Outputs
@description('Virtual network name')
output vnetName string = virtualNetwork.name
@description('Subnet resource ID')
output subnetId string = subnet.id

Copilot uses AI. Check for mistakes.
var vnetAddressPrefix = '10.0.0.0/16'
var subnetAddressPrefix = '10.0.0.0/24'

// Network Security Group with default rules
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says "Network Security Group with default rules", but this module defines explicit inbound allow rules (RDP/HTTP/HTTPS). Update the comment to avoid implying Azure's built-in default NSG rules are being used.

Suggested change
// Network Security Group with default rules
// Network Security Group with explicit inbound demo rules (RDP/HTTP/HTTPS)

Copilot uses AI. Check for mistakes.
// VM administrator password - MUST be provided at deployment time
// Use: az deployment sub create --parameters main.bicepparam --parameters adminPassword='YourSecurePassword123!'
// Or use: az deployment sub create --parameters main.bicepparam (will prompt for password)
param adminPassword = readEnvironmentVariable('ADMIN_PASSWORD', '')
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adminPassword is set in the .bicepparam file with a default of empty string when ADMIN_PASSWORD isn't present. This prevents the CLI from prompting and will fail the template's @minLength(12) validation (and Azure password rules). Remove adminPassword from the parameter file (provide via CLI at deployment time), or make missing env var an explicit error rather than defaulting to ''.

Suggested change
param adminPassword = readEnvironmentVariable('ADMIN_PASSWORD', '')

Copilot uses AI. Check for mistakes.
Comment thread infra/bicep/README.md
Comment on lines +132 to +135
1. **Get deployment outputs:**
```bash
az deployment sub show \
--name main \
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs show az deployment sub show --name main, but the earlier az deployment sub create examples don't specify --name main, so this command likely won't find the deployment. Either add --name main to the create/what-if/validate commands or update the "show outputs" step to use the actual deployment name.

Suggested change
1. **Get deployment outputs:**
```bash
az deployment sub show \
--name main \
1. **Get deployment outputs** (replace `<deploymentName>` with the name you used in `az deployment sub create`, for example `main`):
```bash
az deployment sub show \
--name <deploymentName> \

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Demo IaC Generator: Azure VM + Network

3 participants