diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-08-23 00:37:31 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-23 00:37:31 +0300 |
| commit | c9601b9396532a552679328c8f0804d52909bc84 (patch) | |
| tree | 407359aad803b3dd4fc7491f0b47656ebfb448a2 /website | |
| parent | db6f301f1301d85ca7a4271363760836f53ac0d0 (diff) | |
fix(windows): add local cmd installer bootstrap (#3133)
* fix(windows): add local cmd installer bootstrap
refs #2751
* fix(windows): bound installer downloads
refs #2751
Diffstat (limited to 'website')
| -rw-r--r-- | website/_headers | 8 | ||||
| -rw-r--r-- | website/agent-guide.md | 9 | ||||
| -rw-r--r-- | website/index.html | 2 | ||||
| -rw-r--r-- | website/install.cmd | 21 | ||||
| -rw-r--r-- | website/install.ps1 | 62 | ||||
| -rw-r--r-- | website/scripts/prepare-docs.mjs | 1 |
6 files changed, 98 insertions, 5 deletions
diff --git a/website/_headers b/website/_headers index da99d1b0..6422cca9 100644 --- a/website/_headers +++ b/website/_headers @@ -14,6 +14,14 @@ Content-Type: text/plain Content-Disposition: inline +/install.ps1 + Content-Type: text/plain + Content-Disposition: inline + +/install.cmd + Content-Type: text/plain + Content-Disposition: inline + /latest.json Content-Type: application/json Cache-Control: public, max-age=300 diff --git a/website/agent-guide.md b/website/agent-guide.md index 71392817..b542dd94 100644 --- a/website/agent-guide.md +++ b/website/agent-guide.md @@ -32,13 +32,20 @@ curl -fsSL https://herdr.dev/install.sh | sh herdr ``` -Windows: +Windows PowerShell: ```powershell powershell -ExecutionPolicy Bypass -c "irm https://herdr.dev/install.ps1 | iex" herdr ``` +If endpoint security blocks that fileless PowerShell command, use Command Prompt: + +```cmd +curl.exe -fsSLo install.cmd https://herdr.dev/install.cmd && install.cmd && del install.cmd +herdr +``` + Homebrew, mise, and Nix installs, verification, and manual downloads: https://herdr.dev/docs/install/. Direct installs use the stable channel by default and update with `herdr update`; preview is opt-in. Package-manager installs update through that package manager. Check the version with `herdr --version`. ## First-run walkthrough diff --git a/website/index.html b/website/index.html index 06750444..4186792e 100644 --- a/website/index.html +++ b/website/index.html @@ -475,7 +475,7 @@ <button type="button" id="copy-btn-2" aria-label="Copy install command">copy</button> </div> </div> - <div class="meta">Windows: <code>irm https://herdr.dev/install.ps1 | iex</code> — <a href="/docs/">all install methods →</a></div> + <div class="meta">Windows: <code>irm https://herdr.dev/install.ps1 | iex</code> — <a href="/docs/windows-beta/">endpoint-protected install</a> · <a href="/docs/">all install methods →</a></div> </div> </section> diff --git a/website/install.cmd b/website/install.cmd new file mode 100644 index 00000000..325e3b38 --- /dev/null +++ b/website/install.cmd @@ -0,0 +1,21 @@ +@echo off +setlocal + +set "INSTALLER_URL=https://herdr.dev/install.ps1" +set "CURL_PROTOCOL=--proto =https --tlsv1.2" +if defined HERDR_INSTALLER_URL ( + set "INSTALLER_URL=%HERDR_INSTALLER_URL%" + set "CURL_PROTOCOL=--proto =http,https" +) +set "INSTALLER_PATH=%TEMP%\herdr-install-%RANDOM%-%RANDOM%.ps1" + +curl.exe --fail --silent --show-error --location --connect-timeout 30 --speed-limit 1024 --speed-time 30 %CURL_PROTOCOL% --output "%INSTALLER_PATH%" -- "%INSTALLER_URL%" +if errorlevel 1 ( + del /f /q "%INSTALLER_PATH%" >nul 2>&1 + exit /b 1 +) + +powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%INSTALLER_PATH%" %* +set "INSTALLER_EXIT=%ERRORLEVEL%" +del /f /q "%INSTALLER_PATH%" >nul 2>&1 +exit /b %INSTALLER_EXIT% diff --git a/website/install.ps1 b/website/install.ps1 index 9dacfaa9..94a57314 100644 --- a/website/install.ps1 +++ b/website/install.ps1 @@ -216,6 +216,50 @@ function Get-ManifestAsset { } } +function Invoke-CurlDownload { + param( + [string]$Uri, + [string]$Destination + ) + + $parsedUri = $null + if (-not [System.Uri]::TryCreate($Uri, [System.UriKind]::Absolute, [ref]$parsedUri) -or + $parsedUri.Scheme -notin @("http", "https")) { + throw "Herdr download URL must use HTTP or HTTPS: $Uri" + } + + $curl = Get-Command curl.exe -CommandType Application -ErrorAction SilentlyContinue | + Select-Object -First 1 + if ($null -eq $curl) { + throw "Herdr installation requires curl.exe, which is included with supported Windows versions." + } + + $arguments = @( + "--fail", + "--silent", + "--show-error", + "--location", + "--connect-timeout", "30", + "--speed-limit", "1024", + "--speed-time", "30" + ) + if ($parsedUri.Scheme -eq "https") { + $arguments += @("--proto", "=https", "--tlsv1.2") + } + $arguments += @("--output", $Destination, "--", $Uri) + + $curlOutput = & $curl.Source @arguments 2>&1 + $curlExitCode = $LASTEXITCODE + if ($curlExitCode -ne 0) { + $detail = ($curlOutput | ForEach-Object { $_.ToString() }) -join [Environment]::NewLine + $message = "Failed to download $Uri (curl exit code $curlExitCode)." + if (-not [string]::IsNullOrWhiteSpace($detail)) { + $message += " $detail" + } + throw $message + } +} + function ConvertTo-ManifestObject { param([object]$Manifest) @@ -232,6 +276,18 @@ function ConvertTo-ManifestObject { return $json | ConvertFrom-Json } +function Get-RemoteManifest { + param([string]$Uri) + + $manifestPath = Join-Path ([System.IO.Path]::GetTempPath()) ("herdr-manifest-" + [System.Guid]::NewGuid().ToString("N") + ".json") + try { + Invoke-CurlDownload -Uri $Uri -Destination $manifestPath + return ConvertTo-ManifestObject -Manifest ([System.IO.File]::ReadAllText($manifestPath)) + } finally { + Remove-Item -LiteralPath $manifestPath -Force -ErrorAction SilentlyContinue + } +} + function Test-FileDigest { param( [string]$Path, @@ -685,7 +741,7 @@ if ($useLocalPackage) { } Write-Step "Fetching Herdr $Channel manifest" - $manifest = ConvertTo-ManifestObject -Manifest (Invoke-RestMethod -Uri $ManifestUrl) + $manifest = Get-RemoteManifest -Uri $ManifestUrl $manifestChannelProperty = $manifest.PSObject.Properties["channel"] if (-not $channelWasExplicit -and $null -ne $manifestChannelProperty -and [string]$manifestChannelProperty.Value -eq "preview") { $Channel = "preview" @@ -704,7 +760,7 @@ if ($useLocalPackage) { $Channel = "preview" $ManifestUrl = $ManifestUrl.Substring(0, $ManifestUrl.Length - "latest.json".Length) + "preview.json" Write-Step "Fetching Herdr preview manifest" - $manifest = ConvertTo-ManifestObject -Manifest (Invoke-RestMethod -Uri $ManifestUrl) + $manifest = Get-RemoteManifest -Uri $ManifestUrl } $asset = Get-ManifestAsset -Manifest $manifest -Target $target if (-not [string]::IsNullOrWhiteSpace($ExpectedBuildId) -and [string]$manifest.build_id -ne $ExpectedBuildId) { @@ -733,7 +789,7 @@ try { $stagingDir = Join-Path $releasesDir ".staging.$releaseName.$PID" if (-not $useLocalPackage) { Write-Step "Downloading Herdr" - Invoke-WebRequest -Uri $asset.Url -OutFile $downloadPath + Invoke-CurlDownload -Uri $asset.Url -Destination $downloadPath } Test-FileDigest -Path $downloadPath -ExpectedDigest $asset.Sha256 diff --git a/website/scripts/prepare-docs.mjs b/website/scripts/prepare-docs.mjs index 14d62abc..e8278851 100644 --- a/website/scripts/prepare-docs.mjs +++ b/website/scripts/prepare-docs.mjs @@ -68,6 +68,7 @@ async function preparePublicAssets() { for (const file of [ 'install.sh', 'install.ps1', + 'install.cmd', 'agent-guide.md', 'latest.json', 'preview.json', |
