function Install-GoTunnel { $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' $repo = 'bakare-dev/gotunnel-io' $asset = 'gotunnel-windows-amd64.exe' if (-not [Environment]::Is64BitOperatingSystem) { throw 'GoTunnel needs 64-bit Windows.' } $version = if ($env:GOTUNNEL_VERSION) { $env:GOTUNNEL_VERSION } else { 'latest' } if ($version -notmatch '^[A-Za-z0-9._-]+$') { throw "Invalid GOTUNNEL_VERSION: $version" } $base = if ($version -eq 'latest') { "https://github.com/$repo/releases/latest/download" } else { "https://github.com/$repo/releases/download/$version" } $dir = if ($env:GOTUNNEL_INSTALL_DIR) { $env:GOTUNNEL_INSTALL_DIR } else { Join-Path $env:LOCALAPPDATA 'Programs\gotunnel' } [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 $tmp = Join-Path ([IO.Path]::GetTempPath()) ("gotunnel-" + [Guid]::NewGuid()) New-Item -ItemType Directory -Path $tmp | Out-Null try { Write-Host "Downloading $asset ($version)..." $exe = Join-Path $tmp 'gotunnel.exe' try { Invoke-WebRequest -UseBasicParsing -Uri "$base/$asset" -OutFile $exe } catch { throw "Could not download $asset ($version): $($_.Exception.Message)" } $sums = Join-Path $tmp 'checksums.txt' try { Invoke-WebRequest -UseBasicParsing -Uri "$base/checksums.txt" -OutFile $sums } catch { throw "Could not download checksums.txt, so the download can't be verified: $($_.Exception.Message)" } $entry = Get-Content $sums | Where-Object { ($_ -split '\s+')[1] -eq $asset } | Select-Object -First 1 if (-not $entry) { throw "checksums.txt has no entry for $asset." } $want = ($entry -split '\s+')[0].ToLowerInvariant() $got = (Get-FileHash -Algorithm SHA256 -LiteralPath $exe).Hash.ToLowerInvariant() if ($want -ne $got) { throw "Checksum mismatch for $asset; nothing was installed." } New-Item -ItemType Directory -Force -Path $dir | Out-Null try { Move-Item -Force -LiteralPath $exe -Destination (Join-Path $dir 'gotunnel.exe') } catch { throw "Could not replace $dir\gotunnel.exe. Close any running gotunnel and try again. ($($_.Exception.Message))" } } finally { Remove-Item -Recurse -Force -LiteralPath $tmp -ErrorAction SilentlyContinue } $userPath = [Environment]::GetEnvironmentVariable('Path', 'User') $entries = @($userPath -split ';' | Where-Object { $_ }) if ($entries -notcontains $dir) { [Environment]::SetEnvironmentVariable('Path', (($entries + $dir) -join ';'), 'User') Write-Host "Added $dir to your user PATH." } if (($env:Path -split ';') -notcontains $dir) { $env:Path = "$env:Path;$dir" } $installed = & (Join-Path $dir 'gotunnel.exe') version Write-Host "Installed $installed to $dir\gotunnel.exe" Write-Host '' Write-Host 'Get started: gotunnel http 3000' } Install-GoTunnel