Skip to content

Add Setup-HyperVHost-Standalone-v3.ps1 script#2

Open
AlrightLad wants to merge 2 commits intoDTC-Inc:mainfrom
AlrightLad:patch-1
Open

Add Setup-HyperVHost-Standalone-v3.ps1 script#2
AlrightLad wants to merge 2 commits intoDTC-Inc:mainfrom
AlrightLad:patch-1

Conversation

@AlrightLad
Copy link

@AlrightLad AlrightLad commented Jan 30, 2026

Here's an extended description for your GitHub PR:

Hyper-V Host Setup Script v3.4 - MSP RMM Template
Overview
A comprehensive, production-ready PowerShell script for automated Hyper-V host deployment in MSP environments. Designed for both RMM-driven unattended execution and interactive technician-led installations, this script transforms a bare Windows Server into a fully configured Hyper-V host with standardized naming, storage layout, network teaming, and security hardening. Key Features
Dual-Mode Operation

RMM Mode ($RMM=1): Fully non-interactive deployment with pre-configured variables, automatic reboots, and detailed logging for remote management platforms
Interactive Mode: Guided setup with prompts for technicians performing manual deployments

Intelligent Reboot Handling

Two-phase architecture separates reboot-requiring operations (Phase 1) from configuration tasks (Phase 2) Script is re-runnable and idempotent—safely re-execute after each reboot to continue setup Clear logging of pending reboot reasons with automatic or prompted restart options

Dell Hardware Integration

Auto-detects Dell servers and installs OpenManage Server Administrator, iDRAC Service Module, and Dell System Update Downloads from Backblaze B2 public repository with BITS transfer fallback Runs DSU post-install to apply firmware and driver updates Optional iDRAC root password configuration via RACADM

RAID Configuration Validation

Detects single virtual disk configurations where OS and data share the same RAID array Provides detailed remediation instructions specific to Dell PERC controllers Blocks unsafe configurations in RMM mode unless explicitly accepted ($AcceptRAIDWarning)

Storage Automation

Caps OS partition at 127GB and reclaims unallocated space for data volumes Auto-initializes and formats additional data disks with standardized naming (ers-ssd-01, rrs-hdd-02, etc.) Configures Hyper-V default paths on data drives
Supports multiple redundancy naming conventions (ers/rrs/zrs/grs)

Network Teaming (SET)

Creates Switch Embedded Teaming virtual switches with Dynamic load balancing Configurable NICs per team (2 or 4) with automatic PCIe slot grouping option Renames management vNICs for easy identification

Security & Compliance

BitLocker encryption with TPM protector and auto-generated recovery passwords Auto-unlock for data drives using TPM chain
Recovery keys saved locally with clear operator instructions LocalAccountTokenFilterPolicy enabled for admin share access in workgroup scenarios

Windows Configuration

Hyper-V role with all management tools and PowerShell modules High Performance power plan
RDP enabled with firewall rules
Configurable time zone
Server Manager auto-start disabled
Registry backup enabled

Application Deployment

WinGet-based installation of Firefox, 7-Zip, Notepad++, and Windows Terminal Graceful fallback when WinGet unavailable

Parameters
ParameterTypeDefaultDescription$RMMInt0Set to 1 for non-interactive RMM execution$ServerSequenceStringRequiredServer number 01-99 (generates HV01, HV02, etc.)$SkipWindowsUpdateBoolfalseSkip Windows Update installation$SkipBitLockerBoolfalseSkip BitLocker configuration$SkipNetworkTeamingBoolfalseSkip SET team creation$TeamsOfInt2NICs per SET team (2 or 4)$AutoNICTeamingBoolfalseAuto-group NICs by PCIe slot$StorageRedundancyString"ers"Volume label prefix (ers/rrs/zrs/grs)$TimeZoneString"Eastern Standard Time"Target time zone$iDRACPasswordString""iDRAC root password (Dell only)$AcceptRAIDWarningBoolfalseBypass single RAID disk warning Requirements

Windows Server 2019/2022/2025
PowerShell 5.1+
Administrator privileges
TPM 2.0 (for BitLocker)
Network connectivity for Dell tools and Windows Updates

Typical Deployment Flow

First Run: Renames computer, installs Hyper-V and Windows features → Reboot
Second Run: Installs Dell tools (if applicable), runs Windows Updates → Reboot
Third Run: Configures storage, networking, BitLocker, applications → Complete

Summary by CodeRabbit

  • New Features

    • Introduced automated Hyper-V host provisioning script supporting RMM and standalone modes, including Dell hardware integration, storage configuration, network teaming, Windows updates, BitLocker setup, and comprehensive logging.
  • Chores

    • Replaced legacy interactive deployment workflow with new non-interactive automated approach.

✏️ Tip: You can customize this high-level summary in your review settings.

Here's an extended description for your GitHub PR:

Hyper-V Host Setup Script v3.4 - MSP RMM Template
Overview
A comprehensive, production-ready PowerShell script for automated Hyper-V host deployment in MSP environments. Designed for both RMM-driven unattended execution and interactive technician-led installations, this script transforms a bare Windows Server into a fully configured Hyper-V host with standardized naming, storage layout, network teaming, and security hardening.
Key Features
Dual-Mode Operation

RMM Mode ($RMM=1): Fully non-interactive deployment with pre-configured variables, automatic reboots, and detailed logging for remote management platforms
Interactive Mode: Guided setup with prompts for technicians performing manual deployments

Intelligent Reboot Handling

Two-phase architecture separates reboot-requiring operations (Phase 1) from configuration tasks (Phase 2)
Script is re-runnable and idempotent—safely re-execute after each reboot to continue setup
Clear logging of pending reboot reasons with automatic or prompted restart options

Dell Hardware Integration

Auto-detects Dell servers and installs OpenManage Server Administrator, iDRAC Service Module, and Dell System Update
Downloads from Backblaze B2 public repository with BITS transfer fallback
Runs DSU post-install to apply firmware and driver updates
Optional iDRAC root password configuration via RACADM

RAID Configuration Validation

Detects single virtual disk configurations where OS and data share the same RAID array
Provides detailed remediation instructions specific to Dell PERC controllers
Blocks unsafe configurations in RMM mode unless explicitly accepted ($AcceptRAIDWarning)

Storage Automation

Caps OS partition at 127GB and reclaims unallocated space for data volumes
Auto-initializes and formats additional data disks with standardized naming (ers-ssd-01, rrs-hdd-02, etc.)
Configures Hyper-V default paths on data drives
Supports multiple redundancy naming conventions (ers/rrs/zrs/grs)

Network Teaming (SET)

Creates Switch Embedded Teaming virtual switches with Dynamic load balancing
Configurable NICs per team (2 or 4) with automatic PCIe slot grouping option
Renames management vNICs for easy identification

Security & Compliance

BitLocker encryption with TPM protector and auto-generated recovery passwords
Auto-unlock for data drives using TPM chain
Recovery keys saved locally with clear operator instructions
LocalAccountTokenFilterPolicy enabled for admin share access in workgroup scenarios

Windows Configuration

Hyper-V role with all management tools and PowerShell modules
High Performance power plan
RDP enabled with firewall rules
Configurable time zone
Server Manager auto-start disabled
Registry backup enabled

Application Deployment

WinGet-based installation of Firefox, 7-Zip, Notepad++, and Windows Terminal
Graceful fallback when WinGet unavailable

Parameters
ParameterTypeDefaultDescription$RMMInt0Set to 1 for non-interactive RMM execution$ServerSequenceStringRequiredServer number 01-99 (generates HV01, HV02, etc.)$SkipWindowsUpdateBoolfalseSkip Windows Update installation$SkipBitLockerBoolfalseSkip BitLocker configuration$SkipNetworkTeamingBoolfalseSkip SET team creation$TeamsOfInt2NICs per SET team (2 or 4)$AutoNICTeamingBoolfalseAuto-group NICs by PCIe slot$StorageRedundancyString"ers"Volume label prefix (ers/rrs/zrs/grs)$TimeZoneString"Eastern Standard Time"Target time zone$iDRACPasswordString""iDRAC root password (Dell only)$AcceptRAIDWarningBoolfalseBypass single RAID disk warning
Requirements

Windows Server 2019/2022/2025
PowerShell 5.1+
Administrator privileges
TPM 2.0 (for BitLocker)
Network connectivity for Dell tools and Windows Updates

Typical Deployment Flow

First Run: Renames computer, installs Hyper-V and Windows features → Reboot
Second Run: Installs Dell tools (if applicable), runs Windows Updates → Reboot
Third Run: Configures storage, networking, BitLocker, applications → Complete
@coderabbitai
Copy link

coderabbitai bot commented Jan 30, 2026

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (1)
  • Setup-HyperVHost-Standalone-v3.ps1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
📝 Walkthrough

Walkthrough

Replaces interactive deploy.ps1 script with new comprehensive Setup-HyperVHost-Standalone-v3.ps1 that automates non-interactive Hyper-V host configuration. New script adds RMM/non-RMM modes, Dell tooling integration, phase-based execution with reboot orchestration, storage provisioning, network teaming, Windows settings tuning, and extensive logging throughout.

Changes

Cohort / File(s) Summary
Hyper-V Host Automation
Setup-HyperVHost-Standalone-v3.ps1
New 1916-line non-interactive script implementing complete Hyper-V host provisioning with RMM/manual modes, two-phase execution (reboot-gated), Dell OpenManage/DSU integration with BITS fallback, Windows Update orchestration, RAID/storage validation and provisioning, network teaming configuration, Windows registry tuning, BitLocker setup, WinGet app installation, and comprehensive logging with per-step progress tracking.
Legacy Deployment Script Removal
deploy.ps1
Entire 295-line interactive provisioning script removed, eliminating multi-step Read-Host prompts, vendor/server-type selection logic, manual disk partitioning, conditional DC/Hyper-V feature installation, and interactive orchestration workflows.

Sequence Diagram

sequenceDiagram
    participant RMM as RMM/User Input
    participant Phase1 as Phase 1:<br/>Reboot-Needed
    participant Phase2 as Phase 2:<br/>No-Reboot Config
    participant DellTools as Dell Tools<br/>(OpenManage/DSU)
    participant WinUpdate as Windows Update
    participant Storage as Storage<br/>Provisioning
    participant Network as Network<br/>Teaming
    participant Settings as System<br/>Settings
    
    RMM->>Phase1: Input handling & defaults
    Phase1->>Phase1: OS rename
    Phase1->>Phase1: Hyper-V feature install
    Phase1->>DellTools: Download OpenManage (BITS/MSI)
    DellTools->>DellTools: Extract, validate, manage service
    DellTools->>Phase1: Complete
    Phase1->>DellTools: Execute DSU updates
    DellTools->>Phase1: Exit code & reboot handling
    Phase1->>WinUpdate: PSWindowsUpdate installation flow
    WinUpdate->>Phase1: Complete
    Phase1->>Phase1: Reboot Gate
    Phase1->>Phase2: Post-reboot resume
    Phase2->>Storage: RAID validation & remediation
    Storage->>Storage: Provision volumes (resize, partition, format, letters)
    Storage->>Phase2: Complete
    Phase2->>Network: Optional teaming (auto/manual)
    Network->>Phase2: SETx switches & NICs aggregation
    Phase2->>Settings: Registry tuning (RDP, firewall, time zone, power plan)
    Phase2->>Settings: Optional BitLocker (TPM recovery logging)
    Phase2->>Phase2: WinGet app installation
    Phase2->>Phase2: Final reporting & Next Steps
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~75 minutes


🐰 A new script hops in with flair,
Non-interactive, robust, and fair,
Dell tools, storage, phases aligned,
Hyper-V hosts of the finest kind,
Old deploy script takes its bow,
Automation flourishes now! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and directly summarizes the main change: adding the Setup-HyperVHost-Standalone-v3.ps1 script, which is the primary focus of the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🤖 Fix all issues with AI agents
In `@Setup-HyperVHost-Standalone-v3.ps1`:
- Around line 380-388: The catch block for Rename-Computer currently logs the
error and only prompts when $RMM -ne 1, which causes silent continuation in RMM
mode; update the catch to handle $RMM -eq 1 by either calling throw or setting a
persistent failure flag so the script halts or reports at completion.
Specifically, inside the catch after Write-LogProgress, if ($RMM -eq 1) then
throw "Setup cancelled due to computer rename failure: $_" (or set a global flag
like $Script:RenameFailed = $true and ensure later code checks and aborts/report
based on that flag); keep the existing interactive Read-Host/throw behavior for
non-RMM ($RMM -ne 1).
- Around line 1600-1601: The script currently disables the Windows Firewall with
Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False and never
re-enables it; either remove that disable call or add a re-enable step before
the "Setup Complete" section (Phase 2 end) that calls Set-NetFirewallProfile
-Profile Domain, Public, Private -Enabled True and logs the action (e.g.,
Write-LogProgress "Re-enabling Windows Firewall..." "Info") so the firewall is
restored after setup.
- Around line 893-895: The script currently calls Add-RebootReason "Dell
OpenManage and Tools Installation" unconditionally; change this so the reboot
reason is only added when one or more Dell components were actually installed by
introducing and updating a boolean flag (e.g., $dellInstalled) or checking the
install result from the Dell install steps, and wrap the Add-RebootReason and
the Write-Host "Dell tools installed (MAY REQUIRE REBOOT)" call in a conditional
that runs only if that flag/result indicates an installation occurred (refer to
the existing Dell install block and the Add-RebootReason and Write-Host calls to
locate where to add the flag and conditional).
- Around line 1713-1717: The script currently writes BitLocker recovery files to
$recoveryKeyPath on the OS drive and then builds $recoveryFile, which risks
losing keys if the system is encrypted and also leaks the password to the
transcript; change the logic so that when creating the recovery output you (1)
prefer a configurable external location (network share or removable media) and
fall back to prompting the user if not provided, (2) if domain-joined call the
BitLocker backup routine to Active Directory instead of writing locally, and (3)
suppress the recovery password from the PowerShell transcript/console by
ensuring the code paths that produce the password (the code that assigns/outputs
the recovery password variable used to create $recoveryFile) use secure output
methods (e.g., write to a redirected file handle or SecureString) or explicitly
Stop-Transcript/Disable-Transcript around the sensitive write so the plaintext
password is not captured; update references to $recoveryKeyPath, $recoveryFile,
Test-Path and New-Item accordingly.
- Around line 1375-1378: The script currently computes $usedLetters from
Get-Partition which can miss network, CD-ROM, or other volume types; update both
occurrences (the block setting $usedLetters/$availableLetters/$driveLetter and
the same logic near line 1411) to gather used drive letters from Get-Volume (use
the DriveLetter property) and exclude volumes with DriveType values like CD-ROM,
Network, Removable or other non-fixed/system types before computing
$availableLetters from the pool ('D'..'H') and selecting $driveLetter; keep the
existing variable names ($usedLetters, $availableLetters, $driveLetter) so the
change is localized.
- Around line 898-904: The script uses the wrong DSU executable path; update the
$dsuPath assignment and any subsequent checks to match the installer
ValidatePath ("C:\Program Files\Dell\DELL System Update\DSU.exe") so
Test-Path($dsuPath), the Write-Host/Write-LogProgress messages, and the later
occurrence around the second check all reference the correct "C:\Program
Files\Dell\DELL System Update\DSU.exe" value (update the $dsuPath variable and
any uses of Test-Path or invocation that reference the old path).
- Around line 1011-1013: The Start-Process call that invokes RACADM with the
password in $iDRACPassword (see $setPasswordProcess, Start-Process, $racadmPath)
will be captured by Start-Transcript; to fix, temporarily suspend or stop the
transcript before invoking Start-Process and restart it afterward, or better:
write a temporary secure RACADM config file containing the password and call
RACADM with its file option (e.g., -f) instead of passing the password on the
command line, then securely remove the temp file (Remove-Item -Force)
immediately after use; update the block that constructs the RACADM invocation to
use one of these approaches and ensure no plaintext password appears in logged
arguments.
- Around line 1690-1692: The stray "continue" inside the BitLocker section is
outside any loop and must be replaced with valid control flow; locate the
BitLocker block containing the "continue" token and either (a) change it to
"return" if you intend to exit the script/function immediately, (b) introduce a
boolean flag (e.g., $skipBitLocker) that you set at that point and check later
before running the BitLocker logic, or (c) wrap the BitLocker logic in a do {
... } while ($false) so "continue" is valid — pick the approach consistent with
surrounding flow and update any subsequent checks to respect the new flag/return
or loop wrapper.
- Around line 1482-1483: The current one-liner unconditionally removes all
VMSwitches matching "SET*" which can disconnect running VMs; instead iterate
over the switches returned by Get-VMSwitch and for each switch (identify by
$_.Name) check for attached VMs/network adapters (e.g. via Get-VMNetworkAdapter
-SwitchName or equivalent); if no attachments remove it (Remove-VMSwitch
-Force), otherwise skip and emit a warning or prompt for confirmation before
removal so you don't destructively disconnect running VMs. Ensure you reference
the existing Get-VMSwitch, Where-Object, and Remove-VMSwitch calls when
implementing the loop and checks.
- Around line 267-272: The switch on $physicalDisk.MediaType currently maps
"SCM" to "nvme" which is incorrect; update the switch handling of
$physicalDisk.MediaType (the switch block that returns
"ssd"/"hdd"/"nvme"/default) so that the "SCM" case returns "scm" instead of
"nvme" (leave the "SSD" -> "ssd", "HDD" -> "hdd" and default behavior
unchanged).
🧹 Nitpick comments (2)
Setup-HyperVHost-Standalone-v3.ps1 (2)

121-122: Avoid shadowing PowerShell's automatic $input variable.

The variable name $input shadows PowerShell's built-in automatic variable. While this works in most cases, it can cause unexpected behavior in certain pipeline scenarios. Consider using a more descriptive name like $userInput or $response.

This same pattern appears on lines 134, 141, 146, and 157.

♻️ Suggested rename
-    $input = Read-Host "Enter company name (default: DTC)"
-    if (![string]::IsNullOrEmpty($input)) { $CompanyName = $input }
+    $userInput = Read-Host "Enter company name (default: DTC)"
+    if (![string]::IsNullOrEmpty($userInput)) { $CompanyName = $userInput }

298-328: Consider caching PnP device lookup and using ArrayList for better performance.

Get-PnpDevice is called inside the loop for each adapter, which is inefficient. Additionally, using += with arrays in PowerShell creates a new array on each iteration.

♻️ Suggested optimization
 function Get-NICDetails {
-    $nicInfo = @()
+    $nicInfo = [System.Collections.ArrayList]::new()
+    
+    # Cache PnP devices outside the loop
+    $pnpDevices = Get-PnpDevice -ErrorAction SilentlyContinue

     Write-LogProgress "Enumerating network adapters..." "Debug"
     # ... adapter enumeration ...

     foreach ($adapter in $adapters) {
-        $pnpDevice = Get-PnpDevice -ErrorAction SilentlyContinue | Where-Object { $_.FriendlyName -eq $adapter.InterfaceDescription }
+        $pnpDevice = $pnpDevices | Where-Object { $_.FriendlyName -eq $adapter.InterfaceDescription }
         # ... rest of loop ...
-        $nicInfo += $nicDetail
+        [void]$nicInfo.Add($nicDetail)
     }

     return $nicInfo | Sort-Object PCIBus, PCIDevice, PCIFunction
 }

Comment on lines +267 to +272
switch ($physicalDisk.MediaType) {
"SSD" { return "ssd" }
"HDD" { return "hdd" }
"SCM" { return "nvme" }
default { return "hdd" }
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

PowerShell Get-PhysicalDisk MediaType values documentation

💡 Result:

Get-PhysicalDisk surfaces the MediaType from the underlying CIM/WMI class MSFT_PhysicalDisk.MediaType (a UInt16 enum). The documented values are: 0 = Unspecified, 3 = HDD, 4 = SSD, 5 = SCM (Storage Class Memory). [1]

Related PowerShell cmdlets that take a -MediaType parameter use the same enum (commonly shown as strings Unspecified/HDD/SSD/SCM in cmdlet help). For example, Set-PhysicalDisk -MediaType lists accepted values HDD, SSD, SCM [2], and Set-StoragePool -MediaTypeDefault includes Unspecified, HDD, SSD, SCM. [3]

Sources
[1] MSFT_PhysicalDisk class (MediaType values) https://learn.microsoft.com/en-us/windows-hardware/drivers/storage/msft-physicaldisk
[2] Set-PhysicalDisk (Storage) https://learn.microsoft.com/en-us/powershell/module/storage/set-physicaldisk?view=windowsserver2025-ps
[3] Set-StoragePool (Storage) https://learn.microsoft.com/en-us/powershell/module/storage/set-storagepool?view=windowsserver2025-ps


🌐 Web query:

Storage Class Memory SCM vs NVMe difference PowerShell

💡 Result:

SCM (Storage Class Memory) vs NVMe — what’s different?

  • SCM / PMem (persistent memory, e.g., NVDIMM-N / Intel Optane PMem-era devices): a lower-latency storage class that can be presented to Windows as SCM/PMem and used in Windows storage stacks (including Storage Spaces Direct). It’s treated as a distinct drive type from NVMe/SSD/HDD in Microsoft guidance. [2]
  • NVMe: a storage protocol/interface for SSDs on PCIe (U.2/AIC/M.2 form factors). It’s still block storage (SSD), generally higher latency than PMem/SCM but faster than SATA/SAS SSDs/HDDs. [2]
  • In Storage Spaces Direct, Microsoft supports persistent memory (PMem) and NVMe as different device types. [2], [3]

PowerShell: how to tell SCM vs NVMe on Windows

1) Show BusType / MediaType

Get-PhysicalDisk |
  Select FriendlyName, SerialNumber, BusType, MediaType, Size |
  Sort BusType, FriendlyName

2) List only SCM devices (Microsoft specifically documents BusType = "SCM")

Get-PhysicalDisk | Where-Object BusType -eq 'SCM' |
  Select FriendlyName, SerialNumber, HealthStatus, OperationalStatus, OperationalDetails

(From Microsoft’s SCM health management guidance.) [1]

3) List NVMe devices

Get-PhysicalDisk | Where-Object BusType -eq 'NVMe' |
  Select FriendlyName, SerialNumber, MediaType, Size

Important caveat: If your NVMe SSD is behind a RAID controller / vendor storage stack, BusType may show RAID instead of NVMe, so Get-PhysicalDisk won’t reliably identify it as NVMe in that configuration. [4]


Sources

[1] Microsoft Learn — Storage-class Memory (NVDIMM-N) Health Management in Windows (learn.microsoft.com)
[2] Microsoft Learn — Choose drives for Azure Local and Windows Server clusters (learn.microsoft.com)
[3] Microsoft Learn — Storage Spaces Direct overview (learn.microsoft.com)
[4] Stack Overflow — Windows API for identifying whether a drive is NVMe (BusType shows RAID) (stackoverflow.com)

Citations:


Incorrect media type mapping: SCM should map to "scm", not "nvme".

Storage Class Memory (SCM) is a distinct technology (e.g., Intel Optane persistent memory) and should not be mapped to "nvme". According to PowerShell documentation, Get-PhysicalDisk.MediaType has four enum values: Unspecified, HDD, SSD, and SCM. There is no "NVMe" MediaType value — NVMe drives report as SSD with a separate BusType attribute. The correct fix maps SCM to its own label:

🔧 Proposed fix
             switch ($physicalDisk.MediaType) {
                 "SSD" { return "ssd" }
                 "HDD" { return "hdd" }
-                "SCM" { return "nvme" }
+                "SCM" { return "scm" }
                 default { return "hdd" }
             }
🤖 Prompt for AI Agents
In `@Setup-HyperVHost-Standalone-v3.ps1` around lines 267 - 272, The switch on
$physicalDisk.MediaType currently maps "SCM" to "nvme" which is incorrect;
update the switch handling of $physicalDisk.MediaType (the switch block that
returns "ssd"/"hdd"/"nvme"/default) so that the "SCM" case returns "scm" instead
of "nvme" (leave the "SSD" -> "ssd", "HDD" -> "hdd" and default behavior
unchanged).

Comment on lines +380 to +388
} catch {
Write-LogProgress "Failed to rename computer: $_" "Error"
if ($RMM -ne 1) {
$continue = Read-Host "Failed to rename computer. Continue anyway? (y/n)"
if ($continue -ne 'y') {
throw "Setup cancelled due to computer rename failure"
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

In RMM mode, computer rename failure is silently ignored.

When $RMM -eq 1, if Rename-Computer fails, the script logs the error but continues execution. This could result in the server running with an incorrect name while other configuration proceeds, leading to inconsistent state.

Consider exiting with an error in RMM mode when rename fails, or at minimum, setting a flag to warn at completion.

🐛 Proposed fix
         } catch {
             Write-LogProgress "Failed to rename computer: $_" "Error"
             if ($RMM -ne 1) {
                 $continue = Read-Host "Failed to rename computer. Continue anyway? (y/n)"
                 if ($continue -ne 'y') {
                     throw "Setup cancelled due to computer rename failure"
                 }
+            } else {
+                Write-LogProgress "CRITICAL: Computer rename failed in RMM mode - exiting" "Error"
+                throw "Setup cancelled due to computer rename failure in RMM mode"
             }
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch {
Write-LogProgress "Failed to rename computer: $_" "Error"
if ($RMM -ne 1) {
$continue = Read-Host "Failed to rename computer. Continue anyway? (y/n)"
if ($continue -ne 'y') {
throw "Setup cancelled due to computer rename failure"
}
}
}
} catch {
Write-LogProgress "Failed to rename computer: $_" "Error"
if ($RMM -ne 1) {
$continue = Read-Host "Failed to rename computer. Continue anyway? (y/n)"
if ($continue -ne 'y') {
throw "Setup cancelled due to computer rename failure"
}
} else {
Write-LogProgress "CRITICAL: Computer rename failed in RMM mode - exiting" "Error"
throw "Setup cancelled due to computer rename failure in RMM mode"
}
}
🤖 Prompt for AI Agents
In `@Setup-HyperVHost-Standalone-v3.ps1` around lines 380 - 388, The catch block
for Rename-Computer currently logs the error and only prompts when $RMM -ne 1,
which causes silent continuation in RMM mode; update the catch to handle $RMM
-eq 1 by either calling throw or setting a persistent failure flag so the script
halts or reports at completion. Specifically, inside the catch after
Write-LogProgress, if ($RMM -eq 1) then throw "Setup cancelled due to computer
rename failure: $_" (or set a global flag like $Script:RenameFailed = $true and
ensure later code checks and aborts/report based on that flag); keep the
existing interactive Read-Host/throw behavior for non-RMM ($RMM -ne 1).

Comment on lines +1713 to +1717
$recoveryKeyPath = "$env:SystemDrive\BitLocker-Recovery-Keys"
if (!(Test-Path $recoveryKeyPath)) {
New-Item -Path $recoveryKeyPath -ItemType Directory -Force | Out-Null
}
$recoveryFile = Join-Path $recoveryKeyPath "BitLocker-Recovery-Passwords-$(Get-Date -Format 'yyyy-MM-dd-HHmmss').txt"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

BitLocker recovery passwords stored locally on the encrypted drive.

Recovery passwords are saved to C:\BitLocker-Recovery-Keys\, which is on the OS drive that's being encrypted. If BitLocker locks out the system, the recovery keys won't be accessible. Additionally, the recovery password is logged to the transcript at line 1757.

Consider:

  1. Storing keys to a network location or removable media
  2. Backing up to Active Directory (if domain-joined)
  3. Suppressing recovery password from transcript logs
🔒 Suggested improvements
+                # WARNING: Saving recovery key locally - ensure this is backed up externally!
+                Write-Host "IMPORTANT: Back up recovery keys to a secure external location!" -ForegroundColor Red
                 $recoveryKeyPath = "$env:SystemDrive\BitLocker-Recovery-Keys"

For the transcript logging concern:

-                    Write-LogProgress "  Recovery Password: $recoveryPassword" "Info"
+                    Write-LogProgress "  Recovery Password saved to file (not logged for security)" "Info"
🤖 Prompt for AI Agents
In `@Setup-HyperVHost-Standalone-v3.ps1` around lines 1713 - 1717, The script
currently writes BitLocker recovery files to $recoveryKeyPath on the OS drive
and then builds $recoveryFile, which risks losing keys if the system is
encrypted and also leaks the password to the transcript; change the logic so
that when creating the recovery output you (1) prefer a configurable external
location (network share or removable media) and fall back to prompting the user
if not provided, (2) if domain-joined call the BitLocker backup routine to
Active Directory instead of writing locally, and (3) suppress the recovery
password from the PowerShell transcript/console by ensuring the code paths that
produce the password (the code that assigns/outputs the recovery password
variable used to create $recoveryFile) use secure output methods (e.g., write to
a redirected file handle or SecureString) or explicitly
Stop-Transcript/Disable-Transcript around the sensitive write so the plaintext
password is not captured; update references to $recoveryKeyPath, $recoveryFile,
Test-Path and New-Item accordingly.

Summary of changes pushed:

All 10 CodeRabbit issues addressed
Security hardening for firewall and credential handling
Bug fixes for DSU path, BitLocker flow, and virtual switch management
Code quality improvement (variable shadowing fix)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant