param( [Parameter(Mandatory = $true)][string]$ConfigJson, [Parameter(Mandatory = $true)][string]$CloudflaredDir ) $ErrorActionPreference = 'Stop' $cfg = Get-Content -LiteralPath $ConfigJson -Raw | ConvertFrom-Json if (-not $cfg.hostname) { throw 'tunnel-config.json: hostname is required' } if (-not $cfg.origin) { throw 'tunnel-config.json: origin is required (e.g. http://127.0.0.1:8989)' } if (-not $cfg.tunnel_token) { throw 'tunnel-config.json: tunnel_token is required' } $tokenJson = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($cfg.tunnel_token)) | ConvertFrom-Json if (-not $tokenJson.a -or -not $tokenJson.t -or -not $tokenJson.s) { throw 'tunnel_token is not a valid Cloudflare tunnel token' } New-Item -ItemType Directory -Force -Path $CloudflaredDir | Out-Null $credPath = Join-Path $CloudflaredDir 'credentials.json' $configPath = Join-Path $CloudflaredDir 'config.yml' $credentials = [ordered]@{ AccountTag = [string]$tokenJson.a TunnelSecret = [string]$tokenJson.s TunnelID = [string]$tokenJson.t } ($credentials | ConvertTo-Json) | Set-Content -LiteralPath $credPath -Encoding UTF8 $credPathYaml = ($credPath -replace '\\', '/') $config = @" # AetherForge local tunnel routing (written by install-tunnel.bat) tunnel: $($tokenJson.t) credentials-file: $credPathYaml ingress: - hostname: $($cfg.hostname) service: $($cfg.origin) - service: http_status:404 "@ Set-Content -LiteralPath $configPath -Value $config -Encoding UTF8 Write-Output "TUNNEL_ID=$($tokenJson.t)" Write-Output "HOSTNAME=$($cfg.hostname)" Write-Output "ORIGIN=$($cfg.origin)" Write-Output "CONFIG=$configPath" Write-Output "CREDENTIALS=$credPath"