Skip to content

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