m4nifest0-tech

Search the site

Linux and Windows Server

Windows Server: a basic Active Directory lab with AD DS, DNS and GPO

How to build a test Active Directory domain on a Proxmox VM: AD DS role, integrated DNS, OUs, users, groups, GPO, joining a client and backup.
Published on 7 min readLevel: Intermediate

You learn an Active Directory domain by building it and breaking it. A VM on Proxmox lets you do that without risk: you create the domain, organize users and computers, apply a group policy and, if something goes wrong, roll back to a snapshot. This guide covers Windows Server 2022 or 2025 and a lab with a single domain controller and one client. All names and addresses are examples.

Lab requirements

The VM hosts the domain controller (DC) and needs few resources: two vCPUs and a few GiB of RAM are enough for a domain with no load. On Windows guests it is worth installing the VirtIO drivers and the QEMU guest agent, which allows consistent backups from the hypervisor. The lab network should be isolated from the one carrying real services, for example on a dedicated VLAN.

Before promotion you need a final hostname, a static IP address and a DNS pointing at the server itself: the name cannot be changed painlessly after promotion. Time matters too, because Kerberos by default tolerates at most five minutes of skew between the DC and clients.

ItemExample value
Domainad.example.com
NetBIOS nameLAB
DC hostnamedc1
DC address192.0.2.10/24
Gateway192.0.2.1
On the DC VM, PowerShell as administrator
Get-NetAdapter
New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 192.0.2.10 -PrefixLength 24 -DefaultGateway 192.0.2.1
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 192.0.2.10
Rename-Computer -NewName "dc1" -Restart

Note

ad.example.com is a domain reserved for documentation. On a real network you use a subdomain (for example ad) of a domain you actually own.

Installing the AD DS role

On the DC VM
Install-WindowsFeature AD-Domain-Services -IncludeManagementTools

The command installs the role and the management tools, including the ActiveDirectory PowerShell module. The server is not a domain controller yet: promotion is still missing.

Promoting to domain controller

Choosing the domain name

Choose the name first: changing it later is a complex operation. Avoid the "local" suffix or other made-up suffixes: "local" is reserved for multicast DNS (RFC 6762) and causes resolution conflicts with macOS, Linux and recent Windows clients, while an unregistered suffix prevents you from getting public certificates and can coincide with someone else's domain. The recommended practice is a subdomain of a domain you own, such as ad.example.com.

Creating the forest

The Directory Services Restore Mode (DSRM) password is requested interactively and never appears in the script.

On the DC VM
$dsrm = Read-Host -Prompt "Credenziale DSRM" -AsSecureString
Test-ADDSForestInstallation -DomainName "ad.example.com" -InstallDns -SafeModeAdministratorPassword $dsrm
Install-ADDSForest -DomainName "ad.example.com" -DomainNetbiosName "LAB" -InstallDns -SafeModeAdministratorPassword $dsrm -Force

Test-ADDSForestInstallation runs only the preliminary checks, without making changes. Install-ADDSForest promotes the server and reboots it. The forest and domain functional levels can stay at their defaults, which are the maximum the operating system supports.

Important

The DSRM credential is needed to restore the DC and cannot be recovered any other way: keep it in a secrets manager, not in a text file or a script.

Integrated DNS

Active Directory depends on DNS: clients find the DC through SRV records, for example _ldap._tcp.dc._msdcs.ad.example.com, published by the DC itself. With -InstallDns the ad.example.com zone is created AD-integrated and replicated with the directory. The DC's DNS is the only one domain clients should use. Resolution of external names is delegated to a forwarder:

On the DC VM
Add-DnsServerForwarder -IPAddress 198.51.100.53
Resolve-DnsName -Name "_ldap._tcp.dc._msdcs.ad.example.com" -Type SRV

If the second command returns the record, the DC's registration in DNS is correct.

OUs, users and groups

Group policies are linked to organizational units (OUs), not to the default Users and Computers containers, so it is worth building your own structure. Permissions are assigned to groups, not to individual users.

On the DC VM
$base = "DC=ad,DC=example,DC=com"
New-ADOrganizationalUnit -Name "Laboratorio" -Path $base
New-ADOrganizationalUnit -Name "Utenti" -Path "OU=Laboratorio,$base"
New-ADOrganizationalUnit -Name "Gruppi" -Path "OU=Laboratorio,$base"
New-ADOrganizationalUnit -Name "Computer" -Path "OU=Laboratorio,$base"
 
New-ADGroup -Name "GG-Tecnici" -GroupScope Global -GroupCategory Security -Path "OU=Gruppi,OU=Laboratorio,$base"
 
$iniziale = Read-Host -Prompt "Credenziale iniziale per mario.rossi" -AsSecureString
New-ADUser -Name "Mario Rossi" -SamAccountName "mario.rossi" -UserPrincipalName "mario.rossi@ad.example.com" -Path "OU=Utenti,OU=Laboratorio,$base" -AccountPassword $iniziale -ChangePasswordAtLogon $true -Enabled $true
 
Add-ADGroupMember -Identity "GG-Tecnici" -Members "mario.rossi"

Read-Host -AsSecureString avoids writing credentials into the script and the shell history. The credential must meet the domain policy, otherwise New-ADUser fails, and -ChangePasswordAtLogon forces a change at first sign-in. The classic scheme assigns users to global groups and global groups to domain local groups that receive the permissions on resources.

An example GPO

The demonstration GPO disables Autoplay on all drives and is linked only to the Computer OU.

On the DC VM
New-GPO -Name "Esempio-Disattiva-Autoplay" -Comment "GPO dimostrativa"
Set-GPRegistryValue -Name "Esempio-Disattiva-Autoplay" -Key "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer" -ValueName "NoDriveTypeAutoRun" -Type DWord -Value 255
New-GPLink -Name "Esempio-Disattiva-Autoplay" -Target "OU=Computer,OU=Laboratorio,DC=ad,DC=example,DC=com" -LinkEnabled Yes

Tip

Try new GPOs on a test OU, not at the root of the domain. On the client, gpupdate /force forces them to apply and gpresult /r lists the GPOs actually applied.

Joining a client to the domain

The client must use the DC as its DNS and must be a Windows edition that supports joining (Home editions do not). The account requested by Get-Credential is a user with the rights to join computers to the domain.

On the client, PowerShell as administrator
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 192.0.2.10
Add-Computer -DomainName "ad.example.com" -Credential (Get-Credential) -Restart

New computers end up in the Computers container: to bring them within the scope of the GPO they must be moved to the dedicated OU.

On the DC VM
Get-ADComputer -Identity "client1" | Move-ADObject -TargetPath "OU=Computer,OU=Laboratorio,DC=ad,DC=example,DC=com"

Verification

On the DC VM
dcdiag /q
Get-ADDomain | Select-Object DNSRoot, NetBIOSName, DomainMode, PDCEmulator
Get-ADDomainController -Filter * | Select-Object Name, IPv4Address, IsGlobalCatalog

dcdiag /q shows only errors: no output means no failed tests. Without /q each test reports its outcome:

Starting test: Connectivity
   ......................... DC1 passed test Connectivity

Snapshots and domain controller backup

A snapshot is handy before a promotion or a test, but it is not a backup: it lives on the same storage as the VM and shares its fate.

Warning

In a domain with several DCs, rolling a controller back to an earlier state can cause a USN rollback: the restored DC's directory no longer realigns with its replicas. Proxmox exposes the VM-Generation ID (the vmgenid option), which Windows DCs use to detect a restore, but the rule still stands: restore a DC only with a supported procedure, not with a simple rollback.

For an application-level backup, use a system state backup, on a volume other than the system volume:

On the DC VM
Install-WindowsFeature Windows-Server-Backup
wbadmin start systemstatebackup -backupTarget:E: -quiet

A backup of the whole VM goes alongside the system state backup, it does not replace it: the 3-2-1 backup strategy with Proxmox Backup Server describes how to organize copies and test restores. To watch the DC over time you can use windows_exporter, as described in monitoring with Prometheus and Grafana in an LXC.

Related articles