npm run build
TENANT_MASTER_TOKEN_DEMO=... npm startEnv vars (defaults): TENANT_BIND_HOST (0.0.0.0; set 127.0.0.1 behind a
local reverse proxy), PORT (8080), TENANT_BASE_DOMAIN (inbs.dev),
TENANT_CANONICAL_HOST (tenant.{base}), TENANT_MASTER_TOKEN_PROD /
TENANT_MASTER_TOKEN_DEMO (an env without a token doesn't serve),
TENANT_API_BASE_* / TENANT_STORAGE_BASE_* (DropCoreEnv defaults),
FORM_KEY (enables the min-fill-time form guard; honeypot + rate limit are
always on — with it set, page kits MUST fetch the guard fields via
GET /form/:locale/:form at load and send them back, or every submission is
rejected as bot; see the drop-core-server README, "built-in POST /form"),
TENANT_RESERVED_LABELS, TENANT_MAX_SITES,
TENANT_RECHECK_MS (10 min — the sweep cadence),
TENANT_SWEEP_CONCURRENCY (8, clamped 1–32 — core calls in flight per sweep
or warm-boot pass), TENANT_CORE_TIMEOUT_MS (10000 — every
/system/tenant/* call and every store site's core reads),
TENANT_ORIGIN_KEY (unset = off; a comma list of 16+ character keys — store
subdomains then answer 403 without the edge's matching x-drop-origin-key
header; a keyed request is routed by its real Host (never a visitor-sent
x-forwarded-host) and its stats use cf-connecting-ip;
origin_gate.ts, the rollout order in server-tenant/fly-setup.md §12),
TENANT_NEGATIVE_TTL_MS,
TENANT_CLIENT_IP_HEADER (fly-client-ip — the header the front proxy sets
to the visitor's IP; x-real-ip behind vshosting's nginx. The resolver reads
it, else the first x-forwarded-for hop, and passes it to every
WebPreviewServer as clientIp: it keys the form rate limit, rides to the
core as a form submission's reCAPTCHA remoteIp and feeds the stats visitor
hash),
TENANT_REQUIRE_BODY_SEED (off; 1 refuses hook pushes without a valid
body-bound x-drop-body-seed — see docs/hooks-and-caching.md),
TENANT_FEED_TTL_MS + the per-env TENANT_FEED_TTL_MS_DEMO /
TENANT_FEED_TTL_MS_PROD (one process serves both envs; the per-env value
wins) — the TTL of every hook-covered cache (meta, data, render + deps,
templates, assets, sitemap slug index) as a number of ms, or legacy for the
old short defaults (render 30 min / data 60 min / assets 60 min / meta 60 s /
templates 30 min); unset = the library default 4 h, applied to every
mount that has a hook key (a keyless mount keeps the legacy numbers). Meta
misses stay 60 s regardless. TENANT_TEMPLATE_TTL_MS still overrides the
template cache alone. See the repo-root docs/hooks-and-caching.md for the
whole map and why 4 h is safe — and keep one replica per deployment: a
push reaches one process,
TENANT_CACHE_DIR (default /var/cache/drop-tenant on Linux — the image
creates it owned by node, mode 0700, and the process runs with umask 077 — else the OS temp dir; an unwritable directory falls back to the temp
dir with a warning; 0/false/off reverts to in-memory caches),
SERVICE_SLOTS / TENANT_ONLY / SERVICE_SANDBOX / TENANT_SERVICES (store
services — see above),
TENANT_CACHE_RENDER_MAX_MB / TENANT_CACHE_ASSETS_MAX_MB (per-store byte
budgets for the two big slots, defaults 32 / 128),
TENANT_ASSET_MAX_OBJECT_MB (option assetMaxObjectBytes, default 16 — the
largest object a store site relays itself; a bigger one, a video or a
1 GiB download, answers /assets/** with a 302 to storage without being
read, so the fleet's RAM and disk stay flat — WebSiteAssetsOptions.maxObjectBytes),
TENANT_WARM_BOOT (default on — pre-mounts everything from
/system/tenant/list), TENANT_STATS (default on — traffic-statistics
reporting, see below; 0/false/off disables) + TENANT_STATS_FLUSH_MS
(default 15000), TENANT_CUSTOM_DOMAINS_ONLY (refuses the store hosts
under TENANT_BASE_DOMAIN, while external domains and the canonical ops host
keep working), TENANT_CERTS=probe (reports public managed-TLS reachability
without creating/removing certificates), FLY_API_TOKEN + FLY_APP_NAME
(enable Fly custom-domain certificate registration; Fly takes precedence
over probe mode). Without either provider domains still bind and serve, but
certificate status reports certs_unconfigured.
Build chain#
core-lib → sdk-js → service-host → sdk-server-js → sdk-server-tenant-js
(each npm run build; service-host is the sandbox engine drop-core-server
depends on). This package deliberately stays thin — the whole render pipeline
lives in drop-core-server; the two seams it rides on are
WebSiteOptions.reads: 'public' (site metadata via POST /public/web) and
WebPreviewServerOptions.siteOptions (per-store credential injection).