Prerequisites
- A cluster that meets the requirements, preferably a clean cluster dedicated to this deployment.
- Shared storage mounted at the same path on every node.
- Registry access configured, and a chart version chosen on the Self Host page — see Releases.
- Prometheus installed, or approved for installation.
- Reference voice archives prepared, if your traffic uses
reference_id.
fish-audio is the supported default namespace. If you must use a different
one, change both the Helm --namespace argument and
MODEL_DISCOVERY_NAMESPACE in your values file. Otherwise the edge API looks
for the model services in the wrong namespace.Choose a delivery form
“Offline” here means runtime-offline. Installation still pulls images and the
chart from a registry. For an install with no network at all, see
Air-gapped deployments.
Preflight
findmnt -T /mnt/share should report an nfs or nfs4 filesystem. Without node
access:
Create the namespace and secrets
For production, prefer External Secrets, Sealed Secrets, or your cloud secret
manager over plain Kubernetes Secrets.
Prepare a values file
The chart carries a values file for each delivery form underprofiles/, so
pulling the chart gets you a starting point:
helm pull --untar fails rather than overwriting the
directory it created, so upgrading means deleting it first.
A profile sets the deployment mode and the shared-storage path. What a cluster
usually has to change:
Image references are pinned in the chart. Change them only when mirroring into
your own registry, as Air-gapped
deployments describes — a version is
otherwise selected with
--version, not by editing tags.
Talk to your account team before changing replica counts. The profiles ship the
single-worker shape the delivery was sized against, and the API, GPU, aligner,
normalizer and router deployments read a replica change in a values file on install but
not on helm upgrade, where the running count wins. oxidengine, the model warehouse
and Redis are the other way round: they take the value every time, so a kubectl scale
on those is undone by the next upgrade.
Ingress and TLS are disabled by default. Enable them only if you want Kubernetes
to manage your access layer; otherwise put your own ingress controller or load
balancer in front of the edge-api-production service.
Install Prometheus
The chart exposes metrics throughprometheus.io/* pod annotations and creates
no ServiceMonitors. An annotation-scraping Prometheus works out of the box:
Stage reference voices
A self-hosted deployment never downloads reference audio from the network. Requests that pass areference_id resolve from Redis, then from a local archive
on shared storage. Stage one zip per voice before enabling that traffic:
.txt transcript of the same basename:
.wav, .mp3, and .opus. Do not nest
directories inside the archive, and do not add prefixes to the filename — the
file name must match the reference id exactly.
If you have no node shell, stage archives through a helper pod that mounts the
share, then confirm the edge API can see the file:
Validate the release
Render the manifests before touching the cluster:Install
Wait for readiness
On the first install the inference worker compiles its GPU graphs and the vocoder builds its inference engine, which takes far longer than later rollouts. Wait on every workload in the release, Deployments and StatefulSets alike:Smoke test
The acceptance signal is a successful generation, not a health probe. With no ingress configured, port-forward the edge API:
Also confirm that the GPU workloads see the shared storage mount, that Redis is
ready, that reference archives are visible if you use them, and that no pod is in
a crash or image-pull loop.
Upgrade
helm-diff plugin is not installed, review helm template output before
applying. Re-run the smoke test after every upgrade and keep the previous
revision available until the deployment is accepted.
Roll back
Uninstall
Next steps
- Air-gapped deployments to install with no network access.
- Operations for monitoring signals, scaling, and troubleshooting.

