Wait for the agent's bootstrap sentinel before any work.
gcp-bootstrap-completed in the same directory instead. Different file name, same place.
Accept every status code that means "server is responsive" — 200, 302 (auth redirect), 401 (auth required but listening).
Avoids the brittle "expected 200, got 302" false-not-ready failure when the service is up but redirecting to login.
For processes on localhost (Flask, uvicorn, in-VM dashboards) where exponential backoff is overkill.
Five attempts, doubling timeout each failure (1s / 2s / 4s / 8s / 16s). For SaaS APIs and cloud control planes.
Random sleep avoids thundering herd when many learners boot simultaneously and all hit the same shared SaaS tenant.
set +e/set -e if your script uses set -euo pipefail and the until body's intermediate failures would otherwise abort.
Ship a /usr/local/bin/retry wrapper for clean per-call usage.
Don't trust kubectl cluster-info — it can return OK before the API is fully ready.
Service principal login can transiently fail right after a subscription is provisioned. Tenant edge propagation lags credential injection.
For per-challenge cloud-side setup, extend to 12 iterations — propagation can take longer than 50 seconds.
sleep N as a substitute for actual polling is brittle. If provisioning takes longer than expected, the script breaks; if shorter, time is wasted. Always poll a real signal — file existence, HTTP status, port responsiveness — when one is available.unattended-upgrades may hold the dpkg lock at first boot. Wait it out: while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do sleep 2; done before any apt-get.timeout --kill-after=30 300 cmd || { echo "Timed out"; exit 1; }. The --kill-after=30 sends SIGKILL 30 seconds after SIGTERM if the process refuses to die.