# install-hydrahotspot.ps1 # Installs "HydraHotspot": auto-start + self-heal for the Windows Mobile Hotspot on a # venue-kiosk machine. Reproduces what was hand-installed on fluffy-dumpling-87 # (hostname hydra-s-0000) at the gallo-romeins-museum venue, 2026-07-17..23. # Goal: turn this into a hydracluster role recipe (recipes/hydra-hotspot-windows.yaml). $ErrorActionPreference = 'Stop' # --- 1. Runtime script: idempotently turn the Mobile Hotspot ON (retry loop for uplink settle) --- $runtime = @' $null = [System.Reflection.Assembly]::LoadWithPartialName('System.Runtime.WindowsRuntime') function Await($t,$rt){ $m=([System.WindowsRuntimeSystemExtensions].GetMethods()|Where-Object{$_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1'})[0]; $g=$m.MakeGenericMethod($rt); $nt=$g.Invoke($null,@($t)); $nt.Wait(-1)|Out-Null; $nt.Result } for($i=0;$i -lt 30;$i++){ try{ $p=[Windows.Networking.Connectivity.NetworkInformation,Windows.Networking.Connectivity,ContentType=WindowsRuntime]::GetInternetConnectionProfile() if($p){ $m=[Windows.Networking.NetworkOperators.NetworkOperatorTetheringManager,Windows.Networking.NetworkOperators,ContentType=WindowsRuntime]::CreateFromConnectionProfile($p) if($m.TetheringOperationalState -ne 'On'){ Await ($m.StartTetheringAsync()) ([Windows.Networking.NetworkOperators.NetworkOperatorTetheringOperationResult]) | Out-Null } if($m.TetheringOperationalState -eq 'On'){ "$(Get-Date -Format o) hotspot ON" | Out-File -Append 'C:\hydra\hotspot.log'; break } } }catch{ "$(Get-Date -Format o) err $($_.Exception.Message)" | Out-File -Append 'C:\hydra\hotspot.log' } Start-Sleep -Seconds 5 } '@ New-Item -ItemType Directory -Force -Path 'C:\hydra' | Out-Null Set-Content -Path 'C:\hydra\start-hotspot.ps1' -Value $runtime -Encoding UTF8 # --- 2. Scheduled task: start at logon (+15s) AND self-heal every 5 min --- $act = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File C:\hydra\start-hotspot.ps1' $tLogon = New-ScheduledTaskTrigger -AtLogOn -User 'hydra'; $tLogon.Delay = 'PT15S' $tRepeat = New-ScheduledTaskTrigger -Once -At (Get-Date).Date -RepetitionInterval (New-TimeSpan -Minutes 5) -RepetitionDuration (New-TimeSpan -Days 3650) $prin = New-ScheduledTaskPrincipal -UserId 'hydra' -LogonType Interactive -RunLevel Highest $set = New-ScheduledTaskSettingsSet -StartWhenAvailable -MultipleInstances IgnoreNew -ExecutionTimeLimit (New-TimeSpan -Minutes 4) Register-ScheduledTask -TaskName 'HydraHotspot' -Description 'Auto-start + self-heal Windows Mobile Hotspot for venue kiosk devices' -Action $act -Trigger $tLogon,$tRepeat -Principal $prin -Settings $set -Force # --- Dependencies / notes (parametrise for a recipe) --- # * Mobile Hotspot SSID/password/shared-uplink must already be configured in Windows Settings (it persists; only the ON state does not). # On fluffy: SSID "experiencenet", shares the Ethernet uplink. # * Requires AutoAdminLogon for an admin user (here: 'hydra') so the logon trigger fires unattended after boot. # The tethering WinRT API needs an interactive, elevated session — SYSTEM-at-boot does not work reliably. # * Windows auto-disables Mobile Hotspot ~5 min after the LAST client disconnects; the 5-min repeat re-asserts it. # * 'hydra' is the venue-specific kiosk user — parametrise (user, SSID) when turning this into a recipe.