Skip to content

Self-Host Config Reference

This page is for the solo self-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:

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).
  • provider and modelId — 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 solo bundle.
  • The root .env.example in 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.