Back to changelog
Milestone
Runtime Settings: Encrypted Billing and Storage in the Database
Payment and S3 credentials leave environment variables and land in encrypted database rows. Production requires MUSE_SETTINGS_SECRET. Checkout uses stable plan IDs, and the admin billing page nests each gateway's product IDs inside a collapsed provider panel.
This is a breaking configuration change for existing forks: gateway keys and S3 credentials are no longer read from env at runtime.
Why the template changed
- Payment and storage secrets used to sit next to mail and OAuth in
.env. Rotating a key meant a rebuild, and day-two operations mixed with bootstrap secrets. - Runtime now reads only the
app_settingtable for billing and S3. There is no environment-variable fallback after you import leftover local values.
What you must set
- Add
MUSE_SETTINGS_SECRET(at least 32 characters). It wraps encrypted settings with HKDF-SHA256 + AES-256-GCM and is never stored in the database. A production runtime missing this secret fails at startup. - Apply migration
0001_dry_terror.sqlsoapp_settingandapp_setting_revisionexist (pnpm drizzle:migrate). - Create an admin, then open Admin → Runtime settings (
/app/admin/settings). Save gateway credentials, checkout product IDs, and S3 settings. Use Test connection before going live. - Optional one-shot:
pnpm muse:settings:importcopies leftover local gateway/storage credentials into the database. Runtime never reads those env vars afterward. Checkout product IDs are entered in the admin page, not env.
Billing and checkout
- Public pricing still uses stable app plan IDs (
pro_monthly,pro_yearly,lifetime). Provider product IDs live inbilling.productMap. - Direct checkout mode is gone. Paid plans launch through Muse Billing against the stored default gateway (Creem, Stripe, Dodo, or Waffo).
- On the admin billing tab, the default-gateway card stays at the top. Each provider starts collapsed; expand it to edit credentials and that gateway's product IDs together. Badges show Default, Configured / Not configured, mapped product-ID count, and Unsaved.
Storage and deploy
- S3 access key, secret, endpoint, and the avatars bucket are admin settings.
NEXT_PUBLIC_AVATARS_PROXY_URLstays in env because the browser builds avatar URLs from it. - Docker, Vercel, Cloudflare Workers, and EdgeOne production env lists now require
MUSE_SETTINGS_SECRETand no longer treat gateway or S3 keys as env.