Petal's data directory (petal.db, uploaded images, and the TTS cache -- which is synthesized audio of her sentences) now lives on a LUKS volume. LUKS-on-a-file rather than gocryptfs because Petal is SQLite in WAL mode: WAL needs a shared-memory index mapped consistently across processes, and FUSE has a long history of subtle mmap/locking differences. A block device with ext4 behaves exactly like a disk to SQLite. The key sits on the same host, which is a deliberate availability tradeoff and is documented as such: it stops a decommissioned disk or a raw block-device read, not anyone holding the whole VM image. Two bugs found by rehearsing a reboot rather than trusting the setup: - Mounting over a directory HIDES its contents, it does not remove them. The first run left the original plaintext petal.db and WAL sitting on the unencrypted root filesystem, invisible under the mount -- exactly what the exercise was meant to eliminate. Now shredded before the mount, with a refusal if the mountpoint will not come up empty. - systemd-cryptsetup was not installed on the host, so /etc/crypttab was being ignored entirely and the volume would never have unlocked at boot. The script now refuses to run without the generator present.
🌸 Petal
A self-hosted, privacy-first writing editor with warm bubbly design, auto-save, and
local-LLM grammar/ESL suggestions. See petal-spec.md for the full
design spec and BUILD_PLAN.md for build progress.
Stack
Go + chi backend · SQLite (modernc, pure Go) · React + Vite + Tiptap + Tailwind v4 frontend ·
local vLLM/Ollama for AI suggestions. Single-binary deployment (frontend embedded via go:embed).
Local development
Two processes during development:
# 1. Backend (serves /api on :8080)
go run ./cmd/server
# 2. Frontend dev server (HMR on :5173, proxies /api → :8080)
cd web && npm install && npm run dev
Open http://localhost:5173 while developing.
Production build (single binary)
cd web && npm run build # emits web/dist (embedded by the Go binary)
cd .. && go build -o petal ./cmd/server
./petal # serves UI + API on :8080
Configuration is via environment variables — copy .env.example to .env.
Deployment
docker compose up -d --build # petal + the two Piper read-aloud sidecars
Behind Traefik on the parodia.dev VPS; vLLM stays on millenia over headscale.
Full runbook — first deploy, the LLM link, backups and restore — in
deploy/README.md.
Status
Early build, multi-session. Auth (Authentik OIDC) is next; Copyleaks plagiarism is
still parked — see BUILD_PLAN.md.