Skip to content

Commit fabeaab

Browse files
hhfrancoisclaude
andcommitted
fix(agent): Windows installer host detection works from Git Bash
The one-liner failed from Git Bash with "no cluster host detected": the installer read the host off the live ssh process's command line, which is unreadable when that ssh is Git's MSYS build. Accept it explicitly via $env:PLUG_HOST/PLUG_PORT (the native Windows OpenSSH client is still auto-detected). Also make Die actually stop the script — a piped `powershell -Command -` ignored the old exit, so plug.exe could fail yet the script ran on and copied wintun.dll — and rewrite the README Windows section assuming Git for Windows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent edebfba commit fabeaab

3 files changed

Lines changed: 60 additions & 25 deletions

File tree

README.md

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -164,28 +164,41 @@ use its FQDN (`myservice.othernamespace`). See [deploy/README.md](deploy/README.
164164
165165
## Windows
166166
167-
Native Windows is supported (no WSL2 needed). Install straight from the cluster,
168-
one line — same model as unix, just piped into PowerShell instead of `sh`:
167+
Native Windows is supported (no WSL2 needed). You need an `ssh` client; this guide
168+
**assumes [Git for Windows](https://git-scm.com/download/win) is installed** — it
169+
ships both `ssh` and Git Bash, which nearly every Windows dev already has. (Windows'
170+
built-in OpenSSH client works too — see the note below.)
169171
170-
```powershell
172+
**1. Install — from Git Bash, one line.** Same model as unix, piped into PowerShell
173+
instead of `sh`. The `ssh` bundled with Git is an MSYS process whose Windows command
174+
line the installer can't introspect, so **pass the cluster host/port explicitly** on
175+
the PowerShell side of the pipe — that's what names your profile:
176+
177+
```bash
171178
# host key regenerated each start (not a secret) — skip the check, as plug does internally:
172-
ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL get@<cluster-host> install-windows | powershell -NoProfile -Command -
179+
ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
180+
get@<cluster-host> install-windows \
181+
| PLUG_HOST=<cluster-host> PLUG_PORT=2222 powershell -NoProfile -Command -
173182
```
174183

175184
This downloads `plug.exe` and `wintun.dll` into `%LOCALAPPDATA%\Programs\plug`,
176-
adds it to your PATH, and pre-creates a `~/.plug/<host>.conf` profile from your
177-
`ssh` line. Installing needs **no administrator rights**. Requires the built-in
178-
Windows OpenSSH client (*Settings → Apps → Optional Features → OpenSSH Client*).
185+
adds it to your PATH, and pre-creates a `~/.plug/<host>.conf` profile. Installing
186+
needs **no administrator rights**. Open a new terminal afterwards so the PATH takes
187+
effect.
179188

180-
**Running — the one caveat.** plug's Windows data path is a WinTUN adapter, and
181-
creating it plus its routes requires **Administrator**. Unlike Linux (`setcap`) or
182-
macOS (setuid helper) — where one grant at install lets every later run start
183-
unprivileged — Windows has no per-binary privilege bit, and the process holding
184-
the adapter is the same one running your command in the foreground. So **for now,
185-
start `plug` from an elevated terminal** (*Run as administrator*):
189+
> **Using Windows' native OpenSSH client instead?** Run the same line from a normal
190+
> PowerShell (with `UserKnownHostsFile=NUL`) and **drop the `PLUG_HOST=/PLUG_PORT=`
191+
> prefix** — that client's command line *is* readable, so the host is auto-detected.
192+
193+
**2. Run — the one caveat: an elevated terminal.** plug's Windows data path is a
194+
WinTUN adapter, and creating it plus its routes requires **Administrator**. Unlike
195+
Linux (`setcap`) or macOS (setuid helper) — where one grant at install lets every
196+
later run start unprivileged — Windows has no per-binary privilege bit, and the
197+
process holding the adapter is the same one running your command in the foreground.
198+
So **for now, start `plug` from an elevated terminal** (*Run as administrator*):
186199

187200
```powershell
188-
plug npm run start:dev
201+
plug <your command> # several clusters? plug -p <name> <your command>
189202
```
190203

191204
A future release will move the Windows data path into a persistent **SYSTEM

RELEASE_NOTES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
## NEXT RELEASE
44

5+
- **Windows installer works from Git Bash.** The one-liner used to fail there with
6+
`no cluster host detected`: the installer read the host off the live `ssh`
7+
process's command line, which is unreadable when that `ssh` is Git's MSYS build.
8+
You can now pass it explicitly — `… install-windows | PLUG_HOST=<host> PLUG_PORT=<port>
9+
powershell -NoProfile -Command -` — while the native Windows OpenSSH client is
10+
still auto-detected with no prefix. Also, a fatal installer error now actually
11+
stops the script (a piped `powershell -Command -` ignored the old `exit`), and the
12+
README documents the Git-Bash path assuming Git for Windows is present.
513
- **Attribution hardened against PID recycling.** The by-process router now stamps
614
each hop of the ancestry walk with the process's start time and refuses a
715
temporally impossible chain — an "ancestor" that started *after* its child is a

agent/install.ps1

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ $PlugExe = Join-Path $InstallDir 'plug.exe'
3636
$WintunDll = Join-Path $InstallDir 'wintun.dll'
3737

3838
function Info($msg) { Write-Host "plug: $msg" }
39-
function Die($msg) { Write-Error "plug: $msg"; exit 1 }
39+
# throw (not Write-Error + exit): under `powershell -Command -` a piped script's
40+
# `exit` does not reliably stop it, so an error used to print yet the script ran on.
41+
function Die($msg) { throw "plug: $msg" }
4042

4143
# --- 1. Discover the cluster host/port from the live ssh invocation ----------
4244
# You reached the agent with `ssh ... get@<host> install-windows`; the agent can
@@ -48,15 +50,27 @@ function Die($msg) { Write-Error "plug: $msg"; exit 1 }
4850
$SshHost = $null
4951
$SshPort = $DefaultPort
5052
$profileMsg = $null
51-
try {
52-
$line = Get-CimInstance Win32_Process -Filter "Name='ssh.exe'" |
53-
Where-Object { $_.CommandLine -match 'get@' -and $_.CommandLine -match 'install-windows' } |
54-
Select-Object -First 1 -ExpandProperty CommandLine
55-
if ($line) {
56-
if ($line -match 'get@([A-Za-z0-9._-]+)') { $SshHost = $Matches[1] }
57-
if ($line -match '-p[ =]*([0-9]+)') { $SshPort = $Matches[1] }
58-
}
59-
} catch { }
53+
54+
# (a) Explicit override — the robust path from Git Bash / MSYS, where the ssh that
55+
# streams this script is an MSYS process whose Win32 CommandLine the auto-detect
56+
# below cannot read. Pass it on the powershell side of the pipe:
57+
# ssh ... get@<host> install-windows | PLUG_HOST=<host> PLUG_PORT=<port> powershell -NoProfile -Command -
58+
if ($env:PLUG_HOST) { $SshHost = $env:PLUG_HOST }
59+
if ($env:PLUG_PORT) { $SshPort = $env:PLUG_PORT }
60+
61+
# (b) Otherwise auto-detect from the live ssh invocation — works with the native
62+
# Windows OpenSSH client, whose process CommandLine is readable.
63+
if (-not $SshHost) {
64+
try {
65+
$line = Get-CimInstance Win32_Process -Filter "Name='ssh.exe'" |
66+
Where-Object { $_.CommandLine -match 'get@' -and $_.CommandLine -match 'install-windows' } |
67+
Select-Object -First 1 -ExpandProperty CommandLine
68+
if ($line) {
69+
if ($line -match 'get@([A-Za-z0-9._-]+)') { $SshHost = $Matches[1] }
70+
if ($line -match '-p[ =]*([0-9]+)') { $SshPort = $Matches[1] }
71+
}
72+
} catch { }
73+
}
6074

6175
if ($SshHost) {
6276
$plugCfgDir = Join-Path $env:USERPROFILE '.plug'
@@ -76,7 +90,7 @@ New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
7690

7791
function Get-AgentBinary($outFile) {
7892
if (-not $SshHost) {
79-
Die 'cannot download plug.exe: no cluster host detected (run from an `ssh ... get@<host> install-windows | powershell -` line)'
93+
Die 'no cluster host detected. From Git Bash, pass it on the powershell side of the pipe: | PLUG_HOST=<host> PLUG_PORT=<port> powershell -NoProfile -Command - (the native Windows OpenSSH client is auto-detected without this)'
8094
}
8195
if (-not (Get-Command ssh -ErrorAction SilentlyContinue)) {
8296
Die 'ssh.exe not found. Install the Windows OpenSSH client (Settings > Apps > Optional Features > OpenSSH Client), then re-run.'

0 commit comments

Comments
 (0)