-
Notifications
You must be signed in to change notification settings - Fork 21
Add enterprise appliance and release-history pages #124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| --- | ||
| title: "Enterprise Appliance" | ||
| description: "Run the Fish Audio TTS stack on your own hardware from a single container" | ||
| icon: "server" | ||
| --- | ||
|
|
||
| The enterprise appliance is the whole Fish Audio TTS stack — model weights included — in one | ||
| container. It needs no Kubernetes and no network access at runtime, which makes it suitable for | ||
| on-prem, single-tenant, and air-gapped deployments. | ||
|
|
||
| <Note> | ||
| The appliance is part of an enterprise agreement. Your team needs the **Self | ||
| Host** feature and a grant for the All-in-One artifact before the commands | ||
| below will work. If Developer → Self Host does not appear in your dashboard, | ||
| contact your account manager. | ||
| </Note> | ||
|
|
||
| ## What you get | ||
|
|
||
| | | | | ||
| | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | Exposed port | `8088` — the TTS API. Nothing else is published. | | ||
| | GPUs | **2**, validated on 2× RTX 5090 (32 GB) and 2× H100 80 GB. GPU 0 runs the language model, GPU 1 runs the vocoder. No NVLink required. | | ||
|
Check warning on line 23 in developer-guide/self-hosting/enterprise-appliance.mdx
|
||
| | Scaling | one inference worker on two GPUs. It does not shard across more GPUs or nodes — for elastic or multi-tenant throughput, use the Helm deployment instead. | | ||
|
Check warning on line 24 in developer-guide/self-hosting/enterprise-appliance.mdx
|
||
| | Network at runtime | none. Weights are baked into the image. | | ||
|
|
||
| ## 1. Prerequisites | ||
|
|
||
| - Docker with the **NVIDIA Container Toolkit** installed and the `nvidia` runtime registered. | ||
| Verify with `docker run --rm --gpus all <cuda-image> nvidia-smi`. | ||
| - Enough disk for the image: roughly **28 GB compressed, 60 GB unpacked**. | ||
| - A **deploy token**, created in Developer → Self Host. That page also shows the version to run. | ||
|
|
||
| ## 2. Sign in and pull | ||
|
|
||
| Your username is your Fish Audio account email; the password is a deploy token. | ||
|
|
||
| ```bash | ||
| echo '<your-deploy-token>' | docker login registry.fish.audio -u '<your-email>' --password-stdin | ||
| docker pull registry.fish.audio/self-hosted/enterprise/all-in-one:<version> | ||
| ``` | ||
|
|
||
| <Tip> | ||
| Developer → Self Host renders both of these commands with your email and the | ||
| current version already filled in. Copy them from there rather than typing the | ||
| version by hand. | ||
| </Tip> | ||
|
|
||
| For an air-gapped host, pull on a machine that can reach the registry, then move the image: | ||
|
|
||
| ```bash | ||
| docker save registry.fish.audio/self-hosted/enterprise/all-in-one:<version> \ | ||
| | zstd -T0 -3 -o all-in-one.tar.zst | ||
| # on the target host: | ||
| zstd -d -c all-in-one.tar.zst | docker load | ||
| ``` | ||
|
|
||
| ## 3. Run | ||
|
|
||
| Generate a JWT secret **once**, store it, and reuse the same value on every run. | ||
|
|
||
| ```bash | ||
| export FISH_JWT_SECRET="$(openssl rand -hex 32)" | ||
|
|
||
| docker run -d --name fish-tts \ | ||
| --gpus all \ | ||
| --shm-size 16g --ulimit memlock=-1 --ulimit stack=67108864 \ | ||
| -p 8088:8088 \ | ||
| -v fish-tts-shared:/mnt/shared \ | ||
| -e JWT_SECRET="$FISH_JWT_SECRET" \ | ||
|
Comment on lines
+60
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Document how to persist and restore The export command only sets the secret in the current shell. A later upgrade can pass an empty value or a new value, which can activate the development default or invalidate existing tokens. Require users to store the value in an approved secret store and load the same value before every 🤖 Prompt for AI Agents |
||
| --restart unless-stopped \ | ||
| registry.fish.audio/self-hosted/enterprise/all-in-one:<version> | ||
| ``` | ||
|
|
||
| <Warning> | ||
| `JWT_SECRET` is required for any production deployment. Without it the | ||
| container falls back to a fixed built-in development default, which is not | ||
| secret. Changing the value later invalidates every token and session issued | ||
| under the old one. | ||
| </Warning> | ||
|
|
||
| **`--gpus all`** pins the worker to GPU 0 and the vocoder to GPU 1. On a host with more than two | ||
| GPUs it takes the first two; to choose specific cards use `--gpus '"device=0,1"'`. | ||
|
|
||
| **`-v fish-tts-shared:/mnt/shared`** is one persistent volume for everything that must survive a | ||
| restart: the compile and CUDA-graph caches, the vocoder engine, reference voices, and the usage | ||
| ledger. It is what makes restarts fast. | ||
|
|
||
| <Note> | ||
| The **first start compiles for around 10 minutes** once the image is on the | ||
| host. A completely cold host that also has to transfer the ~28 GB image can | ||
| take 45–75 minutes end to end, depending on the network. Later starts on the | ||
| same volume take minutes. Keep the volume. | ||
| </Note> | ||
|
|
||
| The container runs fully non-root — PID 1 and every service as UID 1000. A fresh named volume | ||
| inherits that ownership and works as-is; an existing volume or a host bind-mount must be writable | ||
| by UID 1000. | ||
|
|
||
| ## 4. Check it is serving | ||
|
|
||
| ```bash | ||
| curl -fsS http://localhost:8088/health | ||
| ``` | ||
|
|
||
| ## Upgrading | ||
|
|
||
| Developer → Self Host shows the version your team recorded and tells you when a newer one is | ||
| available, with a link to what changed. Upgrading is: pull the new tag, stop the old container, | ||
| start a new one with the same volume and the same `JWT_SECRET`. | ||
|
|
||
| ```bash | ||
| docker pull registry.fish.audio/self-hosted/enterprise/all-in-one:<new-version> | ||
| docker stop fish-tts && docker rm fish-tts | ||
| # re-run the command from step 3 with the new tag | ||
| ``` | ||
|
|
||
| The volume is reused deliberately: the caches in it are keyed by content, so a new image rebuilds | ||
| only what actually changed. Keep the old image on the host until the new one has served traffic — | ||
| rolling back is then just starting the previous tag again. | ||
|
|
||
| See [Appliance Releases](/developer-guide/self-hosting/enterprise-releases) for the version list. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Use relative paths for both internal links. Both links use absolute internal paths.
As per coding guidelines, “Use relative paths for internal links” and “Do not use absolute URLs for internal links.” 📍 Affects 2 files
🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| --- | ||
| title: "Appliance Releases" | ||
| description: "Version history for the Fish Audio enterprise appliance" | ||
| icon: "tag" | ||
| --- | ||
|
|
||
| Every version of the [enterprise appliance](/developer-guide/self-hosting/enterprise-appliance) | ||
| we have released, newest first. Developer → Self Host shows which one your team recorded as | ||
| running and links here when a newer one is available. | ||
|
|
||
| <Note> | ||
| Versions are immutable. A tag always refers to the same image — we never | ||
| re-point one at different content, so a deployment pinned to a tag keeps | ||
| getting the bytes it was tested with. Fixes ship as a new version. | ||
| </Note> | ||
|
|
||
| ## How to read a version | ||
|
|
||
| ``` | ||
| s2.1-pro-20260803-offline | ||
| └──┬───┘ └──┬───┘ └──┬──┘ | ||
| │ │ └─ variant: `offline` records usage to a local signed ledger | ||
| │ └─ the date we published it | ||
| └─ the model generation it serves | ||
| ``` | ||
|
Comment on lines
+19
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Add a language tag to the version-format block. Use a As per coding guidelines, “Include language tags on all code blocks.” 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
|
|
||
| --- | ||
|
|
||
| ## s2.1-pro-20260803-offline | ||
|
|
||
| <Update label="2026-08-03" tags={["current"]}> | ||
| First generally available build of the appliance. | ||
|
|
||
| - Serves the S2.1 Pro voice model, weights baked in — no network access at runtime. | ||
| - Two GPUs: language model on GPU 0, vocoder on GPU 1. | ||
|
Check warning on line 35 in developer-guide/self-hosting/enterprise-releases.mdx
|
||
| - Usage recorded to a local signed ledger; nothing is reported off the host. | ||
| - Runs fully non-root (UID 1000). | ||
|
|
||
| **Upgrading:** nothing to migrate — this is the first release. | ||
|
|
||
| </Update> | ||
|
|
||
| --- | ||
|
|
||
| ## Getting an older version | ||
|
|
||
| The dashboard lists the versions we currently recommend. If you need one that is no longer | ||
| listed — to reproduce a node exactly as it was, for instance — contact your account manager | ||
| rather than guessing a tag. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Add
zstdto the air-gapped prerequisites.Both commands require
zstd. List it as a prerequisite on the connected host and the target host, or provide an alternative transfer method.As per coding guidelines, “Include prerequisites at the start of procedural content.”
🤖 Prompt for AI Agents
Source: Coding guidelines