Files
Nikolas Garza 31ea4944b5 fix(helm): wait for the object store at startup and keep the MinIO PVC on retire (#16431)
## 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.
2026-10-22 00:39:08 +00:00
..
2023-06-14 00:11:25 -07:00

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.