fix(selfhost): stop the documented setup path producing an unbootable container (#9487 follow-up) - #9789
Merged
Merged
Conversation
… container scripts/selfhost-init-secrets.sh deliberately creates ZERO-BYTE placeholders for the four externally-issued secrets it cannot generate (github_app_private_key.pem, orb_enrollment_secret.txt, pagerduty_routing_key.txt, claude_code_oauth_token.txt), and compose refuses to start unless those files exist. #9487 then made an empty secret file fatal at boot. Together those mean: run the documented setup, start the container, crash-loop. Observed live on the ORB, where an unused GitHub App key took the instance down on upgrade to orb-v3.6.0-beta.1. For those four ONLY, an empty file now means "not configured": skip it, leave the target var genuinely unset, and log a named warning. Strictly better than the pre-#9487 behavior it resembles -- that set an empty string every nonBlank() read as unconfigured with no signal at all. Every other secret keeps #9487's fail-closed behavior exactly. An empty file there can only be a truncated write, which is the bug it was written to catch.
Contributor
|
Important 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏳ LoopOver is waiting…LoopOver has seen this pull request and is waiting on CI checks to finish before reviewing it. This comment will update once the review runs. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed · 🟨 Waiting |
Contributor
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9789 +/- ##
==========================================
- Coverage 90.30% 89.48% -0.82%
==========================================
Files 913 913
Lines 113595 113599 +4
Branches 26963 26964 +1
==========================================
- Hits 102584 101658 -926
- Misses 9682 10851 +1169
+ Partials 1329 1090 -239
Flags with carried forward coverage won't be shown. Click here to find out more.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
Two correct-in-isolation behaviours combine into a broken onboarding path:
scripts/selfhost-init-secrets.shdeliberately creates zero-byte placeholders for the four secrets it cannot generate, because they come from an external party.secrets/README.mdsays so outright: it "creates only an empty placeholder for the four externally-issued ones."Net effect: follow the documented setup, start the container, crash-loop. Every new self-hoster who isn't using all four capabilities hits this.
Observed live on the ORB upgrading to
orb-v3.6.0-beta.1— an unused GitHub App private key (a 0-byte placeholder, no App configured,loopover-orbhandles auth here) took the whole instance down:The fix
For those four variables only, an empty file means "not configured": skip it, leave the target var genuinely unset, and log a named
selfhost_secret_file_empty_optionalwarning.This is not a revert to the pre-#9487 behaviour it superficially resembles. That set the target to an empty string, which every downstream
nonBlank()read as unconfigured with no signal whatsoever. Here the var is left truly unset and the operator gets a warning naming it at boot.Every other secret keeps #9487's fail-closed behaviour exactly. The init script writes a real random value for those, so an empty file there can only mean a truncated write — which is precisely the bug #9487 was written to catch (a truncated
GITHUB_WEBHOOK_SECRETbooting an instance that silently rejected every webhook). An invariant test pins that.An unreadable file stays fatal for all four too: missing is not the same as deliberately empty.
Why not the alternatives
${VAR:-default}substitutes on empty as well as unset, so it cannot be cleared from.env; and dropping the default breaks everyone who does use the capability.Tests
7 new cases, including a regression that reproduces the exact ORB crash (empty App key + real webhook secret → boots, App key unset, webhook secret loaded) and the invariant that a self-generated secret's empty file still throws. 26 pass.
docs:drift-checkandselfhost:env-reference:checkgreen;secrets/README.mddocuments the split.