## Description Fixes two Helm issues from the v5.0 bug bash: [ENG-4445](https://linear.app/onyx-app/issue/ENG-4445/helm-the-copy-job-and-api-server-crash-loop-at-startup-before) and [ENG-4447](https://linear.app/onyx-app/issue/ENG-4447/helm-retiring-minio-needs-a-manual-pvc-keep-annotation-and-leaves-pvcs). **Why** - The api server's startup bucket check and the legacy copy's `ensure_bucket` fail with `EndpointConnectionError` until SeaweedFS is ready, so on the 0.8 → 0.9 upgrade they crash-loop and the copy spends its `backoffLimit`. - An install upgraded with `--reuse-values` never gets `helm.sh/resource-policy: keep` on `<release>-minio`, so the upgrade that sets `minio.enabled: false` deletes the PVC and MinIO's data unless the admin annotates it by hand. **What** - A `wait-for-object-store` init container on the app image polls the object store's `/healthz` before the api server and the copy Job start. It takes the guarded container's resources and securityContext. External object storage gets none. - With MinIO disabled, `minio-retired-pvc.yaml` renders the existing MinIO claim from its live spec with `keep`, so Helm updates it instead of deleting it. MIGRATION.md drops the manual step and says how to delete the claim. - The copy Job's name hash changes, so a release still on MinIO reruns the copy once (idempotent). Chart 0.9.21. ## How Has This Been Tested? kind with Helm 4, starting from a MinIO-only install with no keep annotation, then `--reuse-values` upgrades. Main's chart: the copy Job restarted twice before SeaweedFS was ready, and retiring MinIO deleted `onyx-minio`. This branch: the api and copy Job waited about 18 s in `wait-for-object-store` (six one-line logs each) with 0 restarts, the copy completed, and retiring MinIO kept `onyx-minio` with the same UID, `keep` added and the MinIO data still on the volume. A second upgrade changed nothing. `test_object_store_wait_render.py` renders the init container in each case and runs the wait against a refused, then 503, then 200 store. All 81 render tests pass. ## Additional Options - [x] [Optional] Please cherry-pick this PR to the latest release version.
Documentation for how to deploy Onyx can be found in our official docs: https://docs.onyx.app/deployment/overview
Maintaining the compose files (contributors)
docker_compose/docker-compose.yml, docker-compose.prod.yml and
docker-compose.prod-no-letsencrypt.yml are generated from the single source of truth
docker_compose/docker-compose.template.yml — do not hand-edit them. To change any of the three,
edit the template (per-variant differences are expressed with #!for / #!only / #!value
directives, documented in ods generate-compose --help) and regenerate:
ods generate-compose --write
The generator lives in tools/ods (internal/composegen) and ships with the onyx-devtools
package. The docker-compose-sync pre-commit hook runs it automatically for commits touching the
template or the generated files, so a stray edit to a generated file gets reverted on the next
commit.
onyx-cli embeds copies of the guided-install deployment files (the generated
docker-compose.yml and docker-compose.prod.yml, the lite/craft overlays, the env templates,
the nginx config, and docker_compose/README.md) under
cli/internal/deploy/deployfiles/embedded/. The same ods generate-compose --write run refreshes
them after rendering the variants, and a drift test in the cli module (go test ./...) gates
staleness. If you change any of those files, re-run the generator and commit the refreshed embedded
copies.
Note that docker_compose/README.md ships inside every self-hosted install, so keep it
user-facing — contributor notes like this one belong here instead.