Files
petal/deploy
prosolis 5b221cc7a3 Gate the VPS instance behind Traefik basic auth until Phase 16
Petal authenticates nobody yet -- StaticResolver hands every request the
same local user -- so on a public host the whole API is open: anyone who
finds the hostname can read and write documents and fill the disk with
image uploads. Traefik holds the door until the OIDC flow exists.

/api/health keeps its own higher-priority router with no middleware, so
the acceptance criterion (public health endpoint, reachable by the
monitoring on this box) still holds. Both the middleware and that router
are deleted when Phase 16 lands.
2026-07-26 23:21:43 -07:00
..

Deploying read-aloud (Piper TTS) to millenia

Petal's read-aloud generates audio with a local Piper neural-TTS server and transcodes it to mp3 with ffmpeg. Both run on millenia (192.168.1.212); nothing leaves the box. If Piper is down or TTS_ENDPOINT is unset, the frontend falls back to the browser's Web Speech API automatically.

1. Piper as a systemd service (one-time)

# from this repo, on your workstation:
scp deploy/piper.service deploy/setup-piper.sh 192.168.1.212:/tmp/
ssh 192.168.1.212 'cd /tmp && sudo ./setup-piper.sh'

setup-piper.sh creates ~/piper/venv, installs piper-tts[http], downloads the en_US-amy-medium voice into ~/piper/voices, installs+enables piper.service (loopback :5005), and smoke-tests it. Idempotent.

Check it any time: systemctl status piper, journalctl -u piper -f.

2. Point petal at Piper + redeploy the binary

Add to petal's environment (its .env or launch env):

TTS_ENDPOINT=http://127.0.0.1:5005
TTS_VOICE_EN=en_US-amy-medium
TTS_AUDIO_FORMAT=mp3

Then ship the rebuilt binary (go build -o petal ./cmd/server already done) and restart the petal :8088 session. Confirm the log line: read-aloud enabled (TTS endpoint=http://127.0.0.1:5005).

3. Verify

# on millenia — end-to-end through petal, including ffmpeg transcode:
curl -sf -X POST localhost:8088/api/tts \
  -H 'Content-Type: application/json' \
  -d '{"text":"hello there","lang":"en-US"}' -o /tmp/petal-tts.mp3 \
  && file /tmp/petal-tts.mp3   # expect: Audio file ... MPEG ... layer III
  • Second identical call is served from the cache (~/petal/.../data/tts/*.mp3).
  • A language with no configured instance returns 404 → client uses Web Speech.
  • Browser check via the uitest harness (~/petal/uitest): tap a word in the WordCard / select a sentence and hit speak — expect the natural Piper voice.

Chinese voice (live)

Each Piper HTTP server loads ONE model, so Chinese runs as a second instance: piper-zh.service on :5006 with zh_CN-huayan-medium. Deployed via:

scp deploy/piper-zh.service 192.168.1.212:~/.config/systemd/user/
ssh 192.168.1.212 'export XDG_RUNTIME_DIR=/run/user/$(id -u)
  ~/piper/venv/bin/python -m piper.download_voices zh_CN-huayan-medium --data-dir ~/piper/voices
  systemctl --user daemon-reload && systemctl --user enable --now piper-zh.service'

Then in petal's start.sh: TTS_ENDPOINT_ZH=http://127.0.0.1:5006 and TTS_VOICE_ZH=zh_CN-huayan-medium. The handler maps language → instance from config, so adding more languages is just another instance + env pair (no code change).