Work type
Bug / regression
Observed behavior
internal/workspace/bootstrap.go:36 writes a systemd unit for VM-provisioned workspaces with Environment=HARNESS_ADDR=:8080 and no HARNESS_AUTH_DISABLED or API-key store configuration. Since #1328, cmd/harnessd/bind_guard.go (checkBindSafety) refuses to start an unauthenticated daemon that listens beyond loopback: "refusing to start: :8080 listens beyond this machine but no authentication is configured". The bootstrap then runs systemctl start harnessd || true, so the failure is swallowed and the VM workspace comes up without a daemon. Found during the docs audit for epic #1369 (website docs worker); not yet reproduced on a real VM.
Expected behavior
A VM-provisioned workspace either binds loopback and is reached through the VM's private channel, or binds the VM interface with an API key provisioned at bootstrap, and bootstrap fails loudly if harnessd does not start.
Reproduction
- Read
internal/workspace/bootstrap.go unit template (HARNESS_ADDR=:8080, no auth env).
- Start harnessd with
HARNESS_ADDR=:8080 and no key store on any host: exits with the bind-guard refusal.
- Bootstrap's
systemctl start harnessd || true hides the exit. Reproduction rate: deterministic from the template; live VM path unverified.
User and operational impact
workspace_type: "vm" runs cannot reach a daemon; failure surfaces later as connection errors. Related: #565 (bootstrap never installs harnessd), #567 (VM write path).
Suspected seam and search evidence
internal/workspace/bootstrap.go (unit template), cmd/harnessd/bind_guard.go:12-49. Searched HARNESS_ADDR=:8080 across internal/ and docs; the only remaining wildcard bind is this template.
Blast-radius impact map
VM workspace provisioning only. Config/env: the unit's env block. Security: must not reintroduce an open unauthenticated daemon; provision a key or bind loopback. Tests: internal/workspace bootstrap template tests. Docs: docs/runbooks/deployment.md VM section.
Regression test first
internal/workspace TestBootstrapUnitDoesNotBindWildcardWithoutAuth asserting the rendered unit either binds 127.0.0.1 or sets an auth mechanism; red: go test ./internal/workspace -run TestBootstrapUnit.
Fix boundaries
In scope: the unit template and bootstrap error propagation. Out of scope: key distribution design beyond passing an existing HARNESS_API_KEY/store path into the unit.
Diagnostic and observability evidence
Bind-guard refusal text; systemctl status harnessd on the VM after bootstrap.
Verification plan
Red/green; go test ./internal/workspace -race; if a VM provider is configured, one real provision showing /healthz reachable.
Rollout and rollback
Template change only; revert PR.
Documentation and handoff
Engineering log; deployment runbook VM section.
Definition of done
Process acknowledgement
Work type
Bug / regression
Observed behavior
internal/workspace/bootstrap.go:36writes a systemd unit for VM-provisioned workspaces withEnvironment=HARNESS_ADDR=:8080and noHARNESS_AUTH_DISABLEDor API-key store configuration. Since #1328,cmd/harnessd/bind_guard.go(checkBindSafety) refuses to start an unauthenticated daemon that listens beyond loopback: "refusing to start: :8080 listens beyond this machine but no authentication is configured". The bootstrap then runssystemctl start harnessd || true, so the failure is swallowed and the VM workspace comes up without a daemon. Found during the docs audit for epic #1369 (website docs worker); not yet reproduced on a real VM.Expected behavior
A VM-provisioned workspace either binds loopback and is reached through the VM's private channel, or binds the VM interface with an API key provisioned at bootstrap, and bootstrap fails loudly if harnessd does not start.
Reproduction
internal/workspace/bootstrap.gounit template (HARNESS_ADDR=:8080, no auth env).HARNESS_ADDR=:8080and no key store on any host: exits with the bind-guard refusal.systemctl start harnessd || truehides the exit. Reproduction rate: deterministic from the template; live VM path unverified.User and operational impact
workspace_type: "vm"runs cannot reach a daemon; failure surfaces later as connection errors. Related: #565 (bootstrap never installs harnessd), #567 (VM write path).Suspected seam and search evidence
internal/workspace/bootstrap.go(unit template),cmd/harnessd/bind_guard.go:12-49. SearchedHARNESS_ADDR=:8080across internal/ and docs; the only remaining wildcard bind is this template.Blast-radius impact map
VM workspace provisioning only. Config/env: the unit's env block. Security: must not reintroduce an open unauthenticated daemon; provision a key or bind loopback. Tests:
internal/workspacebootstrap template tests. Docs:docs/runbooks/deployment.mdVM section.Regression test first
internal/workspaceTestBootstrapUnitDoesNotBindWildcardWithoutAuthasserting the rendered unit either binds127.0.0.1or sets an auth mechanism; red:go test ./internal/workspace -run TestBootstrapUnit.Fix boundaries
In scope: the unit template and bootstrap error propagation. Out of scope: key distribution design beyond passing an existing
HARNESS_API_KEY/store path into the unit.Diagnostic and observability evidence
Bind-guard refusal text;
systemctl status harnessdon the VM after bootstrap.Verification plan
Red/green;
go test ./internal/workspace -race; if a VM provider is configured, one real provision showing/healthzreachable.Rollout and rollback
Template change only; revert PR.
Documentation and handoff
Engineering log; deployment runbook VM section.
Definition of done
Process acknowledgement