Post

Building A Nested Virtual Machine In Azure Part 6

Building A Nested Virtual Machine In Azure Part 6

Series Table of contents:

This is the sixth and final part of this series, where we will discuss the final steps to complete our nested virtual machine setup in Azure. In this part, we will focus on configuring the nested VM, ensuring that it is properly set up for our lab environment, and testing its functionality.

The final infrastructure picture will look like this:

Infrastructure Picture

So in this part, we’ll cover:

  • Install PowerShell 7
  • Install Visual Studio Code
  • Install the PowerShell extension for Visual Studio Code
  • Installing Hyper-V
  • Adding a Hyper-V Nat switch so the nested VM can access the internet
  • Installing and configuring a DHCP Server role
  • Installing AutomatedLab
  • Downloading the OS ISOs
  • Deploying a nested VM to the Hyper-V host using AutomatedLab

Installing PowerShell 7

Because we’re on Server 2025 we can use winget to install PowerShell 7. We’ll use the following command to install PowerShell 7:

1
winget install --id Microsoft.Powershell --source winget

Installing Visual Studio Code

1
winget install --id Microsoft.VisualStudioCode.Insiders --scope machine --silent --accept-package-agreements --accept-source-agreements

Installing the PowerShell extension for Visual Studio Code

1
code-insiders --install-extension ms-vscode.powershell

Installing Hyper-V

We’ll use the following PowerShell commands to install and configure Hyper-V:

1
2
# Install the Hyper-V role and include management tools
Install-WindowsFeature -Name Hyper-V -IncludeManagementTools -Restart

Creating a Hyper-V NAT Switch

To allow our nested VM to access the internet, we will create a NAT switch on our Hyper-V host. This will enable the nested VM to communicate with external networks while still being isolated within our lab environment.

We’ll use the following PowerShell commands to create the NAT switch:

1
2
3
4
5
6
7
8
9
10
11
# Create a new internal virtual switch for the nested VM
New-VMSwitch -Name "LabNATSwitch" -SwitchType Internal

# Retrieve the InterfaceAlias of the newly created virtual switch
$Interface = Get-NetAdapter | Where-Object {$_.Name -like "*LabNATSwitch*"}

# Configure the IP address for the virtual switch interface
New-NetIPAddress -IPAddress 192.168.50.1 -PrefixLength 24 -InterfaceAlias "$($Interface.Name)"

# Create a NAT network for the virtual switch
New-NetNat -Name "LabNAT" -InternalIPInterfaceAddressPrefix 192.168.50.0/24

Installing and Configuring a DHCP Server Role

To make our lab environment more dynamic, we will install a DHCP Server role on our Hyper-V host. This will allow the nested VM to receive an IP address automatically, making it easier to manage and connect to the nested VM without having to manually configure network settings.

We’ll use the following PowerShell commands to install the DHCP Server role:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Install the DHCP Server role and include management tools
Install-WindowsFeature -Name DHCP -IncludeManagementTools

# Add the DHCP Server scope and configure the gateway and DNS settings
# for the gateway, we will use the IP address of the Hyper-V NAT switch (192.168.50.1)
# for the DNS, we will use the well known Azure DNS server (168.63.129.16)
$splat = @{
    Name         = "LabScope"
    StartRange   = "192.168.50.10"
    EndRange     = "192.168.50.220"
    SubnetMask   = "255.255.255.0"
}
Add-DhcpServerv4Scope @splat

$splat = @{
    ScopeId      = "192.168.50.0"
    Router       = "192.168.50.1"
    DnsServer    = "168.63.129.16"
}
Set-DhcpServerv4OptionValue @splat

# For safety, restart the DHCP Server service
Restart-Service -Name DHCPServer

Installing AutomatedLab

To simplify the deployment of our nested virtual machines, we will install AutomatedLab on our Hyper-V host. AutomatedLab is a powerful tool that allows us to automate the creation and configuration of lab environments, making it easier to manage and deploy nested VMs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Install PSFramework.Nuget
$splat = @{
  Uri = 'https://raw.githubusercontent.com/PowershellFrameworkCollective/PSFramework.NuGet/refs/heads/master/bootstrap.ps1'
  UseBasicParsing = $true
}
Invoke-WebRequest @splat | Invoke-Expression

# Install AutomatedLab and Pester
Install-PSFModule -Name Pester -Repository PSGallery -TrustRepository -Scope AllUsers
Install-PSFModule -Name AutomatedLab -Repository PSGallery -TrustRepository -Scope AllUsers

# Pre-configure telemetry
# Disable (which is already the default) and in addition skip dialog
[Environment]::SetEnvironmentVariable('AUTOMATEDLAB_TELEMETRY_OPTIN', 'false', 'Machine')
$env:AUTOMATEDLAB_TELEMETRY_OPTIN = 'false'

# Pre-configure Lab Host Remoting
Enable-LabHostRemoting -Force

# Windows
New-LabSourcesFolder

Downloading the OS ISOs

Downloading the OS ISOs from the Microsoft Eval Center or if you have an MSDN subscription, you can download them from there. For this lab, we will be using Windows Server 2025.

Please make sure to download the ISO into E:\LabSources\ISOs folder. To make sure that AutomatedLab can find the OS variants inside the ISO, we will run Get-LabAvailableOperatingSystem

Available Operating Systems

Deploying a Nested VM to the Hyper-V Host Using AutomatedLab

The lab script for creating the nested VM is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$LabName = 'NestedVMLab'

# Create a new lab definition
New-LabDefinition -Name $LabName -DefaultVirtualizationEngine HyperV

$PSDefaultParameterValues = @{
    'Add-LabMachineDefinition:Network'         = 'LabNATSwitch'
    'Add-LabMachineDefinition:ToolsPath'       = "$labSources\Tools"
    'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2025 Datacenter (Desktop Experience)'
    'Add-LabMachineDefinition:Memory'          = 4GB
}

# Configure the lab network
$splat = @{
    Name             = 'LabNATSwitch'
    HyperVProperties = @{ SwitchType = 'Internal'; AdapterName = 'vEthernet (LabNATSwitch)' }
    AddressSpace     = '192.168.50.0/24'
}
Add-LabVirtualNetworkDefinition @splat

$splat = @{
    VirtualSwitch = 'LabNATSwitch'
    UseDhcp       = $true
}
$netAdapter = New-LabNetworkAdapterDefinition @splat

$splat = @{
    Name           = 'LABVM'
    Processors     = 2
    NetworkAdapter = $netAdapter
}
Add-LabMachineDefinition @splat

# Deploy the lab
Install-Lab

# Show the lab summary
Show-LabDeploymentSummary

To prove that the nested VM is working and also retrieves a dhcp address from the DHCP server.

EndResult

That’s it! You have successfully set up a nested virtual machine in Azure using Hyper-V and AutomatedLab. You can now use this environment for testing, development, or learning purposes. Thank you for following along with this series, and I hope you found it helpful. If you have any questions or feedback, feel free to reach out or leave a comment below.

This post is licensed under CC BY 4.0 by the author.