๐ท Azure Bicep โ Ubuntu VM Deployment
Azure Bicep is a domain-specific language (DSL) that uses declarative syntax to deploy Azure resources. It is a transparent abstraction over ARM templates and compiles directly to ARM JSON.
BicepAzure VMUbuntu 22.04 LTSSSHNSGWhat this template deploys
- A Virtual Network (VNet) with a single subnet
- A Network Security Group (NSG) allowing inbound SSH (port 22)
- A Dynamic Public IP address
- A Network Interface Card (NIC)
- An Ubuntu 22.04 LTS VM (Standard_B1s โ free tier eligible)
Bicep Template โ main.bicep
BICEPCloudSchool.ai
param location string = resourceGroup().location
param vmName string = 'cloudschool-ubuntu-vm'
param adminUsername string = 'cloudadmin'
@secure()
param adminPassword string
var vnetName = '${vmName}-vnet'
var subnetName = 'default'
var publicIpName = '${vmName}-pip'
var nicName = '${vmName}-nic'
var nsgName = '${vmName}-nsg'
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-04-01' = {
name: nsgName
location: location
properties: {
securityRules: [
{
name: 'Allow-SSH'
properties: {
priority: 1000
protocol: 'Tcp'
access: 'Allow'
direction: 'Inbound'
sourceAddressPrefix: '*'
sourcePortRange: '*'
destinationAddressPrefix: '*'
destinationPortRange: '22'
}
}
]
}
}
resource vnet 'Microsoft.Network/virtualNetworks@2023-04-01' = {
name: vnetName
location: location
properties: {
addressSpace: { addressPrefixes: ['10.0.0.0/16'] }
subnets: [
{
name: subnetName
properties: {
addressPrefix: '10.0.0.0/24'
networkSecurityGroup: { id: nsg.id }
}
}
]
}
}
resource publicIp 'Microsoft.Network/publicIPAddresses@2023-04-01' = {
name: publicIpName
location: location
sku: { name: 'Basic' }
properties: { publicIPAllocationMethod: 'Dynamic' }
}
resource nic 'Microsoft.Network/networkInterfaces@2023-04-01' = {
name: nicName
location: location
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
subnet: { id: '${vnet.id}/subnets/${subnetName}' }
publicIPAddress: { id: publicIp.id }
privateIPAllocationMethod: 'Dynamic'
}
}
]
}
}
resource vm 'Microsoft.Compute/virtualMachines@2023-07-01' = {
name: vmName
location: location
properties: {
hardwareProfile: { vmSize: 'Standard_B1s' }
osProfile: {
computerName: vmName
adminUsername: adminUsername
adminPassword: adminPassword
}
storageProfile: {
imageReference: {
publisher: 'Canonical'
offer: '0001-com-ubuntu-server-jammy'
sku: '22_04-lts-gen2'
version: 'latest'
}
osDisk: {
createOption: 'FromImage'
managedDisk: { storageAccountType: 'Standard_LRS' }
}
}
networkProfile: {
networkInterfaces: [{ id: nic.id }]
}
}
}
output publicIpAddress string = publicIp.properties.ipAddress
output sshCommand string = 'ssh ${adminUsername}@${publicIp.properties.ipAddress}'Deployment Commands
BASHCloudSchool.ai
# Login to Azure
az login
# Create a Resource Group
az group create --name rg-cloudschool-iac --location eastus
# Deploy the Bicep template
az deployment group create \
--resource-group rg-cloudschool-iac \
--template-file main.bicep \
--parameters adminPassword='YourSecureP@ssw0rd!'
# Get the public IP after deployment
az vm show -d -g rg-cloudschool-iac -n cloudschool-ubuntu-vm --query publicIps -o tsv
# Connect via SSH
ssh cloudadmin@<PUBLIC_IP>Key Concepts
- @secure() decorator โ marks the password parameter as sensitive; never logged or displayed
- Symbolic references โ
nsg.id,vnet.idreplace manual resource ID strings - Outputs โ expose the public IP and SSH command after deployment
- Standard_B1s โ burstable, cost-effective VM size suitable for learning labs
๐ Continue learning: CloudSchool.ai Knowledge Base ยทIaC Glossary