@@ -162,18 +162,27 @@ CLI. The same Dockerfile builds on Linux `amd64` and `arm64`.
162162
163163``` sh
164164umask 077
165- printf ' VOCAGATEWAY_TOKEN=%s\n' " $( openssl rand -hex 32) " > .env
166- printf ' VOCAGATEWAY_PUBLISH_HOST=127.0.0.1\n' >> .env
167- printf ' VOCAGATEWAY_PUBLISH_PORT=8765\n' >> .env
165+ cp .env.example .env
166+ printf ' VOCAGATEWAY_TOKEN=%s\n' " $( openssl rand -hex 32) " >> .env
168167docker compose up --detach --build
169168docker compose ps
170169curl --fail http://127.0.0.1:8765/health/live
171170```
172171
172+ [ ` .env.example ` ] ( .env.example ) is the annotated template: it already sets the
173+ loopback publication defaults and comments out every other supported setting,
174+ so starting from it is how you find out what is tunable. Appending the token
175+ overrides the empty ` VOCAGATEWAY_TOKEN= ` placeholder it ships with — Compose
176+ takes the last assignment of a repeated key.
177+
173178The token is provided as a Compose secret rather than a container environment
174179variable. Models, configuration, and the SQLite database persist in the
175180` vocagateway_vocagateway-data ` named volume mounted at ` /data ` .
176181
182+ Before pairing a phone, read the bridge-network note below: on the default
183+ network the QR cannot auto-discover a reachable address, and
184+ ` VOCAGATEWAY_PUBLIC_URL ` in ` .env ` is what fixes it.
185+
177186The container is live before a model is installed, so ` /health/ready ` initially
178187returns ` 503 ` . Open the WebUI, enter the token from ` .env ` , download/select a
179188recommended sherpa-onnx, Moonshine, or faster-whisper model, and check again:
@@ -190,12 +199,16 @@ firewall. Never expose port 8765 to the public internet.
190199The default bridge network also hides the host's real LAN address from the
191200gateway's own address auto-discovery (used for the pairing QR): the container
192201only ever sees its private bridge IP, not the host's Wi-Fi/Ethernet interface.
193- On Linux Docker Engine (not Docker Desktop on macOS/Windows), set
194- ` VOCAGATEWAY_NETWORK_MODE=host ` in ` .env ` instead so the container shares the
195- host's network namespace and discovery finds the real ` 192.168.x.x ` address.
196- This ignores ` VOCAGATEWAY_PUBLISH_HOST ` /` PORT ` — the container binds directly on
197- the host per ` VOCAGATEWAY_BIND_HOST ` /` VOCAGATEWAY_PORT ` , so lock down port 8765
198- with the host firewall first.
202+ Two ways out, both set in ` .env ` :
203+
204+ - ` VOCAGATEWAY_PUBLIC_URL=http://192.168.1.20:8765 ` names the address the phone
205+ should use and skips discovery entirely. This works everywhere, including
206+ Docker Desktop on macOS and Windows.
207+ - ` VOCAGATEWAY_NETWORK_MODE=host ` , on Linux Docker Engine only, shares the
208+ host's network namespace so discovery finds the real ` 192.168.x.x ` address by
209+ itself. This ignores ` VOCAGATEWAY_PUBLISH_HOST ` /` PORT ` — the container binds
210+ directly on the host per ` VOCAGATEWAY_BIND_HOST ` /` VOCAGATEWAY_PORT ` , so lock
211+ down port 8765 with the host firewall first.
199212
200213## WebUI
201214
@@ -387,14 +400,28 @@ uv run vocaphone-server
387400| ` VOCAGATEWAY_CONFIG_FILE ` | ` ~/.config/vocagateway/config.json ` | ` /data/config/config.json ` | WebUI engine/model choice |
388401| ` VOCAGATEWAY_ENGINE ` | ` auto ` | ` auto ` | ` auto ` , ` vocamac ` , ` handy ` , ` mlx-audio ` , ` whisperkit ` , ` sherpa-onnx ` , ` faster-whisper ` , ` moonshine ` , or ` whisper.cpp ` |
389402| ` VOCAGATEWAY_WHISPER_BINARY ` | ` /opt/homebrew/bin/whisper-cli ` | ` /usr/local/bin/whisper-cli ` | ` whisper.cpp ` executable |
390- | ` VOCAGATEWAY_WHISPER_MODEL ` | base model path | base model path | Fallback ` whisper.cpp ` model |
403+ | ` VOCAGATEWAY_WHISPER_MODEL ` | ` ~/.local/share/whisper.cpp/models/ggml- base.en.bin ` | same, and normally absent | Fallback ` whisper.cpp ` model used only when no model is selected in the WebUI |
391404| ` VOCAGATEWAY_WHISPERKIT_BINARY ` | ` whisperkit-cli ` | unavailable | WhisperKit executable |
392405| ` VOCAGATEWAY_VOCAMAC_APP ` | ` /Applications/VocaMac.app ` | unavailable | Optional VocaMac app bundle |
393406| ` VOCAGATEWAY_VOCAMAC_MODEL ` | unset | unset | Pin a VocaMac model instead of following the app's choice |
407+ | ` VOCAGATEWAY_HANDY_BINARY ` | ` /Applications/Handy.app/Contents/MacOS/handy ` | unavailable | Optional Handy application binary |
408+ | ` VOCAGATEWAY_HANDY_MODEL ` | unset | unset | Pin a Handy model (` owner/repository/model.gguf ` ) |
409+ | ` VOCAGATEWAY_HANDY_FALLBACK_MODEL ` | ` handy-computer/whisper-base-gguf/whisper-base-Q8_0.gguf ` | unavailable | Model used when the pinned Handy model is missing |
394410| ` VOCAGATEWAY_RETENTION_HOURS ` | ` 24 ` | ` 24 ` | Failed-session retry retention |
395411| ` VOCAGATEWAY_DELETE_SUCCESSFUL_AUDIO ` | ` true ` | ` true ` | Delete source/normalized audio after success |
396-
397- Compose-specific variables live in ` .env ` :
412+ | ` VOCAGATEWAY_PUBLIC_URL ` | unset | unset | Address the pairing QR encodes, overriding auto-discovery |
413+ | ` VOCAGATEWAY_PAIRING_URL ` | unset | unset | Alias for ` VOCAGATEWAY_PUBLIC_URL ` , checked second |
414+ | ` VOCAGATEWAY_DEBUG ` | ` false ` | ` false ` | Serve the Swagger UI at ` /docs ` and the schema at ` /openapi.json ` |
415+
416+ Under Compose, ` VOCAGATEWAY_BIND_HOST ` , ` PORT ` , ` ENGINE ` , ` RETENTION_HOURS ` ,
417+ ` DELETE_SUCCESSFUL_AUDIO ` , ` PUBLIC_URL ` , ` PAIRING_URL ` , and ` DEBUG ` are read
418+ from ` .env ` and passed into the container. ` VOCAGATEWAY_TOKEN ` becomes a
419+ Compose secret at ` /run/secrets/vocagateway_token ` rather than an environment
420+ variable. The remaining paths and binaries are fixed by the image to their
421+ container locations, and the macOS-only engine variables have no effect there.
422+
423+ Compose-only variables, which the gateway process itself never reads, also live
424+ in ` .env ` :
398425
399426| Variable | Default | Purpose |
400427| --- | --- | --- |
0 commit comments