Files
AetherForge/cloudflare/repair-tunnel.ps1
AetherForge 3605d540da Add self-healing Cloudflare tunnel with 60s watchdog for USB deck.
Replaces fragile batch-based tunnel install with a single PowerShell
script (cloudflare/start-tunnel.ps1) that installs cloudflared as a
Windows service (admin) or runs as a background process (non-admin),
clears stale EventLog registry keys that caused service rollback, and
runs a 60-second watchdog that auto-restarts the connector on failure.
Hostname changed to aether.thetempleofdoom.com. LAUNCH.bat and
pack-usb.bat updated accordingly.
2026-06-01 15:03:17 -07:00

116 lines
3.8 KiB
PowerShell

param(
[Parameter(Mandatory = $true)][string]$Root,
[ValidateRange(1, 4)][int]$Level = 1
)
$ErrorActionPreference = 'Continue'
$Root = $Root.TrimEnd('\')
$configJson = Join-Path $Root 'cloudflare\tunnel-config.json'
$installBat = Join-Path $Root 'cloudflare\install-tunnel.bat'
$writer = Join-Path $Root 'cloudflare\write-tunnel-config.ps1'
$cfDir = Join-Path $env:ProgramData 'AetherForge\.cloudflared'
$cfConfig = Join-Path $cfDir 'config.yml'
$cfExe = Join-Path $env:ProgramData 'AetherForge\bin\cloudflared.exe'
function Write-RepairLog([string]$Message) {
$line = "{0} [CF-HEAL-L{1}] {2}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $Level, $Message
Write-Output $line
}
function Get-ServiceRunning {
$q = sc.exe query cloudflared 2>&1 | Out-String
return ($q -match 'STATE\s+:\s+\d+\s+RUNNING')
}
function Start-CloudflaredService {
$null = net.exe start cloudflared 2>&1
Start-Sleep -Seconds 3
return (Get-ServiceRunning)
}
function Stop-CloudflaredService {
$null = net.exe stop cloudflared 2>&1
Start-Sleep -Seconds 2
}
function Restart-CloudflaredService {
Stop-CloudflaredService
return (Start-CloudflaredService)
}
Write-RepairLog "Repair level $Level starting..."
switch ($Level) {
1 {
Write-RepairLog "Action: net start cloudflared"
if (Start-CloudflaredService) {
Write-RepairLog "Service is RUNNING"
exit 0
}
Write-RepairLog "net start failed"
exit 1
}
2 {
Write-RepairLog "Action: restart cloudflared service"
if (Restart-CloudflaredService) {
Write-RepairLog "Service restarted OK"
exit 0
}
Write-RepairLog "Restart failed"
exit 1
}
3 {
Write-RepairLog "Action: rewrite config.yml + restart + DNS route"
if (-not (Test-Path $configJson)) {
Write-RepairLog "Missing tunnel-config.json"
exit 1
}
if (-not (Test-Path $writer)) {
Write-RepairLog "Missing write-tunnel-config.ps1"
exit 1
}
$tunnelId = $null
$hostname = $null
& $writer -ConfigJson $configJson -CloudflaredDir $cfDir | ForEach-Object {
if ($_ -match '^TUNNEL_ID=(.+)$') { $tunnelId = $Matches[1] }
if ($_ -match '^HOSTNAME=(.+)$') { $hostname = $Matches[1] }
Write-RepairLog $_
}
if (-not (Test-Path $cfConfig)) {
Write-RepairLog "config.yml write failed"
exit 1
}
Restart-CloudflaredService | Out-Null
if ($cfExe -and (Test-Path $cfExe) -and $tunnelId -and $hostname) {
Write-RepairLog "Action: tunnel route dns $hostname"
& $cfExe --config $cfConfig tunnel route dns $tunnelId $hostname 2>&1 | ForEach-Object { Write-RepairLog $_ }
}
if (Get-ServiceRunning) {
Write-RepairLog "Config refresh + service RUNNING"
exit 0
}
Write-RepairLog "Still not RUNNING after config refresh"
exit 1
}
4 {
Write-RepairLog "Action: full tunnel reinstall (install-tunnel.bat)"
if (-not (Test-Path $installBat)) {
Write-RepairLog "Missing install-tunnel.bat"
exit 1
}
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
[Security.Principal.WindowsBuiltInRole]::Administrator
)
if ($isAdmin) {
& cmd.exe /c "`"$installBat`" `"$Root`""
exit $LASTEXITCODE
}
Write-RepairLog "Requesting elevated reinstall (UAC)..."
$p = Start-Process -FilePath $installBat -ArgumentList "`"$Root`"" -Verb RunAs -Wait -PassThru
exit $p.ExitCode
}
}
Write-RepairLog "Unknown level"
exit 1