-
Notifications
You must be signed in to change notification settings - Fork 0
Add Azure VM + Network Bicep IaC with modular structure #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,228 @@ | ||
| # Bicep IaC | ||
| # Bicep IaC - Azure VM + Network | ||
|
|
||
| This directory contains Azure Bicep Infrastructure as Code (IaC) for deploying a demo Windows Server virtual machine with associated networking resources in Azure. | ||
|
|
||
| ## What's Deployed | ||
|
|
||
| The infrastructure includes: | ||
|
|
||
| - **Resource Group**: Container for all Azure resources | ||
| - **Virtual Network (VNet)**: 10.0.0.0/16 address space | ||
| - **Subnet**: 10.0.0.0/24 address space (default subnet) | ||
| - **Network Security Group (NSG)**: With inbound rules for RDP (3389), HTTP (80), and HTTPS (443) | ||
| - **Public IP Address**: Static IP with DNS name for accessing the VM | ||
| - **Network Interface (NIC)**: Connects the VM to the VNet and public IP | ||
| - **Virtual Machine**: Windows Server 2022 Datacenter | ||
| - **Managed OS Disk**: StandardSSD_LRS for the OS disk | ||
|
|
||
| All resources are deployed to **Sweden Central** region by default. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| Before deploying, ensure you have: | ||
|
|
||
| 1. **Azure CLI** installed and authenticated | ||
| ```bash | ||
| az login | ||
| az account show # Verify you're in the correct subscription | ||
| ``` | ||
|
|
||
| 2. **Bicep CLI** installed (included with Azure CLI 2.20.0+) | ||
| ```bash | ||
| bicep --version | ||
| ``` | ||
|
|
||
| 3. **Azure Subscription** with appropriate permissions (Contributor or Owner role at subscription level) | ||
|
|
||
| ## File Structure | ||
|
|
||
| ``` | ||
| infra/bicep/ | ||
| ├── main.bicep # Main template (subscription scope) | ||
| ├── main.bicepparam # Parameter file with example values | ||
| ├── modules/ | ||
| │ ├── network.bicep # Network infrastructure (VNet, Subnet, NSG) | ||
| │ └── vm.bicep # Virtual machine resources (VM, NIC, Public IP) | ||
| └── README.md # This file | ||
| ``` | ||
|
|
||
| ## Deployment | ||
|
|
||
| ### Option 1: Deploy with Parameter File | ||
|
|
||
| The easiest way to deploy is using the parameter file. You'll need to provide the admin password: | ||
|
|
||
| ```bash | ||
| # Navigate to the bicep directory | ||
| cd infra/bicep | ||
|
|
||
| # Deploy (will prompt for adminPassword) | ||
| az deployment sub create \ | ||
| --location swedencentral \ | ||
| --template-file main.bicep \ | ||
| --parameters main.bicepparam | ||
|
|
||
| # Or provide password inline (for automation) | ||
| az deployment sub create \ | ||
| --location swedencentral \ | ||
| --template-file main.bicep \ | ||
| --parameters main.bicepparam \ | ||
| --parameters adminPassword='YourSecurePassword123!' | ||
| ``` | ||
|
|
||
| ### Option 2: Deploy with Individual Parameters | ||
|
|
||
| You can override any parameters at deployment time: | ||
|
|
||
| ```bash | ||
| az deployment sub create \ | ||
| --location swedencentral \ | ||
| --template-file main.bicep \ | ||
| --parameters resourceGroupName='rg-my-demo' \ | ||
| --parameters adminUsername='myadmin' \ | ||
| --parameters adminPassword='MySecurePassword123!' \ | ||
| --parameters resourcePrefix='myvm' | ||
| ``` | ||
|
|
||
| ### Option 3: Deploy with What-If (Preview Changes) | ||
|
|
||
| Preview what resources will be created before deploying: | ||
|
|
||
| ```bash | ||
| az deployment sub what-if \ | ||
| --location swedencentral \ | ||
| --template-file main.bicep \ | ||
| --parameters main.bicepparam \ | ||
| --parameters adminPassword='YourSecurePassword123!' | ||
| ``` | ||
|
|
||
| ## Validation | ||
|
|
||
| ### Local Validation (Fast) | ||
|
|
||
| Validate Bicep syntax and compile to ARM template: | ||
|
|
||
| ```bash | ||
| # Validate main template | ||
| bicep build main.bicep | ||
|
|
||
| # Validate network module | ||
| bicep build modules/network.bicep | ||
|
|
||
| # Validate VM module | ||
| bicep build modules/vm.bicep | ||
| ``` | ||
|
|
||
| ### Azure Validation (Comprehensive) | ||
|
|
||
| Validate against Azure APIs (checks permissions, quotas, API versions): | ||
|
|
||
| ```bash | ||
| az deployment sub validate \ | ||
| --location swedencentral \ | ||
| --template-file main.bicep \ | ||
| --parameters main.bicepparam \ | ||
| --parameters adminPassword='YourSecurePassword123!' | ||
| ``` | ||
|
|
||
| ## Connecting to Your VM | ||
|
|
||
| After deployment completes, you'll receive outputs including the public IP address: | ||
|
|
||
| 1. **Get deployment outputs:** | ||
| ```bash | ||
| az deployment sub show \ | ||
| --name main \ | ||
| --query properties.outputs | ||
| ``` | ||
|
|
||
| 2. **Connect via RDP:** | ||
| - Open Remote Desktop Connection (mstsc.exe on Windows) | ||
| - Enter the public IP address or FQDN | ||
| - Login with the credentials you provided during deployment | ||
|
|
||
| ## Customization | ||
|
|
||
| You can customize the deployment by modifying parameters: | ||
|
|
||
| | Parameter | Default | Description | | ||
| |-----------|---------|-------------| | ||
| | `location` | `swedencentral` | Azure region for resources | | ||
| | `resourceGroupName` | `rg-demo-vm` | Name of the resource group | | ||
| | `adminUsername` | `azureuser` | VM administrator username | | ||
| | `adminPassword` | *(required)* | VM administrator password (min 12 chars) | | ||
| | `vmSize` | `Standard_B2s` | VM size (2 vCPU, 4 GB RAM) | | ||
| | `osVersion` | `2022-Datacenter` | Windows Server version (2019 or 2022) | | ||
| | `resourcePrefix` | `demo` | Prefix for resource naming | | ||
|
|
||
| ## Clean Up | ||
|
|
||
| To delete all deployed resources: | ||
|
|
||
| ```bash | ||
| # Delete the resource group (deletes all resources within it) | ||
| az group delete --name rg-demo-vm --yes --no-wait | ||
| ``` | ||
|
|
||
| ## Cost Considerations | ||
|
|
||
| This demo configuration uses low-cost resources: | ||
|
|
||
| - **VM Size**: Standard_B2s (burstable B-series, ~$30-40/month) | ||
| - **OS Disk**: StandardSSD_LRS (128 GB, ~$5/month) | ||
| - **Public IP**: Standard SKU Static (~$3/month) | ||
| - **Networking**: VNet and NSG have no additional cost | ||
|
|
||
| **Total estimated cost**: ~$40-50 USD/month when running continuously. | ||
|
|
||
| To minimize costs: | ||
| - Stop (deallocate) the VM when not in use: `az vm deallocate --resource-group rg-demo-vm --name <vm-name>` | ||
| - Delete resources when no longer needed | ||
|
|
||
| ## Security Notes | ||
|
|
||
| ⚠️ **This is a demo configuration**. For production use: | ||
|
|
||
| 1. **Restrict NSG rules**: Don't allow RDP from `*` (any source). Limit to your IP address or corporate network. | ||
| 2. **Use Azure Bastion**: Instead of exposing RDP publicly, use Azure Bastion for secure access. | ||
| 3. **Enable JIT Access**: Use Azure Security Center's Just-In-Time VM access. | ||
| 4. **Key-based authentication**: Consider using Azure Key Vault for secrets management. | ||
| 5. **Monitoring**: Enable Azure Monitor and diagnostic settings. | ||
| 6. **Backup**: Configure Azure Backup for production VMs. | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Bicep Build Errors | ||
|
|
||
| ```bash | ||
| # Check Bicep version | ||
| bicep --version | ||
|
|
||
| # Upgrade Bicep | ||
| az bicep upgrade | ||
|
|
||
| # Validate specific file | ||
| bicep build <file>.bicep | ||
| ``` | ||
|
|
||
| ### Deployment Errors | ||
|
|
||
| ```bash | ||
| # View deployment logs | ||
| az deployment sub show --name main | ||
|
|
||
| # List all subscription deployments | ||
| az deployment sub list --output table | ||
| ``` | ||
|
|
||
| ### Common Issues | ||
|
|
||
| 1. **Password complexity**: Ensure password meets Azure requirements (min 12 chars, includes uppercase, lowercase, number, special char) | ||
| 2. **Quota limits**: Check your subscription quotas for the selected VM size and region | ||
| 3. **Permissions**: Ensure you have Contributor or Owner role at subscription level | ||
|
|
||
| ## Additional Resources | ||
|
|
||
| - [Azure Bicep Documentation](https://learn.microsoft.com/azure/azure-resource-manager/bicep/) | ||
| - [Azure VM Sizes](https://learn.microsoft.com/azure/virtual-machines/sizes) | ||
| - [Azure Naming Conventions](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| // Main Bicep template for Azure VM + Network infrastructure | ||
| // Deployment scope: subscription (creates resource group) | ||
| targetScope = 'subscription' | ||
|
|
||
| // Parameters | ||
| @description('Azure region for all resources') | ||
| param location string = 'swedencentral' | ||
|
|
||
| @description('Name of the resource group to create') | ||
| @minLength(1) | ||
| @maxLength(90) | ||
| param resourceGroupName string = 'rg-demo-vm' | ||
|
|
||
| @description('Administrator username for the VM') | ||
| @minLength(1) | ||
| @maxLength(20) | ||
| param adminUsername string = 'azureuser' | ||
|
|
||
| @description('Administrator password for the VM') | ||
| @secure() | ||
| @minLength(12) | ||
| param adminPassword string | ||
|
|
||
| @description('Virtual machine size') | ||
| param vmSize string = 'Standard_B2s' | ||
|
|
||
| @description('Windows Server OS version') | ||
| @allowed([ | ||
| '2019-Datacenter' | ||
| '2022-Datacenter' | ||
| ]) | ||
| param osVersion string = '2022-Datacenter' | ||
|
|
||
| @description('Prefix for naming resources') | ||
| @minLength(3) | ||
| @maxLength(10) | ||
| param resourcePrefix string = 'demo' | ||
|
|
||
| // Variables | ||
| var uniqueSuffix = uniqueString(subscription().subscriptionId, resourceGroupName) | ||
|
|
||
| // Create resource group | ||
| resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = { | ||
| name: resourceGroupName | ||
| location: location | ||
| } | ||
|
|
||
| // Deploy network infrastructure | ||
| module network 'modules/network.bicep' = { | ||
| scope: resourceGroup | ||
| name: 'networkDeployment' | ||
| params: { | ||
| location: location | ||
| resourcePrefix: resourcePrefix | ||
| uniqueSuffix: uniqueSuffix | ||
| } | ||
| } | ||
|
|
||
| // Deploy virtual machine | ||
| module virtualMachine 'modules/vm.bicep' = { | ||
| scope: resourceGroup | ||
| name: 'vmDeployment' | ||
| params: { | ||
| location: location | ||
| resourcePrefix: resourcePrefix | ||
| uniqueSuffix: uniqueSuffix | ||
| adminUsername: adminUsername | ||
| adminPassword: adminPassword | ||
| vmSize: vmSize | ||
| osVersion: osVersion | ||
| subnetId: network.outputs.subnetId | ||
| nsgId: network.outputs.nsgId | ||
| } | ||
| } | ||
|
|
||
| // Outputs | ||
| @description('Resource group name') | ||
| output resourceGroupName string = resourceGroup.name | ||
|
|
||
| @description('Virtual machine name') | ||
| output vmName string = virtualMachine.outputs.vmName | ||
|
|
||
| @description('Public IP address') | ||
| output publicIpAddress string = virtualMachine.outputs.publicIpAddress | ||
|
|
||
| @description('Virtual network name') | ||
| output vnetName string = network.outputs.vnetName |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,26 @@ | ||||
| // Parameter file for main.bicep | ||||
| // This file contains example parameter values for demo deployment | ||||
| using './main.bicep' | ||||
|
|
||||
| // Azure region for resources | ||||
| param location = 'swedencentral' | ||||
|
|
||||
| // Resource group name | ||||
| param resourceGroupName = 'rg-demo-vm' | ||||
|
|
||||
| // VM administrator username | ||||
| param adminUsername = 'azureuser' | ||||
|
|
||||
| // 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', '') | ||||
|
||||
| param adminPassword = readEnvironmentVariable('ADMIN_PASSWORD', '') |
There was a problem hiding this comment.
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 earlieraz deployment sub createexamples don't specify--name main, so this command likely won't find the deployment. Either add--name mainto the create/what-if/validate commands or update the "show outputs" step to use the actual deployment name.