Building My First Azure Local (aka Azure Stack HCI) Cluster at Home
It all began on a lazy Sunday afternoon. I had been dreaming of setting up my very own Azure Local cluster for months, but the cost had always seemed prohibitive. I decided to spend my day browsing through various online marketplaces, hoping to find some hidden gems.
That’s when I stumbled upon an incredible deal on a very famous Chinese online store. There it was: a budget-friendly motherboard with a powerful Xeon CPU, boasting 18 cores and 36 logical processors, and 128 GB of RAM expandable up to 256 GB—all for £220. My heart raced as I saw the price; it was a fraction of what I had expected to spend. Without hesitation, I clicked "Buy Now" and felt a rush of excitement.
A few weeks later, the package arrived at my doorstep. Unboxing it felt like opening a treasure chest. Along with the motherboard, CPU, and RAM, I had also managed to get my hands on two SSDs—one 250 GB for the operating system and a massive 4 TB for the virtual machines. Everything had cost me around £400. (At the time of writing this blog, for the same price, you can get a motherboard with dual CPUs.)
The assembly process was both exhilarating and challenging. I carefully installed the CPU, slotted in the RAM, and connected the SSDs. Each step brought me closer to my goal. With the hardware set up, I moved on to the software installation.
To keep licensing affordable, I installed Windows 10 (as it's used only to host the virtualization and is the cheap way to avoid using Windows Server—you can also use a different virtualization platform, but this guide is for Hyper-V). I followed this by installing the necessary roles for Hyper-V, where I planned to install my Azure Local Cluster. Configuring the networking was a breeze: I used one network card and created two virtual switches—one connected to the physical card (Management network) and another on a private network (Storage network).
I installed three VMs, each assigned 32 GB of RAM and 8 virtual CPUs. Each VM was equipped with three disks: a 127 GB disk for the OS and two additional 500 GB disks for data. Additionally, each VM had two NICs—one attached to the management virtual switch and the other to the storage switch. The VMs were generation 2 with TPM and nested virtualization enabled. I also disabled time synchronization and configured the VLAN settings on the storage network.
Finally, the moment of truth arrived. I started the Azure Stack HCI creation from the portal, running the wizard. After more or less three hours, I had a cluster where I was able to create VMs and AKS on-premises directly from the Azure portal. I realized that I had turned my dream into reality. My humble home server had transformed into a powerful, enterprise-grade infrastructure, capable of handling complex workloads and integrating seamlessly with the cloud.
I stood back and admired my creation. This was just the beginning—I had opened the door to endless possibilities, and I couldn’t wait to see where this journey would take me next.
Installing an Azure Stack HCI 3-node cluster on your on-premises server with budget-friendly parts is definitely possible!
For more detailed instructions, refer to Azure Local, version 23H2 deployment overview - Azure Local | Microsoft Learn
Here’s a step-by-step guide to help you get started:
Macro Steps for Deployment:
Step 1: Install Hyper-V to host the infrastructure
Install a Windows OS—either Windows Server (minimum recommended is Windows Server 2016) or Windows Client (Windows 10 or 11), which has a cheaper license compared to Windows Server.
For Windows 10, you can use the UI to install the Hyper-V role.
For Windows Server, run the following commands in PowerShell (Run As Administrator):
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell -All
Open Virtual Switch Manager and create two Virtual Switches:
Step 2: Prepare the infrastructure
One important element for Azure Local deployment is to have an infrastructure ready. Assuming you have already set up the following pre-requisites (I am not going to spend a lot of time on this topic as this is out of scope for this guide):
Step 3: Prepare Active Directory
Follow the guide and run a simple script to create an OU and a user with minimum privileges for installation:
Ensure the password is complex with a minimum of 12 characters.
Step 4: Create the Nodes
This setup works with an odd number of nodes. If you use an even number of nodes, you will need to create a witness, which is out of scope for this guide.
To create nodes on Hyper-V with the right parameters already set, run the provided script once for each node. Don't forget to change the node name and base path (location to store the VM) in the script.
#Parameters
$VMName = "<node name>"
$BasePath = "<F:\vms\hcicluster\>"
# Variables
$VirtualDisksPath = "$BasePath\$VMName\Virtual Disks"
$OSDiskPath = "$VirtualDisksPath\$VMName\OSdisk.vhdx"
$DataDiskPath = "$VirtualDisksPath\$VMName\datadisk.vhdx"
$DataDisk2Path = "$VirtualDisksPath\$VMName\datadisk2.vhdx"
$MemoryStartupBytes = 32768MB
$ProcessorCount = 8
$ManagementSwitchName = "Management"
$StorageSwitchName = "HCI-Storage"
$ComputeSwitchName = $ManagementSwitchName
$StorageVlanId = 711 # Assign the desired VLAN ID for the storage network adapter
# Create the virtual disks folder if it doesn't exist
if (!(Test-Path -Path $VirtualDisksPath)) {
New-Item -ItemType Directory -Path $VirtualDisksPath
}
# Create VM
New-VM -Name $VMName -MemoryStartupBytes $MemoryStartupBytes -Generation 2 -Path $BasePath -BootDevice CD -SwitchName $ManagementSwitchName
Get-VMNetworkAdapter -VMName $VMName | Set-VMNetworkAdapter -MacAddressSpoofing On
# Set the number of processors
Set-VMProcessor -VMName $VMName -Count $ProcessorCount
# Create and attach the OS disk
New-VHD -Path $OSDiskPath -SizeBytes 127GB -Dynamic
Add-VMHardDiskDrive -VMName $VMName -Path $OSDiskPath
# Create and attach the data disk
New-VHD -Path $DataDisk2Path -SizeBytes 500GB -Dynamic
Add-VMHardDiskDrive -VMName $VMName -Path $DataDisk2Path
# Create and attach the data disk2
New-VHD -Path $DataDiskPath -SizeBytes 500GB -Dynamic
Add-VMHardDiskDrive -VMName $VMName -Path $DataDiskPath
# Add network adapters for compute (2 adapters)
for ($i = 1; $i -le 0; $i++) {
Add-VMNetworkAdapter -VMName $VMName -SwitchName $ComputeSwitchName -Name "Compute$i"
}
# Add network adapters for management (2 adapters)
for ($i = 1; $i -le 0; $i++) {
Add-VMNetworkAdapter -VMName $VMName -SwitchName $ManagementSwitchName -Name "Management$i"
}
# Add network adapter for storage (1 adapter) with VLAN ID
Add-VMNetworkAdapter -VMName $VMName -SwitchName $StorageSwitchName -Name "Storage"
Get-VMNetworkAdapter -vmname $VMName |?{$_.switchname -eq 'HCI-Storage'}| Set-VMNetworkAdapterVlan -Trunk -NativeVlanId 0 -AllowedVlanIdList 711-712
# Enable TPM
Set-VMFirmware -VMName $VMName -EnableSecureBoot On
Set-VMKeyProtector -VMName $vmName -NewLocalKeyProtector
Enable-VMTPM -VMName $VMName
# Enable Nested Virtualization
Set-VMProcessor -VMName $VMName -ExposeVirtualizationExtensions $true
# Disable the time synchronization feature
Disable-VMIntegrationService -VMName $VMName -Name "Time Synchronization"
# Start VM
Start-VM -Name $VMName
Write-Host "Virtual Machine $VMName created successfully with specified configuration."
Step 5: Install the Azure Stack HCI OS using default settings
Once all the node VMs have been created and started, download the latest Azure Stack HCI Image ISO. Attach it to the nodes and begin the installation:
Leave all settings as default.
Ensure the password is complex with a minimum of 12 characters.
Step 6: Configure each node with the software and configuration
Execute the following steps on each node:
Recommended by LinkedIn
Get-NetIPAddress |ft
Use the InterfaceIndex from the output of the previous command to populate the next command.
New-NetIPAddress -InterfaceIndex <Interface Index> -IPAddress <IP Address to assign to the node> -PrefixLength 24 -DefaultGateway <Default gateway IP>
Set-DnsClientServerAddress -InterfaceIndex <Interface Index> -ServerAddresses <IP Address of your Domain Controller>
$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi; Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'; Remove-Item .\AzureCLI.msi
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell -All
# Disable IPv6 on the Ethernet adapter
Get-NetAdapter|Disable-NetAdapterBinding -ComponentID ms_tcpip6
$domaincontrollerfqdn="<FQDN of your Domain Controller>"
w32tm /config /manualpeerlist:$domaincontrollerfqdn /syncfromflags:manual /reliable:yes /update
w32tm /resync /force
w32tm /query /status
#Sample script
Get-NetAdapter
Get-NetIPAddress|ft
Once you have identify the adapters, change the next script to reflect the right name of the NetAdapters.
Rename-NetAdapter -Name "<Ethernet 2>" -NewName "Management"
Rename-NetAdapter -Name "<Ethernet>" -NewName "Storage"
Step 7: Add the nodes to Azure ARC and install all the extensions
Create a Resource Group in the selected Subscription and note down the Resource Group name, Subscription ID, and Tenant ID.
Run the following script on each node using the collected parameters:
#Define the subscription where you want to register your machine as Arc device
$Subscription = "<Your Subscription ID>"
#Define the resource group where you want to register your machine as Arc device
$RG = "<Resource Group name>"
#Define the region you will use to register your machine as Arc device
$Region = "<Region, use one supported>"
#Define the tenant you will use to register your machine as Arc device
$Tenant = "<Your Tenant ID>"
#Define the proxy address if your Azure Local deployment accesses the internet via proxy
$ProxyServer = ""
#Connect to your Azure account and Subscription
Connect-AzAccount -SubscriptionId $Subscription -TenantId $Tenant -DeviceCode
#Get the Access Token for the registration
$ARMtoken = (Get-AzAccessToken).Token
#Get the Account ID for the registration
$id = (Get-AzContext).Account.Id
#Invoke the registration script. Use a supported region.
Invoke-AzStackHciArcInitialization -SubscriptionID $Subscription -ResourceGroup $RG -TenantID $Tenant -Region $Region -Cloud "AzureCloud" -ArmAccessToken $ARMtoken -AccountID $id
Step 8: Start the deployment on the portal
If they are still creating, wait until completion before starting the deployment. If any extension fails, remove it, you have the option to reinstall it during the next step.
During the first screen (Basic tab), when you add the machines, if they miss the extension, you have the option to install it again.
I have used all the recommended options except for the Security settings, where I have deselected everything. The following picture is indicative only and does not show the exact configuration I used.
Proceed through the wizard using the default settings.
Troubleshooting
Here are some hints in case you need to troubleshoot a deployment, which can take 2 to 3 hours.
ls|sort LastAccessTime
Then run this command using the correct file identified in the previous step
Get-Content -Path "C:\CloudDeployment\Logs\<CloudDeployment*.log>" -Wait
Check the Task Status: Open PowerShell as an Administrator and run the following command to check the status of the deployment task:
powershell Get-ScheduledTask -TaskName LCMAzureStackDeploy
try starting the task using:
powershell Start-ScheduledTask -TaskName LCMAzureStackDeploy
Conclusion
I stood back and admired my creation. This was just the beginning—I had opened the door to endless possibilities, and I couldn’t wait to see where this journey would take me next.
Please leave a comment if you find any errors, have suggestions to improve this guide, or want to propose an idea for a new guide.
Sr System Engineer
2moVery nice article and proabably the first article aroud this topic. Since this product is in evolving phase, there's no much step by step info is available on the internet except Microsoft documentation. Thank you for sharing. If possible, please share the dteails of motherbord and CPU link.