Self-Host Config Reference
This page is for the
soloself-host path. Most installs should start with Self-Hosting and only come here when they need optional env details.
Most self-hosted solo installs do not need this page.
The normal path is still:
- set
DOMAIN - set
OPENROUTER_API_KEY - let the installer generate the secrets and local bucket credentials
This page is for the larger set of optional envs that still appear in the published Docker Compose bundle.
Core install
These are the main envs for a normal solo install:
DOMAIN=https://example.com
VIVD_ENABLE_EXPERIMENTAL_SOLO_MODE=true
VIVD_INSTALL_PROFILE=solo
OPENROUTER_API_KEY=sk-or-v1-...
STUDIO_MACHINE_PROVIDER=docker
VIVD_CADDY_TLS_MODE=managed
OPENCODE_MODEL_STANDARD=openrouter/google/gemini-3-flash-preview
OPENCODE_MODEL_ADVANCED=openrouter/google/gemini-3.1-pro-preview
VIVD_SCRATCH_CREATION_MODE=studio_astro
If you are not using install.sh, you must also provide:
BETTER_AUTH_SECRET=...
POSTGRES_USER=postgres
POSTGRES_PASSWORD=...
POSTGRES_DB=vivd
SCRAPER_API_KEY=...
VIVD_LOCAL_S3_ACCESS_KEY=...
VIVD_LOCAL_S3_SECRET_KEY=...
Network and TLS overrides
These are advanced overrides. Most solo installs can leave them unset and use
DOMAIN plus the Instance Settings -> Network UI later.
# Force the canonical public app origin explicitly
VIVD_APP_URL=https://example.com
# Legacy auth/public-origin override
BETTER_AUTH_URL=https://example.com
# Advanced host override when admin lives on another host
CONTROL_PLANE_HOST=app.example.com
# Additional trusted or admin-only hosts
SUPERADMIN_HOSTS=app.example.com
TRUSTED_DOMAINS=preview.example.com
# Bundled Caddy TLS controls
# managed = bundled Caddy gets and renews certificates
# external = another proxy handles TLS; keep the public origin on https
# off = plain HTTP only
VIVD_CADDY_TLS_MODE=managed
VIVD_CADDY_ACME_EMAIL=admin@example.com
VIVD_PUBLISH_INCLUDE_WWW_ALIAS=false
# Optional override for bundled self-host Caddyfile rewrites from Instance Settings -> Network
# default: true on the public solo self-host bundle
# set false to disable UI-managed rewrites when you want deployment-level config to stay manual
VIVD_SELFHOST_CADDY_UI_MANAGED=true
For the admin-side meaning of those settings, read Instance Settings.
Email delivery
Start with one provider plus VIVD_EMAIL_FROM.
VIVD_EMAIL_PROVIDER=smtp
VIVD_EMAIL_FROM=noreply@example.com
SMTP:
VIVD_SMTP_HOST=smtp.example.com
VIVD_SMTP_PORT=587
VIVD_SMTP_USER=your-user
VIVD_SMTP_PASSWORD=your-password
VIVD_SMTP_SECURE=false
Alternative SMTP shortcut:
VIVD_SMTP_URL=smtps://user:pass@smtp.example.com:465
Resend:
VIVD_EMAIL_PROVIDER=resend
RESEND_API_KEY=re_xxx
RESEND_WEBHOOK_SECRET=whsec_xxx
SES:
VIVD_EMAIL_PROVIDER=ses
VIVD_SES_REGION=eu-central-1
VIVD_SES_ACCESS_KEY_ID=...
VIVD_SES_SECRET_ACCESS_KEY=...
VIVD_SES_FROM_EMAIL=noreply@example.com
Optional transactional email identity/footer bootstrap:
VIVD_EMAIL_BRAND_DISPLAY_NAME=Example Studio
VIVD_EMAIL_BRAND_SUPPORT_EMAIL=support@example.com
VIVD_EMAIL_BRAND_WEBSITE_URL=https://example.com
VIVD_EMAIL_BRAND_IMPRINT_URL=https://example.com/imprint
VIVD_EMAIL_BRAND_PRIVACY_URL=https://example.com/privacy
For provider behavior, webhooks, and deliverability workflows, read Email & Deliverability.
Storage
The hosted self-host bundle defaults to the bundled local S3-compatible bucket:
VIVD_BUCKET_MODE=local
VIVD_LOCAL_S3_ACCESS_KEY=...
VIVD_LOCAL_S3_SECRET_KEY=...
In bundled local mode, Vivd infers these internal defaults unless you override them manually:
VIVD_LOCAL_S3_BUCKET=vivd
VIVD_LOCAL_S3_ENDPOINT_URL=http://minio:9000
VIVD_LOCAL_S3_REGION=us-east-1
VIVD_LOCAL_S3_DOWNLOAD_ENDPOINT_URL=<public-origin>/_vivd_s3
Treat those as advanced overrides for custom local-storage topologies. The inline minimal self-host example omits them on purpose.
To switch later to an external S3-compatible bucket:
VIVD_BUCKET_MODE=external
VIVD_S3_BUCKET=vivd
VIVD_S3_ENDPOINT_URL=https://s3.example.com
VIVD_S3_ACCESS_KEY_ID=...
VIVD_S3_SECRET_ACCESS_KEY=...
VIVD_S3_REGION=us-east-1
Optional storage extras:
VIVD_S3_PUBLIC_BASE_URL=https://cdn.example.com
VIVD_S3_DOWNLOAD_ENDPOINT_URL=https://objects.example.com
VIVD_S3_SESSION_TOKEN=...
R2 compatibility aliases still work:
R2_BUCKET=vivd
R2_ENDPOINT=https://<accountid>.r2.cloudflarestorage.com
R2_ACCESS_KEY=...
R2_SECRET_KEY=...
Integrations and optional services
Cloudflare Turnstile automation:
CLOUDFLARE_ACCOUNT_ID=...
CLOUDFLARE_API_TOKEN=...
GitHub backup/sync:
GITHUB_SYNC_ENABLED=true
GITHUB_ORG=your-github-org
GITHUB_TOKEN=ghp_xxx
External scraper service:
SCRAPER_URL=https://scraper.example.com
SCRAPER_API_KEY=...
Optional thumbnail-preview base override for advanced scraper topologies:
VIVD_THUMBNAIL_PREVIEW_BASE_URL=https://app.example.com
The bundled self-host Docker stack infers this automatically and usually does not need it. Set it only when thumbnails should fetch preview pages from a different internal or public origin than the default.
Optional residential proxy for the bundled scraper’s Puppeteer browser. This is mainly useful for advanced scraper setups where outbound browser traffic must use a specific network path:
PROXY_HOST=proxy.example.com
PROXY_PORT=823
PROXY_USERNAME=...
PROXY_PASSWORD=...
Set PROXY_HOST to enable it. PROXY_PORT defaults to 823. Credentials are
only used when both username and password are present. This is an install-level
setting for the bundled scraper service in the published Compose bundle, not
a per-project import option. If you run a separate external scraper via
SCRAPER_URL, configure the proxy on that scraper deployment instead.
Studio / model overrides
Super admins can manage the persisted AI model settings from the admin UI. The environment variables below are still useful as install-time scaffolding and as fallbacks before settings have been saved.
The Studio model picker is driven by a catalog. There are two ways to configure it:
Catalog mode (recommended — supports multiple models per tier)
Set OPENCODE_MODELS to a JSON array. Each entry maps a model to one of the
three tiers (standard, advanced, pro) and provides the display copy that
appears in the in-app picker. Mark one model per tier with
"isTierDefault": true to pick the default; if you omit the flag, the first
entry of each tier wins.
OPENCODE_MODELS=[{"tier":"standard","provider":"openrouter","modelId":"google/gemini-3-flash-preview","displayName":"Gemini 3 Flash","strengthLabel":"Cheaper, current default","isTierDefault":true},{"tier":"standard","provider":"openrouter","modelId":"google/gemini-3.5-flash-preview","displayName":"Gemini 3.5 Flash","strengthLabel":"Newer, slightly stronger"},{"tier":"advanced","provider":"openrouter","modelId":"google/gemini-3.1-pro-preview","displayName":"Gemini 3.1 Pro","strengthLabel":"Best all-rounder","isTierDefault":true},{"tier":"advanced","provider":"openrouter","modelId":"moonshotai/kimi-k2.6","displayName":"Kimi K2.6","strengthLabel":"Best for design / look & feel"},{"tier":"pro","provider":"openrouter","modelId":"openai/gpt-5.4","variant":"high","displayName":"GPT 5.4 High","strengthLabel":"Data-heavy / debugging / complex CMS","isTierDefault":true}]
Per-entry fields:
tier—"standard","advanced", or"pro"(required).providerandmodelId— the OpenCode provider + model identifier (required).variant— optional OpenCode thinking/reasoning variant (e.g."high").displayName— model name shown as the row subtitle.strengthLabel— short “best for…” description shown as the row primary label.isTierDefault— marks the tier’s default selection.
Legacy single-model-per-tier env vars (fallback)
If OPENCODE_MODELS is not set, the studio falls back to the legacy
per-tier env vars (one model per tier):
OPENCODE_MODEL_STANDARD=openrouter/google/gemini-3-flash-preview
OPENCODE_MODEL_ADVANCED=openrouter/google/gemini-3.1-pro-preview
OPENCODE_MODEL_PRO=openrouter/google/gemini-3.1-pro-preview
OPENCODE_MODEL_PRO_VARIANT=high
Each legacy tier can also set an optional OpenCode model variant with
OPENCODE_MODEL_STANDARD_VARIANT, OPENCODE_MODEL_ADVANCED_VARIANT, and
OPENCODE_MODEL_PRO_VARIANT.
Scratch creation mode defaults to studio_astro. Switch back to legacy_html
only if you intentionally want the older backend-generated plain HTML flow:
VIVD_SCRATCH_CREATION_MODE=legacy_html
Design Mode is enabled by default in the published Compose bundle. Draft generation stays off by default, so Design Mode hands the chat brief directly to Studio:
VIVD_DESIGN_MODE_ENABLED=true
VIVD_DESIGN_MODE_DRAFTS_ENABLED=false
VIVD_DESIGN_MODE_DESCRIPTION_MODEL=google/gemini-2.5-flash-lite
VIVD_DESIGN_MODE_DESCRIPTION_FALLBACK_MODEL=google/gemini-2.5-flash
Optional scratch-generation model overrides for the legacy backend HTML flow:
VIVD_GENERATION_MODEL=google/gemini-3.1-pro-preview
VIVD_ANALYSIS_MODEL=google/gemini-3.1-pro-preview
VIVD_HERO_GENERATION_MODEL=google/gemini-3-pro-image-preview
VIVD_IMAGE_EDITING_MODEL=google/gemini-3-pro-image-preview
VIVD_IMAGE_DESCRIPTION_MODEL=google/gemma-3-12b-it:free
VIVD_IMAGE_PRIORITIZATION_MODEL=google/gemini-2.5-flash
VIVD_DESIGN_MODE_STUDIO_IMPLEMENTATION_MODEL=openrouter/google/gemini-3.1-pro-preview
NAVIGATION_MODEL=google/gemini-2.5-flash
Optional Vertex-based configuration:
GOOGLE_CLOUD_PROJECT=your-gcp-project
VERTEX_LOCATION=global
GOOGLE_APPLICATION_CREDENTIALS_JSON='{"type":"service_account",...}'
Optional Docker Studio tuning:
DOCKER_STUDIO_CPUS=2
DOCKER_STUDIO_CPUS_AUTO_RESERVE=1
DOCKER_STUDIO_CPUS_AUTO_MAX=2
# Optional explicit override. Leave unset to use Vivd's reserve-first auto-sized default.
DOCKER_STUDIO_MEMORY_MB=4096
DOCKER_STUDIO_MEMORY_AUTO_RESERVE_MB=1536
DOCKER_STUDIO_MEMORY_AUTO_MIN_MB=1024
DOCKER_STUDIO_MEMORY_AUTO_MAX_MB=4096
DOCKER_STUDIO_NETWORK=vivd-network
DOCKER_STUDIO_ROUTE_PREFIX=/_studio
DOCKER_STUDIO_IMAGE=ghcr.io/vivd-studio/vivd-studio:latest
If DOCKER_STUDIO_CPUS is unset, Vivd auto-sizes Docker-managed Studio CPU
from the detected CPU budget, leaves one CPU for the rest of the stack, and
caps the default auto-sized result at 2 vCPUs unless you raise
DOCKER_STUDIO_CPUS_AUTO_MAX.
If DOCKER_STUDIO_MEMORY_MB is unset, Vivd auto-sizes Docker-managed Studio
RAM from the detected host or cgroup memory budget, subtracts a default
1536 MiB reserve for the rest of the stack and caps the default auto-sized
result at 4096 MiB unless you raise DOCKER_STUDIO_MEMORY_AUTO_MAX_MB. On a
4 GiB host that still yields 2560 MiB by default; on a 16 GiB host it now
yields 4096 MiB by default instead of trying to claim nearly the whole box.
The optional DOCKER_STUDIO_MEMORY_AUTO_MIN_MB floor is opt-in instead of
being forced on smaller boxes by default.
That also means the recommended 4 vCPU / 8 GiB self-host baseline lands on a
useful default split without extra env tuning: 2 vCPUs and 4096 MiB RAM for
the Studio runtime, with the remaining headroom left for the main app stack.
Optional analytics geolocation:
# Enabled by default. Set false to hide the country breakdown.
VIVD_ANALYTICS_COUNTRY_BREAKDOWN_ENABLED=true
# cloudflare = read Cloudflare's cf-ipcountry request header
# off = disable country detection entirely
VIVD_ANALYTICS_GEOLOCATION_PROVIDER=cloudflare
The Analytics country data can be collected when Cloudflare injects the
cf-ipcountry request header before traffic reaches the backend. Set
VIVD_ANALYTICS_COUNTRY_BREAKDOWN_ENABLED=false if you need to hide the
dashboard country breakdown.
Notes
- This reference is intentionally scoped to the self-hosted
solobundle. - The root
.env.examplein the repo is broader because it also covers local dev and platform/SaaS paths. - If an env is not mentioned here, check whether it is really needed for your install before adding it.