# Petal — production environment for the parodia.dev VPS. # Copy to the stack directory as `.env` (docker-compose.yml reads it via # env_file) and fill in the model names. Values the image already fixes # (PORT, DATABASE_PATH, IMAGE_DIR, TTS_CACHE_DIR, TTS endpoints) are set in # docker-compose.yml, not here. # --- Routing ----------------------------------------------------------------- # Must match the DNS A record and the Traefik Host() rule. PETAL_HOST=petal.parodia.dev # Absolute origin the app knows itself by. Phase 16's OIDC redirect URI is # built from this, so it has to be the real public HTTPS origin. BASE_URL=https://petal.parodia.dev # The companion's bedtime nag and the night theme read the container clock. TZ=Europe/Lisbon # The container runs as this uid/gid so it can write the ./data bind mount. # Set both to the output of `id -u` / `id -g` for the account owning the stack # directory. Wrong values show up as "unable to open database file (14)". PETAL_UID=1001 PETAL_GID=1001 # (The interim PETAL_BASIC_AUTH edge gate is gone: Petal authenticates for # itself now, and the auth block at the bottom of this file is what holds the # door. A second password in front of a real login is one more thing to lose.) # --- LLM (millenia, over headscale) ------------------------------------------ # The only cross-VPN dependency. Petal degrades warmly when it's unreachable: # spell check, gloss, garden, search, export and read-aloud all keep working and # the status bar shows 小助手在休息 · Petal's helper is resting. # # 100.64.0.2 is millenia on the headscale network. vLLM must be bound to that # interface (NOT 0.0.0.0 — this host is public); see deploy/README.md. LLM_BACKEND=vllm LLM_ENDPOINT=http://100.64.0.2:8000 LLM_MODEL= LLM_CHAT_MODEL= # 30s is the local-network default. Over WAN + VPN, with the voice and # collocation passes sending a whole document, that truncates real work — the # request is a hard deadline on Complete, and a timeout surfaces as the same # warm 502 as an unreachable model. 90s leaves headroom without letting a # genuinely wedged backend hang the pass forever. LLM_TIMEOUT=90s # --- Read-aloud (Piper sidecars) --------------------------------------------- # Endpoints are wired in docker-compose.yml; these pick the voice each sidecar # loads. Changing one means recreating that container so it downloads the model. # # A language is routable only when both halves are set — a TTS_ENDPOINT_XX with # no TTS_VOICE_XX reads as "no voice for this language" and the browser's own # synthesizer takes over, rather than as an instance that errors on every # request. Adding es is a compose service plus a pair of lines here. # # pt_PT-tugão-medium is the only European Portuguese voice Piper ships; every # other pt model in the catalogue is Brazilian. French has the opposite # property — every fr voice in the catalogue is fr_FR — so there is no wrong # country to land on and no non-ASCII name to trip the downloader. TTS_VOICE_EN=en_US-amy-medium TTS_VOICE_ZH=zh_CN-huayan-medium TTS_VOICE_PT=pt_PT-tugão-medium TTS_VOICE_FR=fr_FR-siwis-medium # Mexican, not peninsular — the es pack is written in neutral Latin American # Spanish, and es_ES-davefx-medium would read it in the accent it avoids. TTS_VOICE_ES=es_MX-ald-medium TTS_AUDIO_FORMAT=mp3 TTS_TIMEOUT=15s # --- Auth (Authentik OIDC) --------------------------------------------------- # NOT OPTIONAL HERE. Authentik already runs on this host; set all three and # Petal authenticates for itself. # # Leave any of them unset and Petal REFUSES TO START, because the alternative is # worse: it would otherwise fall back to resolving every anonymous request to # the single `local` user, handing the open internet full read and write over # every document in the database. That fallback is right on a laptop and a # catastrophe on this host, so the guard is on for any non-loopback BASE_URL. # See PETAL_REQUIRE_AUTH below. # # AUTHENTIK_URL is the provider's issuer, and the redirect URI to register in # Authentik is https://petal.parodia.dev/auth/callback. AUTHENTIK_URL=https://auth.parodia.dev/application/o/petal/ AUTHENTIK_CLIENT_ID=petal AUTHENTIK_CLIENT_SECRET= # Who may sign in: comma-separated subject ids and/or emails. # # SET THIS. Empty means everyone Authentik authenticates, and Authentik on this # host fronts half a dozen applications — being a valid user there is not the # same as belonging in someone's private journal. An empty value is legal (a # single-household instance may genuinely want it) and says so loudly in the # startup log every boot. # # An email is knowable in advance; a subject id is an opaque uuid nobody can # know before that person's first login. Use emails to invite, subject ids to # pin. PETAL_ALLOWED_SUBS=her@example.com,me@example.com # The guard itself. Defaulted from BASE_URL — loopback origins run open, real # ones demand a login — so it does not normally need setting. Set it to false # only for a deployment genuinely reachable from nowhere but a trusted network, # and understand that it means anyone who reaches Petal is the `local` user. # PETAL_REQUIRE_AUTH=true