# Copy to .env and fill in. Every secret lives ONLY here (gitignored), never committed. # VibeClip runs out-of-the-box with a single LLM key; everything else has a sane default. # ─── LLM brain ────────────────────────────────────────────────────────────── # OpenAI-compatible. Set ONE provider. OpenAI is preferred; DeepSeek is a cheaper # drop-in (great for cost-conscious self-hosters). Any OpenAI-compatible endpoint # works via LLM_BASE_URL. OPENAI_API_KEY= OPENAI_MODEL=gpt-4o-mini OPENAI_MODEL_PRO=gpt-4o # DeepSeek fallback (used automatically if OPENAI_API_KEY is empty). DEEPSEEK_API_KEY= DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL=deepseek-chat DEEPSEEK_MODEL_PRO=deepseek-chat # Optional: point the OpenAI client at any OpenAI-compatible server (LM Studio, # Ollama, OpenRouter, a proxy…). Empty = use the provider default above. LLM_BASE_URL= # Who may use the server key above? false (default) = any logged-in user falls # back to it — correct for a solo/trusted self-host. true = ONLY admins # (ADMIN_EMAILS) use the server key; every other account must add their own key # in Settings (BYOK). Set true on a PUBLIC multi-user instance (e.g. vibeclip.dev) # so a random signup can't spend your OpenAI/DeepSeek credits. SERVER_KEY_ADMINS_ONLY=false # ─── Speech-to-text (local, no API key) ───────────────────────────────────── # faster-whisper runs on-device. Model auto-downloads on first run. WHISPER_MODEL=small WHISPER_DEVICE=cpu WHISPER_COMPUTE=int8 # ─── Video encode ─────────────────────────────────────────────────────────── # h264_videotoolbox on Apple Silicon; use libx264 on Linux servers / Docker. VIDEO_ENCODER=libx264 # ─── Stock b-roll (optional) ──────────────────────────────────────────────── # Free key from https://www.pexels.com/api/ . Empty = b-roll search disabled # (local files still work via add_broll(file=...)). PEXELS_API_KEY= # ─── Social connect + share (optional, zernio) ────────────────────────────── # Bearer key from https://zernio.com (free tier = first 2 connected accounts). # Empty = the Share feature is visible but disabled. ZERNIO_API_KEY= ZERNIO_BASE_URL=https://zernio.com/api/v1 # ─── Email / signup verification ──────────────────────────────────────────── # EMAIL_MODE=console -> OTP codes print to the server log (zero-config, default). # EMAIL_MODE=resend -> send real email via Resend (https://resend.com). EMAIL_MODE=console RESEND_API_KEY= RESEND_FROM=VibeClip # Self-host convenience: when false, new accounts are created already-verified so # a solo operator never has to dig an OTP out of the logs. Set true for a public # multi-user instance. NOTE: when true, signup needs a WORKING email provider # (EMAIL_MODE=resend + RESEND_API_KEY + a verified RESEND_FROM domain) — with the # default EMAIL_MODE=console the OTP only lands in the server log, so real users # could never receive it and signup would be effectively blocked. REQUIRE_EMAIL_VERIFICATION=false # Mark the session cookie `Secure` (HTTPS-only). Leave false for self-host over # plain http://localhost (else the browser drops the cookie and login fails); # set true on any HTTPS deployment (e.g. vibeclip.dev) to harden the session. SECURE_COOKIES=false # ─── Hosted studio vs. self-host marketing funnel ─────────────────────────── # Does THIS deployment offer a usable hosted studio (login + signup)? # true (default) — a self-hoster running it locally: the landing shows # Sign in / Start free so they can use their own instance. # false — a PUBLIC marketing site for the self-host-only v1: the # landing hides login/signup and points everyone to GitHub # to self-host. Flip back to true once a paid hosted # platform (v2) is live. Set false on a public marketing # deploy like vibeclip.dev. HOSTED_STUDIO=true # ─── Site / analytics ─────────────────────────────────────────────────────── # Public base URL — used for the blog's canonical/sitemap/OG tags. SITE_URL=http://localhost:8765 # Google Analytics 4 Measurement ID. Empty = no analytics injected (recommended # for self-host). Only set this on a public instance you own. GA_MEASUREMENT_ID= # ─── Per-user storage quota ───────────────────────────────────────────────── # Default 0 = UNLIMITED (self-host on your own disk). On a shared PUBLIC instance # set caps to protect storage, e.g. MAX_UPLOAD_SECONDS=600 and MAX_PROJECTS_PER_USER=1. MAX_UPLOAD_SECONDS=0 # longest video a user may upload, seconds. 0 = no limit MAX_PROJECTS_PER_USER=0 # projects a user may keep at once. 0 = unlimited # ─── Server ───────────────────────────────────────────────────────────────── HOST=127.0.0.1 PORT=8765 # docker-compose publish address. 127.0.0.1 = host-only (default); 0.0.0.0 = # expose on the server's public IP; 172.17.0.1 = reach from a separate proxy # container (e.g. an external Caddy/nginx). VIBECLIP_BIND=127.0.0.1 # Admin allowlist — comma-separated emails. A user whose signup email is listed # here gets the admin role (the /admin dashboard) automatically. Admin is NEVER # set by password — the user still signs up + verifies normally. ADMIN_EMAILS=