<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://schmitt-nieto.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://schmitt-nieto.com/" rel="alternate" type="text/html" /><updated>2026-06-08T18:09:37+02:00</updated><id>https://schmitt-nieto.com/feed.xml</id><title type="html">Cristian Schmitt Nieto´s Blog</title><subtitle>Welcome to my blog, where you will find all kinds of information related to Azure, Azure Virtual Desktop and Azure Local.</subtitle><author><name>Cristian Schmitt Nieto</name></author><entry><title type="html">Awesome Azure Virtual Desktop</title><link href="https://schmitt-nieto.com/blog/awesome-azure-virtual-desktop/" rel="alternate" type="text/html" title="Awesome Azure Virtual Desktop" /><published>2026-05-23T00:00:00+02:00</published><updated>2026-06-03T00:00:00+02:00</updated><id>https://schmitt-nieto.com/blog/awesome-azure-virtual-desktop</id><content type="html" xml:base="https://schmitt-nieto.com/blog/awesome-azure-virtual-desktop/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Azure Virtual Desktop delivers cloud-hosted desktops and remote applications with a consistent management plane in Azure. This page collects the docs, tools, and community resources I use when planning, deploying, and operating Azure Virtual Desktop and Windows 365 environments. It mirrors my public GitHub list so you can search it directly on this site and keep track of updates.</p>

<p>GitHub source: <a href="https://github.com/schmittnieto/awesome-azure-virtual-desktop">https://github.com/schmittnieto/awesome-azure-virtual-desktop</a></p>

<p><strong>Who is this for</strong></p>
<ul>
  <li>Cloud architects and endpoint engineers designing virtual desktop platforms</li>
  <li>AVD and Windows 365 administrators running pooled and personal desktops</li>
  <li>Operations teams that want proven references for day to day work</li>
</ul>

<p><strong>What you will find</strong></p>
<ul>
  <li>Official documentation and learning paths</li>
  <li>FSLogix, Azure Files, and App Attach references</li>
  <li>Windows App, Windows 365, and Microsoft Intune resources</li>
  <li>Third party management, testing, and thin client vendors</li>
  <li>Tools, scripts, and community write ups</li>
</ul>

<p><strong>How to use it</strong></p>
<ul>
  <li>Use the table of contents to jump to a topic</li>
  <li>Press Ctrl F to search within the page</li>
  <li>Open links in a new tab to keep your place</li>
</ul>

<p><em>If you spot a gap or a broken link, open an issue or pull request in the GitHub repo <a href="https://github.com/schmittnieto/awesome-azure-virtual-desktop/issues/new/choose">link</a>.</em></p>

<!-- AWESOMEAZUREVIRTUALDESKTOP:START -->

<h2 id="official">Official</h2>
<p><em>Only official links published or maintained by Microsoft or Azure.</em></p>

<h3 id="whats-new-in-azure-virtual-desktop">What’s new in Azure Virtual Desktop</h3>

<p><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/whats-new">What’s new in Azure Virtual Desktop?</a></p>

<p>Azure Virtual Desktop receives continuous monthly service updates. Below is a summary of key updates from May 2025 onward.</p>

<h4 id="autoscale-and-host-pool-management">Autoscale and Host Pool Management</h4>
<ul>
  <li><strong>Session host creation using a session host configuration</strong> <em>(June 2025)</em> - extending session host creation, auto-retry behavior and diagnostics for host pools that use session host configuration.</li>
  <li><strong>Managed identity support for session host configuration</strong> <em>(validation host pools: August 2025; all host pools: September 2025)</em> - removing the need to assign permissions to the Azure Virtual Desktop service principal when creating and updating session hosts.</li>
  <li><strong>Ephemeral OS disk support</strong> <em>(Public preview: October 2025)</em> - enabling stateless session hosts to use local VM storage for faster provisioning, reimaging and performance.</li>
  <li><strong>RDP Multipath</strong> <em>(GA: July 2025; fully rolled out: November 2025; redundant TCP GA rollout: May 2026)</em> - improving connection reliability by using multiple network paths between the client and session host or Cloud PC.</li>
  <li><strong>Azure Virtual Desktop for hybrid environments with Arc-enabled servers</strong> <em>(Public preview: May 2026)</em> - allowing session hosts to run on any hypervisor or bare-metal Windows Server through the Azure Arc extension, without VM provisioning or power management in this preview.</li>
</ul>

<h4 id="app-delivery-and-profile-management">App Delivery and Profile Management</h4>
<ul>
  <li><strong>App Attach</strong> <em>(MSIX App Attach deprecated: June 2025; Windows Server 2025 and 2022 support: April 2026)</em> - supports MSIX, Appx and App-V package formats and simplifies the staging and assignment workflow through the Azure portal.</li>
  <li><strong>FSLogix support for cloud-only and external identities</strong> <em>(Preview: November 2025)</em> - enabling FSLogix profile containers for both cloud-only and external identities in pooled host pools.</li>
  <li><strong>Enhanced RemoteApps</strong> <em>(Preview: November 2025)</em> - improving RemoteApp behavior with better Windows Snap support, full-screen mode, DPI handling and visual integration with Windows.</li>
</ul>

<h4 id="security-and-compliance">Security and Compliance</h4>
<ul>
  <li><strong>Select redirections disabled for new host pools</strong> <em>(July 2025)</em> - disabling clipboard, drive, opaque low-level USB and printer redirections by default for newly created host pools.</li>
  <li><strong>Token protection support in Windows App on Windows devices</strong> <em>(GA: August 2025)</em> - allowing Conditional Access policies to require sign-in tokens that can only be used from the intended device.</li>
  <li><strong>External identity support</strong> <em>(Preview without FSLogix: September 2025; GA: November 2025; additional client support: April 2026)</em> - allowing external identities to access Azure Virtual Desktop resources with expanded client support.</li>
  <li><strong>Centralized RDP Shortpath management</strong> <em>(GA: January 2026)</em> - enabling administrators to configure RDP Shortpath transport modes through Microsoft Intune or Group Policy.</li>
  <li><strong>RDP Shortpath over Private Link</strong> <em>(GA: February 2026)</em> - enabling UDP-based RDP Shortpath connections over Azure Private Link with explicit opt-in.</li>
  <li><strong>Windows Cloud Keyboard Input Protection</strong> <em>(Preview: November 2025)</em> - encrypting keystrokes at the kernel level to help protect sessions from keylogger malware and endpoint threats.</li>
</ul>

<h4 id="client-experience">Client Experience</h4>
<ul>
  <li><strong>Direct launch URLs for Windows App</strong> <em>(May 2025)</em> - allowing users to connect directly to a specific desktop or application resource from a browser link.</li>
  <li><strong>Multiple personal desktops for a single user</strong> <em>(GA: May 2025)</em> - assigning more than one personal desktop to a user in a single host pool.</li>
  <li><strong>HEVC/H.265 hardware acceleration</strong> <em>(GA: June 2025)</em> - improving GPU-accelerated frame encoding for graphical workloads in Azure Virtual Desktop sessions.</li>
  <li><strong>Microsoft Teams media optimization</strong> <em>(iOS and iPadOS preview: June 2025; WebRTC-based Teams GA and macOS preview: March 2026)</em> - reducing latency and improving call quality for meetings running inside AVD sessions through newer optimization architectures.</li>
</ul>

<h3 id="azure-virtual-desktop">Azure Virtual Desktop</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/">Azure Virtual Desktop Documentation (Microsoft Docs)</a><br />
Complete documentation for deploying and managing Azure Virtual Desktop.</li>
  <li><a href="https://azure.microsoft.com/en-us/products/virtual-desktop/">Azure Virtual Desktop Product Page</a><br />
Official product page for Azure Virtual Desktop on the Azure website.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/whats-new">What’s new in Azure Virtual Desktop (Microsoft Docs)</a><br />
Monthly updates listing the latest features and improvements in Azure Virtual Desktop.</li>
  <li><a href="https://azure.microsoft.com/en-us/pricing/details/virtual-desktop/">Azure Virtual Desktop Pricing</a><br />
Overview of the per-user access pricing model and session host virtual machine costs.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/prerequisites">Prerequisites for Azure Virtual Desktop (Microsoft Docs)</a><br />
Network, identity and subscription requirements before deploying Azure Virtual Desktop.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/create-host-pool">Create a host pool (Microsoft Docs)</a><br />
Step-by-step guide to creating pooled or personal host pools in Azure Virtual Desktop.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/autoscale-scaling-plan">Autoscale for Azure Virtual Desktop (Microsoft Docs)</a><br />
How to configure scaling plans to automatically start and stop session hosts based on demand, reducing compute costs.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type">Personal desktop assignment (Microsoft Docs)</a>
How to configure automatic or direct assignment for personal desktops, including multiple personal desktops per user.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/publish-applications-stream-remoteapp">RemoteApp streaming (Microsoft Docs)</a><br />
How to publish individual applications instead of full desktops using RemoteApp, reducing bandwidth and simplifying the user experience.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/watermarking">Watermarking in Azure Virtual Desktop (Microsoft Docs)</a><br />
How to enable QR-code watermarks in RDP sessions to deter and trace unauthorized screen captures.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/screen-capture-protection">Screen capture protection (Microsoft Docs)</a><br />
Policy that prevents client-side tools from capturing session content, relevant for regulated industries.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/licensing">Licensing Azure Virtual Desktop (Microsoft Docs)</a>
Eligible Windows, Microsoft 365 and Remote Desktop Services licenses for Azure Virtual Desktop deployments.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/security-guide">Azure Virtual Desktop Security Guide (Microsoft Docs)</a><br />
Security guidance for AVD deployments covering identity, networking, session security and data protection.</li>
  <li><a href="https://techcommunity.microsoft.com/blog/AzureArchitectureBlog/optimize-azure-virtual-desktop-using-insights-from-a-well-architected-review-assessment/4375459">Optimize Azure Virtual Desktop using insights from a Well-Architected Review Assessment (Tech Community)</a><br />
Guidance on evaluating AVD environments with the Well-Architected Framework assessment to identify risks, measure maturity and improve architecture quality.</li>
</ul>

<h3 id="azure-virtual-desktop-hybrid-and-azure-local">Azure Virtual Desktop Hybrid and Azure Local</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/hybrid-overview">Azure Virtual Desktop Hybrid Overview (Microsoft Docs)</a><br />
Overview of Azure Virtual Desktop Hybrid, which keeps the AVD service in Azure while running session hosts on any on-premises hypervisor or bare-metal Windows Server. It is in public preview with validation host pools only and does not support Windows 10 or Windows 11 Enterprise multi-session.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/azure-local-overview">Azure Virtual Desktop on Azure Local (Microsoft Docs)</a><br />
Running Azure Virtual Desktop session hosts on Azure Local for data residency, latency and on-premises scenarios. In contrast to generic AVD Hybrid, Azure Local also supports Windows 11 and Windows 10 Enterprise multi-session alongside single-session desktops and Windows Server images.</li>
  <li><a href="https://github.com/schmittnieto/awesome-azure-local#avd">Awesome Azure Local - Azure Virtual Desktop (GitHub)</a><br />
Companion curated list for Azure Local with a dedicated Azure Virtual Desktop section covering deployment, management tooling and community resources for running AVD on Azure Local.</li>
</ul>

<h3 id="fslogix">FSLogix</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/fslogix/">FSLogix Documentation (Microsoft Docs)</a><br />
Complete documentation for FSLogix profile and Office container solutions, now part of Microsoft 365.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/fslogix-profile-containers">FSLogix profile containers with Azure Virtual Desktop (Microsoft Docs)</a>
How FSLogix profile containers redirect and persist user profiles in non-persistent virtual environments, replacing roaming profiles and folder redirection.</li>
  <li><a href="https://learn.microsoft.com/en-us/fslogix/how-to-configure-profile-container-azure-files-active-directory">Configure FSLogix profile containers with Azure Files (Microsoft Docs)</a>
How to use Azure Files (SMB) as a storage backend for FSLogix profile containers, suitable for most small and medium deployments.</li>
  <li><a href="https://learn.microsoft.com/en-us/fslogix/how-to-configure-profile-container-netapp">Configure FSLogix profile containers with Azure NetApp Files (Microsoft Docs)</a>
How to use Azure NetApp Files for high-performance FSLogix profile storage in large deployments or latency-sensitive workloads.</li>
  <li><a href="https://learn.microsoft.com/en-us/fslogix/concepts-fslogix-cloud-cache">FSLogix Cloud Cache (Microsoft Docs)</a>
How to use FSLogix Cloud Cache to replicate profile containers across multiple storage locations for resilience and business continuity.</li>
  <li><a href="https://learn.microsoft.com/en-us/fslogix/whats-new">What’s new in FSLogix (Microsoft Docs)</a><br />
Release notes and update history for FSLogix versions.</li>
</ul>

<h3 id="azure-files">Azure Files</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/storage/files/">Azure Files Documentation (Microsoft Docs)</a>
Documentation hub for Azure Files, the managed SMB file share service commonly used as FSLogix profile container storage for AVD.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/storage/files/storage-files-active-directory-overview">Overview of Azure Files identity-based authentication for SMB access (Microsoft Docs)</a>
Overview of identity-based access for Azure Files over SMB, including share-level, directory-level and file-level permission models.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/storage/files/storage-files-identity-auth-hybrid-identities-enable?tabs=azure-portal%2Cintune">Enable Microsoft Entra Kerberos authentication for hybrid and cloud-only identities on Azure Files (Microsoft Docs)</a>
How to enable Kerberos authentication for Azure Files with hybrid identities and cloud-only identities in preview, useful for FSLogix profile containers on Entra-joined AVD session hosts.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/storage/files/storage-files-identity-assign-share-level-permissions">Assign share-level permissions for Azure file shares (Microsoft Docs)</a>
How to grant SMB access with Azure RBAC roles or default share-level permissions, including the default permission model required for cloud-only identities in preview.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/storage/files/storage-files-identity-configure-file-level-permissions">Configure directory and file-level permissions for Azure Files (Microsoft Docs)</a>
How to configure Windows ACLs for Azure file shares, including differences between hybrid identities and cloud-only identities when using Microsoft Entra Kerberos.</li>
  <li><a href="https://azure.microsoft.com/en-us/blog/azure-files-entra-only-identities-advancing-cloud-native-identity-and-security/">Entra-only identities for Azure Files SMB now generally available (Azure Blog)</a>
Announcement of the general availability (May 19, 2026) of Microsoft Entra-only identities for Azure Files SMB, enabling identity-based access to SMB file shares using cloud-only Entra ID accounts without on-premises Active Directory, which is directly relevant to FSLogix profile containers on Entra-joined AVD session hosts.</li>
</ul>

<h3 id="app-attach">App Attach</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/app-attach-overview">App Attach overview (Microsoft Docs)</a><br />
Introduction to App Attach, which allows MSIX, Appx and App-V packages to be staged and delivered dynamically to AVD session hosts without installation.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/app-attach-setup">Set up App Attach (Microsoft Docs)</a><br />
Step-by-step guide to configuring App Attach in the Azure portal, including image storage in Azure Files and assignment to host pools.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows/msix/packaging-tool/tool-overview">MSIX Packaging Tool (Microsoft Docs)</a><br />
Documentation for the MSIX Packaging Tool used to convert existing application installers to MSIX format for use with App Attach.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/app-attach-test-msix-packages">Test MSIX App Attach packages (Microsoft Docs)</a><br />
How to validate MSIX packages before deploying them through App Attach to avoid session host issues.</li>
</ul>

<h3 id="windows-app">Windows App</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/windows-app/">Windows App Documentation (Microsoft Docs)</a><br />
Documentation for Windows App, the unified Microsoft client for Azure Virtual Desktop, Windows 365 and Remote Desktop Services.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-app/get-started-connect-devices-desktops-apps">Get started with Windows App on Windows (Microsoft Docs)</a><br />
How to install and connect to Azure Virtual Desktop resources using Windows App on Windows.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-app/get-started-connect-devices-desktops-apps?pivots=macos">Windows App on macOS (Microsoft Docs)</a><br />
How to use Windows App to access AVD on macOS devices.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-app/compare-platforms-features?pivots=azure-virtual-desktop">Compare Windows App features across platforms and devices (Microsoft Docs)</a>
Feature matrix comparing Windows App support for Azure Virtual Desktop across Windows, macOS, iOS, iPadOS, Android, Chrome OS, web browsers and Meta Quest.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-app/whats-new">What’s new in Windows App (Microsoft Docs)</a><br />
Release notes and changelogs for the Windows App client across all supported platforms, including public release downloads for Windows outside of the Microsoft Store.
    <ul>
      <li><a href="https://go.microsoft.com/fwlink/?linkid=2262633">Windows App public release download - Windows 64-bit</a>
Direct Windows App installer for 64-bit Windows devices outside of the Microsoft Store.</li>
      <li><a href="https://go.microsoft.com/fwlink/?linkid=2318514">Windows App public release download - Windows 32-bit</a>
Direct Windows App installer for 32-bit Windows devices outside of the Microsoft Store.</li>
      <li><a href="https://go.microsoft.com/fwlink/?linkid=2318621">Windows App public release download - Windows Arm64</a>
Direct Windows App installer for Arm64 Windows devices outside of the Microsoft Store.</li>
    </ul>
  </li>
</ul>

<h3 id="windows-365">Windows 365</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/">Windows 365 Documentation (Microsoft Docs)</a>
Documentation hub for Windows 365, Microsoft’s Cloud PC service for streaming personalized Windows desktops from the Microsoft Cloud.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/overview">What is Windows 365? (Microsoft Docs)</a>
Overview of Windows 365 editions, Cloud PC concepts, licensing and access options including Windows App, the web client and Windows 365 Link.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/enterprise/">Windows 365 Enterprise and Frontline Documentation (Microsoft Docs)</a>
Documentation for planning, provisioning, managing and securing Cloud PCs with Microsoft Intune.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/business/">Windows 365 Business Documentation (Microsoft Docs)</a>
Documentation for smaller organizations using Windows 365 Business Cloud PCs with streamlined setup and management.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/enterprise/requirements">Windows 365 requirements (Microsoft Docs)</a>
Identity, licensing, Intune, Azure and role requirements for Windows 365 Enterprise, Frontline and Government deployments.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/enterprise/provisioning">Provisioning in Windows 365 (Microsoft Docs)</a>
Overview of the automated process that creates, configures and assigns Cloud PCs to licensed users.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/enterprise/create-provisioning-policy">Create provisioning policies (Microsoft Docs)</a>
How to define the rules Windows 365 uses to provision Cloud PCs for assigned Microsoft Entra groups.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/end-user-access-cloud-pc">Access a Cloud PC (Microsoft Docs)</a>
Supported client and browser options for users connecting to Windows 365 Cloud PCs.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/architecture/guide/virtual-desktop/windows-365-azure-network-connection">Windows 365 Azure network connection (Azure Architecture Center)</a>
Architecture guidance for connecting Windows 365 Cloud PCs to customer-managed Azure networks and on-premises resources.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/enterprise/whats-new">What’s new in Windows 365 Enterprise and Frontline (Microsoft Docs)</a>
Release notes for Windows 365 Enterprise and Frontline features, updates and service improvements.</li>
</ul>

<h3 id="windows-365-link">Windows 365 Link</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/link/">Windows 365 Link Documentation (Microsoft Docs)</a>
Documentation hub for Windows 365 Link, Microsoft’s purpose-built Cloud PC hardware device.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/link/overview">What is Windows 365 Link? (Microsoft Docs)</a>
Overview of the secure Cloud PC device experience, hardware concept, Intune management model and core requirements.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/link/deployment-overview">Windows 365 Link deployment overview (Microsoft Docs)</a>
Admin guidance for preparing Microsoft Entra ID, Intune enrollment, filters and Conditional Access before onboarding devices.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/link/requirements">Requirements for Windows 365 Link deployment (Microsoft Docs)</a>
Licensing, Microsoft Entra ID, Intune and Windows 365 single sign-on requirements for deploying Windows 365 Link devices.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/link/setup">Set up your Windows 365 Link and sign in (Microsoft Docs)</a>
First-run setup flow for users connecting Windows 365 Link to their work or school account and Cloud PC.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/link/sign-in">Sign in to, sign out, or lock your Windows 365 Link (Microsoft Docs)</a>
User guidance for daily sign-in, sign-out and lock workflows on Windows 365 Link.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/link/whats-new">What’s new in Windows 365 Link (Microsoft Docs)</a>
Release notes for Windows 365 Link builds, product improvements and device updates.</li>
</ul>

<h3 id="microsoft-intune">Microsoft Intune</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/mem/intune/">Microsoft Intune Documentation (Microsoft Docs)</a>
Documentation hub for Microsoft Intune endpoint management, app management, endpoint security and device compliance.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/management">Manage the operating system of Azure Virtual Desktop session hosts (Microsoft Docs)</a>
Overview of using Microsoft Intune or Configuration Manager to manage Azure Virtual Desktop session hosts.</li>
  <li><a href="https://learn.microsoft.com/en-us/intune/solutions/azure-virtual-desktop">Using Azure Virtual Desktop single-session with Microsoft Intune (Microsoft Docs)</a>
How to manage personal desktop session hosts with Intune policy, apps, compliance policy and Conditional Access.</li>
  <li><a href="https://learn.microsoft.com/en-us/intune/solutions/azure-virtual-desktop-multi-session">Using Azure Virtual Desktop multi-session with Microsoft Intune (Microsoft Docs)</a>
How to manage Windows Enterprise multi-session session hosts using device-scope and user-scope Intune policies.</li>
  <li><a href="https://learn.microsoft.com/en-us/intune/intune-service/configuration/settings-catalog">Use the Intune settings catalog (Microsoft Docs)</a>
How to create granular configuration profiles with device and user scope settings, including Windows Enterprise multi-session filters.</li>
  <li><a href="https://learn.microsoft.com/en-us/intune/device-security/security-baselines/overview">Intune security baselines (Microsoft Docs)</a>
Overview of Intune security baseline profiles for Windows devices and endpoint security configuration.</li>
  <li><a href="https://learn.microsoft.com/en-us/intune/intune-service/apps/apps-windows-10-app-deploy">Windows App deployment by using Microsoft Intune (Microsoft Docs)</a>
How to deploy Windows applications with Intune, including app assignment and Windows app deployment behavior.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/redirection-configure-clipboard?tabs=intune">Configure clipboard redirection with Microsoft Intune (Microsoft Docs)</a>
How to configure clipboard redirection for Azure Virtual Desktop session hosts using Intune settings catalog or Group Policy.</li>
  <li><a href="https://learn.microsoft.com/en-us/intune/device-updates/windows/update-rings">Manage Windows Update ring policies with Intune (Microsoft Docs)</a>
How Windows Update ring policies define update behavior for Windows devices; for AVD multi-session, use supported Windows Update settings in the Settings catalog.</li>
</ul>

<h3 id="monitoring-and-insights">Monitoring and Insights</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/insights">Azure Virtual Desktop Insights (Microsoft Docs)</a><br />
How to use AVD Insights, an Azure Monitor workbook, to monitor session host health, user connections and resource consumption from a single view.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/azure-monitor">Use Azure Monitor for Azure Virtual Desktop (Microsoft Docs)</a><br />
Guide to collecting and analyzing AVD diagnostics data in Azure Monitor and Log Analytics for alerting and custom queries.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/diagnostics-log-analytics">Diagnostic settings in Azure Virtual Desktop (Microsoft Docs)</a><br />
How to enable and route AVD diagnostic logs to Log Analytics for custom querying and long-term retention.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/insights-use-cases">Azure Virtual Desktop Insights use cases (Microsoft Docs)</a>
How to use Azure Virtual Desktop Insights to review host performance, connection reliability, latency and client usage.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/set-up-service-alerts">Set up service alerts for Azure Virtual Desktop (Microsoft Docs)</a>
How to create Azure Service Health alerts for Azure Virtual Desktop service issues, health advisories and planned maintenance.</li>
</ul>

<h3 id="network">Network</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/network-connectivity">Network connectivity in Azure Virtual Desktop (Microsoft Docs)</a><br />
Explains how RDP Shortpath, reverse connect transport and the AVD Gateway work together, with guidance for optimizing network paths.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/rdp-shortpath">RDP Shortpath for Azure Virtual Desktop (Microsoft Docs)</a><br />
How to enable direct UDP-based connectivity between clients and session hosts to reduce latency and improve session quality.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/private-link-overview">Private Link for Azure Virtual Desktop (Microsoft Docs)</a><br />
Overview of using Azure Private Link to route AVD control plane and session traffic over private networks, removing the need for public internet exposure.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/private-link-setup">Set up Private Link with Azure Virtual Desktop (Microsoft Docs)</a><br />
Step-by-step guide to creating private endpoints for the AVD feed, connection and global discovery, including the private DNS zones required for name resolution.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/private-link/private-endpoint-dns">Azure Private Endpoint private DNS zone values (Microsoft Docs)</a><br />
Reference of the recommended private DNS zone names for Azure services that support private endpoints, including the <code class="language-plaintext highlighter-rouge">privatelink.wvd.microsoft.com</code> and <code class="language-plaintext highlighter-rouge">privatelink-global.wvd.microsoft.com</code> zones used by Azure Virtual Desktop.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/required-fqdn-endpoint">Required FQDNs and endpoints for Azure Virtual Desktop (Microsoft Docs)</a><br />
List of FQDNs and endpoints that session hosts and clients must be able to reach for Azure Virtual Desktop to deploy and connect, grouped by session host virtual machines and end user devices.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/check-access-validate-required-fqdn-endpoint">Check access to required FQDNs and endpoints for Azure Virtual Desktop (Microsoft Docs)</a><br />
How to run the Azure Virtual Desktop Agent URL Tool on a session host to validate that all required FQDNs and endpoints are reachable.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/firewall/protect-azure-virtual-desktop">Use Azure Firewall to protect Azure Virtual Desktop (Microsoft Docs)</a><br />
How to filter session host outbound traffic with Azure Firewall using the <code class="language-plaintext highlighter-rouge">WindowsVirtualDesktop</code> FQDN tag and service tag, including a sample policy from the RDS-Templates repository.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-network/service-tags-overview">Azure service tags overview (Microsoft Docs)</a><br />
How service tags group Azure service IP ranges so they can be used in network security group rules, Azure Firewall and user-defined routes instead of maintaining IP lists manually.</li>
  <li><a href="https://learn.microsoft.com/en-us/intune/fundamentals/endpoints">Network endpoints for Microsoft Intune (Microsoft Docs)</a><br />
Consolidated list of IP addresses, FQDNs and ports that Intune-managed devices need through firewalls and proxies, relevant when managing AVD session hosts and Cloud PCs with Intune.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-365/enterprise/requirements-network">Network requirements for Windows 365 (Microsoft Docs)</a><br />
Virtual network, DNS, service URL and port requirements for provisioning and connecting to Windows 365 Cloud PCs on a customer-managed Azure network.</li>
  <li><a href="https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges">Microsoft 365 URLs and IP address ranges (Microsoft Docs)</a><br />
Authoritative list of Microsoft 365 endpoints, including Microsoft Entra ID and Office 365, that AVD session hosts and clients often need to reach in restricted networks.</li>
</ul>

<h3 id="architecture-and-best-practices">Architecture and Best Practices</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/azure-virtual-desktop/enterprise-scale-landing-zone">Azure Virtual Desktop Landing Zone Accelerator (Microsoft Docs)</a><br />
Enterprise-scale reference implementation for Azure Virtual Desktop following the Cloud Adoption Framework landing zone model, with Bicep and Terraform modules.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/azure-virtual-desktop/">Cloud Adoption Framework for Azure Virtual Desktop (Microsoft Docs)</a><br />
Strategic and technical guidance for adopting AVD across strategy, planning, readiness, migration and governance phases.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/well-architected/azure-virtual-desktop/">Azure Well-Architected Framework for Azure Virtual Desktop (Microsoft Docs)</a><br />
Guidance aligned with the five pillars of the Well-Architected Framework applied specifically to AVD deployments.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/architecture/example-scenario/wvd/windows-virtual-desktop">Azure Virtual Desktop reference architecture (Azure Architecture Center)</a><br />
Reference architecture for a standard multi-session AVD deployment including networking, identity and storage components.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/architecture/example-scenario/wvd/azure-virtual-desktop-multi-region-bcdr">Multi-region BCDR for Azure Virtual Desktop (Azure Architecture Center)</a><br />
Architecture for deploying AVD across multiple Azure regions to meet business continuity and disaster recovery requirements.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/set-up-golden-image">Image lifecycle management for Azure Virtual Desktop (Microsoft Docs)</a><br />
Guidance on building and maintaining golden images (session host templates) using Azure Compute Gallery and Azure Image Builder.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-machines/image-builder-overview">Azure Image Builder overview (Microsoft Docs)</a><br />
Overview of the Azure Image Builder service used to automate the creation and distribution of custom AVD session host images.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/rbac">RBAC for Azure Virtual Desktop (Microsoft Docs)</a><br />
Overview of built-in roles and how to delegate management tasks across operations, helpdesk and infrastructure teams in AVD.</li>
</ul>

<h3 id="github-repositories">GitHub Repositories</h3>

<ul>
  <li><a href="https://github.com/Azure/avdaccelerator">AVD Accelerator (GitHub)</a><br />
Official Microsoft repository with Bicep and Terraform reference implementations for deploying AVD following the enterprise-scale landing zone pattern.</li>
  <li><a href="https://github.com/Azure/RDS-Templates">RDS-Templates (GitHub)</a><br />
Official Microsoft repository containing ARM templates and PowerShell scripts for host pool creation, session host provisioning and application group management.</li>
</ul>

<hr />

<h2 id="third-party">Third Party</h2>

<p><em>Independent vendors offering management, testing, assessment and access solutions for Azure Virtual Desktop environments.</em></p>

<h3 id="management-platforms">Management Platforms</h3>

<p><em>Software commonly used to manage, automate and optimize Azure Virtual Desktop infrastructure.</em></p>

<h4 id="nerdio">Nerdio</h4>

<ul>
  <li><a href="https://getnerdio.com/nerdio-manager/enterprise/">Nerdio Manager for Enterprise</a>
Enterprise AVD management platform for automating host pool sizing, image management, cost optimization and session lifecycle from a single console.</li>
  <li><a href="https://getnerdio.com/resources/">Nerdio Resource Hub</a>
Official Nerdio resources covering deployment, automation and day-to-day operations.</li>
  <li><a href="https://getnerdio.com/cost-estimator/">Nerdio Cost Estimator</a><br />
Tool to estimate compute cost savings achieved by adopting Nerdio Manager’s autoscale and scheduling features versus managing AVD manually.</li>
  <li><a href="https://getnerdio.com/azure-local/">Nerdio - AVD for Azure Local</a>
Nerdio overview of Azure Local capabilities and how Nerdio Manager supports Azure Virtual Desktop on hybrid infrastructure.</li>
  <li><a href="https://getnerdio.com/avd-hybrid/">Nerdio - Azure Virtual Desktop for Hybrid Environments</a>
Nerdio overview for managing Azure Virtual Desktop session hosts across hybrid infrastructure.</li>
</ul>

<h4 id="controlup">ControlUp</h4>

<ul>
  <li><a href="https://www.controlup.com/solutions/azure-virtual-desktop/">ControlUp - Azure Virtual Desktop</a><br />
ControlUp landing page for AVD, covering real-time session analytics, automated remediation and user experience monitoring.</li>
  <li><a href="https://www.controlup.com/platform/">ControlUp - Platform Overview</a><br />
Overview of ControlUp’s agent-based telemetry, script-based automation and multi-tenant management capabilities for AVD and hybrid EUC environments.</li>
</ul>

<h4 id="hydra-by-login-vsi">Hydra by Login VSI</h4>

<ul>
  <li><a href="https://euc.loginvsi.com/hydra-by-login-vsi">Hydra - Landing Page</a><br />
Hydra product overview from Login VSI, covering image lifecycle management and AVD host pool automation.</li>
  <li><a href="https://blog.itprocloud.de/AVD-Hydra-For-Azure-Stack-HCI-Deplyoment-Management/">Hydra - Imaging, Rollout and Management for Azure Virtual Desktop</a><br />
Article by Marcel Meurer on configuring Hydra for automated image management and rollout in AVD and Azure Local environments.</li>
</ul>

<h4 id="citrix">Citrix</h4>

<ul>
  <li><a href="https://docs.citrix.com/en-us/citrix-daas-azure.html">Citrix DaaS for Azure</a><br />
Citrix Desktop as a Service offering on Azure, providing Citrix application delivery and management capabilities on top of Azure compute infrastructure.</li>
  <li><a href="https://docs.citrix.com/en-us/citrix-daas">Citrix DaaS Documentation</a><br />
Complete Citrix DaaS documentation covering site configuration, machine catalog creation and Citrix policy management.</li>
  <li><a href="https://docs.citrix.com/en-us/citrix-virtual-apps-desktops/2507-ltsr/install-configure/connections/connection-azure-local">Citrix Virtual Apps and Desktops - Connecting Azure Local (Docs)</a><br />
Guide on using Citrix Virtual Apps and Desktops with Azure Local infrastructure as the hosting layer.</li>
</ul>

<h3 id="testing-and-assessment">Testing and Assessment</h3>

<p><em>Tools used to test application compatibility, simulate user load and measure session host performance.</em></p>

<h4 id="login-vsi">Login VSI</h4>

<ul>
  <li><a href="https://www.loginvsi.com/solutions/azure-virtual-desktop/">Login VSI - Load Testing for Virtual Desktops</a><br />
Login VSI landing page for AVD, covering how to benchmark session host capacity and validate user density before production rollout.</li>
  <li><a href="https://www.loginvsi.com/knowledge-base/">Login VSI - Knowledge Base</a><br />
Documentation hub for Login VSI products including Load Generator and VDI Benchmark.</li>
</ul>

<h4 id="lakeside-systrack">Lakeside SysTrack</h4>

<ul>
  <li><a href="https://www.lakesidesoftware.com/solution-briefs/right-size-virtual-desktops-azure-systrack/">Lakeside SysTrack - Azure Virtual Desktop</a><br />
SysTrack landing page for AVD, covering digital experience monitoring, right-sizing and migration readiness assessments for moving workloads to AVD.</li>
  <li><a href="https://www.lakesidesoftware.com/blog/what-is-digital-experience-monitoring/">Lakeside SysTrack - Digital Experience Monitoring</a><br />
How Lakeside collects continuous endpoint telemetry to measure user experience quality inside AVD sessions and identify degradation before it affects users.</li>
</ul>

<h4 id="rimo3">Rimo3</h4>

<ul>
  <li><a href="https://www.rimo3.com/citrix-to-avd-migration">Rimo3 - Application Compatibility Testing for AVD</a><br />
Rimo3 landing page for automated application compatibility and regression testing in AVD and Windows 365 migration projects.</li>
  <li><a href="https://www.rimo3.com/platform/">Rimo3 - Platform Overview</a><br />
How Rimo3 automates application testing at scale, reducing manual effort and risk for large application portfolios migrating to AVD.</li>
</ul>

<h3 id="thin-clients">Thin Clients</h3>

<p><em>Hardware and software vendors offering purpose-built thin client endpoints for accessing Azure Virtual Desktop.</em></p>

<h4 id="igel">IGEL</h4>

<ul>
  <li><a href="https://www.igel.com/microsoft/">IGEL - Azure Virtual Desktop</a><br />
IGEL landing page for AVD, covering how IGEL OS provides a secure and managed thin client endpoint for accessing AVD sessions with minimal local attack surface.</li>
  <li><a href="https://www.igel.de/learn-and-connect/community/">IGEL Community</a><br />
Community hub for IGEL users and administrators with AVD-specific discussions, how-to guides and troubleshooting resources.</li>
  <li><a href="https://www.igel.de/ready/">IGEL Ready Program</a><br />
Partner ecosystem listing hardware and peripherals certified to work with IGEL OS in AVD environments.</li>
</ul>

<h4 id="10zig">10ZiG</h4>

<ul>
  <li><a href="https://www.10zig.com/solutions/azure-virtual-desktop">10ZiG - Azure Virtual Desktop</a><br />
10ZiG landing page for AVD, covering thin client hardware and 10ZiG NOS purpose-built for accessing Azure Virtual Desktop environments.</li>
  <li><a href="https://www.10zig.com/en/product/solutions/10zig-manager/">10ZiG Manager - Central Management</a><br />
Overview of 10ZiG’s endpoint management platform for deploying and maintaining 10ZiG thin clients at scale in AVD deployments.</li>
</ul>

<hr />

<h2 id="community">Community</h2>

<p><em>Resources that do not come from Microsoft or the vendors listed in the Third Party section.</em></p>

<h3 id="blog">Blog</h3>

<p><em>To avoid an excessive list, only entire blogs are referenced, not individual posts.</em></p>

<ul>
  <li><a href="https://schmitt-nieto.com/tags/#azure-virtual-desktop">schmitt-nieto.com</a><br />
Blog with hands-on content about AVD implementation and management.</li>
  <li><a href="https://www.gettothe.cloud/">gettothe.cloud</a><br />
Blog by <a href="https://www.linkedin.com/in/aterneuzen">Alex ter Neuzen</a> focused mainly on AVD, Windows Cloud and IaC.</li>
  <li><a href="https://avdcommunity.com/category/newsletter/">AVD Community Newsletter</a>
Community-run newsletter curated mainly by Aresh Sarkari, with recurring AVD links, Microsoft announcements and contributions from authors such as Johan Vanneuville, Marcel Meurer and Travis Roberts.</li>
  <li><a href="https://www.linkedin.com/newsletters/windows365-avd-weekly-news-7409581308168806400/">Windows365, AVD Weekly News</a>
LinkedIn newsletter by <a href="https://www.linkedin.com/in/michelroth/">Michel Roth</a> collecting weekly Windows 365, Azure Virtual Desktop and endpoint management news from Microsoft and community authors.</li>
  <li><a href="https://askaresh.com/">AskAresh</a>
Blog by Aresh Sarkari with hands-on AVD, Terraform, automation and end-user computing content frequently referenced by the AVD Community Newsletter.</li>
  <li><a href="https://johanvanneuville.com/category/avd/">johanvanneuville.com</a>
Blog by MVP <a href="https://www.linkedin.com/in/johan-vanneuville-64142b4b/">Johan Vanneuville</a> covering Azure Virtual Desktop, Windows 365, Nerdio and cloud endpoint security.</li>
  <li><a href="https://christiaanbrinkhoff.com/">christiaanbrinkhoff.com</a>
Blog by <a href="https://www.linkedin.com/in/christiaanbrinkhoff/">Christiaan Brinkhoff</a>, Senior Director of Product R&amp;D at Nerdio and former Microsoft Windows Cloud product leader, featuring cloud endpoint strategy, AVD, Windows 365 and community content.</li>
  <li><a href="https://blog.itprocloud.de/">blog.itprocloud.de</a><br />
Blog by <a href="https://www.linkedin.com/in/marcelmeurer/">Marcel Meurer</a> featuring AVD automation tools, Hydra technical deep dives and host pool management patterns.</li>
  <li><a href="https://www.ciraltos.com/">ciraltos.com</a>
Blog by Microsoft MVP Travis Roberts with practical AVD networking, regional host pool, Windows 365 and Azure infrastructure walkthroughs.</li>
  <li><a href="https://avdpunks.com/">avdpunks.com</a><br />
Community blog by a group of AVD specialists covering a wide range of topics from initial deployment to advanced optimization and security.</li>
  <li><a href="https://rozemuller.com/">rozemuller.com</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/sanderrozemuller/">Sander Rozemuller</a> focused on Azure Virtual Desktop automation using the REST API, PowerShell and infrastructure-as-code.</li>
  <li><a href="https://www.imab.dk/">imab.dk</a>
Blog by <a href="https://www.linkedin.com/in/mwbengtsson/">Martin Bengtsson</a> with practical Intune, Microsoft 365 and PowerShell content focused on implementation and scripted automation.</li>
  <li><a href="https://andrewstaylor.com/">andrewstaylor.com</a>
Blog by Andrew Taylor covering Intune, FSLogix configuration without Group Policy, application packaging, AVD automation and EUC tooling.</li>
  <li><a href="https://eskonr.com/">All about Endpoint Management</a>
Blog by Eswar Koneti covering Intune, Configuration Manager, Conditional Access, Windows Update for Business and AVD or Windows 365 operational scenarios.</li>
  <li><a href="https://petervanderwoude.nl/">All about Microsoft Intune</a>
Blog by Peter van der Woude covering Intune, Windows 365, Cloud PCs, Conditional Access and endpoint configuration.</li>
  <li><a href="https://blog.hametbenoit.info/">Benoit Hamet</a>
Blog by Benoit Hamet covering Microsoft Intune, Azure Virtual Desktop clipboard redirection and Microsoft 365 administration.</li>
  <li><a href="https://call4cloud.nl/">Call4Cloud</a>
Blog by Rudy Ooms focused on Intune internals, Windows Autopilot, Endpoint Privilege Management and endpoint troubleshooting.</li>
  <li><a href="https://mikemdm.de/">mikemdm.de</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/michael-meier-ba3b72210/">Michael Meier</a> covering AVD and Azure Local labs and real-world implementations.</li>
  <li><a href="https://joeyverlinden.com/">joeyverlinden.com</a><br />
Blog by <a href="https://www.linkedin.com/in/joeyverlinden/">Joey Verlinden</a> featuring AVD implementation guides, FSLogix tips and automation scripts.</li>
  <li><a href="https://msendpointmgr.com/">msendpointmgr.com</a><br />
Multi-author blog covering endpoint management including AVD image management, Intune integration and application packaging for virtual environments.</li>
  <li><a href="https://michaelsendpoint.com/">michaelsendpoint.com</a><br />
Blog by <a href="https://www.linkedin.com/in/michaelsendpoint/">Michael Frank</a> with step-by-step Microsoft guides covering Intune, Microsoft Entra ID, Windows 365, security and PowerShell automation relevant to endpoint and AVD management.</li>
  <li><a href="https://blog.rjz.de/observability_for_avd/">Observability for Azure Virtual Desktop</a><br />
Blog post by <a href="https://www.linkedin.com/in/ruben-zimmermann-9908081a/">Ruben Zimmermann</a> covering Azure Virtual Desktop observability with SquaredUp Cloud, Log Analytics and focused KQL queries for VM state, agent health, performance metrics, user connections, configuration changes and session usage.</li>
</ul>

<h3 id="linkedin">LinkedIn</h3>

<p><em>Most day-to-day news on Azure Virtual Desktop arrives first on LinkedIn. Here are relevant community profiles.</em></p>

<ul>
  <li><a href="https://www.linkedin.com/in/christiaanbrinkhoff/">Christiaan Brinkhoff</a><br />
Senior Director of Product R&amp;D at Nerdio and former Microsoft Windows Cloud product leader who publishes cloud endpoint strategy, AVD, Windows 365 and community content.</li>
  <li><a href="https://www.linkedin.com/in/ryanmangan01/">Ryan Mangan</a><br />
UK-based MVP who publishes detailed AVD content covering new features, optimization techniques and real-world troubleshooting cases.</li>
  <li><a href="https://www.linkedin.com/in/marcelmeurer/">Marcel Meurer</a><br />
Creator of WVD Admin and Hydra who shares AVD tooling updates, automation patterns and community resources.</li>
  <li><a href="https://www.linkedin.com/in/sanderrozemuller/">Sander Rozemuller</a><br />
Dutch MVP publishing AVD automation content focused on REST API usage, Bicep and infrastructure-as-code approaches.</li>
  <li><a href="https://www.linkedin.com/in/sdingemanse/">Stefan Dingemanse</a><br />
Netherlands-based MVP and AVD specialist who publishes practical content covering networking, identity and deployment automation.</li>
  <li><a href="https://www.linkedin.com/in/tomhickling/">Tom Hickling</a><br />
Microsoft Senior Product Manager for Azure Virtual Desktop Engineering covering enterprise deployments, service resilience and best practices.</li>
  <li><a href="https://www.linkedin.com/in/johan-vanneuville-64142b4b/">Johan Vanneuville</a>
Windows and Devices MVP, Nerdio NVP and co-author of <em>Securing Cloud PCs and Azure Virtual Desktop</em> who publishes practical AVD and Windows 365 security guidance.</li>
  <li><a href="https://www.linkedin.com/in/thomasmarcussen/">Thomas Marcussen</a>
Microsoft MVP and early AVD Community contributor involved in newsletter publishing and broader Microsoft endpoint community work.</li>
  <li><a href="https://www.linkedin.com/in/shabaz-darr-900b8361/">Shabaz Darr</a>
Microsoft MVP and I Am IT Geek creator publishing Azure Virtual Desktop, Windows 365, Nerdio and Microsoft cloud architecture content.</li>
  <li><a href="https://www.linkedin.com/in/andrew-taylor-41707916/">Andrew Taylor</a>
Microsoft MVP publishing Intune automation, AVD deployment, FSLogix configuration and endpoint management tooling.</li>
  <li><a href="https://www.linkedin.com/in/joeyverlinden/">Joey Verlinden</a>
AVD and Intune community contributor publishing implementation guides, FSLogix tips, automation scripts and Envoy user environment management updates.</li>
  <li><a href="https://www.linkedin.com/in/peterwoude/">Peter van der Woude</a>
Microsoft MVP focused on Microsoft Intune, Windows 365, Conditional Access and modern endpoint management.</li>
  <li><a href="https://www.linkedin.com/in/benoithamet/">Benoit Hamet</a>
Microsoft cloud specialist publishing Intune, Azure Virtual Desktop, Microsoft 365 and security configuration content.</li>
  <li><a href="https://www.linkedin.com/in/rudyooms/">Rudy Ooms</a>
Microsoft MVP focused on Intune internals, Windows Autopilot, Endpoint Privilege Management and endpoint troubleshooting.</li>
  <li><a href="https://www.linkedin.com/in/basvankaamnl/">Bas van Kaam</a><br />
End-user computing specialist and author who regularly shares community updates, book insights and technical deep dives.</li>
</ul>

<h3 id="youtube">YouTube</h3>

<p><em>Channels with recurring Azure Virtual Desktop, Windows 365, Windows Cloud and related Azure infrastructure content.</em></p>

<ul>
  <li><a href="https://www.youtube.com/c/AzureAcademy">Azure Academy</a>
Channel by Dean Cefola with Azure Virtual Desktop, Windows 365, Azure infrastructure and Microsoft cloud operations walkthroughs.</li>
  <li><a href="https://www.youtube.com/@MSFTMechanics">Microsoft Mechanics</a>
Official Microsoft channel with demos and product walkthroughs for Azure Virtual Desktop, Windows 365, Windows App and Microsoft 365 services.</li>
  <li><a href="https://www.youtube.com/@IamITGeek">I Am IT Geek</a>
Channel by Microsoft MVP Shabaz Darr covering Azure Virtual Desktop, Windows 365, Nerdio, Azure security and Microsoft cloud architecture.</li>
  <li><a href="https://www.youtube.com/@NTFAQGuy">John Savill’s Technical Training</a>
Technical training channel by John Savill covering Azure platform services, identity, networking and selected Azure Virtual Desktop scenarios.</li>
  <li><a href="https://www.youtube.com/@Ciraltos">Travis Roberts</a>
Channel by Microsoft MVP Travis Roberts with Azure, AVD, Windows 365 and infrastructure tutorials often paired with Ciraltos blog posts.</li>
  <li><a href="https://www.youtube.com/@bearded365guy">Jonathan Edwards</a>
Channel covering Microsoft 365, Intune, Windows 365, security and endpoint management topics relevant to AVD operations.</li>
  <li><a href="https://www.youtube.com/@virtualmanc">Neil McLoughlin</a>
Channel by Neil McLoughlin covering Azure Virtual Desktop, Windows 365, Nerdio and EUC architecture topics.</li>
  <li><a href="https://www.youtube.com/@SusanthSutheesh">Susanth Sutheesh</a>
Channel covering Azure Virtual Desktop, Windows 365, Intune, Microsoft 365 and endpoint administration.</li>
  <li><a href="https://www.youtube.com/@mwcloud">Mike in the Cloud</a>
Channel covering Microsoft cloud administration, Azure Virtual Desktop, Windows 365 and endpoint management.</li>
</ul>

<h3 id="github-repos-and-tools">GitHub Repos and Tools</h3>

<ul>
  <li><a href="https://github.com/Azure/avdaccelerator">AVD Accelerator (GitHub)</a><br />
Official Microsoft repository with Bicep and Terraform code for deploying AVD following the enterprise-scale landing zone pattern.</li>
  <li><a href="https://github.com/Azure/RDS-Templates">RDS-Templates (GitHub)</a><br />
Official Microsoft repository with ARM templates and PowerShell scripts for host pool creation, session host registration and application group management.</li>
  <li><a href="https://github.com/GetToThe-Cloud/Website">GetToThe-Cloud - Website (GitHub)</a><br />
Source repository for the GetToThe.Cloud website, including AVD-related Terraform and deployment scripts used across the site.</li>
  <li><a href="https://github.com/srozemuller">Sander Rozemuller - GitHub</a><br />
GitHub profile of Sander Rozemuller (MVP) with scripts and modules for managing Azure Virtual Desktop through the REST API and PowerShell, covering host pools, session hosts and application groups.</li>
  <li><a href="https://github.com/MarcelMeurer/WVD-Hydra">Marcel Meurer - WVD-Hydra (GitHub)</a><br />
Open-source AVD management tool by Marcel Meurer covering host pool automation, image management and session control, predecessor to the commercial Hydra product.</li>
  <li><a href="https://intunedrivemapping.azurewebsites.net/DriveMapping">Intune Drive Mapping Generator</a><br />
Web generator by Nicola Suter for building Intune PowerShell scripts that map network drives on Intune-managed Windows devices. The <a href="https://github.com/nicolonsky/IntuneDriveMapping">GitHub repository</a> includes source code, documentation and examples for migrating existing Group Policy drive mappings or creating mappings from scratch.</li>
  <li><a href="https://github.com/j0eyv/Envoy">Envoy (GitHub)</a>
Open-source lightweight user environment manager by Joey Verlinden for Intune-managed Windows devices, useful in AVD and Windows 365 environments that need logon-time drive mappings, printer mappings, registry settings, file actions and shortcuts targeted by Microsoft Entra ID group membership.</li>
  <li><a href="https://github.com/call4cloud-code/Intunewin-Downloader-Public">Intunewin Downloader (GitHub)</a><br />
Windows troubleshooting tool by Rudy Ooms (Call4Cloud) that downloads and decrypts Win32 app packages and remediation scripts a device is already assigned in Microsoft Intune, without needing Graph API permissions or an app registration. Useful for inspecting and validating app delivery on AVD and Windows 365 session hosts from within the existing Intune enrollment context.</li>
  <li><a href="https://www.linkedin.com/posts/drazen-nikolic-816906142_avd-microsoft-azurevirtualdesktop-ugcPost-7364022385827557376-NEle">AVD - FSLogix Profile Status (Tool)</a><br />
After the deprecation of FXTray, it became difficult to check the status of FSLogix profiles. With this PowerShell script, it is once again possible to verify profile status in a simple and centralized way. The <a href="https://github.com/DrazenNikolic/FSLogix-Profile-Status">GitHub repository</a> contains the Profile Monitor for FSLogix source and releases.</li>
  <li><a href="https://github.com/DrazenNikolic/Profile-Toolkit-for-FSLogix/releases">Profile Toolkit for FSLogix (GitHub)</a><br />
GUI toolkit by Drazen Nikolic for enterprise FSLogix management, built with Electron and React. It covers real-time profile monitoring, profile migration, diagnostics, best practice assessment and advanced VDI operations, extending his earlier FSLogix Profile Status script into a full desktop application.</li>
  <li><a href="https://github.com/jonathan-vella/azure-local-sizing-guides">AVD Sizing Guides (GitHub)</a><br />
Sizing guides for AVD and related services on Azure Local, maintained by Jonathan Vella (Microsoft Senior CSA).</li>
</ul>

<h3 id="chats-and-channels">Chats and Channels</h3>

<ul>
  <li><a href="https://techcommunity.microsoft.com/category/AzureVirtualDesktop">Azure Virtual Desktop Tech Community (Microsoft)</a><br />
Official Microsoft Tech Community space for Azure Virtual Desktop announcements, Q&amp;A and community discussions moderated by the product team.</li>
  <li><a href="https://avdcommunity.com/user-groups/">AVD Community User Groups</a>
Community hub for Azure Virtual Desktop user groups and newsletter-driven community updates.</li>
</ul>

<h3 id="trainings">Trainings</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/credentials/certifications/azure-virtual-desktop-specialty/">AZ-140: Configuring and Operating Azure Virtual Desktop (Microsoft Learn)</a><br />
Official Microsoft certification exam covering AVD deployment, configuration, access management, monitoring and performance optimization.</li>
  <li><a href="https://learn.microsoft.com/en-us/training/paths/m365-wvd/">Deliver remote desktops and apps from Azure with Azure Virtual Desktop (Microsoft Learn)</a><br />
Free official Microsoft Learn path covering the core concepts and deployment tasks for Azure Virtual Desktop.</li>
  <li><a href="https://learn.microsoft.com/en-us/training/modules/m365-wvd-intro/">Introduction to Azure Virtual Desktop (Microsoft Learn)</a><br />
Introductory module explaining the AVD service model, key components and use cases for organizations considering adoption.</li>
  <li><a href="https://learn.microsoft.com/en-us/training/modules/create-configure-host-pools-session-hosts/">Create and configure host pools and session hosts for Azure Virtual Desktop (Microsoft Learn)</a>
Hands-on module covering host pool assignment, session hosts, RDP properties and Windows client licensing for AVD.</li>
</ul>

<h3 id="events">Events</h3>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Description</th>
      <th>Price</th>
      <th>Remote</th>
      <th>Date</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><del><a href="https://www.controlup.com/avd-techfest-2025/">AVD Tech Fest 2025 - Berlin (Germany)</a></del></td>
      <td>Community-driven EUC event focused on Azure Virtual Desktop, Windows 365, Citrix, Omnissa and digital workspace solutions.</td>
      <td><del>99 EUR</del></td>
      <td><del>No</del></td>
      <td><del>September 10-11, 2025</del></td>
    </tr>
    <tr>
      <td><del><a href="https://worldofeuc.org/EUCWorld2026_Virtual">EUC World Virtual 2026</a></del></td>
      <td>Vendor-neutral virtual EUC conference with sessions on digital workspaces, Intune, Nerdio Manager and desktop modernization.</td>
      <td><del>Not listed</del></td>
      <td><del>Yes</del></td>
      <td><del>April 29, 2026</del></td>
    </tr>
    <tr>
      <td><del><a href="https://www.nerdiocon.com/">NerdioCon 2026 - Palm Springs (USA)</a></del></td>
      <td>Nerdio conference focused on Microsoft cloud endpoint management, Azure Virtual Desktop, Windows 365, Intune and AI-driven operations.</td>
      <td><del>Not listed</del></td>
      <td><del>No</del></td>
      <td><del>May 4-6, 2026</del></td>
    </tr>
    <tr>
      <td><a href="https://getnerdio.com/events/">Windows Cloud Workshop series - multiple cities</a></td>
      <td>Hands-on Nerdio and Microsoft workshop series for Azure Virtual Desktop, Windows 365, cloud endpoint strategy and guided lab practice.</td>
      <td>Not listed</td>
      <td>No</td>
      <td>May 13 - June 11, 2026</td>
    </tr>
    <tr>
      <td><a href="https://worldofeuc.org/EUCWorld2026">EUC World 2026 - Milwaukee (USA)</a></td>
      <td>Community-driven EUC conference covering virtual desktops, DaaS, Windows in the Cloud, app delivery and digital workspace operations.</td>
      <td>$250-$400, depending on registration date</td>
      <td>No</td>
      <td>September 29 - October 1, 2026</td>
    </tr>
    <tr>
      <td><a href="https://ignite.microsoft.com/en-US/home">Microsoft Ignite 2026 - San Francisco (USA)</a></td>
      <td>Microsoft flagship conference for Azure, Windows, Microsoft 365 and security, with expected Windows Cloud, Azure Virtual Desktop and Windows 365 announcements.</td>
      <td>Not listed</td>
      <td>To be confirmed</td>
      <td>November 17-20, 2026</td>
    </tr>
  </tbody>
</table>

<!-- AWESOMEAZUREVIRTUALDESKTOP:END -->]]></content><author><name>Cristian Schmitt Nieto</name></author><category term="Blog" /><category term="Github" /><category term="Azure Virtual Desktop" /><category term="Windows 365" /><summary type="html"><![CDATA[Curated catalog of Azure Virtual Desktop and Windows 365 with official, vendor and community resources updated regularly.]]></summary></entry><entry><title type="html">Azure Local: Terraform Deployment</title><link href="https://schmitt-nieto.com/blog/azure-local-terraform/" rel="alternate" type="text/html" title="Azure Local: Terraform Deployment" /><published>2026-04-17T00:00:00+02:00</published><updated>2026-04-17T00:00:00+02:00</updated><id>https://schmitt-nieto.com/blog/azure-local-terraform</id><content type="html" xml:base="https://schmitt-nieto.com/blog/azure-local-terraform/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>If you have been following this series, you already know how I built my Azure Local demolab step by step: preparing the Hyper-V host, configuring the domain controller, registering the node with Azure Arc and then walking through the portal deployment. That workflow works, but it is entirely manual. Every time I tear down and rebuild the lab I repeat the same sequence of clicks and commands and every time I do that I risk a small configuration drift.</p>

<p>A few months ago I decided to change that. The goal was straightforward: replace the portal deployment path with a fully automated Terraform run that I could trigger from a pipeline with a service account and that I could later reuse for AVD, AKS and other workloads on top of Azure Local. Less clicking, more repeatable infrastructure.</p>

<p>Getting there turned out to be more work than I expected. The <a href="https://github.com/Azure/terraform-azurerm-avm-res-azurestackhci-cluster">Azure Verified Module (AVM) for Azure Local</a> is a good starting point, but it was written against a specific point in time and the Azure Local deployment API has moved since then. From the end of 2025 onward, several things changed: resource provider behavior, required role assignments and the API version that the Azure control plane actually accepts. When I first tried to apply the module against my lab, I got a series of failures that took real investigation to understand.</p>

<p>This article covers what I built, what broke, how I fixed it and how the deployment now flows end to end. I will also explain where I plan to take the repository from here.</p>

<h2 id="the-azshci-repository">The AzSHCI Repository</h2>

<p>All of the automation lives in my <a href="https://github.com/schmittnieto/AzSHCI">AzSHCI repository</a>.</p>

<p><a href="https://github.com/schmittnieto/AzSHCI"><img src="https://badgen.net/https/raw.githubusercontent.com/schmittnieto/AzSHCI/refs/heads/main/terraform/lastdeployment.json?cache=300" /></a></p>

<p>It has two parallel paths that work together:</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">scripts/01Lab/</code></strong>: PowerShell scripts that handle everything from Azure prerequisites through Hyper-V infrastructure setup, domain controller configuration and Arc registration. These run before Terraform comes into the picture.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">terraform/</code></strong>: A root Terraform configuration that calls a local fork of the AVM module. The fork carries the fixes and additions that were needed to make the deployment work against the current Azure API.</li>
</ul>

<p>The long-term vision for the repository is a single codebase that can deploy not just the Azure Local cluster but also the workloads on top of it: AVD host pools, AKS clusters and potentially other services. The Terraform path is designed from the start to be consumed from a CI/CD pipeline using a service principal, so every credential is handled through a Key Vault and no secrets live in the repository.</p>

<h2 id="prerequisites-the-first-script">Prerequisites: The First Script</h2>

<p>Before any Terraform runs, Azure needs to be in the right state. The script <code class="language-plaintext highlighter-rouge">scripts/01Lab/00_AzurePreRequisites.ps1</code> handles that in a single, interactive run.</p>

<p>What it does:</p>

<ol>
  <li>Checks for and installs the required Az PowerShell modules (<code class="language-plaintext highlighter-rouge">Az.Accounts</code>, <code class="language-plaintext highlighter-rouge">Az.Resources</code>).</li>
  <li>Verifies your Azure session and prompts a device code login if no active session is found.</li>
  <li>Lets you select a subscription interactively.</li>
  <li>Lets you choose an existing resource group or create a new one.</li>
  <li>Assigns the required RBAC roles to a user or to a newly created service principal.</li>
  <li>Registers all required resource providers.</li>
</ol>

<p>The roles it assigns fall into two scopes. At resource group scope: <code class="language-plaintext highlighter-rouge">Azure Connected Machine Onboarding</code>, <code class="language-plaintext highlighter-rouge">Azure Connected Machine Resource Administrator</code>, <code class="language-plaintext highlighter-rouge">Key Vault Data Access Administrator</code>, <code class="language-plaintext highlighter-rouge">Key Vault Secrets Officer</code>, <code class="language-plaintext highlighter-rouge">Key Vault Contributor</code> and <code class="language-plaintext highlighter-rouge">Storage Account Contributor</code>. At subscription scope: <code class="language-plaintext highlighter-rouge">Azure Stack HCI Administrator</code> and <code class="language-plaintext highlighter-rouge">Reader</code>.</p>

<p>The resource providers it registers cover the full Azure Local stack: <code class="language-plaintext highlighter-rouge">Microsoft.HybridCompute</code>, <code class="language-plaintext highlighter-rouge">Microsoft.AzureStackHCI</code>, <code class="language-plaintext highlighter-rouge">Microsoft.Kubernetes</code>, <code class="language-plaintext highlighter-rouge">Microsoft.KubernetesConfiguration</code>, <code class="language-plaintext highlighter-rouge">Microsoft.ExtendedLocation</code>, <code class="language-plaintext highlighter-rouge">Microsoft.ResourceConnector</code>, <code class="language-plaintext highlighter-rouge">Microsoft.HybridContainerService</code> and several others.</p>

<p>If you create a service principal through this script, it prints the connection details at the end. Those credentials go into your Terraform variables file and Key Vault reference and from that point the pipeline can run unattended. Here is a full run with sensitive values redacted:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Checking required Az modules...
Module 'Az.Accounts' is available.
Module 'Az.Resources' is available.
All required modules loaded.
Active session: admin@&lt;tenant&gt;.com on subscription 'Azure-Abonnement 1'.
Use this session? (Y/N): N
Starting device code login...
[Login to Azure] To sign in, use a web browser to open the page https://login.microsoft.com/device
and enter the code GAX*****QB to authenticate.

Authenticated to Azure.
Retrieving available subscriptions...

Select the subscription to use:
    0. Azure-Abonnement 1
Select subscription: 0
Using subscription 'Azure-Abonnement 1' (&lt;subscription-id&gt;).

Resource Group setup:
  1. Use an existing resource group
  2. Create a new resource group
Select option (1 or 2): 2

Recommended resource group name: 'rg-azlocal-lab'
Enter resource group name (press Enter to accept recommendation): rg-azlocal-demolab

Select the Azure region for the new resource group:
    0. westeurope
    1. northeurope
    2. eastus
    ...
Enter a list number or type a region name directly: 0
Creating resource group 'rg-azlocal-demolab' in 'westeurope'...
Resource group 'rg-azlocal-demolab' created.

Select how to assign the required Azure RBAC roles:
  1. Assign to an existing user account
  2. Create a new Service Principal and assign roles to it
Select option (1 or 2): 2

Recommended SPN name: 'sp-azlocal-lab'
Enter SPN display name (press Enter to accept recommendation): sp-azlocal-demolab
Creating app registration 'sp-azlocal-demolab'...
App registration created. AppId: &lt;app-id&gt;
Creating service principal...
Service principal created. ObjectId: &lt;object-id&gt;
Generating client secret (valid for 2 years)...
Client secret generated.
Waiting 20 seconds for the SPN to propagate before assigning roles...

Assigning resource group scoped roles to 'sp-azlocal-demolab'...
Assigned 'Azure Connected Machine Onboarding' at RG scope.
Assigned 'Azure Connected Machine Resource Administrator' at RG scope.
Assigned 'Key Vault Data Access Administrator' at RG scope.
Assigned 'Key Vault Secrets Officer' at RG scope.
Assigned 'Key Vault Contributor' at RG scope.
Assigned 'Storage Account Contributor' at RG scope.

Assigning subscription scoped roles to 'sp-azlocal-demolab'...
Assigned 'Azure Stack HCI Administrator' at subscription scope.
Assigned 'Reader' at subscription scope.

Checking and registering required resource providers...
Provider 'Microsoft.HybridCompute' is already registered.
Provider 'Microsoft.GuestConfiguration' is already registered.
Provider 'Microsoft.HybridConnectivity' is already registered.
Provider 'Microsoft.AzureStackHCI' is already registered.
Provider 'Microsoft.Kubernetes' is already registered.
Provider 'Microsoft.KubernetesConfiguration' is already registered.
Provider 'Microsoft.ExtendedLocation' is already registered.
Provider 'Microsoft.ResourceConnector' is already registered.
Provider 'Microsoft.HybridContainerService' is already registered.
Provider 'Microsoft.Attestation' is already registered.
Provider 'Microsoft.Storage' is already registered.
Provider 'Microsoft.KeyVault' is already registered.
Provider 'Microsoft.Insights' is already registered.

Azure prerequisites setup completed.

Summary:
  Subscription : Azure-Abonnement 1 (&lt;subscription-id&gt;)
  Resource Group: rg-azlocal-demolab (location: westeurope)
  Principal    : sp-azlocal-demolab

================================================================
  SERVICE PRINCIPAL CONNECTION DETAILS
  Save these values securely. The secret cannot be retrieved
  again after this session ends.
================================================================

  Display Name    : sp-azlocal-demolab
  Tenant ID       : &lt;tenant-id&gt;
  Subscription ID : &lt;subscription-id&gt;
  App ID          : &lt;app-id&gt;
  Client Secret   : &lt;client-secret&gt;
  Secret Expiry   : 2028-04-17

  IMPORTANT: Rotate this secret before it expires to avoid service disruptions.

  To connect with this SPN in PowerShell:

  $spnCredential = New-Object PSCredential(
      "&lt;app-id&gt;",
      (ConvertTo-SecureString "&lt;client-secret&gt;" -AsPlainText -Force))
  Connect-AzAccount -ServicePrincipal `
      -Tenant "&lt;tenant-id&gt;" `
      -Subscription "&lt;subscription-id&gt;" `
      -Credential $spnCredential

================================================================
</code></pre></div></div>

<h2 id="infrastructure-and-cluster-preparation">Infrastructure and Cluster Preparation</h2>

<p>With the Azure side ready, the next scripts prepare the local environment:</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">00_Infra_AzHCI.ps1</code></strong> builds the Hyper-V infrastructure: virtual switches, storage paths and the Azure Local node VM.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">01_DC.ps1</code></strong> sets up the domain controller that the cluster needs for Active Directory integration.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">02_Cluster.ps1</code></strong> performs the Arc registration of the node. After this script completes, the machine appears in Azure as an Arc-enabled server and is ready for the Terraform deployment step.</li>
</ul>

<h2 id="the-terraform-architecture">The Terraform Architecture</h2>

<p>The Terraform configuration is a thin root module that creates a few shared prerequisites and then calls the Azure Local cluster module. The shared prerequisites are:</p>

<ul>
  <li><strong>Key Vault</strong> with RBAC authorization enabled, used to store the deployment credentials.</li>
  <li><strong>Witness storage account</strong> for the cluster quorum.</li>
  <li>Required <strong>role assignments</strong> at resource group scope for the Arc machine identity and the Azure Stack HCI resource provider service principal.</li>
  <li><strong>Edge device registration</strong> (<code class="language-plaintext highlighter-rouge">Microsoft.AzureStackHCI/edgeDevices</code>) for the Arc node.</li>
</ul>

<p>The cluster module is a local fork of the AVM module. The fork is not a divergence for its own sake. It carries specific fixes that the upstream module did not have at the time of writing and I will describe those in the next section.</p>

<h3 id="staged-deployment">Staged deployment</h3>

<p>The deployment happens in two stages, controlled by a single variable:</p>

<p><strong>Stage 1 (<code class="language-plaintext highlighter-rouge">is_exported = false</code>)</strong>: Terraform creates the Key Vault, storage account, RBAC assignments and edge device registration, then submits <code class="language-plaintext highlighter-rouge">deploymentSettings</code> to Azure with <code class="language-plaintext highlighter-rouge">deploymentMode = Validate</code>. Azure runs a validation sequence that checks connectivity, Active Directory and node configuration. This takes roughly 10 to 30 minutes.</p>

<p><strong>Stage 2 (<code class="language-plaintext highlighter-rouge">is_exported = true</code>)</strong>: After validation succeeds in the portal, you flip <code class="language-plaintext highlighter-rouge">is_exported</code> to <code class="language-plaintext highlighter-rouge">true</code> and run <code class="language-plaintext highlighter-rouge">terraform apply</code> again. This patches <code class="language-plaintext highlighter-rouge">deploymentMode</code> to <code class="language-plaintext highlighter-rouge">Deploy</code> and Azure starts the full cluster provisioning, which takes 30 to 60 minutes.</p>

<p>A second variable, <code class="language-plaintext highlighter-rouge">deployment_completed</code>, controls whether Terraform attempts to read post-deployment data sources like the custom location. Set it to <code class="language-plaintext highlighter-rouge">false</code> during and after deployment and flip it to <code class="language-plaintext highlighter-rouge">true</code> only after the Azure portal confirms the deployment is complete.</p>

<h2 id="what-broke-and-how-i-fixed-it">What Broke and How I Fixed It</h2>

<p>This section documents the real debugging journey. I am including it because if you try to use any version of the AVM module against a current Azure subscription, you will likely hit some of these same issues.</p>

<h3 id="missing-edgedevices-resource">Missing edgeDevices resource</h3>

<p>The most impactful missing piece was the <code class="language-plaintext highlighter-rouge">Microsoft.AzureStackHCI/edgeDevices</code> resource. This resource registers each Arc machine with the HCI edge management system and lets the LcmController’s ARM client communicate back to Azure. Without it, every deployment settings validation failed with:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Failed to download deployment settings file using edge Arm client
</code></pre></div></div>

<p>The upstream AVM module did not include this resource at all. Adding <code class="language-plaintext highlighter-rouge">edgedevices.tf</code> with the correct API version (<code class="language-plaintext highlighter-rouge">2025-09-15-preview</code>) and ensuring it depends on the RBAC assignments resolved the failure.</p>

<h3 id="missing-role-assignments">Missing role assignments</h3>

<p>The ARM QuickStart template assigns two roles to the Arc machine identity at resource group scope that the AVM module was not creating:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Azure Stack HCI Device Management Role</code></li>
  <li><code class="language-plaintext highlighter-rouge">Azure Stack HCI Connected InfraVMs</code></li>
</ul>

<p>Without these, the LcmController cannot install the required Arc extensions. I added <code class="language-plaintext highlighter-rouge">machine_rg_role_assign</code> in <code class="language-plaintext highlighter-rouge">rolebindings.tf</code> to mirror the ARM template behavior.</p>

<h3 id="api-version-changes">API version changes</h3>

<p>Between late 2024 and early 2025, the live Azure endpoint stopped accepting <code class="language-plaintext highlighter-rouge">networkingType</code> and <code class="language-plaintext highlighter-rouge">networkingPattern</code> as body fields. Sending them causes an HTTP 400 <code class="language-plaintext highlighter-rouge">ObjectAdditionalProperties</code> error. The fix is to omit them by setting both variables to empty strings; the <code class="language-plaintext highlighter-rouge">merge()</code> logic in <code class="language-plaintext highlighter-rouge">locals.tf</code> then drops them from the JSON body.</p>

<p>The API version itself also matters. The ARM QuickStart template uses <code class="language-plaintext highlighter-rouge">2025-09-15-preview</code> for both <code class="language-plaintext highlighter-rouge">Microsoft.AzureStackHCI/clusters</code> and <code class="language-plaintext highlighter-rouge">Microsoft.AzureStackHCI/clusters/deploymentSettings</code>. Using a newer preview version can change how the control plane processes the request. After several failed attempts with <code class="language-plaintext highlighter-rouge">2026-03-01-preview</code>, reverting to <code class="language-plaintext highlighter-rouge">2025-09-15-preview</code> was the right call.</p>

<h3 id="the-lcmcontroller-0settings-bug">The LcmController 0.settings bug</h3>

<p>This one took the most iterations to nail down and I want to be honest: I went down several wrong paths before finding the real cause. The full investigation trail, including the false leads and the intermediate workarounds I tried, is documented in the <a href="https://github.com/schmittnieto/AzSHCI/blob/main/terraform/CHANGELOG.md">CHANGELOG</a> if you want the unfiltered version. I will keep this section to what actually matters.</p>

<p>The symptom was a BITS failure during validation:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Cannot bind argument to parameter 'Source' because it is an empty string.
</code></pre></div></div>

<p>The root cause is a type-checking bug in <code class="language-plaintext highlighter-rouge">DownloadHelpers.psm1</code> inside the <code class="language-plaintext highlighter-rouge">AzureEdgeLifecycleManager</code> Arc extension (NuGet package <code class="language-plaintext highlighter-rouge">10.2601.0.1162</code>). When Terraform creates <code class="language-plaintext highlighter-rouge">deploymentSettings</code>, Azure writes a minimal object to the LcmController runtime settings file that carries only cloud identity markers and no actual deployment payload. A null-check in <code class="language-plaintext highlighter-rouge">GetTargetBuildManifest</code> fails to detect this correctly because <code class="language-plaintext highlighter-rouge">[string]::IsNullOrEmpty()</code> returns <code class="language-plaintext highlighter-rouge">$false</code> for any non-null PowerShell object, even one with no useful content. The fallback that would download the cloud manifest never activates and the code ends up with four empty download URLs.</p>

<p>One important lesson from this: the four required Arc extensions (<code class="language-plaintext highlighter-rouge">AzureEdgeTelemetryAndDiagnostics</code>, <code class="language-plaintext highlighter-rouge">AzureEdgeDeviceManagement</code>, <code class="language-plaintext highlighter-rouge">AzureEdgeLifecycleManager</code>, <code class="language-plaintext highlighter-rouge">AzureEdgeRemoteSupport</code>) must be installed through the cluster creation process itself. Trying to pre-stage them manually before <code class="language-plaintext highlighter-rouge">terraform apply</code> is not only unnecessary, it can leave the node in a state where validation rejects it. Let Terraform handle the extension installation as part of Stage 1. The <code class="language-plaintext highlighter-rouge">03_TroubleshootingExtensions.ps1</code> script remains in the repository as a troubleshooting tool for environments where extensions end up in a <code class="language-plaintext highlighter-rouge">Failed</code> state after a previous failed apply, not as a required step in the normal flow.</p>

<h2 id="step-by-step-deployment">Step-by-Step Deployment</h2>

<p>With all of the above in place, here is the actual deployment flow.</p>

<h3 id="step-1-azure-prerequisites">Step 1: Azure prerequisites</h3>

<p>Run <code class="language-plaintext highlighter-rouge">00_AzurePreRequisites.ps1</code>, select or create a resource group and either assign roles to your own account or let the script create a service principal. Note the SPN credentials if you created one. The full output of this script is shown in the <a href="#prerequisites-the-first-script">Prerequisites section above</a>.</p>

<h3 id="step-2-build-the-hyper-v-infrastructure">Step 2: Build the Hyper-V infrastructure</h3>

<p>Run <code class="language-plaintext highlighter-rouge">00_Infra_AzHCI.ps1</code> to create the Hyper-V host infrastructure for the lab node. This step is identical to the one described in the <a href="/blog/azure-stack-hci-demolab/">demolab article</a>, so refer to it for a detailed walkthrough.</p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/00_Infra_Overview.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/00_Infra_Overview.webp" alt="Hyper-V infrastructure overview" style="border: 2px solid grey;" />
</a></p>

<h3 id="step-3-configure-the-domain-controller">Step 3: Configure the domain controller</h3>

<p>Run <code class="language-plaintext highlighter-rouge">01_DC.ps1</code> to set up Active Directory on the domain controller VM. Again, this step is identical to the one covered in the <a href="/blog/azure-stack-hci-demolab/">demolab article</a>.</p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/01_DC_Setup.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/01_DC_Setup.webp" alt="Domain controller setup" style="border: 2px solid grey;" />
</a></p>

<h3 id="step-4-register-the-node-with-arc">Step 4: Register the node with Arc</h3>

<p>Run <code class="language-plaintext highlighter-rouge">02_Cluster.ps1</code> to Arc-register the Azure Local node. Confirm the machine appears in Azure portal as an Arc-enabled server before continuing.</p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/02_Cluster_ArcRegistration.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/02_Cluster_ArcRegistration.webp" alt="Cluster Node Setup" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/02_Cluster_ArcPortal.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/02_Cluster_ArcPortal.webp" alt="Arc node in Azure portal" style="border: 2px solid grey;" />
</a></p>

<h3 id="step-5-configure-terraform-variables">Step 5: Configure Terraform variables</h3>

<p>Copy <code class="language-plaintext highlighter-rouge">terraform/terraform.tfvars.example</code> to <code class="language-plaintext highlighter-rouge">terraform/terraform.tfvars</code>. Replace every <code class="language-plaintext highlighter-rouge">TODO</code> value with your actual credentials and network settings. Key variables for a single-node lab:</p>

<div class="language-hcl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">management_adapters</span> <span class="err">=</span> <span class="p">[</span><span class="s2">"MGMT1"</span><span class="p">]</span>
<span class="nx">rdma_enabled</span>        <span class="err">=</span> <span class="kc">false</span>
<span class="nx">networking_type</span>     <span class="err">=</span> <span class="s2">""</span>
<span class="nx">networking_pattern</span>  <span class="err">=</span> <span class="s2">""</span>
<span class="nx">witness_type</span>        <span class="err">=</span> <span class="s2">""</span>
<span class="nx">is_exported</span>         <span class="err">=</span> <span class="kc">false</span>
<span class="nx">deployment_completed</span> <span class="err">=</span> <span class="kc">false</span>
</code></pre></div></div>

<h3 id="step-6-authenticate-with-azure-cli">Step 6: Authenticate with Azure CLI</h3>

<p>Terraform uses the Azure CLI session to authenticate. Log in with the service principal created in Step 1 and set the target subscription:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">az</span><span class="w"> </span><span class="nx">login</span><span class="w"> </span><span class="nt">--service-principal</span><span class="w"> </span><span class="se">`
</span><span class="w">    </span><span class="nt">--username</span><span class="w"> </span><span class="s2">"&lt;app-id&gt;"</span><span class="w"> </span><span class="se">`
</span><span class="w">    </span><span class="nt">--password</span><span class="w"> </span><span class="s2">"&lt;client-secret&gt;"</span><span class="w"> </span><span class="se">`
</span><span class="w">    </span><span class="nt">--tenant</span><span class="w"> </span><span class="s2">"&lt;tenant-id&gt;"</span><span class="w">
</span><span class="n">az</span><span class="w"> </span><span class="nx">account</span><span class="w"> </span><span class="nx">set</span><span class="w"> </span><span class="nt">--subscription</span><span class="w"> </span><span class="s2">"&lt;subscription-id&gt;"</span><span class="w">
</span></code></pre></div></div>

<h3 id="step-7-initialize-and-run-stage-1-validate">Step 7: Initialize and run Stage 1 (Validate)</h3>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">terraform</span><span class="w"> </span><span class="nx">init</span><span class="w">
</span><span class="n">terraform</span><span class="w"> </span><span class="nx">plan</span><span class="w">
</span><span class="n">terraform</span><span class="w"> </span><span class="nx">apply</span><span class="w">
</span></code></pre></div></div>

<p>Review the plan output before confirming the apply. Terraform creates the Key Vault, storage account, RBAC assignments and edge device registration, then submits the deployment settings to Azure for validation.</p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/TF_Init.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/TF_Init.webp" alt="terraform init output" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/TF_Plan_Stage1.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/TF_Plan_Stage1.webp" alt="terraform plan output Stage 1" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/TF_Apply_Stage1_Validate.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/TF_Apply_Stage1_Validate.webp" alt="Stage 1 apply complete" style="border: 2px solid grey;" />
</a></p>

<p>Validation runs as part of the apply itself. Once Terraform reports the apply as complete, Stage 1 is done (takes arround 90 minutes) and you can move straight to Stage 2.</p>

<h3 id="step-8-switch-to-stage-2-deploy">Step 8: Switch to Stage 2 (Deploy)</h3>

<p>Set <code class="language-plaintext highlighter-rouge">is_exported = true</code> in <code class="language-plaintext highlighter-rouge">terraform.tfvars</code> and run <code class="language-plaintext highlighter-rouge">terraform apply</code> again. Terraform patches <code class="language-plaintext highlighter-rouge">deploymentMode</code> to <code class="language-plaintext highlighter-rouge">Deploy</code> and Azure starts the full cluster provisioning. This apply will run for 90 to 180 minutes while Azure works through the FullCloudDeployment plan.</p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/TF_Apply_Stage2.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/TF_Apply_Stage2.webp" alt="Stage 2 terraform apply" style="border: 2px solid grey;" />
</a></p>

<p>While Terraform is waiting, you can follow the deployment progress in real time in the Azure portal under the Azure Local resource. Each step of the plan is shown individually, which makes it much easier to spot a failure early rather than waiting for a Terraform timeout.</p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/TF_Portal_Deploying.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/TF_Portal_Deploying.webp" alt="Azure portal showing deployment steps in progress" style="border: 2px solid grey;" />
</a></p>

<p>Once the apply finishes and all steps complete successfully, this is what it looks like from both sides. First, the Terraform output confirming all resources were created:</p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/TF_Apply_Stage2_completed.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/TF_Apply_Stage2_completed.webp" alt="Terraform apply Stage 2 complete" style="border: 2px solid grey;" />
</a></p>

<p>And the Azure portal showing the cluster as successfully deployed:</p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/TF_Portal_Deployed.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/TF_Portal_Deployed.webp" alt="Azure portal showing deployment complete" style="border: 2px solid grey;" />
</a></p>

<h3 id="step-9-enable-post-deployment-outputs">Step 9: Enable post-deployment outputs</h3>

<p>Once the portal confirms the deployment is complete and Terraform finishes the apply, set <code class="language-plaintext highlighter-rouge">deployment_completed = true</code> in <code class="language-plaintext highlighter-rouge">terraform.tfvars</code> and run <code class="language-plaintext highlighter-rouge">terraform apply</code> once more. This allows Terraform to read the custom location output that is only available after the Azure deployment engine finishes.</p>

<p><a href="/assets/img/post/2026-04-17-azure-local-terraform/TF_Apply_Stage2_Complete.webp" target="_blank">
  <img src="/assets/img/post/2026-04-17-azure-local-terraform/TF_Apply_Stage2_Complete.webp" alt="Terraform apply complete with post-deployment outputs" style="border: 2px solid grey;" />
</a></p>

<h2 id="recovery-helpers">Recovery Helpers</h2>

<p>If a <code class="language-plaintext highlighter-rouge">terraform apply</code> times out or you lose Terraform state after a successful apply, the configuration includes two recovery variables to help you get back on track without destroying and rebuilding:</p>

<ul>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">import_deployment_settings</code></strong> (<code class="language-plaintext highlighter-rouge">bool</code>, default <code class="language-plaintext highlighter-rouge">false</code>): When <code class="language-plaintext highlighter-rouge">true</code>, imports the pre-existing <code class="language-plaintext highlighter-rouge">deploymentSettings/default</code> into state before the plan phase. Use this when a previous apply timed out but the resource already exists in Azure.</p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">import_machine_rg_role_assignment_ids</code></strong> (<code class="language-plaintext highlighter-rouge">map(string)</code>, default <code class="language-plaintext highlighter-rouge">{}</code>): When the <code class="language-plaintext highlighter-rouge">machine_rg_role_assign</code> role assignments already exist in Azure and a new apply would fail with <code class="language-plaintext highlighter-rouge">409 Conflict</code>, populate this map with the existing assignment GUIDs (visible in the 409 error message) and run <code class="language-plaintext highlighter-rouge">terraform apply</code> to import them. Reset to <code class="language-plaintext highlighter-rouge">{}</code> afterward.</p>
  </li>
</ul>

<p>If the Arc machine was manually deleted from Azure and you need to run <code class="language-plaintext highlighter-rouge">terraform destroy</code>, set <code class="language-plaintext highlighter-rouge">enable_cluster_module = false</code> to skip the cluster module and avoid failing Arc data-source lookups.</p>

<p>It is also worth noting that the cluster deployment creates additional Azure resources such as Arc extensions and logical networks that are lifecycle-managed by the cluster resource itself: they are created and destroyed together with it, so they do not need to be imported separately. The custom location is the exception, it is the only post-deployment resource that Terraform captures in state and exposes as an output, since workload modules (AVD, AKS) need to reference it. Everything else is handled by Azure as part of the cluster’s own lifecycle.</p>

<h2 id="what-is-next">What Is Next</h2>

<p>The cluster deployment is the foundation. The repository’s goal from the start has been to automate the full workload lifecycle on top of Azure Local, not just the cluster itself. The next steps are:</p>

<ul>
  <li><strong>Azure Virtual Desktop</strong>: A Terraform module for AVD host pools, session hosts and workspace configuration, deployable against the custom location created by the cluster deployment.</li>
  <li><strong>AKS on Azure Local</strong>: Terraform for AKS cluster creation using the Arc-enabled Kubernetes stack, scoped to the same resource group and custom location.</li>
  <li><strong>Pipelines</strong>: GitHub Actions or Azure DevOps pipeline definitions that call these Terraform configurations using the service principal created by <code class="language-plaintext highlighter-rouge">00_AzurePreRequisites.ps1</code>. The goal is a single pipeline trigger that goes from a fresh Arc-registered node to a fully deployed cluster with workloads.</li>
</ul>

<p>If you have questions, hit issues, or have already gone through a similar Terraform journey with Azure Local, I would love to hear from you in the comments below. The repository is public and pull requests are welcome.</p>]]></content><author><name>Cristian Schmitt Nieto</name></author><category term="Blog" /><category term="Azure Local" /><category term="Azure Stack HCI" /><category term="Terraform" /><category term="Automation" /><category term="Infrastructure as Code" /><summary type="html"><![CDATA[Deploy Azure Local with Terraform using a fixed AVM fork, staged validation and a service principal ready for pipeline-driven AVD and AKS automation.]]></summary></entry><entry><title type="html">Reflecting on 2025 and Goals for 2026</title><link href="https://schmitt-nieto.com/blog/year-recap-2025/" rel="alternate" type="text/html" title="Reflecting on 2025 and Goals for 2026" /><published>2025-12-31T00:00:00+01:00</published><updated>2025-12-31T00:00:00+01:00</updated><id>https://schmitt-nieto.com/blog/year-recap-2025</id><content type="html" xml:base="https://schmitt-nieto.com/blog/year-recap-2025/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Hello everyone, another year has gone by. As I did last year, I’ve set myself the goal of writing down a list of objectives for 2026, along with the main events that took place during 2025. This blog post is a bit more personal and less technical than usual, and its main purpose is to track the progress of my blog as well as my personal goals.</p>

<p>I want to be able to come back here next December and clearly see what I’ve managed to move forward and what I didn’t quite achieve, since my focus tends to change quite a bit throughout the year 😅</p>

<h2 id="2025-recap">2025 Recap</h2>

<h3 id="personal-highlights">Personal Highlights</h3>

<p>When I look back at my photo albums, I realize just how much has happened over the year. 2025 has been a great year, at least when it comes to personal and family goals. I’ve truly enjoyed spending time with my loved ones, and I’ve gained a much healthier perspective on how I approach life.</p>

<p>On the professional side, I’ve also continued to grow and evolve, and you’ll see a couple of articles about that during 2026 😜. Even though I didn’t manage to achieve some of the goals I set at the beginning of last year, like attending Ignite, I did attend several conferences and surrounded myself with some truly amazing people in the professional space, not all of them coworkers, which also led to making a few new friends along the way 🤗</p>

<h3 id="professional-achievements">Professional Achievements</h3>

<p>I wrapped up 2024 and started 2025 by earning Microsoft certifications in the areas I focused on the most throughout the year, namely Microsoft Identity and Access Administrator and Endpoint Administrator. During 2025, I was heavily focused on strengthening my overall knowledge and further developing my expertise around AVD, both in cloud and hybrid environments, with all the related challenges that come with them.</p>

<p>That said, this didn’t stop me from continuing to write and dedicating my free time to one of my favorite hobbies: Azure Local. In 2025, I published eight blog posts focused exclusively on Azure Local and solutions built for or around it. While I initially planned to write more about other topics, the way I approach each article, in terms of quality and the time invested, made it harder to branch out as much as I intended.</p>

<p>This time, I won’t include a list of articles like I did last year, nor a list of books I’m reading or have finished. This year, that list would be way too long, over 30 new books, and yes, I did finish the ones from last year as well. If anyone is curious about what I’m reading, feel free to reach out to me on LinkedIn and I’ll happily share the list 😜</p>

<h3 id="blog-stats-for-2025">Blog Stats for 2025</h3>

<p>Overall, blog statistics have improved this year, even though I slowed down a bit in the second half in terms of posting frequency. Since this is the first year where I have a full set of statistics, it’s honestly great to see how well the blog is being received, especially considering it focuses on a very niche topic, currently almost exclusively Azure Local.</p>

<p>As usual, the main statistics are split across Google Analytics, Google Search Console, Clarity, Bing, LinkedIn and this year I’m also adding my GitHub Rewind.</p>

<h4 id="google-analytics">Google Analytics</h4>
<p><a href="/assets/img/post/2025-12-31-new-year/google-analytics.png" target="_blank">
  <img src="/assets/img/post/2025-12-31-new-year/google-analytics.png" alt="Google Analytics Screenshot" style="border: 2px solid grey;" />
</a></p>

<h4 id="google-search-console">Google Search Console</h4>
<p><a href="/assets/img/post/2025-12-31-new-year/google-search-console.png" target="_blank">
  <img src="/assets/img/post/2025-12-31-new-year/google-search-console.png" alt="Google Search Console Screenshot" style="border: 2px solid grey;" />
</a></p>

<h4 id="clarity">Clarity</h4>
<p><a href="/assets/img/post/2025-12-31-new-year/clarity.png" target="_blank">
  <img src="/assets/img/post/2025-12-31-new-year/clarity.png" alt="Microsoft Clarity Screenshot" style="border: 2px solid grey;" />
</a></p>

<h4 id="bing-webmaster-tools">Bing Webmaster Tools</h4>
<p><a href="/assets/img/post/2025-12-31-new-year/bing-webmaster.png" target="_blank">
  <img src="/assets/img/post/2025-12-31-new-year/bing-webmaster.png" alt="Bing Webmaster Screenshot" style="border: 2px solid grey;" />
</a></p>

<h4 id="linkedin">LinkedIn</h4>
<p><a href="/assets/img/post/2025-12-31-new-year/linkedin1.png" target="_blank">
  <img src="/assets/img/post/2025-12-31-new-year/linkedin1.png" alt="LinkedIn Stats Screenshot 1" style="border: 2px solid grey;" />
</a>
<a href="/assets/img/post/2025-12-31-new-year/linkedin2.png" target="_blank">
  <img src="/assets/img/post/2025-12-31-new-year/linkedin2.png" alt="LinkedIn Stats Screenshot 2" style="border: 2px solid grey;" />
</a>
<a href="/assets/img/post/2025-12-31-new-year/linkedin3.png" target="_blank">
  <img src="/assets/img/post/2025-12-31-new-year/linkedin3.png" alt="LinkedIn Stats Screenshot 3" style="border: 2px solid grey;" />
</a></p>

<h4 id="github">GitHub</h4>
<p><a href="/assets/img/post/2025-12-31-new-year/github.png" target="_blank">
  <img src="/assets/img/post/2025-12-31-new-year/github.png" alt="Github Rewind" style="border: 2px solid grey;" />
</a></p>

<p>Overall, the growth this year has been quite positive, both in terms of community engagement and content. It’s true that I should have, and wanted to, publish more blog posts, but work commitments and family time took priority, which led me to put the blog slightly on hold during the second half of the year. This is clearly reflected in the statistics.</p>

<h2 id="goals-for-2026">Goals for 2026</h2>

<p>This year, I’m setting goals that are less focused on technology and the blog itself:</p>

<ul>
  <li>Don’t start smoking again (I relapsed in 2025 😅)</li>
  <li>Go to the gym more regularly</li>
  <li>Improve my Chinese (I started studying it last year)</li>
  <li>Further reduce mobile phone usage and aim for less than one hour per day</li>
  <li>Publish one blog post per month</li>
</ul>

<p>As always, I wrap up the year by thanking everyone who has been by my side, and especially my wife and my daughter ♥️</p>

<p>I wish you all a happy 2026!</p>]]></content><author><name>Cristian Schmitt Nieto</name></author><category term="Blog" /><category term="Blog" /><summary type="html"><![CDATA[A look back at 2025's milestones and a roadmap for 2026. Personal growth, professional achievements and ambitious goals for the future.]]></summary></entry><entry><title type="html">Azure Local: How to Deploy LLMs on AKS</title><link href="https://schmitt-nieto.com/blog/azure-local-llm/" rel="alternate" type="text/html" title="Azure Local: How to Deploy LLMs on AKS" /><published>2025-11-30T00:00:00+01:00</published><updated>2025-11-30T00:00:00+01:00</updated><id>https://schmitt-nieto.com/blog/azure-local-llm</id><content type="html" xml:base="https://schmitt-nieto.com/blog/azure-local-llm/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Welcome to a new article on my blog. Today I’m covering a topic that helps deepen your understanding of Kubernetes: the deployment of Large Language Models (LLMs) on Azure Kubernetes Services (AKS) running on Azure Local. I’ll explain some basic concepts along the way. If anything sounds unfamiliar, I recommend checking out my previous article: <a href="/blog/azure-local-aks/">Azure Local: AKS and SQL Managed Instances</a>.</p>

<p>Let me also apologize up front for the slight clickbait in the title. Because of my lab setup (a laptop with 64 GB of RAM, where Azure Local only gets 34 GB) I didn’t deploy an actual LLM, but a Small Language Model (SLM). The process and implementation are identical, though.</p>

<h2 id="infrastructure-design">Infrastructure Design</h2>

<p>Before deploying anything, we should review the resources we have available and come up with a plan. As mentioned, I only have my “Azure Local Lab” running fully virtualized on my laptop. Since I can’t use a GPU on AKS here and RAM is limited (around 20 GB free for AKS, shared between the control plane and the worker nodes), I designed a simple and lightweight proof of concept.</p>

<p>If I had the right hardware, I would have deployed KAITO (<a href="https://github.com/kaito-project/kaito">Kubernetes AI Toolchain Operator</a>). But since I currently don’t have a GPU available, we’ll stick to my CPU-only variant. Still, here is the KAITO architecture for reference:<br />
<a href="/assets/img/post/2025-11-29-azure-local-llm/Kaito.png" target="_blank">
  <img src="/assets/img/post/2025-11-29-azure-local-llm/Kaito.png" alt="KAITO" style="border: 2px solid grey;" />
</a></p>

<p>To make the architecture of my lab easier to understand, I prepared a diagram based on the one shown in the official <a href="https://learn.microsoft.com/en-us/azure/architecture/example-scenario/hybrid/aks-baseline">Baseline Architecture for AKS on Azure Local</a>.</p>

<p><a href="/assets/img/post/2025-11-29-azure-local-llm/AKS-Architecture.png" target="_blank">
  <img src="/assets/img/post/2025-11-29-azure-local-llm/AKS-Architecture.png" alt="AKS Architecture" style="border: 2px solid grey;" />
</a></p>

<p>In the diagram you can see the components we’ll deploy:</p>

<ul>
  <li><strong>Azure Local</strong>: A single virtualized node that in turn hosts the nested AKS cluster</li>
  <li><strong>AKS VMs</strong>:
    <ul>
      <li>One control plane VM that acts as API server and LoadBalancer (via MetalLB)</li>
      <li>One worker node responsible for running the workloads</li>
      <li>Control plane size: Standard_K8S3_v1 (4 vCPUs, 6 GB RAM)</li>
      <li>Worker node size: Standard_A4_v2 (4 vCPUs, 8 GB RAM)</li>
    </ul>
  </li>
  <li><strong>Logical AKS infrastructure</strong>:
    <ul>
      <li>A dedicated namespace for LLM-related workloads</li>
      <li>A single external IP from MetalLB (172.19.19.90) for Open WebUI</li>
      <li>Persistent storage of 25 Gi for Ollama to keep the model files between updates</li>
    </ul>
  </li>
</ul>

<p>This is the workload architecture inside AKS:</p>

<p><a href="/assets/img/post/2025-11-29-azure-local-llm/slm-llm-stack-arch.png" target="_blank">
  <img src="/assets/img/post/2025-11-29-azure-local-llm/slm-llm-stack-arch.png" alt="SLM AKS Architecture on Azure Local" style="border: 2px solid grey;" />
</a></p>

<p>The whole deployment is carried out from my laptop, which has direct Layer 2 network access to the AKS cluster. I use Az CLI, kubectl and Helm. Throughout the process I’ll point out which tool is used and why. The goal here is to test LLM capabilities in this specific environment, not to deploy a standardized production-grade AKS hybrid application.</p>

<p>If you’re interested in the proper deployment approach for production AKS hybrid applications, I recommend reading:<br />
<a href="https://learn.microsoft.com/en-us/azure/architecture/example-scenario/hybrid/aks-hybrid-azure-local">Deploy and operate apps with AKS enabled by Azure Arc on Azure Local</a>.<br />
That article covers pipelines, GitOps, Flux, Helm and other components, giving you a great high-level overview of the possibilities.</p>

<p>Another option would be a hybrid model using self-hosted agents and a Service Bearer Token (which we’ll create later in this article under “Creating a Service Account to Manage AKS Locally”). This can give you more flexibility, though I personally recommend the GitOps approach.</p>

<p>With the architecture clear, let’s move on to implementation.</p>

<h2 id="requirements-and-tool-installation">Requirements and Tool Installation</h2>

<p>To deploy everything, you’ll need:</p>

<ul>
  <li>A client machine (in my case the laptop running the lab) with direct network access to the AKS cluster running on Azure Local</li>
  <li>The following tools installed:
    <ul>
      <li>Helm, for deploying workloads to AKS</li>
      <li>Az CLI with the aksarc module, to authenticate and retrieve local AKS credentials</li>
      <li>kubectl, to manage AKS directly</li>
    </ul>
  </li>
  <li>An AKS cluster capable of running the workload (at least 8 GB RAM on the worker node) with temporary internet access during deployment</li>
  <li>The ability to add or modify local IP addresses used by the LoadBalancer (MetalLB)</li>
</ul>

<p>Some of these requirements were already covered in the previous article, but let’s go through the ones that weren’t.</p>

<h3 id="modifying-aks">Modifying AKS</h3>

<p>As mentioned, my lab runs nested on a laptop with 64 GB RAM, and Azure Local can only use around 36 GB or else the laptop becomes unusable. The Azure Arc Resource Bridge VM alone consumes 8 GB (or 16 GB during updates since another image is temporarily mounted). Azure Local itself uses between 4 and 8 GB depending on the moment. That leaves roughly 20 GB for AKS.</p>

<p>This memory has to be shared between the control plane and the worker nodes. To simplify the scenario, I limited the cluster to:</p>

<ul>
  <li>One control plane with the minimum RAM → <strong>6 GB</strong></li>
  <li>One worker node with enough RAM to run Ollama and Open WebUI → <strong>8 GB</strong></li>
</ul>

<p>I made these changes directly in the Azure Local portal under <em>Settings &gt; Node pools</em>.<br />
I also added the IP range 172.19.19.90–172.19.19.99 for MetalLB under <em>Settings &gt; Networking</em>.</p>

<p><a href="/assets/img/post/2025-11-29-azure-local-llm/AKSnodemodificationandLB.png" target="_blank">
  <img src="/assets/img/post/2025-11-29-azure-local-llm/AKSnodemodificationandLB.png" alt="AKS Nodes Modification and LB changes" style="border: 2px solid grey;" />
</a></p>

<p>Once AKS is ready, we need a local management channel using a bearer token.</p>

<h3 id="creating-a-service-account-to-manage-aks-locally">Creating a Service Account to Manage AKS Locally</h3>

<p>I’ve needed bearer tokens long before AI workloads became trendy. In past projects I used them for self-hosted agents and even started a repository almost two years ago that covered this topic:<br />
<a href="https://github.com/schmittnieto/AKSHybrid/">AKS Hybrid</a>.<br />
It’s a bit abandoned because I moved the more interesting content to other repositories.</p>

<p>The goal in this section is to access the AKS cluster locally. So I created this script:<br />
<a href="https://raw.githubusercontent.com/schmittnieto/AzSHCI/refs/heads/main/scripts/02Day2/12_AKSArcServiceToken.ps1">12_AKSArcServiceToken.ps1</a></p>

<p>This script:</p>

<ul>
  <li>Uses Az CLI and aksarc (installing the extension automatically if missing)</li>
  <li>Retrieves local AKS credentials</li>
  <li>Creates an admin user to manage the cluster</li>
  <li>Generates both a kubeconfig file and a txt file with the token</li>
  <li>Saves everything in the same directory</li>
  <li>Includes an extensive description</li>
  <li>Runs interactively if no parameters are provided</li>
</ul>

<p>When the script finishes, set your kubeconfig environment variable:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$</span><span class="nn">env</span><span class="p">:</span><span class="nv">KUBECONFIG</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"</span><span class="bp">$HOME</span><span class="s2">\.kube\AzSHCI\aks-arc-kube-config"</span><span class="w">
</span></code></pre></div></div>

<p>After that you can manage AKS directly with kubectl.</p>

<p><a href="/assets/img/post/2025-11-29-azure-local-llm/kubeconfig.png" target="_blank">
  <img src="/assets/img/post/2025-11-29-azure-local-llm/kubeconfig.png" alt="Kubeconfig" style="border: 2px solid grey;" />
</a></p>

<p>Now we can proceed with the workloads.</p>

<h3 id="installing-helm">Installing Helm</h3>

<p>We’ll use Helm to deploy the workloads. Helm is a package manager for Kubernetes. It lets you install and update complete applications using charts, which define deployments, services, volumes and configuration. In hybrid environments like AKS on Azure Local, Helm is extremely convenient because it helps you avoid writing raw YAML by hand and makes versioning and updates easier.</p>

<p>Install it using Winget:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">winget</span><span class="w"> </span><span class="nx">install</span><span class="w"> </span><span class="nx">Helm.Helm</span><span class="w">
</span></code></pre></div></div>

<p>With Helm installed, we’re ready for the next part: deploying the LLM and exposing it on the local network.</p>

<h2 id="llm-deployment">LLM Deployment</h2>

<p>Before going into commands, I want to explain why I chose <strong>Ollama</strong> as the base for the LLM. In a hybrid environment like AKS on Azure Local, you want something light, flexible and easy to operate. Ollama fits this perfectly. It’s one of the most popular inference engines in the community, offers a wide variety of ready-to-use models and is extremely simple to work with. It doesn’t require complex dependencies, starts quickly and lets you load models with a single command. This makes it ideal for demos, internal testing or small services running on limited hardware.</p>

<p>In this section we’ll deploy the full stack consisting of Ollama and Open WebUI inside the cluster. The goal is to maintain a simple, easy-to-manage architecture while still having the flexibility to run lightweight models in a controlled environment.</p>

<p>Below I explain each command step by step and what it means for the overall setup.</p>

<h3 id="create-the-namespace">Create the namespace</h3>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">kubectl</span><span class="w"> </span><span class="nx">create</span><span class="w"> </span><span class="nx">namespace</span><span class="w"> </span><span class="nx">slm</span><span class="w">
</span></code></pre></div></div>

<p>This creates a dedicated namespace called <strong>slm</strong>. It keeps all LLM-related components isolated, making it easier to manage, clean up or extend later.</p>

<h3 id="add-helm-repositories">Add Helm repositories</h3>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">helm</span><span class="w"> </span><span class="nx">repo</span><span class="w"> </span><span class="nx">add</span><span class="w"> </span><span class="nx">otwld</span><span class="w"> </span><span class="nx">https://helm.otwld.com/</span><span class="w">
</span><span class="n">helm</span><span class="w"> </span><span class="nx">repo</span><span class="w"> </span><span class="nx">add</span><span class="w"> </span><span class="nx">open-webui</span><span class="w"> </span><span class="nx">https://helm.openwebui.com/</span><span class="w">
</span><span class="n">helm</span><span class="w"> </span><span class="nx">repo</span><span class="w"> </span><span class="nx">update</span><span class="w">
</span></code></pre></div></div>

<p>These are the official repositories for Ollama and Open WebUI.</p>

<h3 id="deploy-ollama-as-an-internal-service">Deploy Ollama as an internal service</h3>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">helm</span><span class="w"> </span><span class="nx">install</span><span class="w"> </span><span class="nx">ollama</span><span class="w"> </span><span class="nx">otwld/ollama</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--namespace</span><span class="w"> </span><span class="nx">slm</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--set</span><span class="w"> </span><span class="nx">service.type</span><span class="o">=</span><span class="n">ClusterIP</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--set</span><span class="w"> </span><span class="nx">ollama.port</span><span class="o">=</span><span class="mi">11434</span><span class="w"> </span><span class="err">`</span><span class="w">
  </span><span class="nt">--set</span><span class="w"> </span><span class="n">persistentVolume.enabled</span><span class="o">=</span><span class="n">true</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--set</span><span class="w"> </span><span class="nx">persistentVolume.size</span><span class="o">=</span><span class="mi">20</span><span class="n">Gi</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--set</span><span class="w"> </span><span class="nx">ollama.models.pull</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">=</span><span class="n">phi4-mini:latest</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--set</span><span class="w"> </span><span class="nx">ollama.models.run</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">=</span><span class="n">phi4-mini:latest</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--set</span><span class="w"> </span><span class="nx">resources.requests.cpu</span><span class="o">=</span><span class="s2">"2"</span><span class="w"> </span><span class="err">`</span><span class="w">
  </span><span class="nt">--set</span><span class="w"> </span><span class="n">resources.requests.memory</span><span class="o">=</span><span class="s2">"2Gi"</span><span class="w"> </span><span class="err">`</span><span class="w">
  </span><span class="nt">--set</span><span class="w"> </span><span class="n">resources.limits.cpu</span><span class="o">=</span><span class="s2">"4"</span><span class="w"> </span><span class="err">`</span><span class="w">
  </span><span class="nt">--set</span><span class="w"> </span><span class="n">resources.limits.memory</span><span class="o">=</span><span class="s2">"4Gi"</span><span class="w">
</span></code></pre></div></div>

<p>Key points:</p>

<ul>
  <li><strong>ClusterIP</strong> keeps the service internal</li>
  <li><strong>Port 11434</strong> is the default Ollama API port</li>
  <li><strong>20 Gi persistent volume</strong> ensures models don’t have to be re-downloaded</li>
  <li><strong>phi4-mini:latest</strong> is pulled and launched automatically</li>
  <li>Resource requests and limits prevent the node from being overloaded</li>
</ul>

<p>Check the pods:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">kubectl</span><span class="w"> </span><span class="nx">get</span><span class="w"> </span><span class="nx">pods</span><span class="w"> </span><span class="nt">-n</span><span class="w"> </span><span class="nx">slm</span><span class="w">
</span></code></pre></div></div>

<h3 id="deploy-open-webui-as-a-loadbalancer">Deploy Open WebUI as a LoadBalancer</h3>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">helm</span><span class="w"> </span><span class="nx">install</span><span class="w"> </span><span class="nx">openwebui</span><span class="w"> </span><span class="nx">open-webui/open-webui</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--namespace</span><span class="w"> </span><span class="nx">slm</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--set</span><span class="w"> </span><span class="nx">service.type</span><span class="o">=</span><span class="n">LoadBalancer</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--set</span><span class="w"> </span><span class="nx">ollama.enabled</span><span class="o">=</span><span class="n">false</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--set</span><span class="w"> </span><span class="nx">ollamaUrls</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">=</span><span class="s2">"http://ollama.slm.svc.cluster.local:11434"</span><span class="w"> </span><span class="err">`</span><span class="w">
  </span><span class="nt">--set</span><span class="w"> </span><span class="n">persistence.enabled</span><span class="o">=</span><span class="n">true</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="nt">--set</span><span class="w"> </span><span class="nx">persistence.size</span><span class="o">=</span><span class="mi">5</span><span class="n">Gi</span><span class="w">
</span></code></pre></div></div>

<p>Key points:</p>

<ul>
  <li>Exposed via MetalLB</li>
  <li>Connects internally to Ollama</li>
  <li>5 Gi persistence for settings and local data</li>
  <li>You can define a static IP by adding <code class="language-plaintext highlighter-rouge">--set loadBalancerIP=&lt;your-ip&gt;</code></li>
</ul>

<p>Check pods again:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">kubectl</span><span class="w"> </span><span class="nx">get</span><span class="w"> </span><span class="nx">pods</span><span class="w"> </span><span class="nt">-n</span><span class="w"> </span><span class="nx">slm</span><span class="w">
</span></code></pre></div></div>

<h3 id="final-result">Final result</h3>

<p>Retrieve the external IP:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">kubectl</span><span class="w"> </span><span class="nx">get</span><span class="w"> </span><span class="nx">svc</span><span class="w"> </span><span class="nt">-n</span><span class="w"> </span><span class="nx">slm</span><span class="w">
</span></code></pre></div></div>

<p><a href="/assets/img/post/2025-11-29-azure-local-llm/extipwebui.png" target="_blank">
  <img src="/assets/img/post/2025-11-29-azure-local-llm/extipwebui.png" alt="External IP from WebUI" style="border: 2px solid grey;" />
</a></p>

<p>You can now create an admin user and start using the deployed LLM:</p>

<p><a href="/assets/img/post/2025-11-29-azure-local-llm/LLMAKS.gif" target="_blank">
  <img src="/assets/img/post/2025-11-29-azure-local-llm/LLMAKS.gif" alt="Testing OpenWebUI and Ollama in Azure Local AKS" style="border: 2px solid grey;" />
</a></p>

<p>Here are the token-per-second results. Not great, but considering everything is running triple-nested (laptop → Azure Local → AKS) with 4 vCPUs, it’s actually not bad:</p>

<p><a href="/assets/img/post/2025-11-29-azure-local-llm/tokenspersecond.png" target="_blank">
  <img src="/assets/img/post/2025-11-29-azure-local-llm/tokenspersecond.png" alt="Tokens per Second using Ollama in Azure Local AKS" style="border: 2px solid grey;" />
</a></p>

<p>With these two deployments you now have:</p>

<ul>
  <li>A running LLM engine (Ollama) inside the cluster, only accessible internally</li>
  <li>A modern UI (Open WebUI) exposed via MetalLB</li>
  <li>Persistent storage for both models and daily usage</li>
  <li>A clean namespace (<code class="language-plaintext highlighter-rouge">slm</code>) ready for future additions</li>
</ul>

<p>This stack is a great foundation for experimenting in a hybrid AKS environment, adding observability or even scaling to more nodes.</p>

<h2 id="conclusion">Conclusion</h2>

<p>With this setup you now have a functional environment capable of running lightweight language models inside an AKS cluster on Azure Local. Helm simplifies the deployment of Ollama and Open WebUI and gives you a stable base for further experimentation. Even though this lab runs on limited resources, the approach is perfectly valid for learning more about AKS and understanding how to integrate AI workloads in a hybrid environment.</p>

<p>From here, you can try more models, add observability, integrate GitOps workflows or even move to solutions like KAITO if you get access to a GPU.</p>]]></content><author><name>Cristian Schmitt Nieto</name></author><category term="Blog" /><category term="Azure Local" /><category term="AKS" /><category term="LLM" /><category term="Helm" /><summary type="html"><![CDATA[A detailed walkthrough of deploying lightweight LLMs on AKS inside an Azure Local environment.]]></summary></entry><entry><title type="html">Azure Local Deep Insights Workbook</title><link href="https://schmitt-nieto.com/blog/azure-local-deep-insights-workbook/" rel="alternate" type="text/html" title="Azure Local Deep Insights Workbook" /><published>2025-10-31T00:00:00+01:00</published><updated>2025-10-31T00:00:00+01:00</updated><id>https://schmitt-nieto.com/blog/azure-local-deep-insights-workbook</id><content type="html" xml:base="https://schmitt-nieto.com/blog/azure-local-deep-insights-workbook/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Welcome back to the Azure Local series. Today I want to cover a topic that comes up often with customers: observability for Azure Local. Many organizations already use on premises monitoring like Checkmk or PRTG. Integrating clusters into those tools is possible, but it usually adds moving parts such as privileged WMI from a PAW to the cluster and that can become brittle.</p>

<p>Microsoft ships a basic workbook under <strong>Monitoring &gt; Insights</strong> on the Azure Local resource. It does a good job for cluster and node level views like CPU, RAM, Storage and Network. What it does not show is a deeper look at the <strong>guest VMs</strong>.</p>

<p>So I built <strong>Azure Local Deep Insights</strong>, a workbook that reuses the Insights pipeline and adds extra signals. The goal is to give you a single place to understand cluster health and guest VM behavior without touching the cluster from the inside. Everything runs from the Azure portal.</p>

<h2 id="what-the-workbook-looks-like">What the workbook looks like</h2>

<p>The following snapshot is from <strong>Monday 27.10.2025</strong>, taken during an upgrade from <strong>2509</strong> to <strong>2510</strong>. You can see how <strong>Arc Resource Bridge</strong> moved to a fresh VM during the process.</p>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/AzureLocalWorkBookDemo.gif" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/AzureLocalWorkBookDemo.gif" alt="Azure Local Deep Insights Workbook demo" style="border: 2px solid grey;" />
</a></p>

<h2 id="one-click-deployment">One click deployment</h2>

<p>You can deploy the workbook with the button below. The template expects Insights to be configured on the cluster. We will adjust its Data Collection Rule in the next section.</p>

<p><a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fschmitt-nieto.com%2Fassets%2Fimg%2Fpost%2F2025-10-31-azure-local-deep-insights%2FAzureLocalDeepInsights.json"><img src="https://aka.ms/deploytoazurebutton" alt="Deploy to Azure" /></a></p>

<p>Prefer direct code instead of the button?</p>

<ul>
  <li>
    <p>If you want the <strong>gallery template code</strong> as a <code class="language-plaintext highlighter-rouge">.workbook</code> file, use this link:<br />
<a href="https://schmitt-nieto.com/assets/img/post/2025-10-31-azure-local-deep-insights/AzureLocalDeepInsights.workbook">https://schmitt-nieto.com/assets/img/post/2025-10-31-azure-local-deep-insights/AzureLocalDeepInsights.workbook</a></p>
  </li>
  <li>
    <p>If you want the <strong>raw JSON</strong> for <strong>manual deployment</strong>, use this link:<br />
<a href="https://schmitt-nieto.com/assets/img/post/2025-10-31-azure-local-deep-insights/AzureLocalDeepInsights.json">https://schmitt-nieto.com/assets/img/post/2025-10-31-azure-local-deep-insights/AzureLocalDeepInsights.json</a></p>
  </li>
</ul>

<h2 id="prerequisites">Prerequisites</h2>

<ul>
  <li>Azure Local resource enabled with <strong>Monitoring &gt; Insights</strong></li>
  <li>A <strong>Log Analytics Workspace</strong> dedicated to Azure Local data or shared by policy</li>
  <li>Permission to create or update a <strong>Data Collection Rule</strong> for the cluster</li>
</ul>

<h2 id="enable-insights-on-the-cluster">Enable Insights on the cluster</h2>

<p>Open <strong>Monitoring &gt; Insights</strong>, select <strong>Get started</strong>, then create:</p>

<ul>
  <li>A <strong>Data Collection Rule</strong></li>
  <li>A <strong>DCR endpoint name</strong></li>
  <li>A <strong>Log Analytics Workspace</strong></li>
</ul>

<p>If you already use Insights you can keep your existing workspace and rule.</p>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/InsightsGetStarted.webp" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/InsightsGetStarted.webp" alt="Get started with Insights" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/NewDataCollectionRule.webp" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/NewDataCollectionRule.webp" alt="Create Data Collection Rule" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/InsightsGetStarted2.webp" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/InsightsGetStarted2.webp" alt="Get started with Insights" style="border: 2px solid grey;" />
</a></p>

<p>Once created, agents install on each node and a basic set of signals starts to flow. Initial ingestion can take about fifteen minutes. The default rule includes a few performance counters and event logs. The workbook extends this to include VM level views.</p>

<h2 id="extend-the-data-collection-rule">Extend the Data Collection Rule</h2>

<p>To power the VM states and per VM performance, add the following data sources to the <strong>existing</strong> DCR. A <strong>60 second</strong> sample rate works well in practice. It keeps costs low while keeping charts responsive.</p>

<h3 id="windows-event-logs-for-vm-state">Windows Event Logs for VM state</h3>

<p>In your DCR open <strong>Data sources &gt; Windows Event Logs &gt; Custom</strong> and add both filters below.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Microsoft-Windows-Hyper-V-Worker-Admin![System[(EventID=18500 or EventID=18502 or EventID=18504 or EventID=18510 or EventID=18512 or EventID=18514 or EventID=18516 or EventID=18518 or EventID=18596 or EventID=18601)]]
</code></pre></div></div>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Microsoft-Windows-Hyper-V-VMMS-Admin![System[(EventID=13002 or EventID=13003)]]
</code></pre></div></div>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/WindowsEventlogs.webp" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/WindowsEventlogs.webp" alt="Windows Event Logs in DCR" style="border: 2px solid grey;" />
</a></p>

<p>These events capture VM lifecycle from the Hyper-V view. The workbook uses them to build a timeline of <strong>Running</strong>, <strong>Off</strong>, <strong>Saved</strong>, <strong>Paused</strong>, <strong>Deleted</strong>, <strong>Created</strong> and more.</p>

<h3 id="performance-counters-for-cpu">Performance counters for CPU</h3>

<p>In your DCR open <strong>Data sources &gt; Performance Counters &gt; Custom</strong> and add the counters below to chart per VM CPU and hypervisor time.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\Hyper-V Hypervisor Virtual Processor()% Guest Run Time
\Hyper-V Hypervisor Virtual Processor()% Total Run Time
\Hyper-V Hypervisor Virtual Processor(*)% Hypervisor Run Time
\Hyper-V Hypervisor Logical Processor(_Total)% Total Run Time
</code></pre></div></div>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/CPUPerformanceCounters.webp" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/CPUPerformanceCounters.webp" alt="CPU performance counters" style="border: 2px solid grey;" />
</a></p>

<h3 id="performance-counters-for-network">Performance counters for Network</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\Hyper-V Virtual Network Adapter(*)\Bytes Received/sec
\Hyper-V Virtual Network Adapter(*)\Bytes Sent/sec
\Hyper-V Virtual Switch(*)\Bytes Received/sec
\Hyper-V Virtual Switch(*)\Bytes Sent/sec
</code></pre></div></div>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/NetworkPerformanceCounters.webp" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/NetworkPerformanceCounters.webp" alt="Network performance counters" style="border: 2px solid grey;" />
</a></p>

<h3 id="performance-counters-for-memory">Performance counters for Memory</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\Hyper-V Dynamic Memory VM(*)\Guest Available Memory
\Hyper-V Dynamic Memory VM(*)\Guest Visible Physical Memory
</code></pre></div></div>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/RAMPerformanceCounters.webp" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/RAMPerformanceCounters.webp" alt="Memory performance counters" style="border: 2px solid grey;" />
</a></p>

<p>I plan to add more counters over time. When that happens I will update the workbook introduction and this post.</p>

<h2 id="cross-check-with-vmfleet">Cross check with VMFleet</h2>

<p>If you are new to <strong>VMFleet</strong>, it is a handy PowerShell module to view cluster state from a single dashboard.</p>

<p>Run the following from a machine that can reach the cluster and with a user that has administrative rights.</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Install-Module</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="s2">"VMFleet"</span><span class="w">
</span><span class="n">Import-Module</span><span class="w"> </span><span class="nx">VMFleet</span><span class="w">
</span><span class="n">Watch-FleetCluster</span><span class="w"> </span><span class="nt">-Cluster</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">ClusterName</span><span class="err">&gt;</span><span class="w"> </span><span class="nt">-Sets</span><span class="w"> </span><span class="o">*</span><span class="w">
</span></code></pre></div></div>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/VMFleet.webp" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/VMFleet.webp" alt="VMFleet dashboard" style="border: 2px solid grey;" />
</a></p>

<p>The VMFleet view is a great way to validate what you see in the workbook and get a live insights from what´s happening in the cluster.</p>

<h2 id="workbook-layout">Workbook layout</h2>

<p>The workbook ships with the following sections:</p>

<ul>
  <li><strong>Overview</strong><br />
Quick health and Workbook information.</li>
  <li><strong>VM States</strong><br />
Timeline and counts based on Hyper-V events. Filter by host and time.</li>
  <li><strong>CPU</strong><br />
Per VM and per host charts using guest and hypervisor run time.</li>
  <li><strong>Storage</strong><br />
Capacity and trends from Insights data.</li>
  <li><strong>Network</strong><br />
Per VM and per switch throughput.</li>
  <li><strong>RAM</strong><br />
Guest Available and Guest Visible memory for density planning.</li>
</ul>

<h2 id="version-indicator">Version indicator</h2>

<p>The workbook includes a simple image based version hint. If you see <strong>Current Version</strong> in green, you are on the latest release. If you see <strong>Need Update</strong> in blue, there is a newer build with fixes or features.</p>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/current-version.webp" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/current-version.webp" alt="Current Version" style="border: 2px solid grey; width: 20%; height: auto;" />
</a></p>

<p><a href="/assets/img/post/2025-10-31-azure-local-deep-insights/need-update.webp" target="_blank">
  <img src="/assets/img/post/2025-10-31-azure-local-deep-insights/need-update.webp" alt="Need Update" style="border: 2px solid grey; width: 20%; height: auto;" />
</a></p>

<h2 id="roadmap">Roadmap</h2>

<p>Planned additions include <strong>AKS</strong> and <strong>AVD</strong> views that reuse the same pipeline. Priority depends on adoption, reported issues, and spare time for development.</p>

<h2 id="changelog">Changelog</h2>

<table>
  <thead>
    <tr>
      <th>Version</th>
      <th>Features</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1.0.0</td>
      <td>Initial release with sections Overview, VM States, CPU, Storage, Network, and RAM</td>
    </tr>
  </tbody>
</table>]]></content><author><name>Cristian Schmitt Nieto</name></author><category term="Blog" /><category term="Azure Stack HCI" /><category term="Azure Local" /><category term="Monitoring" /><category term="Workbook" /><summary type="html"><![CDATA[A practical workbook for Azure Local that extends Insights with guest VM visibility, richer performance counters, and easy deployment.]]></summary></entry><entry><title type="html">Awesome Azure Local</title><link href="https://schmitt-nieto.com/blog/awesome-azure-local/" rel="alternate" type="text/html" title="Awesome Azure Local" /><published>2025-08-09T00:00:00+02:00</published><updated>2026-05-29T00:00:00+02:00</updated><id>https://schmitt-nieto.com/blog/awesome-azure-local</id><content type="html" xml:base="https://schmitt-nieto.com/blog/awesome-azure-local/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Azure Local brings Azure services into your data center with a consistent control plane. This page collects the docs, guides, and labs I use when planning and operating Azure Local environments. It mirrors my public GitHub list so you can search it directly on this site and keep track of updates.</p>

<p>GitHub source: <a href="https://github.com/schmittnieto/awesome-azure-local">https://github.com/schmittnieto/awesome-azure-local</a></p>

<p><strong>Who is this for</strong></p>
<ul>
  <li>Cloud architects and platform engineers designing hybrid setups</li>
  <li>AVD administrators building or running desktops on Azure Local</li>
  <li>Operations teams that want proven references for day to day work</li>
</ul>

<p><strong>What you will find</strong></p>
<ul>
  <li>Official documentation and learning paths</li>
  <li>AVD on Azure Local</li>
  <li>AKS on Azure Local</li>
  <li>OEM notes and reference designs</li>
  <li>Tools, scripts, and community write ups</li>
</ul>

<p><strong>How to use it</strong></p>
<ul>
  <li>Use the table of contents to jump to a topic</li>
  <li>Press Ctrl F to search within the page</li>
  <li>Open links in a new tab to keep your place</li>
</ul>

<p><em>If you spot a gap or a broken link, open an issue or pull request in the GitHub repo <a href="https://github.com/schmittnieto/awesome-azure-local/issues/new/choose">link</a>.</em></p>

<!-- AWESOMEAZURELOCAL:START -->

<h2 id="official">Official</h2>
<p><em>Only official links published or maintained by Microsoft or Azure.</em></p>

<h3 id="whats-new-in-azure-local-version-2605">What’s new in Azure Local (version 2605)</h3>

<p><a href="https://learn.microsoft.com/en-us/azure/azure-local/whats-new?view=azloc-2605">What’s new in hyperconverged deployments of Azure Local?</a></p>

<p><strong>Version:</strong> 12.2605.1003.210
<strong>Availability date:</strong> May 28, 2026
<strong>OS build:</strong> 26100.32860</p>

<p>The May 2026 release focuses on reliability improvements, updated OS and runtime baselines, and GPU metrics for Azure Local VMs using GPU Partitioning (GPU-P).</p>

<h4 id="platform-and-os">Platform and OS</h4>
<ul>
  <li>All new and existing Azure Local deployments run OS version <strong>26100.32860</strong>, downloadable from the Azure portal.</li>
  <li>Requires drivers compatible with OS <strong>26100.32860</strong> or Windows Server 2025.</li>
  <li>Integrated System and Premier solution hardware from the Azure Local Catalog includes the OS preinstalled.</li>
  <li>Work with the OEM to obtain a compatible OS image and driver package when needed.</li>
</ul>

<h4 id="runtime-updates">Runtime updates</h4>
<ul>
  <li>Platform updated to <strong>.NET 8.0.27</strong> for both .NET Runtime and ASP.NET Core.</li>
  <li>Also includes <strong>.NET 10.0.8</strong> for both .NET Runtime and ASP.NET Core.</li>
</ul>

<h4 id="gpu-monitoring">GPU monitoring</h4>
<ul>
  <li>Azure Local can now monitor <strong>GPU metrics</strong> for GPUs configured using <strong>GPU Partitioning (GPU-P)</strong>.</li>
  <li>See <a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/monitor-cluster-with-metrics?view=azloc-2605#metrics-for-gpu">Metrics for GPU</a> for details.</li>
</ul>

<h4 id="reliability">Reliability</h4>
<ul>
  <li>Includes reliability improvements and general bug fixes across platform operations.</li>
  <li>Microsoft lists <strong>no known issues specific to version 2605</strong> in the current release notes.</li>
</ul>

<h4 id="fixed-issues">Fixed issues</h4>
<ul>
  <li>Fixed an issue where Azure Local version <strong>2601 and later</strong> could experience unintended VM deletion when a platform component incorrectly classified VMs during routine system operations.</li>
  <li>Fixed an issue where the <code class="language-plaintext highlighter-rouge">az stack-hci-vm stop</code> command could fail when using CLI version <strong>1.14.x</strong> against clusters running versions prior to <strong>2604</strong>.</li>
  <li>See the <a href="https://learn.microsoft.com/en-us/azure/azure-local/known-issues?view=azloc-2605#fixed-issues">Azure Local 2605 fixed issues</a> release notes for the official list.</li>
</ul>

<h3 id="azure-local">Azure Local</h3>

<ul>
  <li><a href="https://azure.com/hci">Azure Local Product Page</a><br />
Official product page for Azure Local on the Azure website.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/azure-local/overview">What is Azure Local (Microsoft Docs)</a><br />
Introduction to Azure Local (formerly Azure Stack HCI) and its core components.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/azure-local/whats-new">What is new in Azure Local (Microsoft Docs)</a><br />
Lists the latest features and improvements available in Azure Local.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/azure-local/deploy/deployment-introduction">Azure Local Deployment (Microsoft Docs)</a><br />
First article in a series that describes how to deploy Azure Local.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/azure-local/deploy/enable-external-storage?view=azloc-2605&amp;tabs=Dell-PowerStore">External SAN Storage for Azure Local (Microsoft Docs)</a>
GA support for external Fibre Channel SAN storage in Azure Local 2604 and later, including MPIO, cluster validation, CSV integration, and Storage Path configuration.</li>
  <li><a href="https://azure.microsoft.com/en-us/pricing/details/azure-local/">Azure Local Pricing</a><br />
Overview of licensing options, cost model, and subscription details.</li>
  <li><a href="https://azurelocalsolutions.azure.microsoft.com/#/catalog">Azure Local Hardware Catalog</a><br />
Certified hardware from Microsoft partners.</li>
  <li><a href="https://azurelocalsolutions.azure.microsoft.com/#/sizer">Azure Local Sizer</a><br />
Tool that estimates hardware requirements based on selected parameters.</li>
  <li><a href="https://learn.microsoft.com/en-us/windows-server/get-started/azure-hybrid-benefit?tabs=azure-local#getting-azure-hybrid-benefit">Azure Hybrid Benefit on Azure Local (Microsoft Docs)</a><br />
Link describing the contractual requirements for using Azure Hybrid Benefit with Azure Local.</li>
  <li><a href="https://azurelocalsolutions.azure.microsoft.com/#/Learn">Azure Local Solutions Category</a><br />
Overview of Azure Local solution types, outlining the differences between Validated Systems, Integrated Systems, and Premier solution.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/azure-local/security-book/overview">Azure Local Security Book (Microsoft Docs)</a><br />
The Azure Local security book discusses in detail the built-in security layers found in Azure Local, from core to cloud.</li>
  <li><a href="https://techcommunity.microsoft.com/blog/AzureArchitectureBlog/optimize-azure-local-using-insights-from-a-well-architected-review-assessment/4458433">Optimize Azure Local using insights from a Well-Architected Review Assessment</a><br />
Guidance on evaluating Azure Local environments with the Well-Architected Framework assessment to identify risks, measure maturity, and improve architecture quality.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/architecture/hybrid/azure-local-baseline">Azure Local Baseline Architecture</a><br />
Baseline reference architecture providing workload-agnostic guidance for configuring Azure Local 2311 and later, ensuring a reliable platform for highly available virtualized and containerized workloads.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-local">Architecture Best Practices for Azure Local</a><br />
Guidance aligned with the Azure Well-Architected Framework that outlines architectural recommendations for Azure Local and Azure Arc, supporting hybrid and edge deployments across validated hardware.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/azure-local/concepts/rack-aware-cluster-overview">Rack Aware Cluster (Microsoft Docs)</a><br />
This article provides an overview of the Azure Local rack aware clustering feature, including its benefits, use cases, supported configurations, and deployment requirements. Applies only to new deployments of Azure Local.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/azure-local/concepts/sdn-overview">SDN enabled by Arc on Azure Local (Microsoft Docs)</a><br />
This article explains Software Defined Networking (SDN) enabled by Azure Arc on Azure Local. It describes SDN management methods, guidance on when to use each approach, and outlines supported and unsupported SDN scenarios.</li>
  <li><a href="https://techcommunity.microsoft.com/blog/azurearcblog/what%E2%80%99s-new-in-azure-local-cloud-infrastructure-for-distributed-locations-enabled/4469773">What’s new in Azure Local for distributed locations (Tech Community)</a><br />
Summary of Azure Ignite 2025 announcements highlighting SAN support (Preview), rack aware clustering (Preview), NVIDIA RTX PRO 6000 Blackwell Server Edition GPU support (GA), Azure Local for larger deployments (Preview), network segmentation (GA) and local identity with Azure Key Vault (Preview).</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/azure-local/deploy/about-private-endpoints">Private Endpoints on Azure Local (Microsoft Docs)</a><br />
Overview of Azure Private Endpoints on Azure Local, including supported and unsupported scenarios, connectivity requirements, and key considerations for secure access to Azure services from on-premises environments.</li>
</ul>

<h3 id="avd">AVD</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/">Azure Virtual Desktop documentation (Microsoft Docs)</a><br />
Complete documentation for deploying and managing Azure Virtual Desktop.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/virtual-desktop/deploy-azure-virtual-desktop">Deploying AVD on Azure Local (Microsoft Docs)</a><br />
Step-by-step guide for running Azure Virtual Desktop in an Azure Local environment.</li>
  <li><a href="https://azure.microsoft.com/en-us/pricing/details/virtual-desktop/">AVD on Azure Local pricing</a><br />
To view pricing for Azure Virtual Desktop on Azure Local, open the “Pricing overview tab” (the rate is currently “<em>$0.01 per virtual core per hour</em>”).</li>
</ul>

<h3 id="aks">AKS</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/aks/aksarc/cluster-architecture">Architecture overview for AKS on Azure Local (Microsoft Docs)</a><br />
Architecture overview for running AKS clusters on Azure Local.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/aks/aksarc/aks-create-clusters-portal">AKS Deployment on Azure Local (Microsoft Docs)</a><br />
How to create a Kubernetes cluster in the Azure portal; clusters are Azure Arc-connected by default.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/azure-arc/data/managed-instance-overview">SQL Managed Instance enabled by Azure Arc (Microsoft Docs)</a><br />
Azure SQL Managed Instance that runs on your infrastructure of choice through Arc Data Services inside an AKS cluster.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/aks/aksarc/deploy-ai-model?tabs=portal">KAITO - Kubernetes AI toolchain operator (Microsoft Docs)</a><br />
This article describes how to deploy an AI model on AKS enabled by Azure Arc with the Kubernetes AI toolchain operator (KAITO).</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/architecture/example-scenario/hybrid/aks-baseline">Azure Kubernetes Service (AKS) Baseline Architecture for AKS on Azure Local</a><br />
Scenario describing how to design and implement a baseline architecture for Azure Kubernetes Service (AKS) running on Azure Local.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/architecture/example-scenario/hybrid/aks-hybrid-azure-local">Deploy and operate apps with AKS enabled by Azure Arc on Azure Local</a><br />
Recommendations for building an app deployment pipeline for containerized workloads using AKS enabled by Azure Arc on Azure Local, with guidance for GitOps-based operations.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/aks/aksarc/scale-requirements">AKS on Azure Local scale requirements</a><br />
This article describes the minimum and maximum supported scale limits for AKS on Azure Local clusters and node pools.</li>
</ul>

<h3 id="backup-and-disaster-recovery">Backup and Disaster Recovery</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/backup/back-up-azure-stack-hyperconverged-infrastructure-virtual-machines">Back up Azure Local virtual machines with Azure Backup Server (Microsoft Docs)</a><br />
How to back up virtual machines on Azure Local by using Microsoft Azure Backup Server.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/azure-site-recovery">Azure Site Recovery on Azure Local (preview) (Microsoft Docs)</a><br />
Guide to protect Windows and Linux workloads on Azure Local during a disaster.</li>
</ul>

<h3 id="github-repositories">GitHub Repositories</h3>

<ul>
  <li><a href="https://jumpstart.azure.com/azure_jumpstart_localbox/getting_started">Jumpstart Local Box</a> <br />
LocalBox is a turnkey solution that provides a complete sandbox for exploring Azure Local capabilities and hybrid cloud integration in a virtualized environment (hosted on Azure).</li>
  <li><a href="https://github.com/microsoft/azure_arc">Arc Jumpstart source code</a><br />
Source for Arc Jumpstart automation scripts and tools, supporting the official documentation site.</li>
  <li><a href="https://github.com/Azure/AzureLocal-Supportability">Azure Local Supportability Forum</a><br />
Central repository for troubleshooting guides, known issues, and feedback used by support teams and the community.</li>
  <li><a href="https://github.com/Azure-Samples/AzureLocal">Azure Local sample repository</a><br />
Samples covering SDN training, security baselines, and alternate OS image download links such as the <a href="https://github.com/Azure-Samples/AzureLocal/blob/main/os-image/os-image-tracking-table.md">OS image tracking table</a>.</li>
  <li><a href="https://github.com/microsoft/MSLab">MSLab</a><br />
Scripts and resources to create nested Hyper-V labs, ideal for testing Azure Local in a virtual environment.</li>
</ul>

<hr />

<h2 id="oems">OEMs</h2>
<p><em>Resources from key original equipment manufacturers with dedicated Azure Local content.</em></p>

<h3 id="sbe">SBE</h3>

<ul>
  <li><a href="https://aka.ms/AzureStackSBEUpdate/DellEMC">Dell Azure Local SBE Updates</a><br />
Main entry point for Dell firmware and driver update bundles validated for Azure Local.</li>
  <li><a href="https://aka.ms/AzureStackSBEUpdate/Lenovo">Lenovo Azure Local SBE Updates</a><br />
Main entry point for Lenovo firmware and driver update bundles validated for Azure Local.</li>
  <li><a href="https://aka.ms/AzureStackSBEUpdate/HPE">HPE Azure Local SBE Updates</a><br />
Main entry point for HPE firmware and driver update bundles validated for Azure Local.</li>
</ul>

<h3 id="dell">Dell</h3>

<ul>
  <li><a href="https://www.dell.com/en-us/shop/ax-system-for-azure-local/sf/ax-system-for-azure-local">Dell - Azure Local Landing Page</a><br />
Dell landing page for Azure Local.</li>
  <li><a href="https://infohub.delltechnologies.com/de-de/t/guides-azure-stack-hci-os-24h2-or-ws-2025-and-later/">Dell - Deployment Guides for Azure Local</a><br />
Technical guides for Dell AX System for Azure Local or Dell AX System for Windows Server with operating system version 24H2 or Windows Server 2025 and later.</li>
  <li><a href="https://github.com/DellGEOS/AzureLocalHOLs">Dell - Azure Local Hands on Labs (GitHub)</a><br />
Detailed guides on building a lab for Azure Local, tips, and deep dives.</li>
  <li><a href="https://dell.github.io/azurestack-docs/docs/hci/">Dell - Dell Technologies Solutions for Microsoft Azure - Azure Local</a><br />
Website backed by the Dell GitHub repository that lists supported versions and architectural guidance for Azure Local.</li>
  <li><a href="https://infohub.delltechnologies.com/t/microsoft-hci-solutions-from-dell-technologies-1/">Dell - Azure Local InfoHub</a><br />
Main page that aggregates the Dell Azure Local resources mentioned above.</li>
  <li><a href="https://www.dell.com/support/kbdoc/en-us/000224407/dell-for-microsoft-azure-stack-hci-ax-hardware-updates-release-notes">Dell - SBE Page</a><br />
Page for managing firmware and driver updates on Dell hardware.</li>
  <li><a href="https://www.delltechnologies.com/asset/en-us/products/converged-infrastructure/technical-support/reliable-performance-at-scale-white-paper.pdf">Dell - External Storage with PowerFlex for Azure Local (White Paper)</a><br />
White paper explaining the possibility and results of adding external storage to Azure Local as Cluster Storage using Dell PowerFlex (currently the only supported option).</li>
  <li><a href="https://www.dell.com/support/kbdoc/en-us/000195872/how-to-expand-a-csv-in-ps-and-wac">Dell - How to Expand a CSV in PowerShell and Windows Admin Center</a><br />
Guide explaining how to expand a Cluster Shared Volume (CSV) or Virtual Disk in Storage Spaces Direct (S2D) using PowerShell and Windows Admin Center.</li>
</ul>

<h3 id="hpe">HPE</h3>

<ul>
  <li><a href="https://www.hpe.com/us/en/alliance/microsoft/azurelocal.html">HPE - Azure Local Landing Page</a><br />
HPE landing page for Azure Local.</li>
  <li><a href="https://support.hpe.com/hpesc/public/docDisplay?docId=sd00006156en_us&amp;docLocale=en_US">HPE - ProLiant for Azure Local Integrated Systems User Guide</a><br />
Management guide for HPE ProLiant for Azure Local, aimed at administrators who install, manage, and troubleshoot servers.</li>
  <li><a href="https://www.hpe.com/psnow/doc/a50008245enw">HPE - Solutions for Azure Local - Deployment Guide</a><br />
Technical white paper with solution guidelines and example configurations for Azure Local HCI on HPE ProLiant, Alletra, and Edgeline servers.</li>
  <li><a href="https://myenterpriselicense.hpe.com/cwp-ui/product-details/SBE_UPDATES/-/sw_free">HPE - SBE Page</a><br />
Page for managing firmware and driver updates on HPE hardware.</li>
  <li><a href="https://support.hpe.com/hpesc/public/docDisplay?docId=sd00003953en_us&amp;page=GUID-86C4BE9C-0B69-4596-B333-69D099B3DC65.html">HPE - ProLiant for Azure Local Firmware and Software Compatibility Guide</a><br />
A list of components, drivers and their status for system installation, especially useful for Validated Systems.</li>
  <li><a href="https://community.hpe.com/t5/alliances/elevating-innovation-hpe-proliant-dl380-server-premier-solution/ba-p/7257651">HPE - DL380 now part of Premier Solution category</a><br />
Announcement confirming that HPE ProLiant DL380 systems are now included in the <strong>Azure Local Premier Solution</strong> category, expanding supported configurations for enterprise and AI workloads.</li>
</ul>

<h3 id="lenovo">Lenovo</h3>

<ul>
  <li><a href="https://www.lenovo.com/us/en/resources/streams/microsoft-azure-stack-hci">Lenovo - Azure Local Landing Page</a><br />
Lenovo landing page for Azure Local.</li>
  <li><a href="https://pubs.lenovo.com/thinkagile-mx/">Lenovo - ThinkAgile MX Series for Microsoft Azure Local</a><br />
Installation and deployment guides for Azure Local and related services on Lenovo hardware.</li>
  <li><a href="https://pubs.lenovo.com/thinkagile-mx/de/mx_sbe">Lenovo - SBE Page</a><br />
Page for managing firmware and driver updates on Lenovo hardware.</li>
</ul>

<h3 id="dataon">DataON</h3>

<ul>
  <li><a href="https://www.dataonstorage.com/azurestackhci/">DataON - Azure Local Landing Page</a><br />
DataON landing page for Azure Local.</li>
  <li><a href="https://dataon.io/knowledge-base-categories/azure-stack-hci/">DataON - Azure Local Knowledge Base</a><br />
Extensive knowledge base with articles covering many Azure Local services and components.</li>
  <li><a href="https://dataon.io/dataon-quick-reference-guides/">DataON - Azure Local Quick Reference Guide</a><br />
Set of reference guides that compare Azure Local solutions and services.</li>
  <li><a href="https://dataon.io/apply-updates-to-your-azure-stack-hci-cluster-with-the-solution-builder-extension-sbe/">DataON - SBE Page</a><br />
Page for managing firmware and driver updates on DataON Hardware.</li>
</ul>

<h3 id="fujitsu">Fujitsu</h3>

<ul>
  <li><a href="https://www.fujitsu.com/de/products/computing/integrated-systems/azure-stack-hci.html">Fujitsu - Azure Local Landing Page</a><br />
Fujitsu landing page for Azure Local with product information and references.</li>
  <li><a href="https://docs.ts.fujitsu.com/dl.aspx?id=6c594a34-97fa-46b4-a0e8-1a78887524e9">Fujitsu - Azure Local Infographic</a><br />
Infographic that summarizes the Azure Local solution from Fujitsu.</li>
</ul>

<hr />

<h2 id="third-party">Third Party</h2>

<p><em>Independent vendors offering backup or AVD management solutions for Azure Local environments.</em></p>

<h3 id="backup-management">Backup Management</h3>

<p><em>Software commonly used to perform backups of Azure Local infrastructure.</em></p>

<h4 id="veeam">Veeam</h4>

<ul>
  <li><a href="https://www.veeam.com/kb4047">Veeam - Veeam Support for Azure Stack HCI</a><br />
Documentation covering backup, restore, and replication of virtual machines on the initial Azure Stack HCI by Veeam Backup &amp; Replication.</li>
  <li><a href="https://community.veeam.com/blogs-and-podcasts-57/guide-vbr-step-by-step-configure-azure-stack-hci-os-azure-local-backup-10827">Veeam - VBR step by step configure Azure Stack HCI OS - Azure Local Backup</a><br />
Community article offering a deeper technical implementation of Veeam Backup for Azure Local.</li>
</ul>

<h4 id="commvault">Commvault</h4>

<ul>
  <li><a href="https://docs.commvault.com/saas/azure_local.html">Commvault - Azure Local Configuration and Documentation</a>
Guide to install and configure Commvault for protecting workloads on Azure Local.</li>
  <li><a href="https://www.commvault.com/resources/solution-brief/commvault-for-microsoft-azure-local">Commvault - Blueprint for Azure Local</a>
Document explaining core concepts and Commvault capabilities for backing up Azure Local infrastructure.</li>
</ul>

<h3 id="avd-management">AVD Management</h3>

<p><em>Software used to manage Azure Virtual Desktop infrastructure on Azure Local.</em></p>

<h4 id="nerdio">Nerdio</h4>

<ul>
  <li><a href="https://getnerdio.com/azure-local/">Nerdio - Azure Local Landing Page</a><br />
Objective overview of Azure Local, covering architecture, edge scenarios, security, connectivity, and pricing.</li>
  <li><a href="https://nmehelp.getnerdio.com/hc/en-us/articles/34054417281165-How-can-I-integrate-AVD-resources-provisioned-to-Azure-Local-Stack-HCI-with-Nerdio-Manager">Nerdio - Integrate AVD resources provisioned to Azure Local with Nerdio Manager</a><br />
Guide to integrate existing AVD infrastructure on Azure Local into Nerdio Manager for simpler management.</li>
  <li><a href="https://nmehelp.getnerdio.com/hc/en-us/articles/25499377328909-AVD-for-Azure-Local-and-Nerdio-Manager">Nerdio - AVD for Azure Local and Nerdio Manager</a><br />
How to configure Nerdio to manage tasks on Azure Local, including golden images and host pool configuration.</li>
</ul>

<h4 id="hydra-by-login-vsi">Hydra by Login VSI</h4>

<ul>
  <li><a href="https://euc.loginvsi.com/hydra-by-login-vsi">Hydra - Landing Page</a><br />
Hydra product overview from Login VSI.</li>
  <li><a href="https://blog.itprocloud.de/AVD-Hydra-For-Azure-Stack-HCI-Deplyoment-Management/">Hydra - Imaging, Rollout and Manage Azure Virtual Desktop on Azure Local</a><br />
Article by Marcel Meurer on configuring Hydra for Azure Local.</li>
</ul>

<h4 id="citrix">Citrix</h4>

<ul>
  <li><a href="https://docs.citrix.com/en-us/citrix-virtual-apps-desktops/2507-ltsr/install-configure/connections/connection-azure-local">Citrix Virtual Desktop / App - Connecting Azure Local</a><br />
As of August 22, 2025, Citrix has published a guide on how to use Citrix Virtual Desktop and Apps with Azure Local.</li>
</ul>

<h3 id="sizing">Sizing</h3>

<p><em>Tools to estimate Azure Local sizing and choose the right hardware.</em></p>

<h4 id="acuutech">Acuutech</h4>
<ul>
  <li><a href="https://www.acuutech.com/azurelocal/">Acuutech - Azure Local Landing Page</a><br />
Objective overview of Azure Local, covering architecture, edge scenarios, security, connectivity and pricing.</li>
  <li><a href="https://www.acuutech.com/scopesys/">Acuutech - Scopesys Azure Local Sizing Tool</a><br />
Make the design, configuration and ordering of Azure Local or Windows Server solutions easy, by removing the technical complexity associated with scoping Azure Local or Windows Server environments.</li>
</ul>

<hr />

<h2 id="community">Community</h2>

<p><em>Resources that do not come from Microsoft, OEMs, or the vendors listed in the Third Party section.</em></p>

<h3 id="blog">Blog</h3>

<p><em>To avoid an excessive list, only entire blogs are referenced, not individual posts.</em></p>

<ul>
  <li><a href="https://schmitt-nieto.com/tags/#azure-local">schmitt-nieto.com</a><br />
Yes, naming my own blog first is bad form, but here I share hands-on content about Azure Local implementation and management.</li>
  <li><a href="https://hybridcore.ca/posts/adopting-azlocal-vms/">hybridcore.ca</a><br />
Blog by <a href="https://www.linkedin.com/in/rtiberiu/">Tiberiu Radu</a>  featuring, in my opinion, the best article on how to adopt (indirectly migrate) a VM from Hyper-V to Azure Local.</li>
  <li><a href="https://www.darifer.net/index.php/category/azure-local/">darifer.net</a><br />
Blog by <a href="https://www.linkedin.com/in/davidriverafer">David Rivera</a> with detailed posts in Spanish on Azure Local, covering version upgrades, deployment and comparisons with Windows Server.</li>
  <li><a href="https://mikemdm.de/tag/azure-local/">mikemdm.de</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/michael-meier-ba3b72210/">Michael Meier</a> covering the topic Azure Local and AVD Labs.</li>
  <li><a href="https://blog.graa.dev/tags/azure-local/">blog.graa.dev</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/erikgraa/">Erik Grina Raassum</a> focused on Azure Local and PowerShell implementations.</li>
  <li><a href="https://jtpedersen.com/">jtpedersen.com</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/jan-tore-pedersen-4863a82/">Jan-Tore Pedersen</a> covering Azure Local troubleshooting and insights.</li>
  <li><a href="https://www.azurelab.blog/">azurelab.blog</a><br />
Italian-language blog by <a href="https://www.linkedin.com/in/pandolfino/">Luigi Pandolfino (MVP)</a> and others about Azure Local and related topics.</li>
  <li><a href="https://www.chkja.dk/">chkja.dk</a><br />
Blog by <a href="https://www.linkedin.com/in/christoffer-klarskov-jakobsen-7b168266/">Christoffer Klarskov Jakobsen</a> featuring Azure Local implementations.</li>
  <li><a href="https://thisismydemo.cloud/tags/azure-local/">thisismydemo.cloud</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/kristopherjturner/">Kristopher Turner</a> on Azure Local and infrastructure solutions.</li>
  <li><a href="https://francescomolfese.it/en/">francescomolfese.it</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/francescomolfese/">Francesco Molfese</a> focused on Azure Local and IaC.</li>
  <li><a href="https://www.auxiliumtechtalk.com/home/categories/azure-local">auxiliumtechtalk.com</a><br />
Blog by <a href="https://www.linkedin.com/in/alyn-p-0989975b/">Alyn Peden</a> discussing real-world Azure Local scenarios.</li>
  <li><a href="https://jakewalsh.co.uk/tag/azure-local/">jakewalsh.co.uk</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/jakewalsh90/">Jake Walsh</a> on Azure Local implementations.</li>
  <li><a href="https://www.silviodibenedetto.com/">silviodibenedetto.com</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/silviodibenedetto/">Silvio Di Benedetto</a> on Azure Local and related topics.</li>
  <li><a href="https://www.hciharrison.com/">hciharrison.com</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/lee-harrison-749b7215/">Lee Harrison</a> covering all things Azure Local.</li>
  <li><a href="https://www.kennylowe.org/">kennylowe.org</a>
Blog by MVP <a href="https://www.linkedin.com/in/kennylowe1/">Kenny Lowe</a> on Azure Local and infrastructure.</li>
  <li><a href="https://www.erniecosta.com/blog/">erniecosta.com</a><br />
Blog by MVP <a href="https://www.linkedin.com/in/erniecosta/">Ernie Costa</a> focusing on Azure Local, Storage Spaces Direct and services.</li>
  <li><a href="https://www.thomasmaurer.ch/">thomasmaurer.ch</a><br />
Blog by former Microsoft employee <a href="https://www.linkedin.com/in/thomasmaurer2/">Thomas Maurer</a> (Principal Program Manager &amp; Chief Evangelist for Azure Hybrid) covering a wide range of Azure services, including Azure Local.</li>
  <li><a href="https://www.gettothe.cloud/">gettothe.cloud</a><br />
Blog by <a href="https://www.linkedin.com/in/aterneuzen">Alex ter Neuzen</a> focused mainly on AVD, Azure Local and IaC. I highly recommend reading it.</li>
  <li><a href="https://azurelocal.cloud/">azurelocal.cloud</a><br />
New website by MVP <a href="https://www.linkedin.com/in/kristopherjturner">Kristopher Turner</a> with scripts, deployments and Azure Local guidance. In my view, it is currently one of the best IaC resources in the Azure Local space.</li>
</ul>

<h3 id="linkedin">LinkedIn</h3>

<p><em>Most day-to-day news on Azure Local arrives first on LinkedIn. Here are two profiles worth following.</em></p>

<ul>
  <li><a href="https://www.linkedin.com/in/darrylvanderpeijl/">Darryl van der Peijl</a><br />
One of the most active MVPs posting news and technical content. He also runs the <a href="https://www.linkedin.com/newsletters/7094952705042841602/">Azure Local Insider</a> newsletter, which I recommend.</li>
  <li><a href="https://www.linkedin.com/in/dinobordonaro/">Dino Bordonaro</a><br />
The MVP who brought me into this space. Practical content, including the article <em><a href="https://www.linkedin.com/pulse/why-expensive-azure-local-hardware-becomes-datacenter-dino-bordonaro-mw0ie/">Why Expensive Azure Local Hardware Becomes Datacenter Decoration (7 Mistakes That Turn Investment Into Inventory)</a></em>.</li>
  <li><a href="https://www.linkedin.com/in/svenlangenfeld/">Sven Langenfeld</a><br />
Former Microsoft Senior Azure Local Commercial Sales Specialist (DACH) who leads a large Azure Local community across technical and business topics. Founder of the LinkedIn group <a href="https://www.linkedin.com/groups/12885745/">Azure Local Tech Talk</a>.</li>
  <li><a href="https://www.linkedin.com/in/manfredhelber/">Manfred Helber</a><br />
Germany-based MVP active in community events and live streams.</li>
  <li><a href="https://www.linkedin.com/in/karl-wester-ebbinghaus-a41507153/">Karl Wester-Ebbinghaus</a><br />
Germany-based MVP who contributes extensively to the Azure Local Tech Talk channel.</li>
  <li><a href="https://www.linkedin.com/in/florianklaffenbach/">Flo Fox</a><br />
Former Microsoft Senior Technical Program Manager (Azure Risk) who runs the Hybrid Friends YouTube channel.</li>
</ul>

<h3 id="youtube">YouTube</h3>

<p><em>Channels that focus primarily on Azure Local rather than hosting only an occasional video.</em></p>

<ul>
  <li><a href="https://youtube.com/@alexanderortha8490">Azure Hybrid Insider</a><br />
YouTube channel managed by Alexander Ortha, focused on Azure Arc, Azure Local, and hybrid integrations across Azure.</li>
  <li><a href="https://www.youtube.com/@thehybridfriends">The Hybrid Friends</a><br />
Practical use cases and deep dives in the Azure Local space.</li>
  <li><a href="https://www.youtube.com/@ManfredHelber">Manfred Helber</a><br />
German- and English-language channel by MVP Manfred Helber featuring <em>Azure Local Show</em>, a weekly update on Azure Local news.</li>
  <li><a href="https://www.youtube.com/@CarstenRachfahl">Carsten Rachfall</a><br />
German-language channel by MVP Carsten Rachfall streaming Azure Local and Azure Virtual Desktop implementations.</li>
  <li><a href="https://youtube.com/playlist?list=PLJBGLF8tZlXNPqodqi33xXokfBH3gd4yx&amp;si=ZByGRqDkgJlFnyRu">I am IT Geek - Shabaz Darr</a><br />
Practical use cases by MVP Shabaz Darr covering topics like Azure Arc and Hybrid Kubernetes.</li>
</ul>

<h3 id="github-repos--tools">Github Repos &amp; Tools</h3>

<ul>
  <li><a href="https://github.com/schmittnieto/AzSHCI">schmittnieto - AzSHCI (GitHub)</a> <br />
This repository brings together multiple scripts, each with its own purpose and structure, allowing you to spin up a fully functioning Azure Local environment quickly.</li>
  <li><a href="https://github.com/bfrankMS/AzureLocal_AzStackHCI">bfrankMS - AzureLocal_AzStackHCI (GitHub)</a><br />
Azure Local repository with findings on automating installations of HCI, AKS, and AVD.</li>
  <li><a href="https://github.com/jonathan-vella/azure-local-sizing-guides">Azure Local Sizing Guides (GitHub)</a><br />
Azure Local Sizing Guides provides comprehensive documentation, best practices, and tools for deploying and managing Azure services, such as AKS, AVD, and Arc-enabled SQL Managed Instance, on Azure Local. This repository is maintained by <a href="https://www.linkedin.com/in/jonathanvella/">Jonathan Vella</a>, Senior Cloud Solution Architect at Microsoft.</li>
  <li><a href="https://techcommunity.microsoft.com/blog/windowsservernewsandbestpractices/introducing-the-vm-conversion-tool-in-windows-admin-center-%E2%80%93-public-preview/4446604">VMWare to Hyper-V VM Conversion tool in Windows Admin Center (Tool)</a><br />
This agentless, cost-free tool streamlines the conversion of virtual machines from VMware to Windows Server with Hyper-V.</li>
  <li><a href="https://s2d-calculator.com/">S2D Capacity Calculator (Tool)</a><br />
Use this Storage Spaces Direct Calculator to estimate storage capacity, resiliency, and hardware requirements for your Storage Spaces Direct (S2D) deployment.</li>
  <li><a href="https://schmitt-nieto.com/azurelocal-calculator/">Azure Local Calculator (Tool)</a><br />
A calculator currently focused mainly on pricing, since storage is covered by S2D Calculator and CPU is a separate track; created by me and available open source at <a href="https://github.com/schmittnieto/AzureLocal-Calculator">Azure Local Calculator</a>.</li>
  <li><a href="https://www.linkedin.com/posts/drazen-nikolic-816906142_avd-microsoft-azurevirtualdesktop-ugcPost-7364022385827557376-NEle">AVD - FSLogix Profile Status (Tool)</a><br />
After the deprecation of FXTray, it became difficult to check the status of FSLogix profiles. With this PowerShell script, it is once again possible to verify profile status in a simple and centralized way.</li>
  <li><a href="https://azure.github.io/odinforazurelocal/">Odin for Azure Local (Tool)</a><br />
Odin, inspired by the Norse god of strategy and architecture, is an Optimal Deployment and Infrastructure Navigator for Azure Local. It provides a decision-tree interface to help select the appropriate Azure Local deployment type and instance design based on validated architecture and network configuration guidance.</li>
  <li><a href="https://techcommunity.microsoft.com/blog/azurearchitectureblog/azure-local-lens-workbook%e2%80%94deep-insights-at-scale-in-minutes/4490608?WT.mc_id=AZ-MVP-5001191">Azure Local LENS Workbook (Tool)</a><br />
A community-driven Azure Workbook that delivers deep insights into the status, compliance, and operational trends of large Azure Local fleets in minutes.</li>
  <li><a href="https://github.com/GetToThe-Cloud/Website">GetToThe-Cloud - Website (GitHub)</a><br />
Source repository for the GetToThe.Cloud website, including the scripts used across the site, such as Terraform-based examples and other deployment resources.</li>
</ul>

<h3 id="chats--channels">Chats &amp; Channels</h3>

<ul>
  <li><a href="https://aka.ms/azurelocal-slack">Azure Local Slack Channel</a><br />
Slack channel (the real Community) managed by Darryl van der Peijl that provides community support for all Azure Local questions.</li>
</ul>

<h3 id="trainings">Trainings</h3>
<ul>
  <li><a href="https://learn.microsoft.com/en-us/training/paths/azure-local-accreditation-2025/">Azure Local Accreditation 2025</a><br />
Part of the official Microsoft Learn documentation, this training path helps you get in touch with Azure Local and its core capabilities.</li>
  <li><a href="https://360.articulate.com/review/content/6c4554d6-8ccc-4b9b-bc6b-328c7429efce/review">Azure Local Training</a> <br />
Training module covering how to deploy and register Azure Local using OEM licenses, among other key topics.</li>
</ul>

<h3 id="events">Events</h3>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Description</th>
      <th>Price</th>
      <th>Remote</th>
      <th>Date</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><del><a href="https://www.controlup.com/de/avd-techfest-2025/">AVD Tech Fest - Berlin (Germany)</a></del></td>
      <td>Community-driven event focused on Azure Virtual Desktop and Azure Local integration.</td>
      <td><del>99 €</del></td>
      <td><del>No</del></td>
      <td><del>September 10-11, 2025</del></td>
    </tr>
    <tr>
      <td><del><a href="https://register.ignite.microsoft.com/">Microsoft Ignite - San Francisco (USA)</a></del></td>
      <td>Flagship Microsoft conference featuring hybrid cloud and Azure Local sessions.</td>
      <td>2325 $</td>
      <td>Yes (Digital pass are <strong>Free</strong>)</td>
      <td>November 17-21, 2025</td>
    </tr>
    <tr>
      <td><del><a href="https://ignite.microsoft.com/en-US/sessions/BRK147?source=sessions">Microsoft Ignite 2025 - Breakout Session BRK147</a></del></td>
      <td>Discover what’s new in Azure Local, see a live demo, and hear from a customer modernizing operations and enabling AI in a regulated environment.</td>
      <td>Included in Ignite pass</td>
      <td>Yes</td>
      <td>November 18, 2025</td>
    </tr>
    <tr>
      <td><del><a href="https://www.manfredhelber.de/hybrit-conference-2025/">HybrIT - Würzburg (Germany)</a></del></td>
      <td>Two-day conference in <strong>German</strong> on Microsoft hybrid infrastructure (Windows Server, Azure Local, and Azure Arc).</td>
      <td>299€ / 599 €</td>
      <td>No</td>
      <td>November 26-27, 2025</td>
    </tr>
    <tr>
      <td><del><a href="https://connect.mc2mc.be/agenda/">MC2MC - Antwerp (Belgium)</a></del></td>
      <td>MC2MC Connect is a dynamic, full-day event for tech professionals, enthusiasts, and IT decision-makers, centered on three core Microsoft focus areas: Cloud / Hybrid, Endpoint &amp; Security, Compliance and Identity</td>
      <td>137,81€ / 162,14 €</td>
      <td>No</td>
      <td>February 05, 2026</td>
    </tr>
    <tr>
      <td><del><a href="https://expertslive.de/">Experts Live Germany 2026 - Leipzig (Germany)</a></del></td>
      <td>Community conference bringing together the German-speaking IT community around Microsoft Cloud &amp; AI, On-Premises, Hybrid, Workplace and Security. Includes sessions, demos, discussions with MVPs and Microsoft experts, plus optional deep-dive workshops.</td>
      <td>€249–€499 (net, depending on ticket type)</td>
      <td>No</td>
      <td>March 3–4, 2026</td>
    </tr>
    <tr>
      <td><a href="https://techcommunity.microsoft.com/event/windowsserver-events/windows-server-summit-2026/4501032">Windows Server Summit 2026</a></td>
      <td>Free virtual event covering Windows Server 2025 in practice, networking updates, server management roadmap and tooling, hybrid scenarios with Azure Arc, and an early look at Windows Server vNext.</td>
      <td>Free</td>
      <td>Yes</td>
      <td>May 11–13, 2026</td>
    </tr>
    <tr>
      <td><a href="https://www.cdc-germany.de/">CDC Germany 2026 - Hanau (Germany)</a></td>
      <td>Two-day Cloud &amp; Datacenter Conference focused on real-world Microsoft infrastructure topics such as Azure Local, Windows Server, Hyper-V and Hybrid Cloud.</td>
      <td>€499–€999 (net, depending on ticket type)</td>
      <td>No</td>
      <td>September 30 – October 1, 2026</td>
    </tr>
  </tbody>
</table>

<!-- AWESOMEAZURELOCAL:END -->]]></content><author><name>Cristian Schmitt Nieto</name></author><category term="Blog" /><category term="Github" /><category term="Azure Stack HCI" /><category term="Azure Local" /><summary type="html"><![CDATA[Curated catalog of Azure Local (formerly Azure Stack HCI), AVD and AKS with official and community resources updated regularly.]]></summary></entry><entry><title type="html">Nerdio Scripted Actions: Windows Scripts</title><link href="https://schmitt-nieto.com/blog/nerdio-scripted-actions-windows-scripts/" rel="alternate" type="text/html" title="Nerdio Scripted Actions: Windows Scripts" /><published>2025-05-17T00:00:00+02:00</published><updated>2025-05-17T00:00:00+02:00</updated><id>https://schmitt-nieto.com/blog/nerdio-scripted-actions-windows-scripts</id><content type="html" xml:base="https://schmitt-nieto.com/blog/nerdio-scripted-actions-windows-scripts/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Welcome to a new post! Today I’m diving into a topic I’ve discussed with countless colleagues in the Azure Virtual Desktop (AVD) community: <strong>Nerdio Scripted Actions</strong>, and in particular <strong>Windows Scripts</strong>. When I chat with fellow IT pros about how they handle AVD deployments, some lean on a variation of <a href="https://github.com/Azure/avdaccelerator">AVD Accelerator</a>, others use tools like <a href="https://getnerdio.com/">Nerdio</a> or <a href="https://www.itprocloud.com/Hydra/">Hydra</a>, and many stick with native deployment and management.</p>

<p>Personally, I avoid debates about which option is “best”, since each has its own niche and use cases. What I can say with confidence is that the projects where I’ve used Nerdio have been incredibly easy to adapt for clients, thanks to its simplicity. One feature that both I and my clients rely on heavily is <a href="https://nmehelp.getnerdio.com/hc/en-us/articles/26124327585421-Scripted-Actions-Overview">Scripted Actions</a>, specifically <a href="https://nmehelp.getnerdio.com/hc/en-us/articles/26124334667149-Scripted-Actions-for-Windows-Scripts">Windows Scripts</a>, which let you automate repetitive tasks in a very straightforward way.</p>

<p>As more scenarios emerge that require AVD without a traditional Active Directory, using scripts to configure session hosts before they even boot up is on the rise, since applying those settings via Intune can take time. With that in mind, I created the GitHub repository “<a href="https://github.com/schmittnieto/nerdio-scripted-actions">nerdio-scripted-actions</a>,” where I’ll be hosting most of the scripts I develop. More on that later!</p>

<h2 id="how-scripted-actions-work">How Scripted Actions Work</h2>

<p>Scripted Actions in Nerdio Manager are PowerShell scripts that run either on Windows VMs (Windows Scripts) or as Azure Runbooks. They let you customize and automate tasks, like installing software, configuring settings, or performing maintenance, at various points in the VM lifecycle.</p>

<p><a href="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/diagramm.png" target="_blank">
  <img src="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/diagramm.png" alt="Nerdio Scripted Actions" style="border: 2px solid grey;" />
</a></p>

<h3 id="azure-runbooks-in-nerdio">Azure Runbooks in Nerdio</h3>

<p>Azure Runbooks run your PowerShell scripts <em>outside</em> of a VM, leveraging Azure Automation. This is great for tasks that don’t require logging into each machine:</p>

<ul>
  <li>Add data disks to VMs</li>
  <li>Assign or unassign users to personal desktops</li>
  <li>Change OS disk type of stopped VMs</li>
  <li>Shrink FSLogix profiles</li>
  <li>Enable hibernation or OS disk encryption</li>
  <li>Set regional settings</li>
  <li>Create NAT Gateways</li>
  <li>Power on VMs for a specific window</li>
  <li>Update Nerdio Manager or the AVD Agent</li>
</ul>

<h3 id="windows-scripts-in-nerdio">Windows Scripts in Nerdio</h3>

<p>Windows Scripts run <em>inside</em> the VM via the Custom Script Extension. They’re perfect for installing apps, tweaking settings, or running any PowerShell code with admin rights, without interrupting user sessions.</p>

<p><a href="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/diagramm-windows.png" target="_blank">
  <img src="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/diagramm-windows.png" alt="Nerdio Scripted Actions Windows Scripts" style="border: 2px solid grey;" />
</a></p>

<p>Out of the box, Nerdio provides many ready-to-use scripts, such as:</p>

<ul>
  <li>Installing popular apps via Chocolatey (Chrome, 7zip, VSCode, Adobe Reader…)</li>
  <li>Installing Microsoft 365, Teams, OneDrive</li>
  <li>Enabling clipboard transfer or screen-capture protection</li>
  <li>Applying Windows or AVD performance optimizations</li>
  <li>Installing FSLogix or security agents (e.g., Sophos)</li>
  <li>Granting local admin rights to users</li>
  <li>Running Windows 10/11 updates</li>
  <li>Restarting the AVD Agent or adjusting Sysprep settings</li>
</ul>

<h2 id="where-can-scripted-actions-be-used">Where Can Scripted Actions Be Used?</h2>

<p>Scripted Actions in Nerdio Manager can be applied at various stages of the VM lifecycle:</p>

<ol>
  <li><strong>Desktop Images (Golden Images)</strong>
    <ul>
      <li><strong>Purpose</strong>: Customize and prepare your base images.</li>
      <li><strong>Use Cases</strong>: Install or update applications, apply system optimizations, configure settings before sealing the image.</li>
      <li><strong>Application</strong>: During the “Set as image” process, you can run scripts on the source VM or the clone VM.</li>
      <li><strong>Reference</strong>: <a href="https://nmmhelp.getnerdio.com/hc/en-us/articles/26125609569805-Update-a-Desktop-Image-and-Hosts">Update a Desktop Image and Hosts</a></li>
    </ul>
  </li>
  <li><strong>Host Pool VM Lifecycle Events</strong>
    <ul>
      <li><strong>Purpose</strong>: Automate tasks during VM provisioning and management.</li>
      <li><strong>Use Cases</strong>: Execute scripts when a VM is created, started, stopped, or deleted; install agents or configure settings during VM deployment.</li>
      <li><strong>Application</strong>: Assign scripts to specific VM lifecycle events within a host pool.</li>
      <li><strong>Reference</strong>: <a href="https://nmmhelp.getnerdio.com/hc/en-us/articles/26125616197901-Overview-of-Scripted-Actions">Overview of Scripted Actions</a></li>
    </ul>
  </li>
  <li><strong>Re-imaging Hosts</strong>
    <ul>
      <li><strong>Purpose</strong>: Apply updates or changes across existing session hosts.</li>
      <li><strong>Use Cases</strong>: Re-apply configurations or software installations; ensure consistency across all hosts after updating the base image.</li>
      <li><strong>Application</strong>: During the re-image process, scripts can execute to apply necessary changes.</li>
      <li><strong>Reference</strong>: <a href="https://nmmhelp.getnerdio.com/hc/en-us/articles/26125609569805-Update-a-Desktop-Image-and-Hosts">Update a Desktop Image and Hosts</a></li>
    </ul>
  </li>
  <li><strong>Manual Execution on Host Pools</strong>
    <ul>
      <li><strong>Purpose</strong>: Perform ad-hoc tasks across multiple VMs.</li>
      <li><strong>Use Cases</strong>: Run maintenance scripts; apply quick fixes or updates without full redeployment.</li>
      <li><strong>Application</strong>: Use the “Run script” option within a host pool to execute scripts on selected VMs.</li>
      <li><strong>Reference</strong>: <a href="https://nmmhelp.getnerdio.com/hc/en-us/articles/26125616197901-Overview-of-Scripted-Actions">Overview of Scripted Actions</a></li>
    </ul>
  </li>
  <li><strong>Scheduled Tasks</strong>
    <ul>
      <li><strong>Purpose</strong>: Automate recurring maintenance or updates.</li>
      <li><strong>Use Cases</strong>: Schedule regular updates or clean-up tasks; automate routine maintenance scripts.</li>
      <li><strong>Application</strong>: Configure scripts to run on a defined schedule within Nerdio Manager.</li>
      <li><strong>Reference</strong>: <a href="https://nmmhelp.getnerdio.com/hc/en-us/community/posts/4416937676429-Tips-And-Tricks-Keeping-your-Image-Current-with-Windows-Updates-Automatically">Keeping your Image Current with Windows Updates Automatically</a></li>
    </ul>
  </li>
</ol>

<h2 id="scripted-action-groups-in-nerdio-manager">Scripted Action Groups in Nerdio Manager</h2>

<p>Scripted Action Groups let you combine multiple scripted actions (Windows Scripts or Azure Runbooks) into one reusable group. These groups simplify automation by allowing a set of scripts to execute in sequence during tasks like VM provisioning or image updates.</p>

<h3 id="key-features">Key Features</h3>

<ul>
  <li>
    <p><strong>Sequential Execution</strong><br />
Scripts within a group run one after another in the defined order, you can rearrange them with drag &amp; drop.</p>
  </li>
  <li>
    <p><strong>Reusability</strong><br />
Apply the same group to multiple scenarios to reduce manual effort and ensure consistency.</p>
  </li>
  <li>
    <p><strong>Tag Support</strong><br />
Assign tags to groups for better organization and filtering.</p>
  </li>
</ul>

<h3 id="limitations">Limitations</h3>

<ul>
  <li><strong>Maximum of 20 Scripts per Group</strong></li>
  <li><strong>No Nesting</strong>: You cannot include one group inside another.</li>
  <li><strong>Flat Execution</strong>: The system treats each script individually; order matters.</li>
</ul>

<h2 id="my-scripted-actions-repository">My Scripted Actions Repository</h2>

<p>To help you get started with Nerdio Scripted Actions, I’ve curated a dedicated GitHub repo at <a href="https://github.com/schmittnieto/nerdio-scripted-actions">nerdio-scripted-actions</a>. Inside, you’ll find a growing collection of PowerShell scripts designed for everything from image customization to day-to-day host-pool tasks.</p>

<p>Nerdio maintains its own library under <a href="https://github.com/Get-Nerdio/NMW/tree/main/scripted-actions">NMW Scripted Actions</a>, many of which are drawn from Microsoft’s <a href="https://github.com/Azure/RDS-Templates/tree/master/CustomImageTemplateScripts">RDS-Templates</a> project. To illustrate, here are two complementary scripts:</p>

<ul>
  <li><strong>Install language packs.ps1</strong> (Nerdio): <a href="https://github.com/Get-Nerdio/NMW/blob/main/scripted-actions/custom-image-template-scripts/Install%20language%20packs.ps1">Install language packs.ps1</a></li>
  <li><strong>InstallLanguagePacks.ps1</strong> (RDS-Templates): <a href="https://github.com/Azure/RDS-Templates/blob/master/CustomImageTemplateScripts/CustomImageTemplateScripts_2024-03-27/InstallLanguagePacks.ps1">InstallLanguagePacks.ps1</a></li>
</ul>

<p>The Nerdio script begins with a standardized header that defines metadata and user-input variables. For example:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">&lt;#
  Author: Akash Chawla
  Source: https://github.com/Azure/RDS-Templates/tree/master/CustomImageTemplateScripts/CustomImageTemplateScripts_2024-03-27
#&gt;</span><span class="w">

</span><span class="c">#description: Install language packs</span><span class="w">
</span><span class="c">#execution mode: Individual</span><span class="w">
</span><span class="c">#tags: Microsoft, Custom Image Template Scripts</span><span class="w">
</span><span class="cm">&lt;#variables:
{
  "LanguageList": {
    "Description": "Select any additional languages to be added",
    "DisplayName": "Languages"
  }
}
#&gt;</span><span class="w">
</span></code></pre></div></div>

<p>In the <strong>variables</strong> section, you define the fields that end users will interact with, here, a simple language picker:</p>

<p><a href="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/variables.png" target="_blank">
  <img src="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/variables.png" alt="Nerdio Scripted Actions Variables" style="border: 2px solid grey;" />
</a></p>

<p>By hosting these scripts in your own repo, you gain full control over versioning, customizations and integration with Nerdio’s “Script repositories” feature, making your AVD automation both transparent and repeatable.</p>

<h3 id="integrating-the-repository-in-nerdio">Integrating the Repository in Nerdio</h3>

<ol>
  <li>
    <p>Go to <strong>Settings &gt; Environment &gt; Integrations &gt; Script repositories</strong>:</p>

    <p><a href="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/integration01.png" target="_blank">
  <img src="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/integration01.png" alt="Adding a custom repository to Scripted Actions 01" style="border: 2px solid grey;" />
</a></p>
  </li>
  <li>
    <p>Add the repository URL and select folders to sync:</p>

    <p><a href="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/integration02.png" target="_blank">
  <img src="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/integration02.png" alt="Adding a custom repository to Scripted Actions 02" style="border: 2px solid grey;" />
</a></p>
  </li>
  <li>
    <p>Verify the scripts under <strong>Scripted Actions &gt; Windows Scripts &gt; Filter By Source</strong>:</p>

    <p><a href="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/integration03.png" target="_blank">
  <img src="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/integration03.png" alt="Adding a custom repository to Scripted Actions 03" style="border: 2px solid grey;" />
</a></p>
  </li>
</ol>

<h3 id="my-scripts">My Scripts</h3>

<p>Currently, the repository shows three scripts, with three more in development. Here’s what you’ll find today:</p>

<ul>
  <li>
    <p><strong>Hide or Unhide Drives in File Explorer</strong><br />
Hide one or more drives (e.g., “C,D,E”) from File Explorer to simplify the UI. Users can still access them, it just cleans up the view. You can also revert the change without re-entering drive letters.
 <a href="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/script01.png" target="_blank">
   <img src="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/script01.png" alt="Hide or Unhide Drives in File Explorer" style="border: 2px solid grey;" />
 </a></p>
  </li>
  <li>
    <p><strong>Disable Office Updates Task</strong><br />
Prevent <code class="language-plaintext highlighter-rouge">SDXHelper.exe</code> from running in multi-user environments. This script disables, or re-enables, the Office update task on session hosts.
 <a href="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/script02.png" target="_blank">
   <img src="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/script02.png" alt="Disable Office Updates Task" style="border: 2px solid grey;" />
 </a></p>
  </li>
  <li>
    <p><strong>OneDrive Remote App Configuration</strong><br />
Apply the settings required to run OneDrive in AVD Remote App pools (<a href="https://learn.microsoft.com/azure/virtual-desktop/onedrive-remoteapp">Microsoft documentation</a>). This script also supports reverting the changes.
 <a href="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/script03.png" target="_blank">
   <img src="/assets/img/post/2025-05-17-nerdio-scripted-actions-windows-scripts/script03.png" alt="OneDrive Remote App Configuration" style="border: 2px solid grey;" />
 </a></p>
  </li>
</ul>

<h3 id="running-my-scripts-independently-of-nerdio">Running My Scripts Independently of Nerdio</h3>

<p>If you need to test or apply these scripts on a Windows VM without connecting to Nerdio Manager, you can execute them directly. This method is handy for quick troubleshooting or one-off tasks:</p>

<ol>
  <li><strong>Download</strong> the desired <code class="language-plaintext highlighter-rouge">.ps1</code> file from the GitHub repo to your local machine.</li>
  <li><strong>Open</strong> PowerShell as an Administrator.</li>
  <li><strong>Bypass</strong> the execution policy and run the script. For example, to hide drives “C” and “D”:</li>
</ol>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Set-ExecutionPolicy</span><span class="w"> </span><span class="nx">Bypass</span><span class="w"> </span><span class="nt">-Scope</span><span class="w"> </span><span class="nx">Process</span><span class="w"> </span><span class="nt">-Force</span><span class="w">
</span><span class="o">.</span><span class="n">\HideDrives.ps1</span><span class="w"> </span><span class="nt">-Action</span><span class="w"> </span><span class="nx">Hide</span><span class="w"> </span><span class="nt">-DrivesToHide</span><span class="w"> </span><span class="s2">"C,D"</span><span class="w">
</span></code></pre></div></div>

<p>That’s it, your script will run immediately, just as it would within Nerdio’s framework.</p>

<h3 id="how-to-collaborate">How to Collaborate</h3>

<p>I’ll keep this repo updated as new requests and use cases come up. I’m also working on integrating my scripts into the official Nerdio repository via this <a href="https://github.com/Get-Nerdio/NMW/pull/40">pull request</a>. If you want to contribute:</p>

<ul>
  <li>Open an <strong>Issue</strong> on the repo: <a href="https://github.com/schmittnieto/nerdio-scripted-actions/issues">https://github.com/schmittnieto/nerdio-scripted-actions/issues</a></li>
  <li>Fork the repo and submit a <strong>Pull Request</strong> with your scripts</li>
  <li>Not comfortable on GitHub? Feel free to reach out to me on LinkedIn and we can collaborate privately.</li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>Nerdio Scripted Actions, especially Windows Scripts, can significantly streamline your AVD deployments by automating everything from app installation to configuration tweaks. Whether you’re customizing golden images, automating host pool events, or running ad-hoc maintenance, these scripts give you the flexibility and control you need. I hope you find my repository helpful, and I’m eager to see what you build with it. Feel free to dive in, suggest enhancements, or share your own scripts!</p>

<p><strong>Links Used in This Article</strong></p>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>URL</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>AVD Accelerator</td>
      <td>https://github.com/Azure/avdaccelerator</td>
    </tr>
    <tr>
      <td>Nerdio</td>
      <td>https://getnerdio.com/</td>
    </tr>
    <tr>
      <td>Hydra</td>
      <td>https://www.itprocloud.com/Hydra/</td>
    </tr>
    <tr>
      <td>Scripted Actions Overview</td>
      <td>https://nmehelp.getnerdio.com/hc/en-us/articles/26124327585421-Scripted-Actions-Overview</td>
    </tr>
    <tr>
      <td>Windows Scripts</td>
      <td>https://nmehelp.getnerdio.com/hc/en-us/articles/26124334667149-Scripted-Actions-for-Windows-Scripts</td>
    </tr>
    <tr>
      <td>nerdio-scripted-actions</td>
      <td>https://github.com/schmittnieto/nerdio-scripted-actions</td>
    </tr>
    <tr>
      <td>NMW Scripted Actions</td>
      <td>https://github.com/Get-Nerdio/NMW/tree/main/scripted-actions</td>
    </tr>
    <tr>
      <td>Install language packs.ps1</td>
      <td>https://github.com/Get-Nerdio/NMW/blob/main/scripted-actions/custom-image-template-scripts/Install%20language%20packs.ps1</td>
    </tr>
    <tr>
      <td>RDS-Templates</td>
      <td>https://github.com/Azure/RDS-Templates/tree/master/CustomImageTemplateScripts/CustomImageTemplateScripts_2024-03-27</td>
    </tr>
    <tr>
      <td>InstallLanguagePacks.ps1 (RDS-Templates)</td>
      <td>https://github.com/Azure/RDS-Templates/blob/master/CustomImageTemplateScripts/CustomImageTemplateScripts_2024-03-27/InstallLanguagePacks.ps1</td>
    </tr>
    <tr>
      <td>Microsoft documentation</td>
      <td>https://learn.microsoft.com/azure/virtual-desktop/onedrive-remoteapp</td>
    </tr>
    <tr>
      <td>Pull request</td>
      <td>https://github.com/Get-Nerdio/NMW/pull/40</td>
    </tr>
    <tr>
      <td>Issues</td>
      <td>https://github.com/schmittnieto/nerdio-scripted-actions/issues</td>
    </tr>
  </tbody>
</table>]]></content><author><name>Cristian Schmitt Nieto</name></author><category term="Blog" /><category term="Azure Virtual Desktop" /><category term="Nerdio" /><category term="Scripted Actions" /><category term="Windows Scripts" /><summary type="html"><![CDATA[Discover how to leverage Nerdio Scripted Actions with Windows Scripts to automate Azure Virtual Desktop deployments.]]></summary></entry><entry><title type="html">Azure Local: Backup and Disaster Recovery</title><link href="https://schmitt-nieto.com/blog/azure-local-backup-and-disaster-recovery/" rel="alternate" type="text/html" title="Azure Local: Backup and Disaster Recovery" /><published>2025-03-29T00:00:00+01:00</published><updated>2025-03-29T00:00:00+01:00</updated><id>https://schmitt-nieto.com/blog/azure-local-backup-and-disaster-recovery</id><content type="html" xml:base="https://schmitt-nieto.com/blog/azure-local-backup-and-disaster-recovery/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Welcome to a new article in the Chronicloud Series. In this post, I’ll be addressing a topic that is always a key consideration when using Azure Local: <strong>Backup and Disaster Recovery</strong>.</p>

<p>If you’re accustomed to using infrastructure in Azure and haven’t yet experienced Azure Local, this subject might catch you off guard, since the backup and restore process here is completely different. Azure Local is deployed in your chosen location, whether that’s a data center, your company’s basement, or, in my case, my laptop, and it follows backup and recovery procedures that are almost identical to those used in Onpremises environments like Windows Server 2025, VMware, Nutanix, or similar systems.</p>

<p>This means that, for now, you need an on-premises backup infrastructure to secure your workloads. There is one small exception: <a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/azure-site-recovery?view=azloc-24113">Azure Site Recovery</a>, which is currently in <strong>Preview</strong> and will be discussed later in this article.</p>

<p>Throughout this post, I will explore various backup solutions and possibilities, detailing both their dependencies/requirements and their limitations. Although I won’t implement a full technical backup solution (since my testing infrastructure is too limited for such a setup and would take too long to produce a satisfactory result), I will cover Azure Site Recovery in detail as I have a few specific insights to share.</p>

<p>Additionally, I’ll delve into the topic of hydration, a subject I’ve discussed in previous articles, examining its challenges and current possibilities. In my view, this aspect plays a crucial role in the VM recovery process.</p>

<h2 id="the-challenge-hydration-and-vm-recovery">The Challenge: Hydration and VM Recovery</h2>

<p>For those who aren’t familiar with what I mean by Hydration, I’ll try to explain it simply. Hydration is a process where an Azure Local VM, managed and configured as if it were a Hyper-V VM (e.g. using PowerShell commands, Hyper-V Manager, Cluster Manager, or Windows Admin Center), is transformed into an <a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/azure-arc-vm-management-overview?view=azloc-24112">ARC VM</a>. In other words, it converts a “local” VM into a “hybrid” VM that can be managed from the Azure portal.</p>

<p>Regarding the recovery process and hydration of a VM in Azure Local, here’s what I can say:</p>
<ul>
  <li>If your goal is solely to cover the backup and recovery of VMs within a single Azure Local Cluster, I can confidently state that this is currently achievable through various solutions. Restoring the VM in the cluster returns it to its original state, meaning no hydration is needed because the VM functions normally.</li>
  <li>Conversely, if your objective is to back up and restore across different Azure Local Clusters, there are a couple of limitations and challenges to consider. The primary challenge is restoring an ARC VM in an Azure Local Cluster different from the original.
    <ul>
      <li>Since there isn’t currently a hydration service in Azure Local that allows registering (or re-registering) the VM in a cluster other than the one it was originally set up on, the only thing that gets restored is the VM as a local resource (with its CPU, RAM, storage configuration, etc.).</li>
      <li>This doesn’t mean the VM can’t be used in the new cluster; it will simply operate as a basic Hyper-V VM and won’t have the capabilities of an ARC VM since it can’t utilize the ARC Resource Bridge it was configured with.</li>
    </ul>
  </li>
</ul>

<p>As for when and how a hydration service will be implemented in Azure Local, there’s no current information available about its roadmap or status. Despite the absence of a hydration service, there are a couple of workarounds that can help you implement a local VM as an ARC VM, which I’ll explore in more detail in the next section.</p>

<h3 id="workarounds-for-hydration">Workarounds for Hydration</h3>

<p>Personally, I only know of one “functional” workaround and one “theoretical” workaround. <strong>Neither is supported or documented by Microsoft</strong>; what I’m about to describe isn’t designed or validated by Microsoft, this is simply based on my experience as a provisional measure until the service becomes available.</p>

<p>Let’s start with the functional workaround. This method uses <a href="https://learn.microsoft.com/en-ca/azure/azure-local/migrate/migration-azure-migrate-overview?view=azloc-24113">Azure Migrate (<strong>in preview</strong>)</a> and requires a server running Hyper-V to migrate the VM to Azure Local. The migration process, which I’ll detail in my next blog post (Azure Local: Planning, Sizing &amp; Migration), is as follows:
<a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/azure-migrate-workflow-1.png" target="_blank">
  <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/azure-migrate-workflow-1.png" alt="Azure Migrate Workflow" style="border: 2px solid grey;" />
</a></p>

<p>This process allows us to migrate the VM from a Hyper-V environment to Azure Local and have it appear as an ARC VM by registering it with the ARC Resource Bridge. However, if the VM we want to “migrate” is actually a restoration of a VM from <em>another Azure Local cluster</em>, a couple of preparatory steps are necessary to ensure it registers correctly in the new cluster. The most important step noted in the <a href="https://learn.microsoft.com/en-ca/azure/azure-local/migrate/migrate-hyperv-requirements?view=azloc-24113#source-hyper-v-requirements">documentation</a> is:</p>
<ul>
  <li>Verify that <strong>none</strong> of the VMs you plan to migrate have the Azure Connected Machine Agent installed. For more information, see <a href="https://learn.microsoft.com/en-ca/azure/azure-local/migrate/migrate-faq?view=azloc-24113">FAQ</a>.</li>
</ul>

<p>In other words, you need to uninstall the “Azure Connected Machine Agent” and, to avoid issues, also remove any existing resource in the Azure Portal previously linked to that VM. There are also certain limitations with this process, such as the MAC address of the network interfaces changing (<a href="https://learn.microsoft.com/en-ca/azure/azure-local/migrate/migrate-faq?view=azloc-24113&amp;tabs=vmware-and-hyper-v-vms#i-use-dhcp-reservation-for-ip-addresses-for-my-source-vms-does-migration-ensure-that-the-mac-address-is-preserved-so-that-my-migrated-vm-can-get-the-same-ip-address">link</a>). This usually isn’t a problem, but it wouldn’t be the first time that an application requires a specific MAC address due to licensing concerns 🥲.</p>

<p>That said, since my goal isn’t to describe in detail how Azure Migrate works (I’ll cover that in my next article), for those eager to understand the process, I recommend a great article by <a href="https://www.linkedin.com/in/kennylowe1/">Kenny Lowe</a> which details the migration of a local VM (located on a cluster node) to an ARC VM <strong>within the same Azure Local cluster</strong>, in other words, performing the hydration process via Azure Migrate: <a href="https://www.kennylowe.org/2024/06/03/migrate-to-hci.html/">Migrating VMs to Azure Stack HCI 23H2</a>.</p>

<p>Once the functional workaround has been discussed, we move on to the theoretical workaround, which I haven’t yet tested and have serious doubts about. The theoretical workaround is based on some responses from users in the following <a href="https://learn.microsoft.com/en-us/answers/questions/2109722/how-do-i-recover-full-vms-in-azure-stack-hci-23h2">post</a>, which states:</p>
<ul>
  <li>You can deploy a new Azure Stack HCI virtual machine in your newly redeployed cluster and then overwrite the existing virtual disk with your backup data.</li>
</ul>

<p>I personally believe this might work <strong>only if the VM wasn’t previously registered with ARC</strong> and assuming that the ARC Resource Bridge would initiate a new onboarding process upon detecting that the VM isn’t “configured correctly” (which it doesn’t). However, as mentioned, this is an approach I haven’t been able to verify, and I remain quite skeptical about its viability when restoring an ARC VM from another Azure Local cluster.</p>

<p>I plan to take some time in the coming weeks to validate the theoretical workaround and, if it proves functional, update this article to reflect my experiences. For now, though, we’ve covered enough on hydration in Azure Local, so let’s move on to the next topic, which should be the main focus of this article: Backup.</p>

<h2 id="backup">Backup</h2>

<p>This is a topic that always gives us headaches but is fundamental to any infrastructure, whether due to hardware issues, physical incidents (floods, fires…), configuration mistakes (deleted files, corrupt VMs…) or security breaches (ransomware). Without a robust backup, you’re really in trouble…</p>

<p>I won’t delve too deeply into the basic concepts of backup and recovery here, as that would make this article excessively long. Instead, I encourage you to explore these fundamentals through a few links from one of the most popular solutions my clients use (Veeam):</p>

<ul>
  <li><a href="https://www.veeam.com/blog/321-backup-rule.html">What is the 3-2-1 backup rule?</a></li>
  <li><a href="https://www.veeam.com/blog/recovery-time-recovery-point-objectives.html">RPO and RTO: What’s the Difference?</a></li>
  <li><a href="https://bp.veeam.com/vbr/">Best Practices: Assess, Design, Build, Operate &amp; Secure</a></li>
  <li><a href="https://www.veeam.com/calculators/simple/vbr/machines">Backup resource calculator</a></li>
  <li><a href="https://bp.veeam.com/security/Design-and-implementation/Hardening/Workgroup_or_Domain.html">Backup servers and repositories should not depend on the infrastructure (e.g. not be part of AD, be on a separate physical server…)</a></li>
</ul>

<p>As I mentioned in the introduction, even though Azure Local is part of Azure’s hybrid infrastructure, it does not include the native Azure Backup service. On reflection, this makes sense, as it would be very difficult, costly, and inefficient to maintain the required RPOs and RTOs by continuously backing up workloads solely over the Internet (WAN).</p>

<p>There is an approach that comes close to this, which we’ll cover later, called Azure Site Recovery (ASR). This means that if you design an Azure Local solution, you also need to design or adapt your backup strategy. In the sections that follow, I’ll discuss a couple of solutions for the various workloads that can be implemented in Azure Local, along with their dependencies, advantages, and benefits.</p>

<h3 id="host">Host</h3>

<p>Although, in theory, you could back up the hosts (while, of course, avoiding the Cluster Shared Volume), <strong>I do not recommend this practice</strong> since it is not one of Microsoft’s recommended best practices. In case one of the nodes suffers hardware damage, there is some excellent <a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/repair-server?view=azloc-24113">documentation</a> that outlines the node repair process:
<a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/repair-server-workflow-2.png" target="_blank">
  <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/repair-server-workflow-2.png" alt="Azure Migrate Workflow" style="border: 2px solid grey;" />
</a></p>

<p>That said, this guide does not apply to single-node servers. This is the only case where, besides backing up the workloads, I would recommend backing up the node itself (without needing to back up C:\ClusterStorage, as it is redundant). A failure here would constitute a “Disaster Recovery” scenario, and if we want to maintain the ARC VMs and the entire configured infrastructure, it could be a possible method to achieve that.</p>

<p>While I personally wouldn’t back up the entire nodes of a cluster, there are certain folders on each node that I like to keep copies of, and these are:</p>
<ul>
  <li>C:\ProgramData\AzureConnectedMachineAgent\Log</li>
  <li>C:\MASLogs</li>
  <li>C:\Agents</li>
  <li>C:\CloudContent</li>
  <li>C:\CloudDeployment</li>
  <li>C:\ClusterStorage\Infrastructure_1\ArcHci</li>
</ul>

<p>The last folder ideally should not be backed up, but since it contains the log of the last time the ARC Resource Bridge was provisioned in the event of Disaster Recovery and a cluster rebuild, it may contain relevant information.</p>

<h3 id="vms">VMs</h3>

<p>Since VMs are the primary workload in Azure Local (at least in my experience), there are several options for creating backups. Of the solutions I’ll present below, I want to highlight that they are just two of the <a href="https://learn.microsoft.com/en-us/azure/azure-local/concepts/utility-applications?view=azloc-24112#partner-spotlight">seven currently available</a> for Azure Local, in other words, when it comes to backing up VMs, you have plenty of choices.</p>

<p>Before diving into the two solutions I will cover, please note that depending on the workload you intend to run, it makes more or less sense to perform backups (as well as to determine the backup frequency, i.e., how many backups of the VM are performed each day). A couple of examples of this would be:</p>
<ul>
  <li><strong>AVD Multiuser Session Host</strong>: Personally, since I usually manage session hosts using Golden Images, I don’t require a backup of the VMs because the valuable data (user profiles and/or data directories) is already secured via the File Server backup.</li>
  <li><strong>SQL Server</strong>: SQL servers, due to the high volume of changes throughout the day, typically have a much more intensive backup configuration compared to other VMs. Common practices in mission-critical servers include backing up transaction logs every 30 minutes, performing incremental backups every hour, and a full backup once a day.</li>
</ul>

<p>All the solutions we will analyze (and indeed all those available) share the same problem when restoring VMs in an ALR (Alternate Location Recovery), that is, in another cluster: the VMs are restored as Hyper-V VMs rather than as ARC VMs, which is something we discussed in the Hydration section.</p>

<h4 id="microsoft-azure-backup-server">Microsoft Azure Backup Server</h4>

<p>Before anything, I want to share the official guide on how to configure <a href="https://learn.microsoft.com/en-us/azure/backup/back-up-azure-stack-hyperconverged-infrastructure-virtual-machines">Azure Local Backup with Azure Backup Server</a>, which also outlines the supported scenarios.</p>

<p>In my experience, MABS is not one of the most widespread solutions in the market (at least not in Germany 🤔), likely due to its limitations and performance compared to other infrastructure platforms (aside from Azure Local and VMware) and, conversely, the services offered by other solutions. However, it can be a more economically efficient option, as it does not incur additional licensing costs for the backup service, although it should be taken into account that for large data volumes (many terabytes), the cost of storing information in Azure Backup Vaults can be higher compared to other alternatives..</p>

<p>Regarding integration with Azure, MABS integrates natively with hybrid services (storing data in an Azure Backup Vault), which, in my view, simplifies and eases its management.</p>

<p>When it comes to backing up VMs, MABS offers the following features:</p>
<ul>
  <li><strong>Native Hyper-V/Azure Local support</strong>: Backs up VMs in an Azure Local cluster with an agent on each node.</li>
  <li><strong>Host-level backup</strong>: Protects VMs even when stored on local storage, DAS, or CSV (Cluster Shared Volumes).</li>
  <li><strong>Cluster mobility</strong>: Detects live migration; if a VM moves to a different node, MABS continues protecting it on the new host without manual intervention.</li>
  <li><strong>Limitation</strong>: It does not support moving a VM to a different cluster (only within the same cluster).</li>
</ul>

<p>Specific workload limitations/characteristics include:</p>
<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/backup/active-directory-backup-restore"><strong>Domain Controller</strong></a>: It does not offer granular restoration of individual AD objects from the MABS console (there is no “item level restore” for AD); you would need to recover a System State backup and use AD tools (or the AD Recycle Bin) to restore specific objects.</li>
  <li><a href="https://learn.microsoft.com/en-us/azure/backup/backup-azure-sql-mabs"><strong>SQL Server</strong></a>: SQL backups can be sent to an Azure Recovery Services Vault for long-term retention (up to 99 years), with storage isolated from the local infrastructure. It does not protect databases whose files reside on remote shared resources (SMB), nor certain complex scenarios of Availability Groups with mismatched names.</li>
</ul>

<p>For the proper operation and backup of the aforementioned specific workloads, Guest Agents are required, which slightly increases the complexity of the solution.</p>

<p><strong>Concurrency and parallel processing</strong>: Historically, MABS had restrictions on the number of simultaneous tasks, but in version 4 it supports up to 8 parallel backups/restorations of VMs by default (<a href="https://learn.microsoft.com/en-us/azure/backup/backup-mabs-whats-new-mabs">configurable via settings</a>).</p>

<p><strong>Storage efficiency</strong>: MABS can leverage Windows Server deduplication on its backup volumes to reduce consumed space (a strategy inherited from System Center DPM). Additionally, it compresses and encrypts the data sent to the Azure Backup Vault.</p>

<p><strong>Load on the protected systems</strong>: MABS, by using agents on each server/VM for certain tasks (for example, agents within VMs for SQL or for the System State of Domain Controllers), can impose CPU/memory usage on the guest systems during the backup window (due to VSS operations, encryption, and data transfer).</p>

<p><strong>File restoration</strong>: It allows restoring individual files or folders to their original or an alternate location. MABS v4 introduced the ability to browse recovery points in Azure without fully downloading them, making it easier to restore specific files from the cloud (<a href="https://learn.microsoft.com/en-us/azure/backup/backup-mabs-whats-new-mabs">link</a>).</p>

<p><strong>Data encryption at rest</strong>: All content backed up in the Recovery Services Vault (in Azure) is encrypted by default with 256-bit AES (<a href="https://learn.microsoft.com/en-us/azure/backup/backup-encryption">link</a>). In on-premise MABS, data stored locally on the backup server can be encrypted using BitLocker or the operating system’s EFS if needed, but <strong>there is no native encryption option in MABS</strong> for that local storage beyond what Windows provides.</p>

<p><strong>Backup immutability (protection against deletion/modification)</strong>: On-premises, MABS does not have an immutability mechanism for its backup disks beyond protecting server access. However, if you use immutability in the Recovery Services Vault and “lock” it, Azure guarantees that no backup can be deleted or altered before its expiration date according to the configured policy (<a href="https://learn.microsoft.com/en-us/azure/backup/whats-new#worm-enabled-immutable-storage-for-recovery-services-vaults-is-now-generally-available">link</a>). This adds a layer of protection against accidental or malicious deletions, even an attacker with access would not be able to delete the current backups.</p>

<p>Given all of this, if you’re starting from a “Green Field approach” and do not have highly specific backup requirements for your workloads, MABS is a solution that maybe fits your scenario. It is a Microsoft solution for a Microsoft product, and despite not having all the features that other backup providers might offer, I believe the features it does provide are more than sufficient to meet your needs.</p>

<h4 id="veeam">Veeam</h4>

<p>Why Veeam? In many of the infrastructures where I’ve implemented Azure Local or Windows Server, a backup solution was already in place, and in my experience, Veeam was the most widely adopted by my clients. I must say it offers certain benefits over MABS in terms of backup and recovery. Like every backup solution for Azure Local, it also encounters the hydration issue, meaning that its use should be evaluated based on its local infrastructure features rather than its Azure integration.</p>

<p>Without getting too lengthy, I’ll summarize the advantages Veeam brings compared to MABS, as well as the supported scenarios and requirements for integrating Veeam in Azure Local. I’ll start with the integration requirements, which are brief and specific:</p>
<ul>
  <li><strong>Integration with Windows Defender Application Control (WDAC) in Azure Local</strong>: One of the main issues I’ve seen in the past is that Veeam couldn’t be integrated into Azure Local because WDAC blocked its use. Using this <a href="https://www.veeam.com/kb4456">article</a>, you can add a supplemental policy to allow Veeam to integrate.</li>
  <li><strong>Requirements and support</strong>: The supported scenarios and requirements are detailed in this <a href="https://www.veeam.com/kb4047">article</a>. They can be summarized as:
    <ul>
      <li><strong>Minimum version of Veeam Backup &amp; Replication for Azure Local (version 25398.X)</strong>: The current minimum supported version is 12.1 (build 12.1.0.2131).</li>
      <li><strong>No support for Azure Arc VM management (Hydration)</strong>: Azure Arc VMs in a “Running” state can be backed up. Upon restore, these VMs become standard Hyper-V workloads. If a VM is restored (and the original is no longer present) within the period that Azure Arc can reconnect (45 days), the Azure Arc connection should persist if restored to the same cluster.</li>
    </ul>
  </li>
</ul>

<p>I also want to mention an issue that may occur in Azure Local Clusters running an older 22H2 version that hasn’t been updated regularly. This is the <a href="https://www.veeam.com/kb4717">“Hyper-V Resilient Change Tracking Performance Issues”</a>, where general Hyper-V OS performance degradation can occur when using a backup solution to export Hyper-V VM snapshots during backup operations. The fix involves installing the Cumulative Update from February 11 and adding the following registry value:</p>
<ul>
  <li><strong>Key Location</strong>: HKLM\SYSTEM\CurrentControlSet\Policies\Microsoft\FeatureManagement\Overrides</li>
  <li><strong>Value Name</strong>: 636159629</li>
  <li><strong>Value Type</strong>: DWORD (32-Bit) Value</li>
  <li><strong>Value Data</strong>: 1</li>
</ul>

<p>Now, let’s examine the supported scenarios and the advantages of Veeam over MABS for backing up on-premises infrastructure:</p>
<ul>
  <li><strong>Support for Hyper-V/Azure Local</strong>: Veeam backs up VMs in local clusters without needing to install agents on each machine, leveraging hypervisor-level integration.</li>
  <li><strong>Host-level backup</strong>: It protects VMs even on local storage, DAS, or CSV (Cluster Shared Volumes), ensuring continuity in environments with distributed storage.</li>
  <li><strong>Cluster mobility</strong>: Veeam automatically detects VM movements (Live Migration) and continues applying backup policies without manual intervention.</li>
  <li><strong>Additional functionality</strong>: It includes Instant VM Recovery, which allows you to boot a virtual machine directly from the backup, significantly reducing restoration times.</li>
  <li><strong>Support for additional platforms</strong>: Veeam supports backups for Proxmox, Nutanix, Oracle, and Red Hat in addition to Azure Local and VMware (<a href="https://helpcenter.veeam.com/docs/backup/vsphere/platform_support.html?ver=120">link</a>).</li>
  <li>
    <p><strong>Live Migration</strong>: Although VMs won’t be rehydrated in the new cluster, locally (as Hyper-V VMs) it is possible to move VMs between clusters while retaining the backup. In fact, you can even move VMs from other platforms (e.g., VMware) via <a href="https://www.veeam.com/blog/hyper-v-migration-simplify-moving-workloads.html">Instant Recovery</a>. That said, I personally <strong>do not recommend this approach if the goal is to migrate to Azure Local</strong>, as it would forfeit the possibility of integrating the VM as an Arc VM, a process that can be achieved with Azure Migrate, which I’ll cover in my next blog post. Here’s a schematic of the process:
<a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/Veeam-instant-recovery.png" target="_blank">
<img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/Veeam-instant-recovery.png" alt="Azure Migrate Workflow" style="border: 2px solid grey;" />
</a></p>
  </li>
  <li><strong>Workload-specific features</strong>:
    <ul>
      <li><strong>Domain Controller</strong>: Veeam protects domain controllers through its integration with VSS, ensuring consistent backups. With Veeam Explorer for Active Directory, you can perform granular restores of individual objects, making it easy to recover specific users or groups without restoring the entire system.</li>
      <li><strong>SQL Server</strong>: Veeam natively backs up SQL databases using Application-Aware Processing, ensuring data consistency during backups. It also allows sending backups to cloud repositories (e.g., Azure Blob Storage) for long-term retention. In complex scenarios (like Always On Availability Groups or databases with files on remote shared resources), specific configuration adjustments may be necessary for complete protection.</li>
    </ul>
  </li>
  <li><strong>Concurrency and parallel processing</strong>: Veeam is designed for high-demand environments, enabling multiple backup and restore tasks to run in parallel. Thanks to its distributed architecture, with scalable backup proxies and repositories, it efficiently manages large volumes of data in line with the available infrastructure capacity.</li>
  <li><strong>Storage efficiency</strong>: Veeam applies deduplication and compression techniques at the job level, significantly reducing backup storage space. It also offers the option to integrate external deduplication appliances, further optimizing storage usage, especially in environments with high data volumes or frequent changes.</li>
  <li><strong>Data encryption at rest</strong>: Veeam natively encrypts backup files using AES 256-bit (<a href="https://bp.veeam.com/vbr/Support/S_Encryption/overview.html">link</a>), ensuring that stored information, whether in local repositories or in the cloud, remains protected. This option is set at the job or repository level, providing added security against unauthorized access.</li>
  <li><strong>Backup immutability (protection against deletion/modification)</strong>: Recent versions of Veeam offer options to configure immutable repositories to protect against unauthorized deletions or modifications. This is achievable both in local repositories (using Linux systems with immutable attributes) and in cloud storage environments, leveraging the immutability features of Azure Blob Storage.</li>
</ul>

<p>Not everything is an advantage, so here are additional factors to consider when deciding on a backup infrastructure:</p>
<ul>
  <li><strong>No use of Azure Backup Vaults</strong>: Although you can configure Azure Blob Storage as the backup storage, Veeam does not use vaults natively. This means the solution isn’t integrated with Azure out-of-the-box and requires an additional management portal to handle or verify backups. Personally, I’m a fan of the configurations possible with <a href="https://helpcenter.veeam.com/docs/one/monitor/backup_alarms.html?ver=120">Veeam Backup Monitoring &amp; Replication Alarms</a>, so I don’t see this as a major limitation.</li>
  <li><strong>Know-How</strong>: While Veeam is user-friendly, integrating it into a new infrastructure requires specific prior knowledge, a topic that could easily fill 10 blog posts 😅. Veeam backs up infrastructures more effectively and efficiently, but there is an initial learning curve. They even offer a specialized certification program for experts that covers these topics in depth (<a href="https://www.veeam.com/support/training/vmce-certification.html">link</a>).</li>
  <li><strong>Licensing Costs</strong>: I won’t commit to a specific number as costs vary per infrastructure, but you can calculate expenses using their <a href="https://www.veeam.com/solutions/small-business/pricing-calculator.html">pricing calculator</a>. Compared to MABS, depending on the amount of data to back up, Veeam can be a much more expensive option.</li>
  <li><strong>Additional Infrastructure</strong>: Although Veeam can be configured with an infrastructure similar to MABS, leveraging its full potential might require designing additional infrastructure, which can incur extra monetary and operational costs.</li>
</ul>

<p>Taking all these points into account, I conclude that Veeam is a more advanced, focused, and specialized backup solution that offers many more options than MABS, though it does come with additional costs that must be planned for in advance. In my experience, especially in the German market, if a client has on-premises infrastructure and a backup system, it is very likely to be Veeam.</p>

<h3 id="trusted-launch-vms">Trusted launch VMs</h3>

<p>After covering the VMs workload in the previous section, a new question arises: how are Trusted launch VMs backed up and restored? The main difference compared to standard Azure Local VMs is the following:<br />
Trusted Launch VMs in Azure Local environments differ from standard VMs because they use a dedicated key to secure the state of the VM guest, including the virtual TPM state when it is not active. This key is kept safe in a local key vault located on the same Azure Local system as the VM. Additionally, the guest state of a Trusted Launch VM is saved in two separate files: one file contains the guest state and the other contains the runtime state. As a result, any backup or restoration process for a Trusted Launch VM must include all VM files along with the protection key.</p>

<p>I want to highlight the following message from Microsoft’s documentation regarding <a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/trusted-launch-vm-overview?view=azloc-24113#backup-and-disaster-recovery-considerations">Backup and Restore of Trusted launch VMs</a>:</p>

<blockquote>
  <p>Backup and disaster recovery tooling support: Currently, <strong>Trusted launch for Azure Local VMs do not support any third-party or Microsoft-owned backup and disaster recovery tools</strong>, including but not limited to, Azure Backup, Azure Site Recovery, Veeam, and Commvault. If there arises a need to move a Trusted launch for Azure Local TVM to an alternate cluster, see the manual process <a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/trusted-launch-vm-import-key?view=azloc-24113">Manual backup and recovery of Trusted launch for Azure Local VMs</a> to manage all the necessary files and VM protection key to ensure that the VM can be successfully restored.</p>
</blockquote>

<p>Because of this, before deploying a Trusted Launch VM, you need to consider how to back it up, as the current solution is neither elegant nor integrated into standard backup solutions. My main advice is that if you require Trusted Launch VMs, make sure to set up an automation (for example, a PowerShell script that saves the results of the manual process into a CSV which is then backed up) to ensure they are properly secured. Otherwise, you might end up with backups that cannot be used, and as they say, a backup that cannot be restored is as good as having no backup at all (even worse, since you’re wasting space and resources 😅).</p>

<p>With that in mind, the manual backup and restore process is detailed perfectly in the following summary.</p>

<h4 id="manual-backup-and-recovery-of-trusted-launch-vms">Manual backup and recovery of Trusted launch VMs</h4>

<p><strong>Overview</strong><br />
Trusted Launch Arc VMs use a VM Guest State Protection (GSP) key stored in a local key vault to secure the VM guest state (including the vTPM state). The guest state is divided into two files: VM Guest State (VMGS) and VM Runtime State (VMRS). Losing the GSP key prevents the VM from booting, so it’s essential to back up both the VM files and the GSP key regularly.</p>

<p><strong>Manual Backup Process</strong></p>

<ol>
  <li>
    <p><strong>Export the VM Files</strong><br />
Use <code class="language-plaintext highlighter-rouge">Export-VM</code> to back up all VM files (VMGS and VMRS).</p>
  </li>
  <li>
    <p><strong>Back Up the GSP Key</strong></p>
    <ul>
      <li><em>On the Azure Local system with the backup key vault:</em><br />
Create a wrapping key and download its PEM file by running:
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">New-MocKey</span><span class="w"> </span><span class="nt">-name</span><span class="w"> </span><span class="nx">wrappingKey</span><span class="w"> </span><span class="nt">-group</span><span class="w"> </span><span class="nx">AzureStackHostAttestation</span><span class="w"> </span><span class="nt">-keyvaultName</span><span class="w"> </span><span class="nx">AzureStackTvmKeyVault</span><span class="w"> </span><span class="nt">-type</span><span class="w"> </span><span class="nx">RSA</span><span class="w"> </span><span class="nt">-size</span><span class="w"> </span><span class="nx">2048</span><span class="w">
</span></code></pre></div>        </div>
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Get-MocKeyPublicKey</span><span class="w"> </span><span class="nt">-name</span><span class="w"> </span><span class="nx">wrappingKey</span><span class="w"> </span><span class="nt">-group</span><span class="w"> </span><span class="nx">AzureStackHostAttestation</span><span class="w"> </span><span class="nt">-keyvaultName</span><span class="w"> </span><span class="nx">AzureStackTvmKeyVault</span><span class="w"> </span><span class="nt">-outputFile</span><span class="w"> </span><span class="nx">wrappingKey.pem</span><span class="w">
</span></code></pre></div>        </div>
      </li>
      <li><em>On the Azure Local system hosting the VM:</em><br />
Copy the PEM file, verify the VM owner node, and retrieve the VM ID:
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Get-ClusterGroup</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">name</span><span class="err">&gt;</span><span class="w">
</span></code></pre></div>        </div>
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="n">Get-VM</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">name</span><span class="err">&gt;</span><span class="p">)</span><span class="o">.</span><span class="nf">vmid</span><span class="w">
</span></code></pre></div>        </div>
        <p>Then, export the GSP key:</p>
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Export-MocKey</span><span class="w"> </span><span class="nt">-name</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">ID</span><span class="err">&gt;</span><span class="w"> </span><span class="nt">-wrappingKeyName</span><span class="w"> </span><span class="nx">wrappingKey</span><span class="w"> </span><span class="nt">-wrappingPubKeyFile</span><span class="w"> </span><span class="nx">wrappingKey.pem</span><span class="w"> </span><span class="nt">-outFile</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">ID</span><span class="err">&gt;</span><span class="o">.</span><span class="nf">json</span><span class="w"> </span><span class="nt">-group</span><span class="w"> </span><span class="nx">AzureStackHostAttestation</span><span class="w"> </span><span class="nt">-keyvaultName</span><span class="w"> </span><span class="nx">AzureStackTvmKeyVault</span><span class="w"> </span><span class="nt">-size</span><span class="w"> </span><span class="nx">256</span><span class="w">
</span></code></pre></div>        </div>
      </li>
      <li><em>Return to the backup key vault system:</em><br />
Transfer the <code class="language-plaintext highlighter-rouge">&lt;VM ID&gt;</code> and <code class="language-plaintext highlighter-rouge">&lt;VM ID&gt;.json</code> files, and import the GSP key:
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Import-MocKey</span><span class="w"> </span><span class="nt">-name</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">ID</span><span class="err">&gt;</span><span class="w"> </span><span class="nt">-importKeyFile</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">ID</span><span class="err">&gt;</span><span class="o">.</span><span class="nf">json</span><span class="w"> </span><span class="nt">-group</span><span class="w"> </span><span class="nx">AzureStackHostAttestation</span><span class="w"> </span><span class="nt">-keyvaultName</span><span class="w"> </span><span class="nx">AzureStackTvmKeyVault</span><span class="w"> </span><span class="nt">-type</span><span class="w"> </span><span class="nx">AES</span><span class="w"> </span><span class="nt">-size</span><span class="w"> </span><span class="nx">256</span><span class="w">
</span></code></pre></div>        </div>
      </li>
    </ul>
  </li>
</ol>

<p><strong>Manual Restore Process</strong></p>

<ol>
  <li><strong>Prepare the Target System</strong><br />
On the Azure Local system where you want to restore the VM, create a new wrapping key and download its PEM file:
    <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w">  </span><span class="n">New-MocKey</span><span class="w"> </span><span class="nt">-name</span><span class="w"> </span><span class="nx">wrappingKey</span><span class="w"> </span><span class="nt">-group</span><span class="w"> </span><span class="nx">AzureStackHostAttestation</span><span class="w"> </span><span class="nt">-keyvaultName</span><span class="w"> </span><span class="nx">AzureStackTvmKeyVault</span><span class="w"> </span><span class="nt">-type</span><span class="w"> </span><span class="nx">RSA</span><span class="w"> </span><span class="nt">-size</span><span class="w"> </span><span class="nx">2048</span><span class="w">
</span></code></pre></div>    </div>
    <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w">  </span><span class="n">Get-MocKeyPublicKey</span><span class="w"> </span><span class="nt">-name</span><span class="w"> </span><span class="nx">wrappingKey</span><span class="w"> </span><span class="nt">-group</span><span class="w"> </span><span class="nx">AzureStackHostAttestation</span><span class="w"> </span><span class="nt">-keyvaultName</span><span class="w"> </span><span class="nx">AzureStackTvmKeyVault</span><span class="w"> </span><span class="nt">-outputFile</span><span class="w"> </span><span class="nx">wrappingKey.pem</span><span class="w">
</span></code></pre></div>    </div>
  </li>
  <li><strong>Export the GSP Key from the Backup</strong><br />
On the system with the backup key vault, copy the PEM file to the target system. Then, obtain the VM ID (from the VM’s config file or by executing):
    <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w">  </span><span class="p">(</span><span class="n">Get-VM</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">name</span><span class="err">&gt;</span><span class="p">)</span><span class="o">.</span><span class="nf">vmid</span><span class="w">
</span></code></pre></div>    </div>
    <p>Export the GSP key using:</p>
    <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w">  </span><span class="n">Export-MocKey</span><span class="w"> </span><span class="nt">-name</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">ID</span><span class="err">&gt;</span><span class="w"> </span><span class="nt">-wrappingKeyName</span><span class="w"> </span><span class="nx">wrappingKey</span><span class="w"> </span><span class="nt">-wrappingPubKeyFile</span><span class="w"> </span><span class="nx">wrappingKey.pem</span><span class="w"> </span><span class="nt">-outFile</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">ID</span><span class="err">&gt;</span><span class="o">.</span><span class="nf">json</span><span class="w"> </span><span class="nt">-group</span><span class="w"> </span><span class="nx">AzureStackHostAttestation</span><span class="w"> </span><span class="nt">-keyvaultName</span><span class="w"> </span><span class="nx">AzureStackTvmKeyVault</span><span class="w"> </span><span class="nt">-size</span><span class="w"> </span><span class="nx">256</span><span class="w">
</span></code></pre></div>    </div>
  </li>
  <li><strong>Import the GSP Key on the Target System</strong><br />
On the target system, copy the <code class="language-plaintext highlighter-rouge">&lt;VM ID&gt;</code> and <code class="language-plaintext highlighter-rouge">&lt;VM ID&gt;.json</code> files and import the GSP key:
    <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w">  </span><span class="n">Import-MocKey</span><span class="w"> </span><span class="nt">-name</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">ID</span><span class="err">&gt;</span><span class="w"> </span><span class="nt">-importKeyFile</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">VM</span><span class="w"> </span><span class="nx">ID</span><span class="err">&gt;</span><span class="o">.</span><span class="nf">json</span><span class="w"> </span><span class="nt">-group</span><span class="w"> </span><span class="nx">AzureStackHostAttestation</span><span class="w"> </span><span class="nt">-keyvaultName</span><span class="w"> </span><span class="nx">AzureStackTvmKeyVault</span><span class="w"> </span><span class="nt">-type</span><span class="w"> </span><span class="nx">AES</span><span class="w"> </span><span class="nt">-size</span><span class="w"> </span><span class="nx">256</span><span class="w">
</span></code></pre></div>    </div>
  </li>
</ol>

<p><strong>Important:</strong><br />
Ensure that the GSP key is restored on the target system before starting the VM. If the VM is started without the restored key, the system will generate a new GSP key, which may cause errors. In such a case, remove the incorrect key with:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Remove-MocKey</span><span class="w"> </span><span class="nt">-name</span><span class="w"> </span><span class="err">&lt;</span><span class="nx">vm</span><span class="w"> </span><span class="nx">id</span><span class="err">&gt;</span><span class="w"> </span><span class="nt">-group</span><span class="w"> </span><span class="nx">AzureStackHostAttestation</span><span class="w"> </span><span class="nt">-keyvaultName</span><span class="w"> </span><span class="nx">AzureStackTvmKeyVault</span><span class="w">
</span></code></pre></div></div>

<h3 id="cluster-storage">Cluster Storage</h3>

<p>At this point, let’s focus on Cluster Shared Volumes (CSV). Normally, additional backups of the storage aren’t required if the workloads have already been backed up. However, as I mentioned in the Host Backup section, in certain scenarios it might be useful to back up specific CSV folders. I primarily focus on the Infrastructure folders (especially their logs), and if we use Golden Images for deploying certain workloads that are stored on the CSV, you might also want to back those up.</p>

<p>Another possibility, although I don’t recommend implementing it directly, is that if your cluster is designed solely for AVD usage, you could use one of the CSVs as the storage directory for FSLogix user profiles. I wouldn’t recommend this approach directly because it implies that the cluster is in the same Active Directory as the AVD users, and in turn, it would expose a shared folder within a CSV where users can store their profiles. I am in favor of using Fabric Domains (as I mentioned in the previous article and will discuss further in the next post) that are separate from the main domain. However, I understand that if the only workload is AVD, this implementation might be considered to minimize costs and leverage the storage space and performance of the cluster.</p>

<p>I don’t want to dwell too much on this type of backup, since all backup solutions can cover this function. As noted throughout this post, such a backup is only necessary if CSVs are used for specific workloads, in which case I assume the designer will inform the person responsible for backups to ensure they are properly secured.</p>

<h3 id="key-vault">Key Vault</h3>

<p>The Key Vault required for installing Azure Local is not a typical workload. However, considering that the <a href="https://learn.microsoft.com/en-us/azure/azure-local/deploy/deployment-local-identity-with-key-vault?view=azloc-24113">Azure Local deployment with local identities without the need for Active Directory (currently in preview)</a> makes full use of the Key Vault for cluster operations, it is important to note that this component should be backed up in the future.</p>

<p>Currently, and likely in your case as well, the Key Vault contains only three secrets: the <em>AzureStackLCMUserCredential</em>, the <em>DefaultARBApplication</em>, and the <em>LocalAdminCredential</em>. These are created during installation and are valid for one year from deployment. As mentioned, these are not critical because, in case of errors (for example, if the BitLocker key is needed), they can be resolved using other methods. However, given the upcoming changes, I personally recommend taking a look at this article: <a href="https://learn.microsoft.com/en-us/azure/azure-local/deploy/deployment-local-identity-with-key-vault?view=azloc-24113#recover-a-deleted-key-vault-and-resume-backup">Recover a deleted key vault and resume backup</a>.</p>

<p>The Key Vault backup process is detailed in the following section.</p>

<h4 id="key-vault-backup-process">Key Vault Backup Process</h4>

<p><strong>Overview</strong><br />
This article outlines how to back up individual secrets, keys, and certificates from your Azure Key Vault. The backup creates an offline, encrypted snapshot of each object to protect against loss of access to your key vault.</p>

<p><strong>Key Considerations</strong></p>
<ul>
  <li><strong>Backup Scope:</strong> Each key vault object must be backed up individually; there isn’t an option to back up the entire vault in one operation.</li>
  <li><strong>Version Limits:</strong> Only up to 500 previous versions per object can be backed up. Attempting to back up objects beyond this limit may result in errors.</li>
  <li><strong>Snapshot Nature:</strong> The backup is a point-in-time encrypted blob. Because the blob cannot be decrypted outside of Azure, it must be restored within the same Azure subscription and geographic region.</li>
  <li><strong>Operational Challenges:</strong> Managing multiple backups, logs, and permissions can be complex, especially as secrets rotate or expire.</li>
</ul>

<p><strong>Prerequisites</strong></p>
<ul>
  <li>You need Contributor-level (or higher) permissions on your Azure subscription.</li>
  <li>A primary key vault containing the objects to back up and a secondary key vault where these objects can later be restored are required.</li>
</ul>

<p><strong>Backup and Restore Using the Azure Portal</strong></p>
<ul>
  <li><strong>Backup:</strong>
    <ol>
      <li>Go to your key vault in the Azure portal.</li>
      <li>Select the desired object (secret, key, or certificate) and click <strong>Download Backup</strong>.</li>
      <li>Download and securely store the encrypted blob.</li>
    </ol>
  </li>
  <li><strong>Restore:</strong>
    <ol>
      <li>In your key vault, select the object type and click <strong>Restore Backup</strong>.</li>
      <li>Locate the encrypted blob and confirm to complete the restoration.</li>
    </ol>
  </li>
</ul>

<p><strong>Backup and Restore Using Azure PowerShell</strong></p>

<ol>
  <li><strong>Log in and Set Context:</strong>
    <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Connect-AzAccount</span><span class="w">
</span><span class="nx">Set-AzContext</span><span class="w"> </span><span class="nt">-Subscription</span><span class="w"> </span><span class="s1">'{AZURE SUBSCRIPTION ID}'</span><span class="w">
</span></code></pre></div>    </div>
  </li>
  <li><strong>Backup Commands:</strong>
    <ul>
      <li>Back up a certificate:
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Backup-AzKeyVaultCertificate</span><span class="w"> </span><span class="nt">-VaultName</span><span class="w"> </span><span class="s1">'{Key Vault Name}'</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="s1">'{Certificate Name}'</span><span class="w">
</span></code></pre></div>        </div>
      </li>
      <li>Back up a key:
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Backup-AzKeyVaultKey</span><span class="w"> </span><span class="nt">-VaultName</span><span class="w"> </span><span class="s1">'{Key Vault Name}'</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="s1">'{Key Name}'</span><span class="w">
</span></code></pre></div>        </div>
      </li>
      <li>Back up a secret:
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Backup-AzKeyVaultSecret</span><span class="w"> </span><span class="nt">-VaultName</span><span class="w"> </span><span class="s1">'{Key Vault Name}'</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="s1">'{Secret Name}'</span><span class="w">
</span></code></pre></div>        </div>
      </li>
    </ul>
  </li>
  <li><strong>Restore Commands:</strong>
    <ul>
      <li>Restore a certificate:
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Restore-AzKeyVaultCertificate</span><span class="w"> </span><span class="nt">-VaultName</span><span class="w"> </span><span class="s1">'{Key Vault Name}'</span><span class="w"> </span><span class="nt">-InputFile</span><span class="w"> </span><span class="s1">'{File Path}'</span><span class="w">
</span></code></pre></div>        </div>
      </li>
      <li>Restore a key:
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Restore-AzKeyVaultKey</span><span class="w"> </span><span class="nt">-VaultName</span><span class="w"> </span><span class="s1">'{Key Vault Name}'</span><span class="w"> </span><span class="nt">-InputFile</span><span class="w"> </span><span class="s1">'{File Path}'</span><span class="w">
</span></code></pre></div>        </div>
      </li>
      <li>Restore a secret:
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Restore-AzKeyVaultSecret</span><span class="w"> </span><span class="nt">-VaultName</span><span class="w"> </span><span class="s1">'{Key Vault Name}'</span><span class="w"> </span><span class="nt">-InputFile</span><span class="w"> </span><span class="s1">'{File Path}'</span><span class="w">
</span></code></pre></div>        </div>
      </li>
    </ul>
  </li>
</ol>

<h3 id="aks">AKS</h3>

<p>We are now nearing the end of the workloads to be backed up, and of course, we cannot forget AKS Hybrid. Many may wonder why one should back up AKS when, in theory, simply backing up the repository from which AKS is provisioned would suffice. Well, yes and no. I consider the repository as a golden image; if AKS is used in a generalized manner without the need for permanent storage and if the workload itself generates the backup (through copies to external servers or by using backed-up services), then you might not require a backup for AKS since the backup of your repository is more than enough. However, if you are using permanent storage and/or services that require a backup (for example, MongoDB) that are not handled at the application level, then a dedicated backup solution is necessary.</p>

<p>To date, it is not possible to perform native backups of AKS Hybrid in Azure Local, unlike in Azure Public where AKS has its integrated backup service. Therefore, external solutions are required to carry out this process. The only solution I have considered so far is Velero, mainly because there is an article in the documentation (<a href="https://learn.microsoft.com/en-us/azure/aks/aksarc/backup-workload-cluster">Back up, restore workload clusters using Velero</a>) that explains how to do it, although it should be noted that this article applies to <strong>AKS on Azure Local 22H2, AKS on Windows Server</strong>. Since I have not yet integrated Velero in Azure Local 23H2, I cannot say what limitations it may present in the new version of Azure Loca (related to Arc Resource Bridge). Perhaps in the coming weeks, with a bit more time, I will take a closer look at this matter. That said, if your applications have been configured correctly, you likely won’t need to back them up.</p>

<p>There is an excellent guide written by <a href="https://www.linkedin.com/in/alper-can-802781b2/">Alper Can</a> that details the entire backup and restore process in Azure Local using a local backup via Minio Storage installed on an Ubuntu VM. For more information, you can check out the article <a href="https://gist.github.com/plumbery/556914f1b5a51c09a5083bb4254a2c38#backup-azure-stack-hci-aks-aks-hybrid">here</a>.</p>

<h3 id="sql-managed-instances-enabled-by-azure-arc">SQL Managed Instances enabled by Azure Arc</h3>

<p>Although this workload should technically fall under AKS, since it involves Arc Dataservices running within AKS, there is currently no native solution for backing up this workload (or at least I haven’t found adequate information on this topic so far). Therefore, I have decided to dedicate a separate section to it.<br />
Because it is nearly impossible to back up AKS, the Data Controller within it (with its custom location), and then the SQL Managed Instance enabled by Azure Arc, an ordeal in terms of recovery, I have concluded that the most effective, efficient, and straightforward method is to perform a <strong>backup using SQL Server Management Studio</strong>.<br />
Perhaps <a href="https://learn.microsoft.com/en-us/sql/tools/bcp-utility?view=sql-server-ver16&amp;tabs=windows">BCP (Bulk Copy Program)</a> could be used to automate the process, but I personally have no experience with it. From what little I have researched, there are some important considerations:</p>
<ul>
  <li>This method transfers data only. Schema objects such as stored procedures, triggers, and indexes are not transferred and must be handled separately.</li>
  <li>Ensure that the target tables exist in the destination database before importing.</li>
</ul>

<p>Once I have a larger lab where I can run SQL Managed Instances, I will try to find a better solution for this issue (and I will also test Velero). For now, however, you will have to settle with SQL Server Management Studio 😅.</p>

<h4 id="limitations">Limitations</h4>

<p>Based on the only article I have found on this subject in the documentation (<a href="https://learn.microsoft.com/en-us/azure/azure-arc/data/limitations-managed-instance">Limitations of SQL Managed Instance enabled by Azure Arc</a>), here are the limitations of backup in SQL Managed Instances enabled by Azure Arc. Note that I have not been able to find more information on “Automated Backup,” which is why I still consider that the most efficient way to perform the backup is through SQL Server Management Studio.</p>

<p><strong>Backup and Restore Limitations</strong></p>
<ul>
  <li><strong>Automated Backups:</strong>
    <ul>
      <li>User databases using the SIMPLE recovery model aren’t included in backups.</li>
      <li>The system database model is excluded to avoid interfering with administrative operations like creating or deleting databases, which may lock the database during such tasks.</li>
    </ul>
  </li>
  <li><strong>Point-in-Time Restore (PITR):</strong>
    <ul>
      <li>Restoring a database is confined to the same Arc-enabled SQL Managed Instance where the backup was created; cross-instance restores are not supported.</li>
      <li>Renaming databases during a point-in-time restore isn’t supported.</li>
      <li>There is currently no support for restoring databases that have Transparent Data Encryption (TDE) enabled.</li>
      <li>Once a database is deleted, it cannot be restored.</li>
    </ul>
  </li>
</ul>

<p><strong>Other Limitations</strong></p>
<ul>
  <li>Transactional replication is not available.</li>
  <li>Log shipping is blocked.</li>
  <li>Every user database must operate under a full recovery model because they participate in an always-on availability group.</li>
  <li>The instance name for an Azure Arc-enabled SQL Managed Instance must be 15 characters or fewer, including any suffix for instance indexing.</li>
</ul>

<p><strong>Roles and Responsibilities</strong><br />
The responsibilities differ significantly between Azure PaaS services and Azure Arc hybrid services:</p>
<ul>
  <li><strong>Azure PaaS:</strong>
    <ul>
      <li>Microsoft handles the infrastructure, operations, and provides an SLA.</li>
    </ul>
  </li>
  <li><strong>Azure Arc Hybrid Services:</strong>
    <ul>
      <li>While Microsoft supplies the software, customers are responsible for the infrastructure and day-to-day operations. Consequently, Microsoft does not offer an SLA for these services since the underlying infrastructure is customer-managed.</li>
    </ul>
  </li>
</ul>

<h2 id="disaster-recovery">Disaster Recovery</h2>

<p>This is one of the most dreaded events to face, as it means the Azure Local cluster cannot be recovered and you must restore the workloads either on another cluster or directly in Azure using Azure Site Recovery. On the day you need to perform disaster recovery, your least concern should be that the VMs are not Arc VMs, I’ll spare you repeating that no current system can carry out disaster recovery to Azure or another Azure Local cluster while retaining the VMs as Arc VMs.</p>

<p>Regarding the first option (restoring the workloads in a new Azure Local Cluster), I won’t dwell on it since it simply involves restoring the backed-up components described in previous sections.</p>

<p>The second option involves performing backups and restorations using Azure Site Recovery (currently in Preview). This approach allows you to restore VMs in Azure after an incident or a planned event, and once the incident is resolved, to perform a failback, returning the workload to the Azure Local cluster.</p>

<p>For this, let’s delve into the solution in the following section.</p>

<h3 id="azure-site-recovery-preview">Azure Site Recovery (preview)</h3>

<p>Below, I will detail, summarize, and restructure information from the official <a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/azure-site-recovery?view=azloc-24113">documentation</a> on Azure Site Recovery (preview), highlighting key factors to consider when using this service.</p>

<p>We start with the most critical aspect: when you want to use Azure Site Recovery on your cluster, it will install an agent on each node. Because this agent is not “properly signed,” WDAC will block its installation, throwing the error “Microsoft Azure Site Recovery Provider installation has failed with exit code - 1.” To overcome this, you must set WDAC to “Audit” mode. For example, you can run the following command on any node in the cluster:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Enable-AsWdacPolicy</span><span class="w"> </span><span class="nt">-Mode</span><span class="w"> </span><span class="nx">Audit</span><span class="w">
</span></code></pre></div></div>

<p>Next, we analyze the disaster recovery strategy. The Azure Site Recovery process for Azure Local involves four key stages:</p>
<ul>
  <li><strong>Replication:</strong> The VM’s virtual hard disk (VHD) is copied to an Azure Storage account.</li>
  <li><strong>Failover:</strong> In the event of a disaster, the replicated VM is started in Azure. A test failover can also be run without impacting production.</li>
  <li><strong>Re-protect:</strong> After failover, VMs can be re-replicated back from Azure to your on-premises system.</li>
  <li><strong>Failback:</strong> Finally, you can fail back to your original on-premises environment.</li>
</ul>

<p><strong>Important:</strong> The current integration does not support replication, failover, or failback for Arc resource bridges or Arc VMs (although the latter point is nuanced – they might not officially support it, but it works).</p>

<p>The <a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/azure-site-recovery?view=azloc-24113#step-1-prepare-infrastructure-on-your-target-host">documentation</a> details the installation process and available options, so I won’t go into extensive detail for each step. Instead, here’s a simple guide for configuration:</p>

<ol>
  <li>
    <p><strong>Change WDAC to Audit Mode:</strong><br />
Set WDAC to Audit mode as shown above.
<a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-01.png" target="_blank">
  <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-01.png" alt="Azure Site Recovery in Azure Local 01" style="border: 2px solid grey;" />
</a></p>
  </li>
  <li>
    <p><strong>Create a Storage Account and VNet:</strong><br />
Create a Storage Account (using LRS and without SoftDelete for cache purposes) and a virtual network for testing ASR failover, where the workloads will be restored.</p>
  </li>
  <li>
    <p><strong>Prepare the Infrastructure:</strong><br />
Create a Vault, a Hyper-V site, and a replication policy (using the default settings in our case). This step installs the ASR extension on the cluster nodes.<br />
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-02.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-02.png" alt="Azure Site Recovery in Azure Local 02" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-03.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-03.png" alt="Azure Site Recovery in Azure Local 03" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-04.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-04.png" alt="Azure Site Recovery in Azure Local 04" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-05.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-05.png" alt="Azure Site Recovery in Azure Local 05" style="border: 2px solid grey;" />
 </a></p>
  </li>
  <li>
    <p><strong>Configure Replication:</strong><br />
Once the extension is installed and the site is configured, proceed to set up replication for your workloads.<br />
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-06.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-06.png" alt="Azure Site Recovery in Azure Local 06" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-07.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-07.png" alt="Azure Site Recovery in Azure Local 07" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-08.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-08.png" alt="Azure Site Recovery in Azure Local 08" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-09.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-09.png" alt="Azure Site Recovery in Azure Local 09" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-10.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-10.png" alt="Azure Site Recovery in Azure Local 10" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-11.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-11.png" alt="Azure Site Recovery in Azure Local 11" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-12.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-12.png" alt="Azure Site Recovery in Azure Local 12" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-13.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-13.png" alt="Azure Site Recovery in Azure Local 13" style="border: 2px solid grey;" />
 </a></p>
  </li>
  <li>
    <p><strong>Synchronize the Workloads:</strong><br />
The workload will begin to synchronize. In my test lab (set up on a laptop), this took nearly one hour.<br />
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-14.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-14.png" alt="Azure Site Recovery in Azure Local 14" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-15.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-15.png" alt="Azure Site Recovery in Azure Local 15" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-16.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-16.png" alt="Azure Site Recovery in Azure Local 16" style="border: 2px solid grey;" />
 </a></p>
  </li>
  <li>
    <p><strong>Perform Failover Operations:</strong><br />
Once synchronization is complete, you can execute both test failovers and regular failovers, moving the workloads from Azure Local to Azure directly.<br />
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-17.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-17.png" alt="Azure Site Recovery in Azure Local 17" style="border: 2px solid grey;" />
 </a>
 <a href="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-18.png" target="_blank">
   <img src="/assets/img/post/2025-03-29-azure-local-backup-and-disaster-recovery/asr-18.png" alt="Azure Site Recovery in Azure Local 18" style="border: 2px solid grey;" />
 </a></p>
  </li>
</ol>

<p>As you can see, this solution is a viable option if you use Azure Local solely as an edge infrastructure with a few critical workloads that you want to secure and keep operational in case of an incident. It is also suitable for single-node infrastructures, as it allows continued operation if connectivity and resource access requirements are met post-failover. A notable strength is the re-synchronization of workloads after failover and the possibility to fail back to the cluster once it is restored. Personally, I would love to see an automatic failover mechanism triggered by incidents, though I understand that not every disaster recovery scenario needs to operate automatically. I also miss a mechanism that would allow syncing different Azure Local clusters using Azure Site Recovery, but maybe this will be possible in the future.</p>

<p>Since this solution is in Preview, it isn’t supported in production by Microsoft and may present certain challenges (such as the need to set WDAC to Audit mode). Nevertheless, in my view, it can be an alternative for environments where no backup is available or where high workload availability is critical. Keep in mind that for the workloads to function correctly afterward, additional considerations such as connectivity and access (via load balancers, DNS, VPNs, etc.) must be addressed.</p>

<p>With this, I conclude the section on Disaster Recovery using ASR. There are additional points in the <a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/azure-site-recovery?view=azloc-24113">documentation</a> worth reviewing, such as more granular synchronization groups and prioritizing certain workloads.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Much to my regret, this has been an extremely lengthy and somewhat impractical article (at least in terms of lab integration), but I hope you have gained some insights (or at least compared notes) about my experience in this field. If you’d like to add anything or have me correct any points, feel free to contact me directly via LinkedIn.</p>

<p>I hope your experience goes beyond merely configuring a backup, you must test the restores as well. If you don’t test restorations, you can’t be sure your backups work. Given that Azure Local via Arc Bridge is a somewhat complex solution in this regard, I hope you can plan and define the limitations of your backup strategy.</p>

<p>I wish you a very good weekend, and I’m off to work on the next article: Planning, Sizing, and Migration, which will be the final installment of the Chronicloud saga on Azure Local 😊</p>]]></content><author><name>Cristian Schmitt Nieto</name></author><category term="Blog" /><category term="Azure Local" /><category term="Azure Stack HCI" /><category term="Backup" /><category term="Disaster Recovery" /><summary type="html"><![CDATA[Explore Backup & Disaster Recovery in Azure Local: Strategies for VM hydration, on-premises backup options and ASR for Disaster recovery.]]></summary></entry><entry><title type="html">Azure Local: Redundancy</title><link href="https://schmitt-nieto.com/blog/azure-local-redundancy/" rel="alternate" type="text/html" title="Azure Local: Redundancy" /><published>2025-03-01T00:00:00+01:00</published><updated>2025-05-05T00:00:00+02:00</updated><id>https://schmitt-nieto.com/blog/azure-local-redundancy</id><content type="html" xml:base="https://schmitt-nieto.com/blog/azure-local-redundancy/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Welcome to a new chapter in the <strong>Chronicloud series</strong>, specifically one of the last articles about <strong>Azure Local</strong>, where we’ll discuss <strong>Redundancy</strong>. Initially, I wanted to include both <strong>backup</strong> and <strong>disaster recovery</strong> in this post, but as I started writing, I realized it was getting huge and unwieldy. Therefore, I decided to separate those topics into their own dedicated article.</p>

<p>The subject of redundancy tends to be tricky when talking with clients, not because they lack interest, but because the complexities and limitations can be daunting. This article might be more technical than usual, so if you’re unfamiliar with any terminology, please reach out to me directly (LinkedIn is great) and I’ll be happy to clarify the concepts.</p>

<p>Because I’m based in Germany, most customers here love having multiple physical data center locations separated by firewall walls, fully independent “rooms” that can operate if one site goes down. This naturally leads to a desire for multi-location redundancy. In the past (with Azure Stack HCI 22H2), that wasn’t a major problem if you only had two sites and no AKS, because a <strong>Stretch Cluster</strong> could usually do the trick. But with Azure Stack HCI 23H2 (now <strong>Azure Local</strong>), the integrated <strong>Resource Bridge</strong> doesn’t support Stretch Clusters, and that has changed the redundancy equation significantly.</p>

<p>In this post, we’ll tackle redundancy from several angles: <strong>nodes</strong> (physical hardware), <strong>storage</strong>, <strong>network</strong> and <strong>Active Directory</strong>. Let’s get started!</p>

<h2 id="redundancy">Redundancy</h2>

<p>I’m splitting the redundancy discussion into three main parts:</p>

<ol>
  <li><strong>Nodes</strong>: Physical node redundancy in the cluster. For instance, if you have three nodes and two fail, you’ll see a potential loss of data and cluster availability.</li>
  <li><strong>Storage</strong>: We’ll look at data resiliency on disks, such as how a two-node cluster might keep operating if one node fails, but if the remaining node’s single disk dies, data might still be lost.</li>
  <li><strong>Other Infrastructure</strong>: Network design (no point having multiple nodes if everything relies on a single switch), multi-location data centers (e.g., rack-aware clusters) and Active Directory design (including why nesting domain controllers in the cluster can be problematic).</li>
</ol>

<p>Throughout, I’ll do some rough capacity and resource calculations using 2 x 1 TB NVMe capacity drives plus 1 TB RAM per node, just as an example.</p>

<h3 id="redundancy-of-the-nodes">Redundancy of the Nodes</h3>

<p>Talking about node redundancy means asking how many nodes a cluster can have (up to 16) and what happens when multiple nodes fail. In theory, if you have “half plus one” of the nodes functioning, and (or) you have a quorum (Azure File Share in the case of Azure Local), the cluster remains “operational”. However, that doesn’t guarantee that your <strong>storage</strong> remains accessible if the data resiliency requirements aren’t met, which is especially true with <strong>three-way mirrors</strong> in clusters of three or more nodes. If enough nodes go down simultaneously, data could become inaccessible or lost.</p>

<p>Personally, I’m not a huge fan of clusters with more than five nodes for Azure Local. The reason is that <strong>Storage Spaces Direct (S2D)</strong> can handle only so many simultaneous node failures while still keeping the data intact, and I prefer to keep things simpler. Let’s walk through some typical node counts:</p>

<h4 id="one-node">One Node</h4>
<p>You can technically run Azure Local with just one node. But it isn’t really a “cluster” since you have zero redundancy. If that single node fails, so does your entire environment. This setup might be simple in terms of CPU/RAM/storage planning, but I wouldn’t recommend it for any production environment that needs high availability. Even a minor node failure or an update problem can lead to downtime that’s tricky to fix.</p>

<h4 id="two-nodes">Two Nodes</h4>
<p>A two-node cluster gives you basic redundancy. If one node dies, the other automatically takes over the workloads, provided you haven’t over-allocated RAM and CPU. For example, if each node has 1 TB of RAM, you might be tempted to run workloads totaling 2 TB of RAM (like 2 VMs with 700 GB RAM allocated). But in a node-failure scenario, you only have 1 TB left to run everything. You’d see workloads failing to start if they collectively need more than 1 TB.</p>

<p>Overcommitting CPU also has consequences. If you had a 1:3 ratio (physical CPU : vCPU) across both nodes, losing one node means your ratio effectively doubles for the surviving node, possibly halving performance. But at least the cluster remains functional.</p>

<h4 id="three-or-more-nodes">Three or More Nodes</h4>
<p>With three nodes, you can leverage <strong>three-way mirror</strong> resiliency for your data, which allows the cluster to keep running if one node fails, even two nodes can fail in clusters that have more than 3 nodes and data still be safe. But if you run out of “mirrored copies” across multiple failures, data can be inaccessible or lost.</p>

<p>Another consideration is resource usage. Suppose each node has 1 TB RAM and you have workloads requiring 2 TB in total, distributed across the three nodes. If one node fails, you have only 2 TB left across two nodes. But if each of those two remaining nodes is already using a large portion of RAM, certain VMs might not be able to start. This is why you need an overprovisioning plan (or “failover capacity plan”) to handle node failures gracefully.</p>

<p>With bigger clusters, more resources are available for workloads, and you get more “hardware-level” redundancy. But S2D is generally tested up to losing two nodes simultaneously. If a third node also fails, you could run into data integrity issues, even though the cluster might still appear to have a majority for quorum. That’s one reason why I tend to keep my Azure Local clusters within a modest node count (like 2 to 5).</p>

<h3 id="redundancy-and-resiliency-in-the-storage">Redundancy and Resiliency in the Storage</h3>

<p>For raw vs. usable storage capacity calculations, I use the S2D calculator by <strong>Cosmos Darwin</strong> (<a href="https://www.linkedin.com/in/cosmosd/">LinkedIn</a>):  <a href="https://aka.ms/s2dcalc">https://aka.ms/s2dcalc</a></p>

<p><strong>Important</strong>: Azure Local requires <strong>a minimum of two capacity drives per node</strong> (<a href="https://learn.microsoft.com/en-us/windows-server/storage/storage-spaces/storage-spaces-direct-hardware-requirements#physical-deployments">hardware requirements</a>). For two nodes, you’ll generally have a <strong>two-way mirror</strong>, and for three or more nodes, a <strong>three-way mirror</strong>. All nodes should have the same number of disks (same capacity and model).</p>

<h4 id="two-node-cluster">Two-Node Cluster</h4>
<p>A two-node cluster with a two-way mirror ensures that if one node fails, the other still hosts the data. When the failed node is restored, the system automatically re-syncs the data. This re-sync can take minutes or hours depending on network bandwidth, RDMA configuration (RoCE/iWARP), and the amount of data that needs to be copied back.</p>

<p>If each node has two 1 TB NVMe disks, that’s 4 TB raw total. However, because it’s mirrored, you only get about 1 TB of usable capacity:</p>

<p><a href="/assets/img/post/2025-03-01-azure-local-redundancy/2nodesS2D.png" target="_blank">
  <img src="/assets/img/post/2025-03-01-azure-local-redundancy/2nodesS2D.png" alt="Two-node S2D example" style="border: 2px solid grey;" />
</a></p>

<h4 id="four-node-cluster">Four-Node Cluster</h4>
<p>With four nodes, you use a <strong>three-way mirror</strong>. This means data is replicated across at least three different nodes, so you can survive up to two node failures at once without losing data. But if a third node fails, you risk losing data consistency.</p>

<p>Re-sync times also get longer with more copies to rebuild. In extreme scenarios involving enormous data volumes, re-syncs could take days, though in my experience it’s usually hours at most. It depends heavily on your network speed, RDMA adapters, and switch capacity.</p>

<p>Microsoft’s fault tolerance documentation for S2D (like <a href="https://learn.microsoft.com/en-us/windows-server/storage/storage-spaces/fault-tolerance">this link</a>) provides some scenarios:</p>
<ul>
  <li>
    <p>Situations where everything stays online (losing more than two drives but at most two servers):
<a href="/assets/img/post/2025-03-01-azure-local-redundancy/S2DOnline1.png" target="_blank">
<img src="/assets/img/post/2025-03-01-azure-local-redundancy/S2DOnline1.png" alt="S2D Online Tolerances" style="border: 2px solid grey;" />
</a></p>
  </li>
  <li>
    <p>Situations where everything goes offline (drives lost in three or more servers at once, or losing three nodes simultaneously):
<a href="/assets/img/post/2025-03-01-azure-local-redundancy/S2DOffline1.png" target="_blank">
<img src="/assets/img/post/2025-03-01-azure-local-redundancy/S2DOffline1.png" alt="S2D Offline Tolerances" style="border: 2px solid grey;" />
</a></p>
  </li>
</ul>

<p>For example, four nodes each with 4 x 1 TB capacity disks gives you 16 TB raw, but effectively only <strong>4 TB usable</strong> under a three-way mirror:</p>

<p><a href="/assets/img/post/2025-03-01-azure-local-redundancy/4nodesS2D.png" target="_blank">
  <img src="/assets/img/post/2025-03-01-azure-local-redundancy/4nodesS2D.png" alt="Four-node S2D example" style="border: 2px solid grey;" />
</a></p>

<p><strong>Volume Counts</strong>: It’s best practice (see <a href="https://learn.microsoft.com/de-de/windows-server/storage/storage-spaces/plan-volumes#choosing-how-many-volumes-to-create">Microsoft’s volume planning guidelines</a>) to match the number of volumes to a multiple of the number of servers. For four servers, create four volumes if you want balanced performance. Each node can “own” one volume’s metadata orchestration.</p>

<h3 id="other-redundancies-in-the-infrastructure">Other Redundancies in the Infrastructure</h3>

<p>We can’t ignore the rest of the infrastructure that supports Azure Local, such as <strong>network design</strong> and <strong>Active Directory</strong> architecture. Let’s briefly discuss these points:</p>

<h4 id="network-redundancies">Network Redundancies</h4>

<p>You can handle Azure Local networking in multiple ways. Some designs feature a <strong>dedicated storage switch</strong> (especially if you have more than four nodes). You might also want to split nodes across physical data center “rooms,” but official multi-site or campus-cluster setups are currently not supported (“Rack Aware Cluster” is in <strong>private preview</strong>).</p>

<h5 id="switches">Switches</h5>
<p>Well, it depends on the number of nodes, your storage traffic design, and your budget. But you <strong>always</strong> need at least <strong>two switches</strong> for management and compute traffic. A single switch would act as a single point of failure, nullifying your otherwise redundant cluster design.</p>

<p>For up to <strong>four nodes</strong>, you can technically go switchless (often called <strong>Direct Attach</strong>) for the storage network, meaning the nodes are cabled directly to each other. I recommend <strong>RDMA</strong> (especially <strong>RoCEv2</strong>). This setup ensures that if one node fails, the remaining ones maintain inter-node connectivity. Personally, though, I consider switchless challenging beyond two nodes, it requires precise configuration, can be tedious to implement (via ARM templates), and is not very flexible (you can’t easily add new nodes or modify them without major rework). Its one advantage is cost savings if your existing switches can’t handle RDMA traffic.
For reference, here’s a link describing that setup in detail:  <a href="https://learn.microsoft.com/en-us/azure/azure-local/plan/four-node-switchless-two-switches-two-links?view=azloc-24113">Four-node switchless, two switches, two links</a></p>

<p>And here’s the official diagram for that cabling method (props to whoever created it!):
<a href="/assets/img/post/2025-03-01-azure-local-redundancy/4nodesSwitchless.png" target="_blank">
  <img src="/assets/img/post/2025-03-01-azure-local-redundancy/4nodesSwitchless.png" alt="Four-node switchless design" style="border: 2px solid grey;" />
</a></p>

<p>In the image, each node has two connections to its neighbors, using six total network ports exclusively for storage. Because most network cards have two ports, you wouldn’t want to use both ports on a single NIC card to connect to the same node. If that NIC card fails, you’d lose the connection to the node entirely. Additionally, note that you can’t easily expand beyond two nodes in a “switchless” scenario, the only supported move is from a single node to a two-node cluster. Anything above two nodes requires a switch, as explained <a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/add-server?view=azloc-24112">here</a>.</p>

<h5 id="multi-location-or-rack-aware">Multi-Location or Rack Aware</h5>

<p>After deciding how many switches to use, you also need to determine how many physical “locations” your cluster needs, e.g., is it all in one data center room, or multiple? Those familiar with the product already know this, but newcomers might be surprised to learn that <strong>Azure Local (starting 23H2) doesn’t support stretch clusters</strong>, meaning nodes should theoretically be in the same rack. I’ll mention a new way to set up Azure Local for two locations (really just two rooms in the same building) called <strong>Rack Aware Cluster</strong>.</p>

<p>In previous versions, you could configure a so-called <strong>stretch cluster</strong> for two sites, provided your round-trip latency didn’t exceed 5 ms (see <a href="https://learn.microsoft.com/en-us/azure/architecture/hybrid/azure-local-dr#use-stretched-clusters-to-implement-automated-disaster-recovery-for-virtualized-workloads-and-file-shares-hosted-on-azure-local">Microsoft docs</a>). However, that’s now invalid because Azure Local 23H2 includes new cluster management elements (like <strong>Azure ARC Resource Bridge</strong>) that don’t support stretch clustering. In my opinion, there’s also no real need to expand clusters this way because Azure Local is more of an <strong>Edge Datacenter</strong> solution, not a typical “full” data center approach. If you want balanced infrastructure across two sites, <strong>Windows Server 2025</strong> might be a better option, or you could split Azure Local into two separate clusters.</p>

<p>Nevertheless, there is a future possibility (currently in private preview) to meet this need, known as <strong>Rack Aware Cluster</strong> (<a href="https://techcommunity.microsoft.com/blog/azurearcblog/evolving-stretch-clustering-for-azure-local/4352751">TechCommunity article</a>). This upcoming feature may include up to eight nodes (four per side). Its advantage is that it could support the ARC Resource Bridge because the nodes reside in the same Layer 2 network. If I ever get the chance, I’ll test it once a public preview is available. For now, we only have a network diagram:</p>

<p><a href="/assets/img/post/2025-03-01-azure-local-redundancy/azurelocalrackaware.png" target="_blank">
  <img src="/assets/img/post/2025-03-01-azure-local-redundancy/azurelocalrackaware.png" alt="Rack Aware preview diagram" style="border: 2px solid grey;" />
</a></p>

<h4 id="active-directory-redundancy">Active Directory Redundancy</h4>

<p>In my opinion, the most controversial part of designing a new Azure Local environment is <strong>Active Directory</strong>, mainly because there’s no official best-practice guidance covering it. 
Starting with Azure Local 23H3, you can integrate Azure Local into your existing Active Directory with minimal effort by following the prep steps in <a href="https://learn.microsoft.com/en-us/azure/azure-local/deploy/deployment-prep-active-directory?view=azloc-24112">this Microsoft doc</a>. Those steps outline the prerequisites for registering Azure Local and creating the cluster. The question is: <strong>Do I use my current corporate AD (with all existing data), or do I spin up a separate AD domain (often called the Fabric Domain) just for Azure Local?</strong></p>

<p>Unsurprisingly, the answer is: <strong>it depends</strong>, it depends on the management model you want and how you plan to operate the cluster. However, in the majority of cases, I recommend creating a dedicated Active Directory domain for Azure Local, so you avoid unexpected permission issues or admins deciding it’s a great idea to apply random GPOs to the solution (I’ve seen some downright bizarre situations arise that were very tough to fix afterwards! 🤣)</p>

<p>Keep in mind that if you create a new Active Directory, it isn’t strictly required to integrate workloads like AVD or AKS. The users relying on those services and the workloads themselves, base their authentication on Entra ID (and, in terms of network, you can just set VLANs to point to whatever domain controllers they specifically need). You should also remember that Azure Local can be managed through Azure RBAC in the portal, making dedicated Fabric Domain accounts largely unnecessary. For now, as long as Azure Local still requires some form of AD domain (the version without AD is apparently coming later this year), my personal recommendation is to stand up a dedicated AD domain for Azure Local.</p>

<p>So, once you decide you want a new AD domain, <strong>where do you host it?</strong> One possibility is to run a domain controller for that new Fabric Domain in a VM outside Azure Local (for example, in your existing infrastructure or even on a laptop if you’re brave 😜). Then you register Azure Local with Azure and add a second domain controller inside the cluster itself. A frequent question is whether you can nest <em>both</em> DCs in the cluster. Theoretically and practically (if we’re being honest), yes (but you shouldn´t), you can migrate the domain controller you used to register Azure Local into the cluster. The problem arises if there’s a cluster wide outage. The cluster tries to start up, but both domain controllers are also part of that same cluster (even the storage!). You hit the classic chicken-and-egg scenario: the cluster can’t come online because there’s no AD available, and AD can’t come online because the cluster is offline.</p>

<p>Because of this, my one ironclad piece of advice is that <strong>no matter what you do (new domain or existing domain), ensure that at least one domain controller remains outside the cluster</strong> and is configured as DNS for the cluster. You can nest the second domain controller in the cluster without issue, or even migrate it in as an ARC VM. (We’ll talk more about that migration flow in future articles.)</p>

<h2 id="conclusion">Conclusion</h2>

<p>Although I shortened some sections, I think this article still provides a clear (and somewhat “simple”) overview of what to consider when designing <strong>Azure Local</strong> with redundancy in mind. I had to omit <strong>backup</strong> and <strong>disaster recovery</strong> to avoid tripling the size, but those will be covered in the next post.</p>

<p>The best advice I can give is: if you’re new to Azure Local, reach out to a trusted consultant or your OEM for guidance before diving in. If you’re set on going solo, join <a href="https://aka.ms/azurelocal-slack">the Azure Local Slack channel</a> and clarify any doubts first. It’s easy to paint yourself into a corner if you’re not aware of certain limitations.</p>

<p>Thank you for reading all the way through! If you have any questions, feel free to ping me on LinkedIn. I’m always happy to help clarify or share insights from my experience.</p>]]></content><author><name>Cristian Schmitt Nieto</name></author><category term="Blog" /><category term="Azure Local" /><category term="Azure Stack HCI" /><category term="Redundancy" /><category term="Azure Virtual Desktop" /><summary type="html"><![CDATA[Explore the different aspects of redundancy within Azure Local, including node resilience, storage durability, network design, and Active Directory considerations.]]></summary></entry><entry><title type="html">Azure Local meets Nerdio</title><link href="https://schmitt-nieto.com/blog/azure-local-nerdio/" rel="alternate" type="text/html" title="Azure Local meets Nerdio" /><published>2025-02-08T00:00:00+01:00</published><updated>2025-02-08T00:00:00+01:00</updated><id>https://schmitt-nieto.com/blog/azure-local-nerdio</id><content type="html" xml:base="https://schmitt-nieto.com/blog/azure-local-nerdio/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>I decided to write this article outside of my usual Chronicloud series, though it does follow on from the <a href="/blog/azure-stack-hci-azure-virtual-desktop/">Azure Stack HCI: Azure Virtual Desktop</a> post. The reason? Image management for AVD and deploying those images in <strong>Azure Local</strong> can be a real pain point. Currently, the entire process is quite manual, involves tons of steps, and doesn’t offer much flexibility. So, I thought sharing how to use <strong>Nerdio</strong> for this might be helpful.</p>

<p>I was also inspired by attending the Nerdio Micro Hack in Frankfurt last Wednesday (kudos to <strong>Bas van Kaam</strong> (<a href="https://www.linkedin.com/in/basvankaam/">@LinkedIn</a>) and <strong>Bjørn M. Riiber</strong> (<a href="https://www.linkedin.com/in/riibern/">@LinkedIn</a>) for the excellent masterclass). Most attendees seemed to need a solution for running <strong>AVD on-prem</strong>. While it is indeed possible to manage these images without any extra tooling, just a handful of PowerShell scripts and some Azure DevOps pipelines, I find that approach clunky. Nerdio, on the other hand, does a great job by also offering more flexible autoscaling plans and simple scripted tasks that are far easier to configure.</p>

<p>For those unfamiliar with <strong>Nerdio</strong> ( <a href="https://getnerdio.com/">getnerdio.com</a> ), it’s a company that specializes in a simple, straightforward way to manage AVD, Windows 365 Cloud PCs, and Intune (no DevOps overhead or IaC expertise needed). Because I want to specifically focus on the <strong>Azure Local</strong> integration (and there isn’t much up-to-date documentation on this topic), I’m documenting the process here. I won’t be covering the Nerdio installation in your Azure subscription, my friend <strong>Michael Frank</strong> (<a href="https://www.linkedin.com/in/michael-frank-26b86222b/">@LinkedIn</a>) and <strong>Neil McLoughlin</strong> (<a href="https://www.linkedin.com/in/neilmcloughlin/">@LinkedIn</a>) have you covered:</p>

<ul>
  <li>Michael’s blog on how to install Nerdio: <a href="https://michaelsendpoint.com/nerdio/nerdio.html">Blog Link</a></li>
  <li>Neil’s YouTube video on setup and basic config:</li>
</ul>
<iframe width="560" height="315" src="https://www.youtube.com/embed/PwxYiYjCW6s?si=4py_H69BVYps3hGn" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>

<p>I also won’t dive deep into <strong>FSLogix</strong> here. I’ll save that for another article in the Chronicloud series when we talk more about AVD.</p>

<p>The only official documentation I’ve found so far for using Azure Local with Nerdio is:</p>
<ul>
  <li><a href="https://nmehelp.getnerdio.com/hc/en-us/articles/25499377328909-Azure-Stack-HCI-and-Nerdio-Manager">Azure Stack HCI and Nerdio Manager</a></li>
  <li><a href="https://nmehelp.getnerdio.com/hc/en-us/articles/26124280902157-Troubleshoot-Issues-with-Resource-Bridge-in-Azure-Stack-HCI">Troubleshoot Issues with Resource Bridge in Azure Stack HCI</a></li>
</ul>

<p>Below is a diagram illustrating the process for registering Nerdio and deploying AVD on Azure Local through Nerdio:</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/NerdioAzureLocalProcess.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/NerdioAzureLocalProcess.png" alt="Nerdio-Azure Local Integration Process" style="border: 2px solid grey;" />
</a></p>

<p>And here’s a reference architecture of the infrastructure which I´m using:</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/NerdioAzureLocalArchitecture.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/NerdioAzureLocalArchitecture.png" alt="Azure Local Architecture with Nerdio" style="border: 2px solid grey;" />
</a></p>

<h2 id="configuring-nerdio-for-azure-local">Configuring Nerdio for Azure Local</h2>

<p>If you take a look at the earlier documentation, you’ll notice it mentions creating a custom location. This is actually no longer necessary because <strong>Azure Local</strong> now automatically generates a custom location during its deployment process. I believe the existing documentation hasn’t been fully updated to reflect this (and I don’t blame anyone, Azure Local evolves so quickly that staying on top of changes is a challenge, and I face the same issue with my own blog posts).</p>

<p>Before we dive into the configuration, there are a few prerequisites to meet. Thankfully, most of them were already taken care of in the article <a href="/blog/azure-stack-hci-azure-virtual-desktop/">“Azure Stack HCI: Azure Virtual Desktop”</a>:</p>

<ul>
  <li><strong>Install Nerdio Manager</strong>: This should be done using the guides mentioned in the introduction.</li>
  <li>An <strong>Active Directory</strong> for the users who will be using AVD (with identities synced to Microsoft Entra ID).</li>
  <li>A <strong>fully functional Azure Local cluster</strong> (at least 1 node), registered with an Azure subscription that is connected to Nerdio Manager.</li>
  <li><strong>Azure Arc</strong> registration for the Azure Local nodes.</li>
  <li><strong>Resource Bridge</strong> already enabled in Azure Local.</li>
  <li>A <strong>local shared storage path</strong> on the Azure Local cluster for FSLogix profiles.</li>
  <li>The <strong>logical network</strong> and <strong>resource group</strong> where your Azure Local cluster is registered must be linked.</li>
</ul>

<h3 id="registering-resources-in-nerdio">Registering Resources in Nerdio</h3>

<p>Once Nerdio is installed, you’ll need <strong>Owner</strong> permissions on the resources you’re about to register, using the same account that performs the registration in Nerdio. The resources you’ll register are:</p>

<ul>
  <li><strong>Subscription</strong></li>
  <li><strong>Resource Group</strong></li>
  <li><strong>Hybrid Network</strong> (a.k.a. your Logical Network)</li>
</ul>

<p>You can register all of them from the same management window under <strong>Settings &gt; Azure environment</strong>:</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Azureenvironmentconfig.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Azureenvironmentconfig.png" alt="Azure Environment Configuration" style="border: 2px solid grey;" />
</a></p>

<p>You’ll also need to connect your <strong>Active Directory</strong> (with a user who has the rights to join machines in the appropriate OU) and specify the <strong>file share</strong> for FSLogix profiles (in my case, a file share hosted on the domain controller(don´t replicate 😅)). This is done in <strong>Settings &gt; Integration</strong>:</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Integrations.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Integrations.png" alt="Integration Settings in Nerdio" style="border: 2px solid grey;" />
</a></p>

<h2 id="golden-image">Golden Image</h2>

<p>The process of creating a <strong>Golden Image</strong> was outlined in the introduction, and if you’ve worked with Nerdio before, you’ll find it’s a fairly straightforward process. Here’s my quick rundown:</p>

<ol>
  <li>
    <p><strong>Set up a virtual network (vNet) in Azure</strong> (not your local, logical network). I created a simple vNet in the same Resource Group as my Azure Local cluster, changing only the name. You can do this in the Azure portal.</p>
  </li>
  <li>
    <p><strong>Import the VM image from the Azure gallery</strong> by going to <strong>Desktop Images &gt; Add from Azure library</strong>. Select both the vNet you just created and the Azure image you want to use as your Golden Image. My setup looked like this:</p>
  </li>
</ol>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage01.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage01.png" alt="Golden Image Setup in Nerdio" style="border: 2px solid grey;" />
</a></p>

<p>Nerdio will then spend about 30 minutes creating a VM based on the parameters you provided. It places that VM in the specified vNet and Resource Group. By default, this VM won’t be accessible from the internet unless you assign it a public IP and configure RDP access in the Azure portal.</p>

<p>Now, you can modify this VM in two ways:</p>
<ul>
  <li><strong>Direct Access</strong>: Connect to the VM (via VPN or public IP) to configure it manually.</li>
  <li><strong>Run Scripts</strong>: One of my favorite features in Nerdio. You can run scripts to install language packs or other software, either on demand or scheduled. (If you’re thinking what I’m thinking, this is perfect for scheduling and automating Windows Updates on your Golden Images!)</li>
</ul>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage02.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage02.png" alt="Run Scripts in Nerdio" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage03.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage03.png" alt="Script Scheduling in Nerdio" style="border: 2px solid grey;" />
</a></p>

<p>That sets up your base VM to serve as your Golden Image. Next comes the more interesting part: deploying the image into a <strong>Compute Gallery</strong> and syncing (or uploading) it to <strong>Azure Local</strong> so it can be used on your Session Hosts.</p>

<p>You can accomplish this by converting the VM into an Image and syncing it with Azure Local like so:</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage04.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage04.png" alt="Convert to VM Image" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage05.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage05.png" alt="Sync with Azure Local" style="border: 2px solid grey;" />
</a></p>

<p>As you can see in the last screenshot, I’ve enabled <strong>Geographic distribution &amp; Azure compute gallery</strong> because it allows me to pull the image down to Azure Local by selecting my custom location. In my case, I created the Compute Gallery automatically from within Nerdio and selected the custom location <strong>azlfra</strong>. If you wish, you can also configure a schedule so that this process runs automatically the day after Windows Updates are installed on the Golden Image:</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage06.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage06.png" alt="Compute Gallery and Custom Location" style="border: 2px solid grey;" />
</a></p>

<p>It took about 30 minutes for my image to sync. I really appreciate how Nerdio keeps you updated on the entire progress. Here’s what the result looks like:</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage07.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage07.png" alt="Golden Image Sync Result 1" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage08.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/GoldenImage08.png" alt="Golden Image Sync Result 2" style="border: 2px solid grey;" />
</a></p>

<p>And that’s it! You now have a Golden Image you can generate periodically and automatically update through Nerdio. It saves you a ton of time and makes image management much more efficient and user-friendly.</p>

<h2 id="creating-a-workspace">Creating a Workspace</h2>

<p>We now have an image in <strong>Azure Local</strong> that we can use to provision a Session Host. So, what’s next? Since I’m starting from a clean deployment, I’ll create a <strong>Workspace</strong> dedicated to Azure Local, where I’ll implement a “Hybrid host pool”. I use quotes because, realistically, these host pools shouldn’t be mixed between on-prem and cloud (not supported yet), so they’ll reside solely in Azure Local.</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace01.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace01.png" alt="Workspace Creation - Step 1" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace02.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace02.png" alt="Workspace Creation - Step 2" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace03.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace03.png" alt="Workspace Creation - Step 3" style="border: 2px solid grey;" />
</a></p>

<h3 id="adding-a-hybrid-host-pool">Adding a Hybrid Host Pool</h3>

<p>After the Workspace is created, head to <strong>Hybrid host pools</strong> and add a new one. In my case, I chose <strong>Multi user desktop (pooled)</strong>. You’ll need to select the <strong>Active Directory</strong> and <strong>FSLogix profile</strong> you configured under Integrations, pick the <strong>hybrid network</strong> you set up in the Azure Environment settings, and finally select the <strong>Desktop Image</strong> we created earlier. I assigned three users manually via <strong>Quick Assign</strong>, but in a production environment, you’d typically assign users through security groups.</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace04.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace04.png" alt="Host Pool Creation - Step 1" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace05.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace05.png" alt="Host Pool Creation - Step 2" style="border: 2px solid grey;" />
</a></p>

<h3 id="configuring-autoscaling">Configuring Autoscaling</h3>

<p>Once the host pool is created, you’ll see a prompt to configure <strong>Autoscale</strong>. This differs from “Scaling Plans” in the Azure portal, which mainly handle power management (the dynamic autoscaling feature is still in preview). Nerdio offers a far more robust approach to autoscaling, with several factors to consider:</p>

<ul>
  <li>
    <p><strong>HOST POOL PROPERTIES</strong><br />
Specifies max sessions per Session Host and how load balancing is handled.</p>
  </li>
  <li>
    <p><strong>HOST POOL SIZING</strong><br />
Determines when a Session Host is considered active (based on whether the VM is running or if the AVD agent is available), sets a base capacity for Session Hosts, a minimum capacity, and a “bursting” feature that automatically creates Session Hosts to meet demand.</p>
  </li>
  <li><strong>SCALING LOGIC</strong><br />
Lets you use multiple triggers (in parallel if you wish) to scale in and out Session Hosts. For Azure Local, there are currently only three autoscale triggers:
    <ol>
      <li><strong>Avg active sessions</strong>: Scales out when the average number of active sessions exceeds a predefined value.</li>
      <li><strong>Available sessions</strong>: Maintains a specified number of available hosts by scaling in/out within the limits of Host Pool Sizing and max sessions per host.</li>
      <li><strong>User-driven</strong>: Starts hosts when users connect, then automatically deallocates them after a set time of zero user sessions.</li>
    </ol>
  </li>
  <li>
    <p><strong>ROLLING DRAIN MODE</strong><br />
Lets you create multiple “drain windows” and target a percentage of your hosts to place in drain mode.</p>
  </li>
  <li>
    <p><strong>PRE-STAGE HOSTS</strong><br />
Powers on or creates Session Hosts <strong>before</strong> business hours, avoiding massive logon storms.</p>
  </li>
  <li>
    <p><strong>MESSAGING</strong><br />
Allows you to notify users of maintenance or shutdown periods. Changing the time automatically updates the in-session notification.</p>
  </li>
  <li><strong>AUTO-HEAL BROKEN HOSTS</strong><br />
A “killer feature” of Nerdio. If a Session Host VM isn’t recognized as Available by the AVD service, Nerdio Manager can try repairing it automatically. It performs this auto-heal after all scale-out tasks are finished and things are stable.</li>
</ul>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace06.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace06.png" alt="Autoscaling Configuration - Step 1" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace07.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace07.png" alt="Autoscaling Configuration - Step 2" style="border: 2px solid grey;" />
</a></p>

<p>Upon configuring autoscaling, Nerdio provisions a Session Host according to your settings. In my test, the process took roughly <strong>50 minutes</strong> and (to my surprise) completed without any errors. Here’s a snapshot of the provisioning and its final result:</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace08.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace08.png" alt="Workspace Provisioning - Step 1" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace09.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Workspace09.png" alt="Workspace Provisioning - Step 2" style="border: 2px solid grey;" />
</a></p>

<h3 id="post-deployment-tweaks">Post-Deployment Tweaks</h3>

<p>After the deployment, I realized I forgot to install the <strong>multimedia redirection extension</strong> and enable <strong>RDP Shortpath</strong> in my Golden Image. Ordinarily, I’d have to update the Golden Image and roll out a new deployment. But with Nerdio, I can use <strong>Run Script</strong> to fix these settings directly on the Session Host (or multiple Session Hosts simultaneously via bulk operations). Of course, I’ve also integrated these features into my Golden Image as well, but below are two screenshots showing how I added them directly to the Session Host:</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/MultimediaRed.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/MultimediaRed.png" alt="Multimedia Redirection Script" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/RDPShortparth.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/RDPShortparth.png" alt="RDP Shortpath Script" style="border: 2px solid grey;" />
</a></p>

<p>Once everything was in place, I logged into the Virtual Desktop, and sure enough, it performed exactly as expected:</p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Result01.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Result01.png" alt="Result - Session Host Running" style="border: 2px solid grey;" />
</a></p>

<p><a href="/assets/img/post/2025-02-08-azure-local-nerdio/Result02.png" target="_blank">
  <img src="/assets/img/post/2025-02-08-azure-local-nerdio/Result02.png" alt="Result - Azure Local AVD" style="border: 2px solid grey;" />
</a></p>

<h2 id="conclusion">Conclusion</h2>

<p>A process that would normally take three to four hours to handle manually can easily be automated with Nerdio in about one or two hours at most. The main advantages come from the ability to <strong>automate</strong> nearly every step, like managing images, generating them automatically after Windows Updates are applied and running scripts to install applications on the fly.</p>

<p>Being able to implement <strong>unconventional autoscaling plans</strong> is another standout factor of this solution. Although I do wish we had a few extra scaling triggers on Azure Local (for CPU and RAM metrics), the current setup is already quite impressive compared to the Standard processes.</p>

<p>Bear in mind, Azure Virtual Desktop on Azure Local is a pay-as-you-go model (you pay for the Session Hosts while they’re running), so Nerdio’s autoscaling capabilities can help optimize costs. Granted, the cost savings aren’t as pronounced as on Azure Public, but the flexibility and ease of management still make it well worth considering.</p>

<p>Personally, I’m impressed by how straightforward and effective Nerdio is in conjunction with Azure Local. While I’m no stranger to Nerdio in general, seeing it work with Azure Local reinforces how viable this combination can be, especially for admins who want a comprehensive solution without needing deep technical knowledge in DevOps or infrastructure as code.</p>]]></content><author><name>Cristian Schmitt Nieto</name></author><category term="Blog" /><category term="Azure Local" /><category term="Azure Stack HCI" /><category term="Nerdio" /><category term="Azure Virtual Desktop" /><category term="AVD" /><summary type="html"><![CDATA[Discover how Nerdio can simplify Azure Virtual Desktop management on Azure Local, from image creation to automated scaling.]]></summary></entry></feed>