Two related rough edges in the dashboard-onion (#343) provisioning outside of setup.
Bug A — rotate-dashboard-onion crashes
./pithead rotate-dashboard-onion -y
→ aborts:
./pithead: line ~2469: HOST_IP: unbound variable
[ERROR] pithead aborted unexpectedly (exit 1).
Root cause: the rotate function (~pithead:2210-2250) calls provision_tor then render_env, but never calls resolve_dashboard_host — which is what sets the HOST_IP global that render_env reads. Under set -u, render_env dies on the unbound HOST_IP. setup (pithead:2907) and apply (pithead:3138) both call resolve_dashboard_host first; rotate is the only path that skips it.
Consequence: it wipes/regenerates the hidden service, then crashes before render_env persists the new address + client keypair — leaving the onion in a half-provisioned state (new authorized_clients pubkey written, but the private key not saved anywhere).
Fix: call resolve_dashboard_host (non-interactive) inside rotate_dashboard_onion before render_env, mirroring apply.
Bug B — onion address not captured when enabled via upgrade
Enabling dashboard.onion.enabled: true and running ./pithead upgrade generates the tor hidden-service hostname, but the .onion address is never written to .env, so pithead status / onion-client-key can't show it.
Root cause: only apply captures it (pithead:3231 provision_dashboard_onion && render_env), and that block is gated behind change-detection — if a prior upgrade already enabled the onion, the next apply hits pithead:3195 "No configuration changes detected. Nothing to apply." and returns before reaching the capture block. upgrade itself never runs provision_tor/capture.
Fix: capture the dashboard onion address whenever it's enabled-but-uncaptured (address empty/placeholder), independent of change detection — in both apply and upgrade.
Workarounds used (v1.2.1 live deploy)
- Bug A:
HOST_IP=<dashboard host> ./pithead rotate-dashboard-onion -y
- Bug B: the rotate above is what finally provisioned + captured the address.
Suggested tests
tests/stack assertions (stubbing docker/tor as the existing onion tests do): rotate provisions + persists a new address without crashing; enabling the onion + apply captures the address into .env.
Impact: medium — the primary key-rotation/recovery command is unusable as shipped, and the address is invisible after a plain upgrade-based enable.
Two related rough edges in the dashboard-onion (#343) provisioning outside of
setup.Bug A —
rotate-dashboard-onioncrashes→ aborts:
Root cause: the rotate function (~
pithead:2210-2250) callsprovision_torthenrender_env, but never callsresolve_dashboard_host— which is what sets theHOST_IPglobal thatrender_envreads. Underset -u,render_envdies on the unboundHOST_IP.setup(pithead:2907) andapply(pithead:3138) both callresolve_dashboard_hostfirst; rotate is the only path that skips it.Consequence: it wipes/regenerates the hidden service, then crashes before
render_envpersists the new address + client keypair — leaving the onion in a half-provisioned state (newauthorized_clientspubkey written, but the private key not saved anywhere).Fix: call
resolve_dashboard_host(non-interactive) insiderotate_dashboard_onionbeforerender_env, mirroringapply.Bug B — onion address not captured when enabled via
upgradeEnabling
dashboard.onion.enabled: trueand running./pithead upgradegenerates the tor hidden-service hostname, but the.onionaddress is never written to.env, sopithead status/onion-client-keycan't show it.Root cause: only
applycaptures it (pithead:3231provision_dashboard_onion && render_env), and that block is gated behind change-detection — if a priorupgradealready enabled the onion, the nextapplyhitspithead:3195"No configuration changes detected. Nothing to apply." and returns before reaching the capture block.upgradeitself never runsprovision_tor/capture.Fix: capture the dashboard onion address whenever it's enabled-but-uncaptured (address empty/placeholder), independent of change detection — in both
applyandupgrade.Workarounds used (v1.2.1 live deploy)
HOST_IP=<dashboard host> ./pithead rotate-dashboard-onion -ySuggested tests
tests/stackassertions (stubbing docker/tor as the existing onion tests do): rotate provisions + persists a new address without crashing; enabling the onion + apply captures the address into.env.Impact: medium — the primary key-rotation/recovery command is unusable as shipped, and the address is invisible after a plain
upgrade-based enable.