This project deploys a Hub & Spoke network topology in Azure using Bicep as Infrastructure as Code (IaC).
The deployment creates three virtual networks, peering connections, management resources (such as Bastion and Private DNS), as well as test virtual machines and a base storage account.
The main Bicep file orchestrates several modular components:
Network.bicep: creates VNets and subnets.storageaccount.bicep: deploys a standard storage account.VM.bicep: deploys Windows or Linux virtual machines.
The main deployment provisions the following resources:
- VNet1 and VNet2 (Spokes): each with two subnets.
- VNetHub (Hub): a central network containing a Bastion subnet and a main subnet, which can host a Network Virtual Appliance (NVA).
Bidirectional connectivity is established between:
VNetHubβVNet1VNetHubβVNet2
Each peering enables:
allowForwardedTraffic: trueallowGatewayTransit: trueon the HubuseRemoteGateways: falseon the Spokes
This allows inter-spoke traffic to flow through the Hub, following the classic Hub & Spoke model.
The deployment creates two empty route tables:
routetablefor VNet1routetablevnet2for VNet2
βοΈ Post-deployment note:
After deployment, the user must manually associate each route table with the corresponding subnets in VNet1 and VNet2.
In addition, custom routes must be created manually to forward traffic toward the Network Virtual Appliance (NVA) private IP located in the VNetHub.
This ensures that spoke-to-spoke traffic passes through the Hub.
A Private DNS Zone is created and linked to all three VNets:
VNet1VNet2VNetHub
Each link uses registrationEnabled: true, allowing automatic DNS record registration from virtual machines within each VNet.
The deployment includes:
- A static public IP (
AzureBastionPublicIP) - A Bastion host (
AzureBastionSubnet)
This enables secure remote access to VMs without exposing RDP or SSH ports to the Internet.
- Storage Account: a standard storage account for testing or log storage.
- Virtual Machines:
vm1inVNet1vm2inVNet2vm3inVNetHub(with configurableenableIPForwarding, useful for NVA or firewall scenarios)
- Associate each route table with the corresponding subnets in VNet1 and VNet2.
- Create custom routes to the private IP of the NVA in VNetHub.
- Verify internal name resolution using the Private DNS Zone.
- Test spoke-to-spoke connectivity via the Hub (if the NVA is configured).
- Connect to VMs securely using Azure Bastion.
| Parameter | Description |
|---|---|
vnet1location, vnet2location |
Deployment region for the spoke VNets |
vnethubaddresssprefix |
Address prefix for the Hub VNet |
enableIPForwarding |
Enables IP forwarding on the Hub VM (useful for NVA scenarios) |
PrivateDNSname |
Name of the global private DNS zone |
- Azure CLI or Azure PowerShell installed and configured.
- Contributor or higher permissions on the target resource group.
- Bicep CLI v0.24+ (or the version bundled with the latest Azure CLI).
az deployment group create \
--resource-group <ResourceGroupName> \
--template-file main.bicep \
--parameters \
vnet1location=eastus2 \
vnet2location=eastus2 \
vnet1AddressPrefixes="10.0.0.0/16" \
vnet2AddressPrefixes="10.1.0.0/16" \
vnethubaddresssprefix="10.2.0.0/16" \
PrivateDNSname="example.local" \
enableIPForwarding=true