# Copy this file to .env or run scripts/bootstrap-server.sh. # Keep .env private. The bootstrap script generates URL-safe secrets. COMPOSE_PROJECT_NAME=vos VOS_VERSION=local # Public entrypoint. The default is HTTP-only catch-all for first boot. Set a # real hostname such as apps.example.com to let Caddy request public TLS for # that exact host. Use a comma/space-separated Caddy site list such as # "apps.example.com, :80" when an exact TLS host should coexist with HTTP # catch-all Host-header probes to the controller. The catch-all path is routing # evidence only; it is not DNS, ACME, or custom-host certificate evidence. VOS_CADDY_SITE=:80 # Caddy upstream list. Keep the default for one controller; use a # space-separated list only after distinct regional origins and failover proof # are ready. VOS_UPSTREAMS=controller:8080 VOS_PUBLIC_URL=http://localhost VOS_ROOT_DOMAIN=localhost VOS_PRODUCTION_ROOT_DOMAIN= VOS_IMMUTABLE_ROOT_DOMAIN= VOS_PREVIEW_ROOT_DOMAIN= VOS_PULL_REQUEST_PREVIEW_ROOT_DOMAIN= VOS_CREATE_PULL_REQUEST_PREVIEW_ALIAS= VOS_DOMAIN_TLS_FRONT_DOOR_HOSTS= VOS_TLS_FRONT_DOOR_HOSTS= # Domain DNS/TLS provider apply is disabled unless this is 1 or true in the # controller environment. Tokens alone must not trigger provider mutations. VOS_DOMAIN_DNS_TLS_APPLY=0 # Customer-domain Cloudflare push-through helper gate. The helper also requires # VOS_PUBLIC_URL, VOS_PROJECT, VOS_DOMAIN, VOS_ADMIN_TOKEN, the Cloudflare zone # name/id/token, and the DO origin hostname before it posts to the controller. VOS_CUSTOMER_DOMAIN_CLOUDFLARE_PUSH_LIVE=0 VOS_CLOUDFLARE_ZONE_NAME= VOS_CLOUDFLARE_ORIGIN_HOSTNAME= VOS_CLOUDFLARE_ACCOUNT_REF= VOS_CLOUDFLARE_ZONE_REF= VOS_DIGITALOCEAN_ORIGIN_REF= VOS_DIGITALOCEAN_FIREWALL_REF= CLOUDFLARE_API_TOKEN= CLOUDFLARE_ZONE_ID= VOS_HTTP_PORT=80 VOS_HTTPS_PORT=443 VOS_CADDY_MAX_BODY=512MB # CIDR ranges for trusted layer-7 proxies that may supply client IP headers. # Leave empty to ignore Forwarded/X-Forwarded-For/X-Real-IP/CF-Connecting-IP. VOS_TRUSTED_PROXY_CIDRS= # Images. The controller image is built locally until release images exist. VOS_CONTROLLER_IMAGE=vercel-oss-controller:local VOS_CADDY_IMAGE=caddy:2.8-alpine VOS_POSTGRES_IMAGE=postgres:16-alpine VOS_REDIS_IMAGE=redis:7-alpine # Host data paths. Back these up before upgrades. VOS_DATA_ROOT=/srv/vercel-oss VOS_POSTGRES_DATA=/srv/vercel-oss/postgres VOS_REDIS_DATA=/srv/vercel-oss/redis VOS_CONTROLLER_DATA=/srv/vercel-oss/controller VOS_BLOB_DATA=/srv/vercel-oss/blob VOS_CADDY_DATA=/srv/vercel-oss/caddy/data VOS_CADDY_CONFIG=/srv/vercel-oss/caddy/config VOS_BACKUP_DIR=/srv/vercel-oss/backups # Database and Redis credentials. Replace before production use. POSTGRES_USER=vos POSTGRES_DB=vos POSTGRES_PASSWORD=replace-with-generated-url-safe-password REDIS_PASSWORD=replace-with-generated-url-safe-password # Controller runtime. HOST=0.0.0.0 PORT=8080 NODE_ENV=production VOS_DATA_DIR=/data VOS_DEFAULT_PROJECT=default VOS_CONTROL_NETWORK=vos-control-net VOS_RUNTIME_NETWORK=vos-runtime-net VOS_RUNTIME_MEMORY=1536m VOS_RUNTIME_CPUS=1.5 VOS_RUNTIME_USER=1000:1000 VOS_RUNTIME_PIDS_LIMIT=256 VOS_RUNTIME_READ_ONLY=1 VOS_RUNTIME_TMPFS= VOS_RUNTIME_EXTRA_TMPFS= VOS_RUNTIME_DISK_SIZE=512m VOS_RUNTIME_STARTUP_TIMEOUT_MS=90000 VOS_RUNTIME_EGRESS_POLICY=internal-only VOS_RUNTIME_EGRESS_DENY_CIDRS= VOS_RUNTIME_EGRESS_ALLOW_ALL_ACK= VOS_NODE_BASE_IMAGE= VOS_DEPLOYMENT_SKIP_IMAGE_BOOTSTRAP= VOS_DEPLOYMENT_ENV_SCRATCH_DIR=/tmp/vos-deployment-env VOS_DOCKER_SOCKET=/var/run/docker.sock # Build queue and worker throughput. The controller can run a small embedded # worker for local installs; production Compose runs a separate build-worker # service so worker count can be scaled independently from the HTTP controller. VOS_CONTROLLER_BUILD_WORKER=0 VOS_BUILD_QUEUE_WORKER=1 VOS_BUILD_WORKER_ID= VOS_BUILD_CONCURRENCY=2 VOS_BUILD_QUEUE_POLL_MS=1000 VOS_BUILD_LEASE_MS=60000 VOS_BUILD_TIMEOUT_MS=1200000 VOS_BUILD_QUEUE_MAX_PENDING=100 VOS_BUILD_QUEUE_MAX_PENDING_PER_ORG=25 VOS_BUILD_QUEUE_MAX_PENDING_PER_PROJECT=10 VOS_BUILD_MEMORY=2048m VOS_BUILD_CPU_PERIOD=100000 VOS_BUILD_CPU_QUOTA=150000 VOS_BUILD_CPUSET_CPUS= VOS_BUILD_SHM_SIZE=512m VOS_BUILD_NETWORK= VOS_BUILD_WORKER_SERVICE_MEMORY=3g VOS_BUILD_WORKER_SERVICE_CPUS=2.0 VOS_DEPLOYMENT_SOURCE_MAX_BYTES=1073741824 VOS_DEPLOYMENT_ARTIFACT_MAX_BYTES=536870912 VOS_DEPLOYMENT_LOG_RETENTION_LINES=5000 VOS_DEPLOYMENT_LOG_RETENTION_DAYS=14 VOS_DEPLOYMENT_ARTIFACT_STORAGE=filesystem # Blob scaffolding. Local mode is mounted at /blob; S3-compatible values use # the V1 blob abstraction when BLOB_BACKEND=s3. Production/live provider proof # must set BLOB_S3_REQUIRE_FILE_CREDENTIALS=true and use the *_FILE variables; # direct S3_ACCESS_KEY_ID/S3_SECRET_ACCESS_KEY values are local/dev only. BLOB_BACKEND=local BLOB_ROOT=/blob BLOB_MAX_OBJECT_BYTES= BLOB_S3_PROVIDER= BLOB_S3_REQUIRE_FILE_CREDENTIALS=false S3_ENDPOINT= S3_BUCKET= S3_REGION= S3_ACCESS_KEY_ID= S3_ACCESS_KEY_ID_FILE= VOS_S3_ACCESS_KEY_ID_HOST_FILE= S3_SECRET_ACCESS_KEY= S3_SECRET_ACCESS_KEY_FILE= VOS_S3_SECRET_ACCESS_KEY_HOST_FILE= S3_PREFIX= S3_FORCE_PATH_STYLE= # Production object-storage live proof is opt-in and fails closed unless every # value below is set for a disposable accepted prefix plus the S3 settings above. VOS_OBJECT_STORAGE_PROOF_LIVE= VOS_OBJECT_STORAGE_PROOF_PROVIDER= VOS_OBJECT_STORAGE_PROOF_PREFIX= VOS_OBJECT_STORAGE_PROVIDER_PROOF_PATH= VOS_OBJECT_STORAGE_RESOURCE_REGISTRY_REF= VOS_OBJECT_STORAGE_SIGNED_READBACK_EXPIRES_SECONDS= VOS_OBJECT_STORAGE_PROVIDER_EVIDENCE_LIVE= VOS_OBJECT_STORAGE_PROVIDER_EVIDENCE_PROVIDER= VOS_OBJECT_STORAGE_PROVIDER_EVIDENCE_PREFIX= VOS_OBJECT_STORAGE_RESTORE_REPORT_PATH= VOS_OBJECT_STORAGE_PRIVATE_BUCKET_POLICY_REF= VOS_OBJECT_STORAGE_PUBLIC_ACCESS_BLOCK_REF= VOS_OBJECT_STORAGE_SSE_EVIDENCE_REF= VOS_OBJECT_STORAGE_RETENTION_BYPASS_RESTRICTED= VOS_OBJECT_STORAGE_ACCEPT_DESTRUCTIVE_LIFECYCLE= VOS_OBJECT_STORAGE_INVENTORY_MAX_KEYS= VOS_DO_SPACES_OBJECT_STORAGE_LIVE= VOS_DO_SPACES_OBJECT_STORAGE_PREFIX= # Billing provider proof. Production live-provider preflight fails closed when # VOS_BILLING_PROVIDER_REQUIRED=true and any required value is missing. VOS_BILLING_PROVIDER_REQUIRED= VOS_BILLING_PROVIDER= VOS_BILLING_PROVIDER_MODE= VOS_BILLING_PROVIDER_ACCOUNT_ID= VOS_BILLING_PROVIDER_HEALTHCHECK_URL= VOS_BILLING_PRICE_SHEET_REF= VOS_BILLING_WEBHOOK_SECRET_REF= VOS_BILLING_PRICING_VERSION=unpriced-v1 VOS_BILLING_PLAN_SEAT_MAPPING_REF= VOS_BILLING_INVOICE_DELIVERY_REF= VOS_BILLING_RECONCILIATION_WINDOW= VOS_BILLING_CLOSE_INTERVAL_SECONDS=3600 VOS_BILLING_CLOSE_GRACE_SECONDS=3600 VOS_BILLING_CLOSE_LOOKBACK_DAYS=45 VOS_BILLING_CLOSE_DRY_RUN=true # Current V1 security/operator values. Production controller/workers must use # the internal secret broker; direct VOS_VAULT_* values are for live provider # acceptance only, while the broker reads VOS_VAULT_*_FILE runtime secrets. VOS_ADMIN_TOKEN=replace-with-generated-token VOS_KMS_PROVIDER=vault VOS_KMS_KEY_ID=vault-transit VOS_KMS_KEY_VERSION=latest VOS_SECRET_BROKER_URL=http://secret-broker:8090 VOS_SECRET_BROKER_AUTH_TOKEN_FILE=/run/secrets/vos_secret_broker_auth_token VOS_SECRET_BROKER_AUTH_TOKEN_HOST_FILE=/private/path/vos_secret_broker_auth_token VOS_SECRET_KEK_BASE64= VOS_VAULT_ADDR_FILE=/run/secrets/vos_vault_addr VOS_VAULT_ADDR_HOST_FILE=/private/path/vos_vault_addr VOS_VAULT_ADDR= VOS_VAULT_TOKEN_FILE=/run/secrets/vos_vault_token VOS_VAULT_TOKEN_HOST_FILE=/private/path/vos_vault_token VOS_VAULT_TOKEN= VOS_VAULT_TRANSIT_KEY_FILE=/run/secrets/vos_vault_transit_key VOS_VAULT_TRANSIT_KEY_HOST_FILE=/private/path/vos_vault_transit_key VOS_VAULT_TRANSIT_KEY= VOS_VAULT_TRANSIT_MOUNT=transit VOS_VAULT_NAMESPACE= VOS_ANALYTICS_SALT=replace-with-generated-salt VOS_OTEL_EXPORTER_OTLP_ENDPOINT= VOS_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT= VOS_OTEL_EXPORTER_OTLP_HEADERS= # AI Gateway. Provider keys stay server-side; clients authenticate with VOS # tokens and must not send provider API keys to gateway routes. Enable cache in # production only with an encryption key so cached responses are not plaintext. VOS_AI_GATEWAY_CACHE_ENABLE=0 VOS_AI_GATEWAY_CACHE_ENCRYPTION_KEY= VOS_AI_GATEWAY_CACHE_KEY= VOS_AI_GATEWAY_CACHE_TTL_SECONDS=604800 VOS_AI_GATEWAY_RETRY_MAX_ATTEMPTS=3 VOS_AI_GATEWAY_RETRY_BASE_DELAY_MS=50 VOS_AI_GATEWAY_RETRY_MAX_DELAY_MS=10000 VOS_AI_GATEWAY_PROVIDER_TIMEOUT_MS=30000 VOS_AI_GATEWAY_PROVIDER_MAX_RETRIES=2 VOS_AI_GATEWAY_PROVIDER_INITIAL_BACKOFF_MS=250 VOS_AI_GATEWAY_PROVIDER_MAX_BACKOFF_MS=5000 VOS_AI_GATEWAY_RATE_LIMIT_CAPACITY=60 VOS_AI_GATEWAY_RATE_LIMIT_REFILL_TOKENS=60 VOS_AI_GATEWAY_RATE_LIMIT_REFILL_INTERVAL_MS=60000 VOS_AI_GATEWAY_CIRCUIT_FAILURE_THRESHOLD=3 VOS_AI_GATEWAY_CIRCUIT_RECOVERY_TIMEOUT_MS=30000 VOS_AI_GATEWAY_CIRCUIT_SUCCESS_THRESHOLD=1 OPENAI_API_KEY= OPENAI_BASE_URL= AZURE_OPENAI_API_KEY= AZURE_OPENAI_ENDPOINT= AZURE_OPENAI_BASE_URL= ANTHROPIC_API_KEY= ANTHROPIC_BASE_URL= GOOGLE_GENERATIVE_AI_API_KEY= GOOGLE_API_KEY= GOOGLE_GENERATIVE_AI_BASE_URL= GOOGLE_VERTEX_AI_ENDPOINT= MISTRAL_API_KEY= MISTRAL_BASE_URL= XAI_API_KEY= XAI_BASE_URL= GROQ_API_KEY= GROQ_BASE_URL= COHERE_API_KEY= COHERE_BASE_URL= OPENROUTER_API_KEY= OPENROUTER_BASE_URL= TOGETHER_API_KEY= TOGETHERAI_API_KEY= TOGETHER_BASE_URL= TOGETHERAI_BASE_URL= PERPLEXITY_API_KEY= PERPLEXITY_BASE_URL= FIREWORKS_API_KEY= FIREWORKS_BASE_URL= CEREBRAS_API_KEY= CEREBRAS_BASE_URL= DEEPSEEK_API_KEY= DEEPSEEK_BASE_URL= OLLAMA_API_KEY= OLLAMA_BASE_URL= # GitHub App integration. Leave install URL/app slug blank until an app exists, # but always generate a webhook secret before accepting real webhooks. VOS_GITHUB_INSTALL_URL= VOS_GITHUB_APP_SLUG= VOS_GITHUB_APP_ID= VOS_GITHUB_APP_PRIVATE_KEY= VOS_GITHUB_APP_PRIVATE_KEY_HOST_FILE= VOS_GITHUB_APP_PRIVATE_KEY_FILE= VOS_GITHUB_API_BASE_URL= VOS_GITHUB_WEBHOOK_SECRET=replace-with-generated-webhook-secret GITHUB_WEBHOOK_SECRET= VOS_GITHUB_AUTO_DEPLOY= VOS_GITHUB_AUTO_DEPLOY_PRIVATE_REPOS= VOS_GITHUB_AUTO_DEPLOY_FORK_PULL_REQUESTS= # GitHub App live acceptance inputs. Keep real values in a private env file and # use only a disposable proof repository. Set VOS_GITHUB_ACCEPT_LIVE_SAFE=1 only # when the controller is configured with the App credentials and you # intentionally want scripts/accept-github-live.sh to contact the # controller/GitHub or mutate proof refs. VOS_GITHUB_ACCEPT_LIVE_SAFE= VOS_GITHUB_ACCEPT_PUBLIC_URL= VOS_GITHUB_ACCEPT_INSTALLATION_ID= VOS_GITHUB_ACCEPT_REPOSITORY= VOS_GITHUB_ACCEPT_PROJECT= VOS_GITHUB_ACCEPT_COMMIT_SHA= VOS_GITHUB_ACCEPT_CALLBACK_STATE= VOS_GITHUB_ACCEPT_PROOF_BRANCH= VOS_GITHUB_ACCEPT_PROOF_BASE_BRANCH= VOS_GITHUB_ACCEPT_PROOF_REMOTE=origin VOS_GITHUB_ACCEPT_PROOF_WORKTREE= VOS_GITHUB_ACCEPT_PROOF_REPO_CONTRACT= VOS_GITHUB_ACCEPT_PULL_REQUEST_NUMBER= VOS_GITHUB_ACCEPT_CHECK_NAME= VOS_GITHUB_ACCEPT_COMPLETED_EVIDENCE_OUTPUT=output/github-live-deploys-complete-proof.redacted.json VOS_GITHUB_ACCEPT_PROOF_TIMEOUT_SECONDS=600 VOS_GITHUB_ACCEPT_PROOF_POLL_INTERVAL_SECONDS=15 # Current DigitalOcean server reacceptance inputs. Keep real values in a # private operator env file. The wrapper fails closed when required values are # missing and does not mutate the host unless --apply is passed with the apply # env gate set to 1. VOS_CURRENT_SERVER_DEPLOY_MODE=source-compose VOS_CURRENT_SERVER_REACCEPTANCE_APPLY=0 VOS_CURRENT_SERVER_REACCEPTANCE_ROLLBACK_APPLY=0 VOS_DROPLET_TARGET= VOS_DROPLET_PATH= VOS_DROPLET_ENV_FILE=.env.current VOS_DROPLET_SSH_PORT= VOS_SMOKE_PUBLIC_URL= VOS_CLI_SMOKE_PROJECT= VOS_CLI_SMOKE_ORG= VOS_CLI_SMOKE_SUPPORT_BUNDLE_CASE= VOS_REACCEPTANCE_BACKUP_RESTORE_REPORT= VOS_DROPLET_ID= VOS_DROPLET_FIREWALL_ID= CURRENT_OPERATOR_IPV4= VOS_ACTIVE_DEPLOYMENT_ID= VOS_CONTROLLER_SOURCE_IMAGE= VOS_CONTROLLER_SOURCE_BUILD_TIMESTAMP= VOS_CURRENT_CHECKOUT_REF= VOS_RUNTIME_CHANGE_REF= VOS_CURRENT_SERVER_EVIDENCE_TIMESTAMP= VOS_CURRENT_SERVER_REACCEPTANCE_OUTPUT_DIR= VOS_CURRENT_SERVER_LIVE_EVIDENCE_INDEX= VOS_DOCR_CONTROLLER_TARGET_IMAGE= VOS_DOCR_AUTH=doctl VOS_DOCR_EXPIRY_SECONDS=900 # Optional fixture-only checkout root for local acceptance tests. When set, the # builder may materialize `owner/repo` from this root instead of GitHub archives. # Keep unset in production unless you intentionally manage local checkouts. VOS_GITHUB_CHECKOUT_ROOT=