Configuration
Configuration is organized by setting environment variables, read from
.env (copy .env.example to start). This page documents every
variable; defaults shown are from backend/app/config.py.
Database & cache
Variable |
Default |
Description |
|---|---|---|
|
|
Database user |
|
— |
Database password (required) |
|
|
Database name |
|
derived from the above |
Full SQLAlchemy connection string; set directly to override |
|
|
Celery broker/result backend |
LLM providers
Variable |
Default |
Description |
|---|---|---|
|
|
Comma-separated, ordered list — first is primary, rest are fallbacks. Valid values: |
|
— |
Required if |
|
|
|
|
|
Set to a remote host to use Ollama running elsewhere, e.g. |
|
|
|
|
|
Used for semantic clustering regardless of which provider handles text generation — 768-dim; changing it requires a schema migration (see Clustering) |
|
|
Floor, not a fixed value — increase for remote or slow Ollama hosts. Large generations (notably the podcast script) automatically use a longer per-request timeout above this floor, scaled to how much output was requested. |
|
|
How long to wait for an Anthropic Batch API job before cancelling and falling back to synchronous processing |
See LLM Providers for how the fallback chain and batch processing work.
Podcast (text-to-speech)
Variable |
Default |
Description |
|---|---|---|
|
|
Text-to-speech backend for generated podcast episodes. |
|
— |
Required when |
|
|
Floor for the per-request timeout when |
|
|
Spoken words-per-minute used to size podcast scripts (both the LLM’s word-count target and how many stories get selected for a given episode length). Calibrated against Piper’s |
|
— |
Required to enable a podcast show’s public feed link (subscribing in a real podcast app). Must be the fully-qualified, publicly-reachable URL your instance is served at, no trailing slash, e.g. |
PIPER_MODEL_DIR and PODCAST_AUDIO_DIR are fixed container paths (not
meant to be overridden) backed by the piper-voices and podcast-audio
named volumes — see Deployment.
Running TTS synthesis on separate hardware
docker-compose.tts.yml runs a standalone TTS container independent of
the main stack — the same pattern as docker-compose.ollama.yml for LLM
calls. Point the main stack at it and it takes over podcast synthesis:
# On the TTS machine (CPU):
docker compose -f docker-compose.tts.yml up -d --build
# On the TTS machine (GPU):
TTS_GPU=true TTS_DEVICE=cuda docker compose -f docker-compose.tts.yml up -d --build
# (also uncomment the NVIDIA deploy block in docker-compose.tts.yml)
# In the main stack's .env:
TTS_PROVIDER=network
TTS_SERVICE_URL=http://<tts-machine-ip>:8100
GPU use is opt-in at two independent points, both off by default: the
TTS_GPU build arg (whether the image has GPU-capable builds of the ML
backends instead of their CPU-only defaults) and TTS_DEVICE=cuda at
runtime (whether the engine is actually told to use it). A CPU-only
deployment needs neither — except practically speaking for chatterbox
(below), which is slow enough on CPU (~10x real-time) that GPU is worth
having for it specifically.
TTS_ENGINE picks which synthesis backend tts_service/ runs (default
piper; kokoro and chatterbox also available) — all three are always
installed in the image, so this is a plain env var change, no rebuild
needed:
TTS_ENGINE=kokoro docker compose -f docker-compose.tts.yml up -d --build
piper (self-hosted, CPU/ONNX, GPL-3.0) is the original engine and covers
the widest fixed-voice language list. kokoro (hexgrad/Kokoro-82M,
Apache 2.0) offers a smaller set of languages (English, Spanish, French,
Italian, Portuguese) but with distinctly higher-quality, named voices
(af_heart, bm_daniel, etc.) rather than Piper’s numbered speakers —
worth trying if Piper’s default English voice quality isn’t good enough
for your use case. chatterbox (ResembleAI/chatterbox,
MIT) works differently from the other two: instead of picking a named
voice, it clones one from a short reference audio clip. It ships one
built-in default voice per supported language (English, German, French,
Spanish, Italian, Dutch, Polish, Portuguese, Russian, Chinese, Japanese,
Korean, Turkish, Swedish, Danish, Finnish, Norwegian), and you can add more
by dropping a .wav clip into
{TTS_MODEL_DIR}/chatterbox_voices/{language}/your-voice-name.wav on the
TTS host — no restart needed, it’s rescanned on every request. Meaningfully
slower than the other two engines, so it’s the one where the GPU option
actually matters.
Once a network TTS backend is configured, each podcast host can also be
pinned to a specific engine — the default (TTS_PROVIDER) or explicitly
piper/network — instead of every host in a show sharing the same one.
This is a per-host setting in the podcast show form (a “Voice engine”
selector that only appears once TTS_SERVICE_URL is set, since with only
Piper available there’s nothing to choose between); nothing to configure
here beyond TTS_SERVICE_URL itself.
Reddit
Variable |
Default |
Description |
|---|---|---|
|
— |
From a Reddit “personal use script” app. Can also be set per-source instead (or in addition) — see Sources. |
|
|
|
|
— |
Only needed for the OAuth “password” grant (script-type apps); without them Shoebill falls back to app-only |
Authentication
Variable |
Default |
Description |
|---|---|---|
|
|
Change this. Generate with |
|
|
Session length |
|
— |
Default admin account, created (or password-reset) on startup |
|
— |
Push notifications (Web Push / VAPID)
Variable |
Default |
Description |
|---|---|---|
|
— |
Generate with: |
|
|
Notes
Restart required for LLM config changes.
LLM_PROVIDERSand related settings are read once and cached for the process lifetime — the settings UI shows the current LLM configuration but changing it always requires editing.envand restarting, never just an API call.The backend runs from a built Docker image.
docker compose run --rm backend alembic ...does not pick up local file changes — see Development for the correct migration workflow.