> ## Content Index
> Fetch the complete content index at: https://blog.sudowl.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Hyper-V on Windows Server — Your First VM Without the GUI
- URL: https://blog.sudowl.com/hyper-v-create-first-vm-windows-server/
- Published: 2026-05-21T10:00:00.000Z
- Updated: 2026-10-11T08:26:51.000Z
- Description: Install Hyper-V and build your first VM on Windows Server entirely from PowerShell — switch, VHD, ISO, boot order, Secure Boot, checkpoints. The commands I run.
- Author: Lukas
- Tags: Windows Server

Hyper-V Manager is fine for clicking around once. For repeatable work — and for Server Core where there's no GUI at all — you drive Hyper-V from PowerShell. The cmdlets are clean and you can paste a whole VM into existence in one block.

**TL;DR:**

```powershell
Install-WindowsFeature Hyper-V -IncludeManagementTools -Restart
# after reboot:
New-VMSwitch -Name "extSwitch" -NetAdapterName "Ethernet" -AllowManagementOS $true
New-VM -Name "web01" -MemoryStartupBytes 4GB -Generation 2 `
  -NewVHDPath "D:\VMs\web01\web01.vhdx" -NewVHDSizeBytes 60GB -SwitchName "extSwitch"
Set-VMMemory web01 -DynamicMemoryEnabled $true -MinimumBytes 1GB -MaximumBytes 8GB
Set-VMProcessor web01 -Count 4
Add-VMDvdDrive web01 -Path "D:\ISO\WinServer2025.iso"
Set-VMFirmware web01 -FirstBootDevice (Get-VMDvdDrive web01)
Start-VM web01

```

Details below.

## Check the host can actually run Hyper-V

Hyper-V needs hardware virtualization and SLAT. If the box is a VM itself, it needs nested virtualization exposed by the host first.

```powershell
Get-ComputerInfo -Property "HyperV*"

```

You want all four `HyperVRequirement*` properties reading `True`: VM monitor mode extensions, virtualization enabled in firmware, SLAT, and DEP. If `HyperVisorPresent` is already `True`, the role is on (or another hypervisor is — they don't coexist).

If virtualization shows disabled, it's a BIOS/UEFI setting (Intel VT-x / AMD-V), not something PowerShell fixes. Reboot into firmware and enable it.

## Install the role

```powershell
Install-WindowsFeature Hyper-V -IncludeManagementTools -Restart

```

`-IncludeManagementTools` pulls in the Hyper-V PowerShell module and (on full GUI installs) Hyper-V Manager. `-Restart` is mandatory — the hypervisor loads at boot, not on demand. On Server Core, same command, you just won't get the MMC snap-in.

After reboot, confirm:

```powershell
Get-WindowsFeature Hyper-V
Get-Command -Module Hyper-V | Measure-Object

```

## Create a virtual switch

A VM with no switch has no network. Three types:

- **External** — bridges to a physical NIC. The VM is on your LAN like any other host. This is what you want for servers.
- **Internal** — host and VMs talk to each other, no physical network. Good for a NAT lab.
- **Private** — VMs talk only to each other. Host is excluded. Isolated test segments.

External, bound to your physical adapter:

```powershell
Get-NetAdapter | Where-Object Status -eq "Up"   # find the NIC name
New-VMSwitch -Name "extSwitch" -NetAdapterName "Ethernet" -AllowManagementOS $true

```

**The exception:** creating an External switch briefly drops the host's own connectivity while the NIC rebinds to the virtual switch. Don't do this over an RDP session on the same NIC unless you enjoy locking yourself out — do it on the console, an out-of-band link, or a second adapter. `-AllowManagementOS $true` keeps the host reachable through the switch afterward; set it `$false` to dedicate the NIC purely to VMs.

Internal and Private don't touch hardware, so they're safe to create remotely:

```powershell
New-VMSwitch -Name "intSwitch" -SwitchType Internal
New-VMSwitch -Name "labSwitch" -SwitchType Private

```

## Create the VM

Generation 2 unless you have a specific reason not to — UEFI firmware, Secure Boot, SCSI boot, PXE over a standard adapter. Gen 1 is legacy BIOS; only use it for ancient guests or 32-bit OSes Gen 2 won't run.

```powershell
New-VM -Name "web01" -MemoryStartupBytes 4GB -Generation 2 `
  -NewVHDPath "D:\VMs\web01\web01.vhdx" -NewVHDSizeBytes 60GB `
  -SwitchName "extSwitch"

```

`-NewVHDSizeBytes` is the *maximum*. A `.vhdx` is dynamically expanding by default — it only consumes real disk as the guest writes data, so a 60 GB VHDX on a fresh install sits around 10 GB. Put VHDXs on a fast data volume, not the OS drive.

### Memory and CPU

`MemoryStartupBytes` is the boot allocation. Turn on dynamic memory so idle VMs hand RAM back to the pool:

```powershell
Set-VMMemory web01 -DynamicMemoryEnabled $true -MinimumBytes 1GB -MaximumBytes 8GB
Set-VMProcessor web01 -Count 4

```

**The exception:** some workloads refuse to start or behave badly under dynamic memory — older SQL Server, anything that pins a large buffer pool. Leave those static at a fixed `MemoryStartupBytes` with dynamic disabled.

Processor count can't exceed the host's logical processors. Overcommitting CPU across VMs is fine (the scheduler time-slices); overcommitting per-VM beyond physical cores is not.

## Attach the install ISO and fix boot order

A fresh VHDX is empty. Mount an installer ISO as a DVD drive:

```powershell
Add-VMDvdDrive web01 -Path "D:\ISO\WinServer2025.iso"

```

Gen 2 VMs boot from the disk by default, which is empty, so they fall through to PXE. Point the firmware at the DVD for the first boot:

```powershell
Set-VMFirmware web01 -FirstBootDevice (Get-VMDvdDrive web01)

```

After the OS is installed, set it back to the disk (or just remove the DVD drive) so it doesn't re-enter the installer.

### The Linux-on-Gen2 gotcha

Gen 2 Secure Boot uses the Microsoft Windows certificate by default. Boot a Linux ISO under that and you get a Secure Boot failure — black screen, no obvious error. The fix is the UEFI CA template:

```powershell
Set-VMFirmware web01 -SecureBootTemplate MicrosoftUEFICertificateAuthority

```

Modern Ubuntu, Debian, RHEL ship shim binaries signed against that CA, so they boot fine with Secure Boot still on. Only disable Secure Boot entirely (`-EnableSecureBoot Off`) for distros without a signed shim.

## Start it and connect

```powershell
Start-VM web01
vmconnect.exe localhost web01

```

`vmconnect` is the console window — you need it to click through OS install. On Server Core there's no `vmconnect`; run it from a management workstation with the Hyper-V tools installed, pointed at the host. Once the guest has an OS and an IP off your External switch, you stop needing the console and just RDP/SSH in.

## Checkpoints — and why they aren't backups

A checkpoint is point-in-time state you can roll back to. Two kinds:

```powershell
Set-VM web01 -CheckpointType Production   # default; uses VSS, app-consistent
# vs Standard — captures live memory + disk, restores to running state

```

**Production** quiesces the guest via VSS (or filesystem freeze on Linux) for a crash-consistent, application-safe snapshot — the right default. **Standard** also saves RAM so you restore to the exact running moment, which is handy for debugging a live state but is *not* application-consistent.

```powershell
Checkpoint-VM web01 -SnapshotName "pre-patch"
Restore-VMSnapshot -VMName web01 -Name "pre-patch" -Confirm:$false

```

Use them before a risky change, then delete them. Do **not** treat checkpoints as backups: they live on the same disk as the VM, the differencing chain grows and slows the VM the longer it exists, and a long-lived chain that merges badly can corrupt the VHDX. For real backups, copy the VHDX out to other media — see my [restic-to-S3 setup](https://blog.sudowl.com/restic-backup-s3-minio-encrypted/) for the offsite side.

## Nested virtualization

Want to run Hyper-V (or Docker's Hyper-V backend, or WSL2) *inside* a VM? Expose the virtualization extensions to the guest — VM off first:

```powershell
Stop-VM web01
Set-VMProcessor web01 -ExposeVirtualizationExtensions $true
Set-VMMemory web01 -DynamicMemoryEnabled $false   # nested needs static memory
Start-VM web01

```

Nested requires static memory, so this trades away the dynamic-memory benefit. Fine for a CI runner or a lab box, wasteful otherwise.

## On a Linux host instead?

If your hypervisor host runs Linux, this whole article is the wrong tool — use Proxmox (KVM under the hood) and drive it with `qm`. The mental model maps cleanly: VMSwitch → Linux bridge, VHDX → qcow2/zvol, checkpoint → snapshot, and cloud-init replaces clicking through an installer entirely. I cover the fast path in [Proxmox + cloud-init VM templates](https://blog.sudowl.com/proxmox-cloud-init-vm-template-ubuntu/). Pick one hypervisor per host — KVM and Hyper-V both want the CPU virtualization extensions and won't share.

## Verify

```powershell
Get-VM                                  # state, CPU, memory, uptime
Get-VM web01 | Select-Object Name, State, Generation, ProcessorCount
Get-VMNetworkAdapter web01              # confirm it's on the right switch
Get-VMFirmware web01                    # boot order + Secure Boot template

```

`Get-VM` showing `Running` with a non-zero uptime means the hypervisor is live and your VM is up. From here it's just OS setup — my [Windows Server initial setup checklist](https://blog.sudowl.com/windows-server-initial-setup-checklist/) and [DHCP setup](https://blog.sudowl.com/windows-server-dhcp-setup/) are the next two things I run on every fresh guest.

## Gotchas

- **No reboot after install** → Hyper-V cmdlets exist but VMs won't start. The hypervisor only loads at boot. `-Restart` or reboot manually.
- **External switch over RDP** → you drop yourself. Console or second NIC only.
- **Linux Gen2 black screen** → Secure Boot template. Set `MicrosoftUEFICertificateAuthority`.
- **VM won't boot off ISO** → Gen2 boot order defaults to disk/PXE. `Set-VMFirmware -FirstBootDevice`.
- **Checkpoints piling up** → differencing chain bloat, eventual VHDX corruption risk. Delete after use; they are not backups.
- **Nested virt won't enable** → VM must be off, and dynamic memory must be disabled.

---

### Related posts

- [DHCP on Windows Server — Scopes, Reservations, and the Gotchas](https://blog.diengdoh.com/windows-server-dhcp-setup/?ref=blog.sudowl.com)
- [Active Directory Part 2 — OUs, Users, and GPO Basics](https://blog.diengdoh.com/active-directory-part-2-ous-users-gpo-basics/?ref=blog.sudowl.com)
- [Active Directory Part 1 — Promoting Your First Domain Controller](https://blog.diengdoh.com/active-directory-promote-first-domain-controller/?ref=blog.sudowl.com)