Introduction
Azure Virtual Network (VNet) forms the networking foundation of any Azure cloud architecture. At an advanced level, this involves orchestrating peering, granular security controls, private endpoints, and custom routing for multi-region and hybrid environments. This tutorial guides you step by step through building a robust, secure, and observable network infrastructure using Terraform for infrastructure as code and PowerShell for advanced operations.
Prerequisites
- Azure account with Owner or Network Contributor rights
- Terraform 1.9+ and Azure CLI 2.60+
- Solid knowledge of IP networking, NSGs, and Private Link
- PowerShell 7+ with the Az.Network module
- Access to two Azure regions (e.g., France Central and West Europe)
Initialize the Terraform Project
terraform {
required_version = ">= 1.9"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg" {
name = "rg-vnet-advanced-2026"
location = "France Central"
}This block initializes the Azure provider and creates the base Resource Group. It ensures reproducibility and Terraform state management for the entire advanced VNet.
Create the Main VNet and Subnets
resource "azurerm_virtual_network" "main" {
name = "vnet-advanced-2026"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
subnet {
name = "subnet-app"
address_prefixes = ["10.0.1.0/24"]
}
subnet {
name = "subnet-db"
address_prefixes = ["10.0.2.0/24"]
}
}Defines the VNet with two subnets. The subnets will later be secured by NSGs and used for peering and Private Endpoints.
Configure Network Security Groups
resource "azurerm_network_security_group" "nsg_app" {
name = "nsg-app"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
security_rule {
name = "AllowHttps"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "10.0.0.0/8"
destination_address_prefix = "*"
}
}Advanced NSG with a strict rule limiting HTTPS traffic to internal ranges. Always associate the NSG with the subnet using azurerm_subnet_network_security_group_association.
Set Up VNet Peering
resource "azurerm_virtual_network_peering" "peer_fr_we" {
name = "peer-france-to-we"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.main.name
remote_virtual_network_id = azurerm_virtual_network.secondary.id
allow_virtual_network_access = true
allow_forwarded_traffic = true
}Enables peering between two VNets in different regions with forwarded traffic enabled to support hub-and-spoke architectures.
Deploy a Private Endpoint
resource "azurerm_private_endpoint" "pe_storage" {
name = "pe-storage-2026"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
subnet_id = azurerm_virtual_network.main.subnet.*.id[0]
private_service_connection {
name = "psc-storage"
private_connection_resource_id = azurerm_storage_account.example.id
is_manual_connection = false
subresource_names = ["blob"]
}
}Creates a Private Endpoint to access a storage account without public exposure, which is essential for compliance and data security.
Best Practices
- Use non-overlapping address ranges for all VNets
- Enable traffic encryption between VNets via Private Link
- Centralize NSGs in a hub and use Azure Firewall for advanced filtering
- Document network flows with Azure Network Watcher
- Enable diagnostics and logs to Log Analytics
Common Mistakes to Avoid
- Forgetting to enable allow_forwarded_traffic on peering
- Associating an NSG directly with a NIC instead of the subnet
- Using public IP addresses on resources that should remain private
- Neglecting custom route rules (UDR) for outbound traffic
Go Further
Deepen your Azure skills with our Learni training courses on cloud network architecture and advanced security.