Azure VM Configuration with cloud-init and Key-Based SSH
You will deploy an Azure VM into your VNet, bootstrap it with cloud-init, and access it via key-based SSH only. By the end you will have a secured, reproducible cloud server configured at first boot.
Learning Objectives
- Deploy a VM with SSH-key authentication.
- Bootstrap packages and config with cloud-init.
- Restrict inbound access to your IP only.
- Time: ~2 hours · Difficulty: Intermediate · Prereqs: a VNet and the Azure CLI.
Architecture Overview
graph LR
CLI[az vm create] --> VM[Azure VM in subnet]
Init[cloud-init.yaml] -->|first boot| VM
You[You] -->|SSH key only| VM
NSG[NSG: your IP] --> VM
Environment Setup
You will need: a VNet/subnet (from the VNet lab), the Azure CLI, and an SSH keypair.
Before you begin: note your public IP to scope SSH access.
Step-by-Step Execution
01
Write a cloud-init file
# cloud-init.yaml
#cloud-config
package_update: true
packages: [nginx]
runcmd:
- systemctl enable --now nginx
02
Deploy the VM with key auth and cloud-init
az vm create -n web01 --image Ubuntu2204 --vnet-name vnet-a --subnet web --admin-username taki --ssh-key-values ~/.ssh/id_ed25519.pub --custom-data cloud-init.yaml03
Restrict SSH to your IP
$ az vm open-port -n web01 --port 22 --priority 100 && az network nsg rule update -g tyf-rg --nsg-name web01NSG -n open-port-22 --source-address-prefixes 203.0.113.10/32
"sourceAddressPrefix": "203.0.113.10/32"
Progress So Far
graph LR
A[01 cloud-init] -->|done| B[02 Deploy VM]
B -->|done| C[03 Scope SSH]
style A fill:#1a4a1a,stroke:#00ff00,color:#fff
style B fill:#1a4a1a,stroke:#00ff00,color:#fff
style C fill:#1a4a1a,stroke:#00ff00,color:#fff
Testing & Validation
ssh taki@$(az vm show -d -n web01 --query publicIps -o tsv) 'systemctl is-active nginx'You should connect with your key (no password) and see active, proving cloud-init bootstrapped the server.
Troubleshooting
- cloud-init did not run: check
/var/log/cloud-init-output.logon the VM. - SSH times out: confirm the NSG allows port 22 from your current IP.
- Password prompt: deploy with
--ssh-key-values, not--admin-password.
Extension Ideas
- Tighten traffic further with NSGs & Route Tables.
- Harden the OS with SSH Hardening.
- Replace imperative creation with ARM templates.
Key Results
- Deployed a cloud VM bootstrapped automatically at first boot.
- Enforced key-only SSH with no password authentication.
- Restricted inbound SSH to a single source IP.
- Verified the service end to end over SSH.