Task 03: Configure Static IP Address
DOCUMENT CATEGORY: Runbook
SCOPE: Network IP configuration
PURPOSE: Assign static management IP addresses to all nodes using explicit IP values fromvariables.yml— not read from DHCP
MASTER REFERENCE: Phase 03: OS Configuration
Status: Active
Overview
Configure a static IP address on the management network adapter of each Azure Local node. All IP parameters — address, subnet prefix, gateway, and DNS — come explicitly from variables.yml. Scripts do not read the current DHCP-assigned address.
All IP values in variables.yml must be correct before running. The scripts hard-fail if any placeholder values remain, and permanently lock in whatever IP you specify.
The process on each node:
- Hard-fails at startup if any
REPLACEplaceholder values remain in the configuration block - Finds the management NIC by exact adapter name — exits and lists all adapters if not found
- Checks idempotency — if already correctly configured as static, exits clean
- Handles the case where the target IP is currently DHCP-assigned (locks it in as static)
- Disables DHCP, removes dynamic IP, sets static IP/prefix/gateway/DNS
- Validates:
PrefixOrigin = Manual,DHCP = Disabled, gateway route present, DNS set - Retries up to
RetryCounttimes if validation fails
Prerequisites
| Requirement | Description | Source |
|---|---|---|
| Tasks 01–02 Complete | WinRM and RDP enabled on all nodes | Task 01, Task 02 |
| Management IP per node | Static IP to assign | variables.yml: nodes.<name>.management_ip |
| Subnet prefix length | e.g. 24 for /24 | variables.yml: network.management.prefix_length |
| Default gateway | Management network gateway | variables.yml: network.management.gateway |
| DNS servers | Primary and secondary DNS | variables.yml: dns.primary, dns.secondary |
| Management NIC name | Exact adapter name on all nodes | variables.yml: cluster.management_nic_name (from Phase 01 hardware discovery) |
Variables from variables.yml
| Path | Type | Description |
|---|---|---|
nodes.<name>.management_ip | string | Static IP to assign to management NIC |
network.management.prefix_length | integer | Subnet prefix (e.g., 24) |
network.management.gateway | string | Default gateway for management network |
dns.primary | string | Primary DNS server IP |
dns.secondary | string | Secondary DNS server IP |
cluster.management_nic_name | string | Management adapter name (e.g., Embedded NIC 1) |
Execution
- SConfig Utility
- Orchestrated Script
- Standalone Script
Run on each node via iDRAC Virtual Console or RDP.
The adapter number shown in SConfig varies. Before selecting, run Get-NetAdapter in PowerShell to list all adapters and confirm the correct name. The management adapter name is recorded in variables.yml: cluster.management_nic_name from the iDRAC discovery performed in Phase 01.
Common adapter names by NIC vendor:
| Vendor | Typical Adapter Name | Notes |
|---|---|---|
| Nvidia / Mellanox ConnectX | Slot 3 Port 1 (or Slot X Port 1) | Slot number set during Phase 01 iDRAC discovery |
| Intel (embedded) | Embedded NIC 1 | Standard on Dell PowerEdge embedded Intel NICs |
| Broadcom (embedded) | Embedded NIC 1 | Standard on Dell PowerEdge embedded Broadcom NICs |
- Open iDRAC Virtual Console or connect via RDP
- Run
Get-NetAdapterin PowerShell — note the adapter name matchingvariables.yml: cluster.management_nic_name - Type
SConfigand press Enter (or it auto-launches) - Select option 8 — Network settings
- SConfig lists adapters by number — select the number corresponding to your management adapter identified in step 2
- Select option 1 — Set Network Adapter Address
- Enter S for Static
- Enter the static IP address from
variables.yml: nodes.<name>.management_ip - Enter the subnet mask (e.g.,
255.255.255.0for /24,255.255.255.128for /25) - Enter the default gateway from
variables.yml: network.management.gateway - Select option 2 — Set DNS Servers; enter primary from
variables.yml: dns.primary - Enter secondary DNS from
variables.yml: dns.secondary - Repeat for every node
When to use: Standard deployment — reads all configuration from
variables.ymland configures all nodes via PSRemoting
Script: scripts/deploy/04-cluster-deployment/phase-03-os-configuration/task-03-configure-static-ip-address/powershell/Invoke-ConfigureStaticIP-Orchestrated.ps1
In most deployments, DHCP reservations mean the node's current IP equals the target static IP — the PSRemoting session stays alive through the configuration. If the IPs differ (e.g. no DHCP reservation was in place), the session will drop when the IP changes. The script catches this disconnect, waits up to 60 seconds, then reconnects to the new static IP and runs a full verification pass.
Script
#Requires -Version 7.0
<#
.SYNOPSIS
Invoke-ConfigureStaticIP-Orchestrated.ps1
Configures static IP addresses on all Azure Local nodes from the management server.
.DESCRIPTION
Runs from the management server. Reads all IP configuration from variables.yml
(management IP, prefix, gateway, DNS, NIC name) and pushes the configuration to
each node via PSRemoting.
Session-loss handling:
When the static IP is applied, the node
session WILL drop — this is expected. The orchestrator catches that disconnect,
waits for the node to stabilise on its new IP, then opens a fresh session to the
new static IP and runs a verification query to confirm all settings took.
Variables.yml paths used per node:
nodes.<name>.management_ip -> static IP to assign
network.management.prefix_length -> subnet prefix (e.g. 24)
network.management.gateway -> default gateway
dns.primary -> primary DNS
dns.secondary -> secondary DNS
cluster.management_nic_name -> exact NIC adapter name
.PARAMETER ConfigPath
Path to variables.yml. Auto-detected from .\configs\ if not specified.
.PARAMETER NodeNames
Specific node names to target. Default: all nodes in variables.yml.
.PARAMETER Credential
PSCredential for PSRemoting. Prompted if not provided.
.PARAMETER RetryCount
Validation retry attempts on the node. Default: 3.
.PARAMETER ReconnectTimeoutSec
Seconds to wait for node to come up on new static IP. Default: 60.
.PARAMETER ReconnectRetrySec
Seconds between reconnect attempts. Default: 10.
.EXAMPLE
.\Invoke-ConfigureStaticIP-Orchestrated.ps1
.EXAMPLE
.\Invoke-ConfigureStaticIP-Orchestrated.ps1 -NodeNames "AZL-NODE01","AZL-NODE02"
.EXAMPLE
.\Invoke-ConfigureStaticIP-Orchestrated.ps1 -ConfigPath ".\configs\infrastructure-poc.yml"
.NOTES
Author: Azure Local Cloud Azure Local Cloud
Version: 2.0.0
Phase: 03-os-configuration
Task: task-03-configure-static-ip-address
Prerequisites: PowerShell 7+, powershell-yaml module, PSRemoting enabled on nodes (Task 01)
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$ConfigPath,
[Parameter(Mandatory = $false)]
[string[]]$NodeNames,
[Parameter(Mandatory = $false)]
[PSCredential]$Credential,
[Parameter(Mandatory = $false)]
[int]$RetryCount = 3,
[Parameter(Mandatory = $false)]
[int]$ReconnectTimeoutSec = 60,
[Parameter(Mandatory = $false)]
[int]$ReconnectRetrySec = 10
)
Set-StrictMode -Version Latest
$ErrorActionPreference =
# ============================================================================
# FUNCTIONS
# ============================================================================
function Write-Log {
param([string]$Message, [string]$Level = "INFO")
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$color = switch ($Level) {
"ERROR" { "Red" }
"WARN" { "Yellow" }
"SUCCESS" { "Green" }
"HEADER" { "Cyan" }
default { "White" }
}
Write-Host "[$timestamp] [$Level] $Message" -ForegroundColor $color
}
function Resolve-ConfigPath {
param([string]$ExplicitPath)
if ($ExplicitPath) {
if (-not (Test-Path $ExplicitPath)) { throw "Config not found: $ExplicitPath" }
Write-Log "Using specified config: $ExplicitPath"
return $ExplicitPath
}
$candidates = Get-ChildItem -Path ".\configs\" -Filter "infrastructure*.yml" -ErrorAction SilentlyContinue
if (-not $candidates -or $candidates.Count -eq 0) {
throw "No infrastructure*.yml found in .\configs\. Use -ConfigPath."
}
if ($candidates.Count -eq 1) {
Write-Log "Auto-detected config: $($candidates[0].FullName)"
return $candidates[0].FullName
}
Write-Host "`nMultiple config files found:" -ForegroundColor Yellow
for ($i = 0; $i -lt $candidates.Count; $i++) {
$default = if ($candidates[$i].Name -eq "variables.yml") { " [DEFAULT]" } else { "" }
Write-Host " [$($i+1)] $($candidates[$i].Name)$default"
}
$defaultIdx = ($candidates | ForEach-Object { $_.Name }).IndexOf("variables.yml")
if ($defaultIdx -lt 0) { $defaultIdx = 0 }
$sel = Read-Host "`nSelect config (Enter for default [$($candidates[$defaultIdx].Name)])"
if ([string]::IsNullOrWhiteSpace($sel)) { return $candidates[$defaultIdx].FullName }
$idx = [int]$sel - 1
if ($idx -lt 0 -or $idx -ge $candidates.Count) { throw "Invalid selection: $sel" }
return $candidates[$idx].FullName
}
function Get-NodeConfigs {
param([hashtable]$Config)
$mgmtNet = $Config.network.management
$dns = $Config.dns
$clusterNIC = $Config.cluster.management_nic_name
if (-not $mgmtNet.gateway) { throw "network.management.gateway not set in variables.yml" }
if (-not $mgmtNet.prefix_length) { throw "network.management.prefix_length not set in variables.yml" }
if (-not $dns.primary) { throw "dns.primary not set in variables.yml" }
if (-not $dns.secondary) { throw "dns.secondary not set in variables.yml" }
if (-not $clusterNIC) { throw "cluster.management_nic_name not set in variables.yml" }
$nodeConfigs = [System.Collections.Generic.List[hashtable]]::new()
foreach ($entry in $Config.nodes.GetEnumerator()) {
$nodeName = $entry.Key
$nodeData = $entry.Value
if (-not $nodeData.management_ip) {
Write-Log "Node $nodeName has no management_ip in variables.yml — skipping" "WARN"
continue
}
$nodeConfigs.Add(@{
NodeName = $nodeName
CurrentIP = $nodeData.management_ip # DHCP-reserved = current IP = target IP
TargetIP = $nodeData.management_ip
PrefixLength = [int]$mgmtNet.prefix_length
Gateway = $mgmtNet.gateway
DNSPrimary = $dns.primary
DNSSecondary = $dns.secondary
ManagementNIC = $clusterNIC
})
}
return $nodeConfigs
}
# The script block that runs INSIDE the PSRemoting session on the node.
# Receives all config values explicitly — never reads DHCP or auto-detects IP.
$NodeConfigScriptBlock = {
param(
[string]$ManagementNIC,
[string]$TargetIP,
[int]$PrefixLength,
[string]$Gateway,
[string]$DNSPrimary,
[string]$DNSSecondary,
[int]$RetryCount,
[int]$RetryDelaySec
)
function Write-NLog {
param([string]$M, [string]$L = "INFO")
$ts = Get-Date -Format "HH:mm:ss"
Write-Output " [$ts][$L] $M"
}
try {
Write-NLog "Node: $($env:COMPUTERNAME)"
# Find adapter — exact name only
$adapter = Get-NetAdapter | Where-Object { $_.InterfaceAlias -eq $ManagementNIC }
if (-not $adapter) {
$available = (Get-NetAdapter | Select-Object -ExpandProperty InterfaceAlias) -join ", "
throw "Adapter
}
Write-NLog "Adapter: $($adapter.InterfaceAlias) MAC: $($adapter.MacAddress)"
# Check if already fully configured (idempotent)
$existingIP = Get-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue
$existingIface = Get-NetIPInterface -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4
$existingGW = Get-NetRoute -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue |
Where-Object { $_.DestinationPrefix -eq "0.0.0.0/0" }
$existingDNS = (Get-DnsClientServerAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4).ServerAddresses
if ($existingIP.IPAddress -eq $TargetIP -and
$existingIP.PrefixLength -eq $PrefixLength -and
$existingIP.PrefixOrigin -eq "Manual" -and
$existingIface.Dhcp -eq "Disabled" -and
$existingGW.NextHop -eq $Gateway -and
($existingDNS -contains $DNSPrimary) -and
($existingDNS -contains $DNSSecondary)) {
Write-NLog "Already correctly configured as static. No changes needed." "INFO"
return @{ Result = "AlreadyConfigured"; IP = $TargetIP }
}
if ($existingIP.IPAddress -eq $TargetIP -and $existingIP.PrefixOrigin -eq "Dhcp") {
Write-NLog "Target IP ($TargetIP) currently assigned via DHCP — locking in as static." "WARN"
}
# Apply static configuration
Write-NLog "Disabling DHCP..."
Set-NetIPInterface -InterfaceIndex $adapter.ifIndex -Dhcp Disabled
Write-NLog "Removing existing IP addresses..."
Get-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue |
Remove-NetIPAddress -Confirm:$false -ErrorAction SilentlyContinue
Write-NLog "Removing existing default routes..."
Get-NetRoute -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue |
Where-Object { $_.DestinationPrefix -eq "0.0.0.0/0" } |
Remove-NetRoute -Confirm:$false -ErrorAction SilentlyContinue
Write-NLog "Setting static IP: $TargetIP/$PrefixLength GW: $Gateway"
New-NetIPAddress -InterfaceIndex $adapter.ifIndex `
-IPAddress $TargetIP -PrefixLength $PrefixLength `
-DefaultGateway $Gateway -ErrorAction Stop | Out-Null
Write-NLog "Setting DNS: $DNSPrimary, $DNSSecondary"
Set-DnsClientServerAddress -InterfaceIndex $adapter.ifIndex `
-ServerAddresses @($DNSPrimary, $DNSSecondary)
# Commands submitted — session will likely drop here as IP changes.
# Return a sentinel so the orchestrator knows commands were sent.
return @{ Result = "CommandsSubmitted"; IP = $TargetIP }
} catch {
return @{ Result = "Error"; Error = $_.Exception.Message }
}
}
# Verification script block — runs on the node AFTER reconnecting to the new static IP
$VerifyScriptBlock = {
param([string]$ManagementNIC, [string]$TargetIP, [int]$PrefixLength,
[string]$Gateway, [string]$DNSPrimary, [string]$DNSSecondary)
$issues = [System.Collections.Generic.List[string]]::new()
$adapter = Get-NetAdapter | Where-Object { $_.InterfaceAlias -eq $ManagementNIC }
if (-not $adapter) { return @{ Valid = $false; Issues = @("Adapter not found") } }
$ip = Get-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue
$iface = Get-NetIPInterface -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4
$gw = Get-NetRoute -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue |
Where-Object { $_.DestinationPrefix -eq "0.0.0.0/0" }
$dns = (Get-DnsClientServerAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4).ServerAddresses
if (-not $ip -or $ip.IPAddress -ne $TargetIP) { $issues.Add("IP: expected $TargetIP got $($ip.IPAddress)") }
if ($ip -and $ip.PrefixLength -ne $PrefixLength) { $issues.Add("Prefix: expected $PrefixLength got $($ip.PrefixLength)") }
if ($ip -and $ip.PrefixOrigin -ne "Manual") { $issues.Add("PrefixOrigin: $($ip.PrefixOrigin) (expected Manual)") }
if ($iface.Dhcp -ne "Disabled") { $issues.Add("DHCP: $($iface.Dhcp) (expected Disabled)") }
if (-not $gw -or $gw.NextHop -ne $Gateway) { $issues.Add("Gateway: expected $Gateway got $($gw.NextHop)") }
if ($dns -notcontains $DNSPrimary) { $issues.Add("DNS primary $DNSPrimary missing") }
if ($dns -notcontains $DNSSecondary) { $issues.Add("DNS secondary $DNSSecondary missing") }
return @{ Valid = ($issues.Count -eq 0); Issues = $issues; IP = $ip.IPAddress }
}
function Invoke-NodeConfiguration {
param([hashtable]$NodeConfig, [PSCredential]$Cred)
$nodeName = $NodeConfig.NodeName
$currentIP = $NodeConfig.CurrentIP
$targetIP = $NodeConfig.TargetIP
$nic = $NodeConfig.ManagementNIC
Write-Log "--- $nodeName ---" "HEADER"
Write-Log " Connecting to: $currentIP"
Write-Log " Target static IP: $targetIP/$($NodeConfig.PrefixLength) GW: $($NodeConfig.Gateway)"
# ---- Phase 1: Send configuration commands ----
$phase1Result = $null
try {
Write-Log " Opening PSRemoting session to $currentIP..."
$phase1Result = Invoke-Command `
-ComputerName $currentIP `
-Credential $Cred `
-ScriptBlock $NodeConfigScriptBlock `
-ArgumentList $nic, $targetIP, $NodeConfig.PrefixLength, $NodeConfig.Gateway,
$NodeConfig.DNSPrimary, $NodeConfig.DNSSecondary, $RetryCount, 5 `
-ErrorAction Stop
} catch [System.Management.Automation.Remoting.PSRemotingTransportException] {
# Session loss after IP change — this is the expected path
Write-Log " Session dropped (expected — IP change applied on node)." "WARN"
$phase1Result = @{ Result = "CommandsSubmitted"; IP = $targetIP }
} catch {
Write-Log " Phase 1 failed: $_" "ERROR"
return @{ NodeName = $nodeName; Success = $false; Error = $_.Exception.Message }
}
if ($phase1Result.Result -eq "Error") {
Write-Log " Node reported error: $($phase1Result.Error)" "ERROR"
return @{ NodeName = $nodeName; Success = $false; Error = $phase1Result.Error }
}
if ($phase1Result.Result -eq "AlreadyConfigured") {
Write-Log " Already correctly configured." "SUCCESS"
return @{ NodeName = $nodeName; Success = $true; IP = $targetIP; AlreadyDone = $true }
}
# ---- Phase 2: Reconnect to new static IP and verify ----
Write-Log " Waiting for node to come up on new IP $targetIP (timeout: ${ReconnectTimeoutSec}s)..." "WARN"
$deadline = (Get-Date).AddSeconds($ReconnectTimeoutSec)
$verifyResult = $null
while ((Get-Date) -lt $deadline) {
try {
Start-Sleep -Seconds $ReconnectRetrySec
Write-Log " Attempting reconnect to $targetIP..."
$verifyResult = Invoke-Command `
-ComputerName $targetIP `
-Credential $Cred `
-ScriptBlock $VerifyScriptBlock `
-ArgumentList $nic, $targetIP, $NodeConfig.PrefixLength,
$NodeConfig.Gateway, $NodeConfig.DNSPrimary, $NodeConfig.DNSSecondary `
-ErrorAction Stop
break # connected
} catch {
Write-Log " Reconnect attempt failed: $_ — retrying in ${ReconnectRetrySec}s..." "WARN"
}
}
if (-not $verifyResult) {
Write-Log " Could not reconnect to $targetIP within ${ReconnectTimeoutSec}s." "ERROR"
return @{ NodeName = $nodeName; Success = $false; Error = "Reconnect to $targetIP timed out" }
}
# ---- Phase 3: Evaluate verification result ----
if ($verifyResult.Valid) {
Write-Log " All configuration checks passed on $targetIP." "SUCCESS"
return @{ NodeName = $nodeName; Success = $true; IP = $targetIP }
} else {
Write-Log " Verification failed:" "ERROR"
foreach ($issue in $verifyResult.Issues) { Write-Log " - $issue" "ERROR" }
return @{ NodeName = $nodeName; Success = $false; Error = ($verifyResult.Issues -join "; ") }
}
}
# ============================================================================
# MAIN
# ============================================================================
try {
Write-Log "=== Invoke-ConfigureStaticIP-Orchestrated.ps1 ===" "HEADER"
# Resolve config file
$resolvedConfig = Resolve-ConfigPath -ExplicitPath $ConfigPath
# Load config
Import-Module powershell-yaml -ErrorAction Stop
$config = Get-Content $resolvedConfig -Raw | ConvertFrom-Yaml
# Build per-node config objects
$allNodeConfigs = Get-NodeConfigs -Config $config
# Filter to requested nodes if specified
if ($NodeNames -and $NodeNames.Count -gt 0) {
$allNodeConfigs = $allNodeConfigs | Where-Object { $NodeNames -contains $_.NodeName }
if ($allNodeConfigs.Count -eq 0) {
throw "None of the specified NodeNames found in variables.yml: $($NodeNames -join ', ')"
}
}
Write-Log "Nodes to configure: $($allNodeConfigs.Count)"
foreach ($nc in $allNodeConfigs) {
Write-Log " $($nc.NodeName) current: $($nc.CurrentIP) target: $($nc.TargetIP)/$($nc.PrefixLength)"
}
# Get credentials
if (-not $Credential) {
$Credential = Get-Credential -Message "Enter local admin credentials for Azure Local nodes"
}
# Process each node sequentially (IP change causes connectivity disruption — serial is safer)
$results = [System.Collections.Generic.List[hashtable]]::new()
foreach ($nc in $allNodeConfigs) {
$result = Invoke-NodeConfiguration -NodeConfig $nc -Cred $Credential
$results.Add($result)
}
# Summary
Write-Log "=== SUMMARY ===" "HEADER"
$ok = @($results | Where-Object { $_.Success })
$fail = @($results | Where-Object { -not $_.Success })
foreach ($r in $ok) { Write-Log " OK $($r.NodeName) $($r.IP)" "SUCCESS" }
foreach ($r in $fail) { Write-Log " FAIL $($r.NodeName) $($r.Error)" "ERROR" }
Write-Log "Configured: $($ok.Count) / $($results.Count)"
if ($fail.Count -gt 0) { exit 1 }
Write-Log "ALL NODES CONFIGURED SUCCESSFULLY" "SUCCESS"
} catch {
Write-Log "CRITICAL ERROR: $_" "ERROR"
exit 1
}
When to use: Use this option for a self-contained deployment without a shared configuration file.
Script: See azurelocal-toolkit for the standalone script for this task.
Standalone script content references the toolkit repository. See the Orchestrated Script tab for the primary implementation.
Validation Checklist
- Static IP configured on all nodes
-
PrefixOriginshowsManualon each management adapter -
DHCPshowsDisabledon each management adapter - Default gateway reachable from each node
- DNS servers responding from each node
# Run on each node — verify static assignment
$nic = "Embedded NIC 1" # replace with cluster.management_nic_name from variables.yml
Get-NetIPAddress -InterfaceAlias $nic -AddressFamily IPv4 |
Select-Object IPAddress, PrefixLength, PrefixOrigin
Get-NetIPInterface -InterfaceAlias $nic -AddressFamily IPv4 |
Select-Object InterfaceAlias, Dhcp
# Test gateway and DNS reachability
Test-Connection -ComputerName (Get-NetRoute -AddressFamily IPv4 | Where-Object { $_.DestinationPrefix -eq "0.0.0.0/0" }).NextHop -Count 1 -Quiet
Resolve-DnsName "azure.microsoft.com" -ErrorAction SilentlyContinue | Select-Object Name, IPAddress
Troubleshooting
| Issue | Cause | Resolution |
|---|---|---|
| Script hard-fails on startup | REPLACE placeholder values remain | Edit #region CONFIGURATION block with real values |
Adapter not found error | NIC name in config doesn't match the node | Run Get-NetAdapter on the node; update cluster.management_nic_name in variables.yml |
| Node unreachable after orchestrated run | IP changed (no DHCP reservation) | Orchestrator will auto-reconnect to target IP; check logs for reconnect status |
PrefixOrigin shows Dhcp after script | DHCP not fully disabled | Run Set-NetIPInterface -InterfaceAlias '<nic>' -Dhcp Disabled on the node |
| Wrong IP locked in permanently | Incorrect value in variables.yml | Correct management_ip in yml; rerun the script — it will detect mismatch and reconfigure |
| Gateway unreachable after config | Wrong gateway in variables.yml | Verify network.management.gateway; check upstream switch VLAN |
| DNS not resolving | DNS not set or wrong servers | Verify dns.primary / dns.secondary; rerun script |
Alternatives
The procedures in this task use the scripted methods shown in the tabs above. Additional deployment methods including Azure CLI and Bash scripts are available in the azurelocal-toolkit repository under scripts/deploy/.
| Method | Description |
|---|---|
| Azure CLI | PowerShell-based Azure CLI scripts for Azure resource operations |
| Bash | Linux/macOS compatible shell scripts for pipeline environments |
Navigation
| ← Task 02: Enable RDP | ↑ Phase 03: OS Configuration | Task 04: Disable DHCP → |
Version Control
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | 2026-01-31 | Azure Local Cloud | Initial document |
| 2.0 | 2026-03-04 | Azure Local Cloud | Full rewrite to standards — complete frontmatter, 4-tab structure |
| 2.1 | 2026-03-04 | Azure Local Cloud | Embed full script code in each tab per provisioning runbook standard |
| 2.2 | 2026-03-04 | Azure Local Cloud | Fix SConfig NIC instructions — add vendor table, Get-NetAdapter step |
| 3.0 | 2026-03-04 | Azure Local Cloud | Replace DHCP-detection scripts with explicit IP configuration; merge Direct+Standalone into Set-StaticIPAddress.ps1; rewrite Orchestrated with session-loss handling and per-node IP from yml; remove Standalone tab |