Configuration¶
Vistilla is configured only through environment variables, read once at
start-up (crates/vistilla-api/src/config.rs).
Yes/no settings accept 1, true, yes or on (any case) as yes. Any
other value means no.
Names from before the rename
The project was called Loom until 2026-10-20. A setting still named
LOOM_… counts as its VISTILLA_… twin (LOOM_STORAGE as
VISTILLA_STORAGE, and so on), in the server and in the hosted start
script; when both are set, the VISTILLA_… one wins. A few stored names
stay as they were, because data already lives under them: the bucket
paths litestream/loom.db and loom-db/…, and the hand-over headers
between two server versions (x-loom-handoff).
Server¶
| Variable | Default | Meaning |
|---|---|---|
VISTILLA_BIND |
0.0.0.0:8787 |
Address and port to listen on. The hosted start script sets it from PORT. |
VISTILLA_PUBLIC_BASE_URL |
http://localhost:8787 |
The public address, used in emails, invitations, share links and link previews. |
VISTILLA_WEB_ROOT |
/app/web |
Folder with the HTML pages, assets/ and sw.js. |
VISTILLA_DOCS_ROOT |
/app/docs |
Folder with the built documentation site, served at /docs. |
VISTILLA_LOG |
info,sqlx=warn |
Log filter (tracing EnvFilter syntax). docker-compose.yml sets info,sqlx=warn,tower_http=info. |
VISTILLA_RUN_WORKERS |
true |
Run the background workers in this process. |
VISTILLA_SIGNUP_ENABLED |
true |
Allow anyone to create a workspace. When off, only invited people can sign up. |
VISTILLA_SECURE_COOKIES |
false |
Add Secure to cookies. Turn on behind HTTPS. |
VISTILLA_SESSION_TTL_DAYS |
30 |
How long a sign-in lasts. |
VISTILLA_MAX_UPLOAD_BYTES |
2147483648 (2 GiB) |
Largest file sent in one request. Keep it at or below what a proxy in front accepts per request (Cloudflare: 100 MB). |
VISTILLA_STORAGE_QUOTA_BYTES |
10 GB for a Backblaze B2 endpoint (its free plan), otherwise none | The object store's size, shown in the library's storage card with the free space; 0 means no size. Nothing is refused when it is reached. |
VISTILLA_MAX_RECORDING_BYTES |
4294967296 (4 GiB) |
Largest video uploaded in parts: recordings, and big files from the library. |
VISTILLA_STREAM_REDIRECT |
false |
With S3 storage, send players and downloads to a presigned bucket URL (307) instead of proxying. |
Database and secrets¶
| Variable | Default | Meaning |
|---|---|---|
VISTILLA_DATABASE_URL |
sqlite:///data/vistilla.db?mode=rwc |
SQLite database. |
VISTILLA_SECRET_KEY |
— | Base64 of 32 bytes. Encrypts stored AI keys. If unset, a key is kept in secret.key. |
VISTILLA_SECRET_DIR |
the database's folder | Where secret.key lives. |
Storage¶
| Variable | Default | Meaning |
|---|---|---|
VISTILLA_STORAGE |
fs |
fs for a folder; s3 (or r2, the same thing) for an S3-compatible bucket. The hosted start script only replicates the database with s3. |
VISTILLA_FS_ROOT |
/data/objects |
Folder for objects when fs. |
VISTILLA_S3_ENDPOINT |
http://minio:9000 |
S3 endpoint the server uses. |
VISTILLA_S3_PUBLIC_ENDPOINT |
same as VISTILLA_S3_ENDPOINT |
Endpoint written into presigned URLs for browsers. |
VISTILLA_S3_REGION |
auto |
Region used for signing. |
VISTILLA_S3_BUCKET |
vistilla |
Bucket name. |
VISTILLA_S3_ACCESS_KEY |
required for S3 | Access key id. |
VISTILLA_S3_SECRET_KEY |
required for S3 | Secret key. |
VISTILLA_S3_PATH_STYLE |
true |
Path-style addressing (/bucket/key). |
VISTILLA_S3_DOWNLOAD_PROXY |
— | An address that passes signed downloads on to the bucket, such as the Worker's https://…/_b2. Downloads (players, the server's own jobs) are sent there instead of to the bucket; uploads are not. |
Email¶
The first transport that is configured is used.
| Variable | Default | Meaning |
|---|---|---|
VISTILLA_SMTP_HOST |
— | Turns on SMTP. |
VISTILLA_SMTP_PORT |
587 |
|
VISTILLA_SMTP_USERNAME, VISTILLA_SMTP_PASSWORD |
— | Used when both are set. |
VISTILLA_SMTP_FROM |
vistilla@localhost |
Sender, Name <address> allowed. |
VISTILLA_SMTP_STARTTLS |
true |
STARTTLS; off means plain text (local relays only). |
VISTILLA_BREVO_API_KEY |
— | Turns on Brevo's HTTPS email API. |
VISTILLA_BREVO_BASE_URL |
https://api.brevo.com |
|
VISTILLA_MAIL_FROM |
— | Sender for Brevo; falls back to VISTILLA_SMTP_FROM, and Brevo stays off if neither is set. For the webhook, only the display name is used (default Vistilla). |
VISTILLA_MAIL_WEBHOOK_URL |
— | Turns on the JSON mail relay. A bare Google Apps Script deployment id (AKfycb…) is expanded to its /exec URL. |
VISTILLA_MAIL_WEBHOOK_SECRET |
— | Sent to the relay as secret. |
AI fallback (set by the operator)¶
Workspaces normally set their own provider under Settings → Transcripts and summaries. These variables are a fallback, used only for workspaces that have not set one.
| Variable | Default | Meaning |
|---|---|---|
VISTILLA_TRANSCRIBE_PROVIDER |
none |
gemini / google for Gemini; any other value except none means an OpenAI-compatible /audio/transcriptions endpoint. |
VISTILLA_TRANSCRIBE_URL |
https://api.openai.com/v1/audio/transcriptions |
Endpoint for the OpenAI-compatible option. |
VISTILLA_TRANSCRIBE_API_KEY |
empty | May be empty for a local whisper server. |
VISTILLA_TRANSCRIBE_MODEL |
whisper-1, or gemini-3.8-flash for Gemini |
|
VISTILLA_SUMMARY_PROVIDER |
none |
gemini / google for Gemini; any other value except none means Anthropic. |
VISTILLA_SUMMARY_MODEL |
claude-opus-5, or gemini-3.8-flash for Gemini |
|
VISTILLA_ANTHROPIC_API_KEY (or ANTHROPIC_API_KEY) |
— | Key for Anthropic summaries. |
VISTILLA_ANTHROPIC_BASE_URL |
https://api.anthropic.com |
|
VISTILLA_GEMINI_API_KEY (or GEMINI_API_KEY, GOOGLE_API_KEY) |
— | Key for Gemini, either purpose. |
VISTILLA_GEMINI_BASE_URL |
https://generativelanguage.googleapis.com |
Read but not applied yet
VISTILLA_TRANSCRIBE_LANGUAGE and VISTILLA_SUMMARY_MAX_TOKENS are read, but
the current code does not use them. The language is always detected,
and summaries use 8,000 output tokens.
Used by the deployment scripts only¶
| Variable | Where | Meaning |
|---|---|---|
PORT |
docker/hosted-entrypoint.sh |
Port given by the host; becomes VISTILLA_BIND. |
RENDER_GIT_COMMIT |
docker/hosted-entrypoint.sh |
Written to /assets/version.txt so the running commit can be checked. |
VISTILLA_DB_REPLICA |
docker/hosted-entrypoint.sh |
off disables Litestream. |
VISTILLA_MIRROR_S3_ENDPOINT, _REGION, _BUCKET, _ACCESS_KEY, _SECRET_KEY |
server | A second bucket that keeps a copy of every recording and picture, and of the database every 6 hours and as the server stops. Reads fall back to it when the first bucket refuses, and a start while the first bucket refuses runs from it. Best in a second free Backblaze account. Off when unset. |
VISTILLA_MIRROR_S3_DOWNLOAD_PROXY |
server | Where players fetch from the second bucket: the Worker's /_b2m (set B2_MIRROR_ORIGIN on the Worker to that bucket's endpoint). |
VISTILLA_DB_HOME |
set by docker/hosted-entrypoint.sh |
bucket or mirror: which bucket Litestream backs the database up to in this run. The server records it in both buckets (loom-db/home) 10 seconds after it starts. |
VISTILLA_HANDOFF_FROM |
docker/hosted-entrypoint.sh |
Address of the running server a new one takes the database over from. Defaults to RENDER_EXTERNAL_URL, which Render sets. Needs VISTILLA_SECRET_KEY, which signs the request. |
VISTILLA_STANDBY_S3_BUCKET, _ENDPOINT, _REGION, _ACCESS_KEY, _SECRET_KEY, VISTILLA_STANDBY_QUOTA_BYTES |
docker/hosted-entrypoint.sh |
A stand-in bucket used in place of the VISTILLA_S3_* one (server and Litestream) while set, with no download proxy. Delete them to go back. |
VISTILLA_PORT |
docker-compose.yml |
Host port for local runs (default 8787). |
Example: the hosted instance¶
These come from render.yaml. Secrets are set in the Render dashboard, not
in the file.
VISTILLA_PUBLIC_BASE_URL=https://vistilla.sylergy.workers.dev
VISTILLA_SECURE_COOKIES=true
VISTILLA_STORAGE=s3
VISTILLA_STREAM_REDIRECT=1
VISTILLA_S3_DOWNLOAD_PROXY=https://vistilla.sylergy.workers.dev/_b2
VISTILLA_S3_ENDPOINT / _REGION / _BUCKET / _ACCESS_KEY / _SECRET_KEY (Backblaze B2)
VISTILLA_MAIL_WEBHOOK_URL (Apps Script relay)
VISTILLA_SECRET_KEY (generated by Render)
VISTILLA_MAX_UPLOAD_BYTES=100000000
VISTILLA_STORAGE_QUOTA_BYTES=10000000000