This lab builds a working Active Directory environment on Hyper-V: two domain controllers, a member server, and a client, on an isolated network. It is the foundation for practising Group Policy, certificate services, replication troubleshooting, and every AD-adjacent topic worth knowing.

Everything runs on a single machine with 32 GB of RAM. Evaluation ISOs from Microsoft are free for 180 days.

What you will build

graph TB subgraph "Hyper-V host" subgraph "LAB-Internal switch — 10.10.10.0/24" DC1[DC01<br/>10.10.10.10<br/>AD DS + DNS] DC2[DC02<br/>10.10.10.11<br/>AD DS + DNS] SRV[FS01<br/>10.10.10.20<br/>File server] CLI[WS01<br/>DHCP<br/>Windows 11] end RTR[RTR01<br/>10.10.10.1<br/>NAT gateway] end RTR --- INET[Host network]

Domain: lab.internal. Never use a domain name you do not control, and never .local — it collides with mDNS.

Prerequisites

  • Windows 10/11 Pro or Windows Server with Hyper-V enabled
  • 32 GB RAM (16 GB works if you run three VMs instead of four)
  • 200 GB free on an SSD
  • Windows Server 2022 and Windows 11 evaluation ISOs

Enable Hyper-V if it is not already:

PowerShell
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
# Reboot required

Step 1 — Networking

Create an internal switch. Internal, not private: the host gets an adapter on it, which lets you provide NAT for updates.

PowerShell
New-VMSwitch -Name "LAB-Internal" -SwitchType Internal

# The host's adapter on that switch becomes the lab's gateway
$ifIndex = (Get-NetAdapter -Name "vEthernet (LAB-Internal)").ifIndex
New-NetIPAddress -IPAddress 10.10.10.1 -PrefixLength 24 -InterfaceIndex $ifIndex

New-NetNat -Name "LAB-NAT" -InternalIPInterfaceAddressPrefix 10.10.10.0/24

Verify:

PowerShell
Get-NetNat
Get-NetIPAddress -InterfaceIndex $ifIndex | Format-Table IPAddress, PrefixLength

Use a checkpoint after each major stage. Checkpoint-VM -Name DC01 -SnapshotName "pre-dcpromo" costs seconds and saves you rebuilding when an experiment goes wrong. That is the entire point of a lab.

Step 2 — Create the VMs

PowerShell
$vmPath = "D:\Hyper-V"
$isoServer = "D:\ISO\WindowsServer2022.iso"

function New-LabVM {
    param([string]$Name, [int64]$MemoryGB, [string]$Iso)

    New-VM -Name $Name -MemoryStartupBytes ($MemoryGB * 1GB) `
           -Generation 2 -Path $vmPath `
           -NewVHDPath "$vmPath\$Name\$Name.vhdx" -NewVHDSizeBytes 80GB `
           -SwitchName "LAB-Internal"

    Set-VM -Name $Name -DynamicMemory `
           -MemoryMinimumBytes 1GB -MemoryMaximumBytes ($MemoryGB * 1GB) `
           -AutomaticCheckpointsEnabled $false

    Add-VMDvdDrive -VMName $Name -Path $Iso
    $dvd = Get-VMDvdDrive -VMName $Name
    Set-VMFirmware -VMName $Name -FirstBootDevice $dvd
}

New-LabVM -Name "DC01" -MemoryGB 4 -Iso $isoServer
New-LabVM -Name "DC02" -MemoryGB 4 -Iso $isoServer
New-LabVM -Name "FS01" -MemoryGB 4 -Iso $isoServer
New-LabVM -Name "WS01" -MemoryGB 4 -Iso "D:\ISO\Windows11.iso"

AutomaticCheckpointsEnabled $false matters. Automatic checkpoints on a domain controller cause USN rollback, which breaks replication in ways that are genuinely difficult to repair.

Never restore a domain controller from a Hyper-V checkpoint in a production environment. AD detects the rolled-back USN and quarantines the DC. In this lab it is fine — that is what a lab is for — but build the habit of using Windows Server Backup for real DCs.

Step 3 — Promote the first domain controller

Install Windows Server on DC01, then configure networking:

PowerShell
Rename-Computer -NewName "DC01" -Restart

New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 10.10.10.10 `
                 -PrefixLength 24 -DefaultGateway 10.10.10.1

# Points at itself — corrected after promotion
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 127.0.0.1

Promote it:

PowerShell
Install-WindowsFeature AD-Domain-Services, DNS -IncludeManagementTools

Install-ADDSForest `
    -DomainName "lab.internal" `
    -DomainNetbiosName "LAB" `
    -ForestMode "WinThreshold" `
    -DomainMode "WinThreshold" `
    -InstallDns:$true `
    -SafeModeAdministratorPassword (Read-Host -AsSecureString "DSRM password") `
    -NoRebootOnCompletion:$false `
    -Force:$true

After reboot, verify:

PowerShell
Get-ADDomain
Get-ADForest
dcdiag /v /c

dcdiag should pass every test. Investigate any failure now — a broken forest root only gets harder to diagnose once you add a second DC.

Step 4 — Second domain controller

Configure DC02 with 10.10.10.11 and DNS pointing at 10.10.10.10 — it must resolve the domain to find it.

PowerShell
Install-WindowsFeature AD-Domain-Services, DNS -IncludeManagementTools

Install-ADDSDomainController `
    -DomainName "lab.internal" `
    -Credential (Get-Credential "LAB\Administrator") `
    -InstallDns:$true `
    -SafeModeAdministratorPassword (Read-Host -AsSecureString "DSRM password") `
    -Force:$true

Once up, fix DNS on both so each prefers its partner and falls back to itself. This avoids the classic "island" problem where a DC that only knows itself cannot start AD services cleanly after a restart:

PowerShell
# On DC01
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 10.10.10.11,127.0.0.1
# On DC02
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 10.10.10.10,127.0.0.1

Verify replication:

PowerShell
repadmin /replsummary
repadmin /showrepl
Get-ADReplicationPartnerMetadata -Target "lab.internal" -Scope Domain |
    Format-Table Server, Partner, LastReplicationSuccess

Step 5 — DHCP and OU structure

Install DHCP on DC01 for the client subnet:

PowerShell
Install-WindowsFeature DHCP -IncludeManagementTools
Add-DhcpServerInDC -DnsName "DC01.lab.internal" -IPAddress 10.10.10.10

Add-DhcpServerv4Scope -Name "LAB" -StartRange 10.10.10.100 `
                      -EndRange 10.10.10.200 -SubnetMask 255.255.255.0
Set-DhcpServerv4OptionValue -ScopeId 10.10.10.0 `
                            -DnsServer 10.10.10.10,10.10.10.11 `
                            -Router 10.10.10.1 -DnsDomain "lab.internal"

Build an OU structure worth practising against — mirroring how real environments separate by function rather than dumping everything in Users:

PowerShell
$base = "DC=lab,DC=internal"

New-ADOrganizationalUnit -Name "LAB" -Path $base
New-ADOrganizationalUnit -Name "Users"    -Path "OU=LAB,$base"
New-ADOrganizationalUnit -Name "Servers"  -Path "OU=LAB,$base"
New-ADOrganizationalUnit -Name "Clients"  -Path "OU=LAB,$base"
New-ADOrganizationalUnit -Name "Groups"   -Path "OU=LAB,$base"
New-ADOrganizationalUnit -Name "Service Accounts" -Path "OU=LAB,$base"

# Populate with test users
1..25 | ForEach-Object {
    $name = "user{0:D2}" -f $_
    New-ADUser -Name $name -SamAccountName $name `
        -UserPrincipalName "$name@lab.internal" `
        -Path "OU=Users,OU=LAB,$base" `
        -AccountPassword (ConvertTo-SecureString "LabP@ssw0rd!" -AsPlainText -Force) `
        -Enabled $true -ChangePasswordAtLogon $false
}

Step 6 — Join and verify

Join FS01 and WS01 to the domain:

PowerShell
Add-Computer -DomainName "lab.internal" `
             -Credential (Get-Credential "LAB\Administrator") `
             -OUPath "OU=Servers,OU=LAB,DC=lab,DC=internal" `
             -Restart

Verification checklist — all of these should succeed:

PowerShell
nltest /dsgetdc:lab.internal          # locates a DC
gpresult /r                            # policy applies
Test-ComputerSecureChannel -Verbose    # secure channel healthy
Resolve-DnsName _ldap._tcp.lab.internal -Type SRV   # SRV records present

What to practise next

The lab exists so you can break things safely. In rough order of value:

  1. Group Policy — build a baseline GPO, apply security filtering, use WMI filters, and work out precedence with gpresult /h report.html.
  2. Fine-grained password policies — a PSO applied to a group, overriding the domain default.
  3. AD Certificate Services on FS01, then issue certificates via autoenrolment.
  4. Break replication deliberately — take DC02 offline for longer than the tombstone lifetime and learn what recovery involves.
  5. Seize FSMO roles after simulating the permanent loss of DC01. ntdsutil is not a tool you want to learn during an outage.
  6. Delegated administration — grant a helpdesk group password-reset rights on the Users OU only, then verify the boundary holds.

Checkpoint before each. Roll back after. That loop is worth more than any amount of reading.