docs: document NPM dedicated-port jail convention and zsh $path footgun

Two real gotchas from today's goddy->gringo Laravel migration: every jail
on an NPM-fronted host needs a dedicated listen port (8000+last-octet),
not just the shared port 80, or NPM cutover silently can't reach it even
though every direct/Host-header test passes. Separately, zsh ties a
variable literally named `path` to $PATH itself - overwriting it broke
every subsequent command in a config-editing script with no clear error.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 19:44:23 +02:00
co-authored by Claude Sonnet 5
parent 27e3a2975f
commit 106e61cfbb
2 changed files with 59 additions and 0 deletions
@@ -60,6 +60,26 @@ decode step per real filesystem boundary crossed is enough.
special characters — check for quoting corruption before looking
elsewhere.
## zsh footgun: never name a variable `path` (or a few other reserved names)
If the remote host's shell is zsh (several boxes in this fleet default to
it), assigning a plain string to a variable literally named `path` does
not create a normal local variable — zsh ties the lowercase `path` array
to `$PATH` (colon-joined ⇄ array elements) automatically. Overwriting it
with a single string **replaces `$PATH` itself**, and every subsequent
command in that shell (including ones on later lines of the same script)
fails with `command not found: cp` / `command not found: awk` / etc. —
confirmed live 2026-08-07 editing nginx configs over SSH into a zsh
remote shell, where a loop using `path="/usr/local/etc/nginx/..."` broke
every command after the assignment with no explanation beyond
`command not found`. **Rename to anything else** (`cfgpath`, `target`,
`dest`, ...) — this isn't specific to nginx configs, it'll happen with
any script that happens to pick `path` as a variable name on a zsh
remote. A few other zsh-reserved lowercase names exist for the same
reason (`status`, `pipestatus`) — when in doubt, avoid single common
English words as variable names in scripts meant to run under an
unknown/remote shell, or check `typeset -p <name>` first if unsure.
## What NOT to do
Don't respond to a quoting failure by adding more layers of escaping