SterlingIndex Docs

Topology and Environments

Local and production deployment topology, domain mapping, and environment contracts for SterlingIndex.

SterlingIndex is deployed as a split system: independent frontend apps at the edge, and a shared backend runtime that owns data access, auth sessions, background work, and runtime dependencies.

The checked-in topology is defined by two repo-visible layers:

  • infra/docker-compose.local.yml for the current monorepo's local backend and stateful services
  • infra/vps/* for the current production-oriented single-host backend baseline

The repo also keeps a Kubernetes reference layer:

  • infra/k8s/* for a heavier future multi-node backend shape

Repo-visible secret management now has a third layer:

  • INFISICAL.md for the recommended Infisical project layout, path mapping, local CLI workflow, and Vercel/Cloudflare sync model

Topology Summary

Local development
browser
  |- apps/www (Next.js, :3000)
  |- apps/dashboard (Vite, :8080)
  |- apps/admin-desktop (Electron admin renderer :3001, local API :13000)
  |- apps/admin-mcp (stdio MCP server, local API :13000 when started)
  |- apps/legacy-admin (legacy Vite reference, :3001)
  |- apps/docs (Next.js, :3001 when run separately)
  `- services/platform-api API (:8000)
          |- Postgres
          |- Redis
          |- MinIO
          |- Ollama
          |- mock DROP API
          |- Celery worker (`scrape-cloud,validation-publish,compliance`)
          `- scheduler tick (`python -m rosterscraper.scheduler_tick`)

optional macOS scrape node
  `- Celery worker (`scrape-local`) against cloud/local Postgres, Redis, and R2-compatible storage

Production baseline
www.sterlingindex.com        dashboard.sterlingindex.com
docs.sterlingindex.com       active admin: macOS Electron
             \                 |                 /
              \                |                /
                 api.sterlingindex.com
                          |
          Cloudflare proxy and origin cert
                          |
      Vercel / Cloudflare Pages / Contabo VPS
                          |
       nginx + Docker Compose on the VPS
                          |
        local Postgres / Redis / R2 / systemd timer
                          |
          optional macOS scrape-local worker over cloud state

Local Development Topology

The root workspace script in package.json starts four processes:

  • pnpm dev:backend -> docker compose -f infra/docker-compose.local.yml --env-file infra/.env.local.example up --build
  • pnpm dev:www -> apps/www
  • pnpm dev:dashboard -> apps/dashboard
  • pnpm dev:admin -> apps/admin-desktop

The docs app is intentionally separate and runs with pnpm dev:docs.

The workspace also exposes Infisical-backed equivalents:

  • pnpm dev:infisical for the main local stack
  • pnpm dev:admin:infisical for the Electron admin with the /apps/admin-desktop secret path
  • pnpm dev:docs:infisical for the docs app alone

The old hosted admin is intentionally outside the active admin path. Use pnpm dev:legacy-admin, pnpm build:legacy-admin, or pnpm test:legacy-admin only when you are checking the retained reference app.

The MCP admin server is also outside the default root pnpm dev script. Use pnpm --dir apps/admin-mcp build and configure an MCP client to launch apps/admin-mcp/dist/index.js, or use pnpm --dir apps/admin-mcp start for local development.

Compose-backed services

ServiceDefault host portPurposeSource of truth
postgres5432Primary relational store for app datainfra/docker-compose.local.yml, infra/.env.local.example
redis6379Queue broker and cacheinfra/docker-compose.local.yml, infra/.env.local.example
minio9000 (9001 console)Local object storage for artifactsinfra/docker-compose.local.yml, infra/.env.local.example
ollama11434Local-first LLM host for backend workflowsinfra/docker-compose.local.yml, infra/.env.local.example
mock-drop-api18081Fixture-backed compliance service for local verificationinfra/docker-compose.local.yml
migratenoneApplies migrations before long-running services start, and optionally seeds demo datainfra/docker-compose.local.yml
api8000FastAPI runtime for sessions, bootstrap data, and platform endpointsinfra/docker-compose.local.yml
workernoneCelery worker consuming scrape-cloud,validation-publish,compliance queues for the default local stackinfra/docker-compose.local.yml
schedulernoneOne-shot scheduler tick container that runs recurring dispatch logic and exitsinfra/docker-compose.local.yml

Optional local scrape node

Hybrid staging and production can attach a separate macOS worker outside Compose:

  • command baseline: pnpm --dir services/platform-api dev:worker:local
  • queue contract: consumes scrape-local only
  • state contract: points at the shared DATABASE_URL, REDIS_URL, OBJECT_STORAGE_*, and ATTORNEY_MEDIA_*
  • model/browser contract: can use local OLLAMA_HOST, LMSTUDIO_BASE_URL, and native macOS browser automation without forcing those dependencies onto the hosted API

This worker is optional capacity, not required infrastructure. If it is offline, the hosted platform can continue routing ad hoc runs to scrape-cloud.

Frontends outside Compose

SurfaceLocal defaultHow it is configuredNotes
Marketing site (apps/www)http://localhost:3000/apps/www/package.json, apps/www/next.config.tsDeploys at the root marketing origin and hands authenticated traffic off to the dashboard host.
Dashboard (apps/dashboard)http://localhost:8080apps/dashboard/vite.config.ts, apps/dashboard/src/main.tsxReads VITE_PLATFORM_API_URL, defaulting to http://localhost:8000.
Admin (apps/admin-desktop)http://localhost:3001 renderer, http://127.0.0.1:13000 local APIapps/admin-desktop/vite.renderer.config.ts, apps/admin-desktop/src/main/main.tsActive Electron admin with desktop bridge, local API supervision, and scrape-local worker controls.
Admin MCP (apps/admin-mcp)stdio MCP server, http://127.0.0.1:13000 local API when startedapps/admin-mcp/src/index.ts, packages/admin-runtime/src/runtime-manager.tsNon-visual operator adapter for Codex/Claude-style clients. Connection is inert until a start/repair or ensure_runtime workflow call.
Legacy admin (apps/legacy-admin)http://localhost:3001apps/legacy-admin/vite.config.ts, apps/legacy-admin/src/components/admin-auth-gate.tsxLegacy hosted reference app only.
Docs (apps/docs)http://localhost:3001/docsapps/docs/package.json, apps/docs/src/lib/site.tsRuns independently from the root pnpm dev script. Its default port overlaps the admin app, so only one can keep 3001 without a local override.

Local environment contract

infra/.env.local.example is the checked-in coordination point for the workspace-level local stack. It defines:

  • stateful services: POSTGRES_*, REDIS_PORT, MINIO_PORT, MINIO_CONSOLE_PORT
  • backend runtime URLs: DATABASE_URL, INTEL_DATABASE_URL, CORE_DATABASE_URL, REDIS_URL, OLLAMA_HOST, LMSTUDIO_BASE_URL
  • orchestration mode and scrape targeting: ORCHESTRATION_EXECUTION_MODE, SCRAPE_EXECUTION_TARGET_DEFAULT
  • worker identity and queue advertisement: SCRAPE_NODE_ROLE, SCRAPE_NODE_LABEL, SCRAPE_NODE_PLATFORM, SCRAPE_NODE_ADVERTISED_QUEUES
  • public app URLs consumed by the backend: APP_PUBLIC_WWW_URL, APP_PUBLIC_DASHBOARD_URL, APP_PUBLIC_ADMIN_URL, APP_PUBLIC_API_URL
  • frontend runtime URLs: VITE_PLATFORM_API_URL, VITE_CONTROL_PLANE_URL, NEXT_PUBLIC_DASHBOARD_URL, NEXT_PUBLIC_DOCS_BASE_URL
  • auth/session defaults: AUTH_PROVIDER, WORKOS_*, CORS_ALLOWED_ORIGINS, SESSION_COOKIE_NAME, SESSION_COOKIE_DOMAIN, SESSION_COOKIE_SECURE
  • observability inputs: APP_RELEASE, MONITORING_SENTRY_DSN, MONITORING_SENTRY_TRACES_SAMPLE_RATE, NEXT_PUBLIC_APP_ENV, NEXT_PUBLIC_APP_RELEASE, NEXT_PUBLIC_SENTRY_DSN, NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE, NEXT_PUBLIC_POSTHOG_KEY, NEXT_PUBLIC_POSTHOG_HOST, VITE_APP_ENV, VITE_APP_RELEASE, VITE_SENTRY_DSN, VITE_SENTRY_TRACES_SAMPLE_RATE, VITE_SENTRY_REPLAY_SESSION_SAMPLE_RATE, VITE_SENTRY_REPLAY_ON_ERROR_SAMPLE_RATE, VITE_POSTHOG_KEY, VITE_POSTHOG_HOST
  • security, storage, and media settings: OBJECT_STORAGE_*, ATTORNEY_MEDIA_*, VITE_TURNSTILE_SITE_KEY, VITE_OPENFREEMAP_COMPACT_STYLE_URL, VITE_OPENFREEMAP_IMMERSIVE_STYLE_URL, SECURITY_TURNSTILE_SECRET_KEY, PRODUCT_DEMO_SEED_ENABLED

The docs app keeps its own .env.example because it publishes docs-site metadata from NEXT_PUBLIC_DOCS_BASE_URL and the shared dashboard-login handoff from NEXT_PUBLIC_DASHBOARD_URL.

Secrets source of truth

The repo-level recommendation is now:

  • use Infisical as the source of truth for local and hosted secrets,
  • sync apps/www and apps/docs public env vars into Vercel,
  • sync apps/dashboard env vars into Cloudflare Pages,
  • keep active admin env values under the /apps/admin-desktop Infisical path or import them through the desktop app's env-import workflow,
  • import Admin MCP env bundles through sterling_runtime_import_env_bundle; the cache is encrypted under ~/Library/Application Support/Sterling Admin MCP/ unless plaintext cache is explicitly enabled for tests,
  • sync apps/legacy-admin to Cloudflare Pages only if you intentionally deploy the reference web admin,
  • use Infisical machine identities for the API, worker, and scheduler where possible.

The checked-in operating guide for that model is INFISICAL.md.

Production-oriented Topology

The checked-in deployment runbook now treats infra/vps as the primary production backend path and keeps the frontend apps as independent deployments:

  • apps/www on Vercel
  • apps/docs on Vercel for docs.sterlingindex.com
  • apps/dashboard on Cloudflare Pages
  • apps/admin-desktop as the packaged Electron control room for operators
  • apps/admin-mcp as a local stdio MCP control surface for agent-assisted operators
  • apps/legacy-admin retained as a reference Vite app, not a default deploy target
  • services/platform-api plus worker, scheduler, Postgres, and Redis on a single Contabo VPS

VPS baseline

AssetResponsibilityKey details
infra/vps/docker-compose.ymlRuntime stackRuns nginx, api, worker, scheduler, postgres, redis, and a one-shot migrate job.
infra/vps/nginx/api.sterlingindex.com.confPublic ingressTerminates TLS with a Cloudflare Origin Certificate and proxies to the internal api:8000 service.
infra/vps/systemd/sterlingindex-platform.serviceHost orchestrationBoots the full Compose stack under systemd and keeps it alive across reboots.
infra/vps/systemd/sterlingindex-postgres-backup.timerBackup scheduleRuns nightly Postgres dumps to Cloudflare R2.
infra/vps/scripts/bootstrap-host.shHost bootstrapInstalls Docker, Compose, ufw, and fail2ban on Ubuntu 24.04.

Operationally, that means the repo-visible production backend is now:

  • Cloudflare proxy in front of api.sterlingindex.com
  • Nginx on the VPS listening on 80/443
  • FastAPI, worker, scheduler tick loop, Postgres, and Redis on an internal Docker network
  • Cloudflare R2 retained for object storage and media
  • Infisical machine identity used to inject backend runtime secrets

Kubernetes reference baseline

The Kubernetes manifests remain useful as a future multi-node reference, but they are no longer the default deployment story for the current production path.

ManifestResponsibilityKey details
infra/k8s/namespace.yamlNamespace boundaryCreates the sterlingindex namespace.
infra/k8s/configmap.example.yamlShared non-secret configDeclares public app domains, database URLs, Redis URL, and session cookie settings.
infra/k8s/configmap.example.yaml (Secret block)Sensitive config placeholdersHolds WORKOS_*, object storage credentials, MONITORING_SENTRY_DSN, SKILL_SIGNING_KEY, CPPA_API_KEY, and SUPPRESSION_ENCRYPTION_KEY.
infra/k8s/platform-api.yamlAPI deployment and serviceRuns uvicorn rosterscraper.api.app:app with 2 replicas and exposes a service on port 80 -> 8000.
infra/k8s/workers.yamlBackground workloadsRuns a platform-worker deployment with 2 replicas and a minutely platform-scheduler-tick CronJob.
infra/k8s/ingress.example.yamlPublic ingressRoutes api.sterlingindex.com to the platform-api service and terminates TLS.

Production domain map

SurfaceProduction hostnameRepo evidence
Marketing sitehttps://www.sterlingindex.cominfra/k8s/configmap.example.yaml
Docs apphttps://docs.sterlingindex.cominfra/k8s/configmap.example.yaml, infra/k8s/README.md
Dashboardhttps://dashboard.sterlingindex.cominfra/k8s/configmap.example.yaml
Active adminPackaged macOS Electron app pointed at the control-plane APIapps/admin-desktop/package.json, apps/admin-desktop/src/main/main.ts, apps/admin-desktop/vite.renderer.config.ts
Admin MCPLocal stdio MCP server pointed at the MCP-managed local control-plane APIapps/admin-mcp/package.json, apps/admin-mcp/src/index.ts, packages/admin-runtime/src/runtime-manager.ts
Legacy admin referencehttps://admin.sterlingindex.com only if manually retained as a hosted referenceinfra/k8s/configmap.example.yaml, apps/legacy-admin
APIhttps://api.sterlingindex.cominfra/k8s/configmap.example.yaml, infra/k8s/ingress.example.yaml

Neither the VPS bundle nor the Kubernetes reference includes manifests for the frontend hosts themselves, so the repo-visible production picture remains "independent frontend deployments pointed at one shared API origin."

The repo now also includes infra/cloudflare/README.md, which is the checked-in runbook for the intended public edge shape:

  • proxy www.sterlingindex.com, dashboard.sterlingindex.com, and api.sterlingindex.com through a single Cloudflare zone
  • enable the free-plan baseline for DDoS mitigation, Bot Fight Mode, and targeted WAF/rate-limit rules
  • keep the api origin proxied to the Contabo VPS behind Nginx and a Cloudflare Origin Certificate
  • keep origin-specific headers and build-time sourcemap behavior in the app repos, because Cloudflare config itself remains an external deployment concern

At the secret-management layer, hosted frontends are expected to receive environment values through Infisical Secret Syncs rather than ad hoc manual editing inside each platform dashboard.

Shared Environment Variables

The environment contract is split by responsibility rather than by app.

Public origin and redirect settings

VariableUsed byWhy it matters
APP_PUBLIC_WWW_URLbackend runtimeCanonical marketing host used by the platform runtime.
APP_PUBLIC_DASHBOARD_URLbackend runtimeCanonical dashboard origin used in auth and link generation.
APP_PUBLIC_ADMIN_URLbackend runtimeCanonical admin origin for control-plane redirects and links.
APP_PUBLIC_API_URLbackend runtimeCanonical API origin surfaced to app consumers and callbacks.
APP_ENVbackend runtime and observabilityAligns backend environment tagging with frontend deploy environments.
APP_RELEASEbackend runtime and observabilityShared release identifier used to correlate frontend and backend deploys.
NEXT_PUBLIC_DASHBOARD_URLapps/www, apps/docsPublic-site login flows link users into the dashboard sign-in handoff.
NEXT_PUBLIC_APP_ENVapps/wwwMarketing-side environment tagging for Sentry and PostHog.
NEXT_PUBLIC_APP_RELEASEapps/wwwMarketing-side release tagging and sourcemap naming.
NEXT_PUBLIC_SENTRY_DSNapps/wwwEnables lean public-site Sentry capture.
NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATEapps/wwwKeeps marketing traces under free-plan limits.
NEXT_PUBLIC_POSTHOG_KEYapps/wwwEnables anonymous marketing analytics in PostHog.
NEXT_PUBLIC_POSTHOG_HOSTapps/wwwSelects the PostHog ingestion host.
NEXT_PUBLIC_DOCS_BASE_URLapps/docsSets docs metadata/canonical origin for docs.sterlingindex.com.
APP_PUBLIC_DOCS_URLapps/docsFallback name supported by apps/docs/src/lib/site.ts.
VITE_PLATFORM_API_URLapps/dashboardDashboard fetches session and bootstrap data from the shared API.
VITE_APP_ENVapps/dashboard, apps/admin-desktop, apps/legacy-adminFrontend environment tagging for authenticated Vite/Electron-renderer surfaces.
VITE_APP_RELEASEapps/dashboard, apps/admin-desktop, apps/legacy-adminFrontend release tagging and sourcemap naming for authenticated Vite/Electron-renderer surfaces.
VITE_SENTRY_DSNapps/dashboard, apps/admin-desktop, apps/legacy-adminEnables browser-side Sentry capture for authenticated Vite/Electron-renderer surfaces.
VITE_SENTRY_TRACES_SAMPLE_RATEapps/dashboard, apps/admin-desktop, apps/legacy-adminControls browser trace volume for authenticated Vite/Electron-renderer surfaces.
VITE_SENTRY_REPLAY_SESSION_SAMPLE_RATEapps/dashboardKeeps replay sampling conservative on the free plan.
VITE_SENTRY_REPLAY_ON_ERROR_SAMPLE_RATEapps/dashboardCaptures replay context on error while still biasing volume downward.
VITE_POSTHOG_KEYapps/dashboardEnables identified product analytics in PostHog.
VITE_POSTHOG_HOSTapps/dashboardSelects the PostHog ingestion host.
VITE_TURNSTILE_SITE_KEYapps/dashboardReserved frontend site key for future login hardening.
VITE_OPENFREEMAP_COMPACT_STYLE_URLapps/dashboardOptional override for the default OpenFreeMap Positron style used by compact city maps.
VITE_OPENFREEMAP_IMMERSIVE_STYLE_URLapps/dashboardOptional override for the default OpenFreeMap Positron style used by immersive city maps.
VITE_CONTROL_PLANE_URLapps/admin-desktop, apps/legacy-admin, and legacy services/platform-api/apps/webThe active desktop renderer defaults to http://127.0.0.1:13000; reference web shells can point at an explicit control-plane API origin.
STERLING_REPO_ROOTapps/admin-mcp, packages/admin-runtimeRepo root used by the MCP runtime to find services/platform-api and workspace paths.
STERLING_MCP_DATA_DIRapps/admin-mcp, packages/admin-runtimeOptional override for the MCP data, log, and env-cache directory.
STERLING_MCP_BACKEND_DIRpackages/admin-runtimeOptional override for the backend working directory. Defaults to services/platform-api.
STERLING_MCP_PYTHONpackages/admin-runtimePython executable used to start uvicorn and Celery.
STERLING_MCP_ALLOW_PLAINTEXT_ENV_CACHEpackages/admin-runtimeTest/dev escape hatch for plaintext env cache. Do not enable for real operator use.
STERLING_MCP_API_HOST, STERLING_MCP_API_PORTpackages/admin-runtimeManaged local API bind target. Defaults to 127.0.0.1:13000.
MONITORING_SENTRY_DSNbackend runtimeEnables API-side Sentry reporting.
MONITORING_SENTRY_TRACES_SAMPLE_RATEbackend runtimeControls API-side trace volume.
SECURITY_TURNSTILE_SECRET_KEYbackend runtimeReserved server-side secret for future Turnstile verification.

State, storage, and runtime dependencies

Variable groupUsed byRepo-visible default
DATABASE_URL, INTEL_DATABASE_URL, CORE_DATABASE_URLAPI, migrations, worker, scheduler tickLocal defaults point at the local Compose postgres container; VPS production points at the host-local postgres service.
REDIS_URLAPI, worker, scheduler tickLocal defaults point at the local Compose redis container; VPS production points at the host-local redis service.
OBJECT_STORAGE_*, ATTORNEY_MEDIA_*API, migrations, worker, scheduler tickLocal default targets MinIO; production baseline keeps Cloudflare R2 and public media credentials.
ORCHESTRATION_EXECUTION_MODE, SCRAPE_EXECUTION_TARGET_DEFAULTAPI, worker, scheduler tickDefault local mode is inline; hosted staging/prod can switch to queued orchestration with auto, cloud, or local targeting.
SCRAPE_NODE_ROLE, SCRAPE_NODE_LABEL, SCRAPE_NODE_PLATFORM, SCRAPE_NODE_ADVERTISED_QUEUESworker, runtime readinessIdentifies whether a node is the hosted worker or an optional macOS scrape node and which queues it can claim.
OLLAMA_HOST, LMSTUDIO_BASE_URL, OPENROUTER_API_KEY, OPENAI_COMPATIBLE_*API, worker, migrations, active admin settingsInternal LLM routing can use local Ollama/LM Studio, OpenRouter, or a bring-your-own OpenAI-compatible endpoint; the admin settings UI keeps these separate from managed execution providers.
BROWSER_USE_API_KEY, Browser Use Agent settings, browser-use-cloud browser settingsAPI, worker, active admin settingsEnables Browser Use diagnostics, the remote CDP browser engine, and Browser Use Agent managed execution when explicitly selected. Budget, timeout, proxy, profile, recording, and cached-rerun controls are stored in control-plane settings.
CPPA_DROP_API_URL, CPPA_MOCK_MODE, CPPA_API_KEYAPI and workersSwitch between fixture-backed local compliance flows and live CPPA integrations.
SKILL_SIGNING_KEY, SUPPRESSION_ENCRYPTION_KEYAPI and workersSigning and encryption keys required by backend flows.

Session and cross-origin assumptions

  • Local Compose defaults use SESSION_COOKIE_DOMAIN=localhost.
  • The VPS production baseline switches to SESSION_COOKIE_DOMAIN=.sterlingindex.com and SESSION_COOKIE_SECURE=true so one product/auth session can span www, dashboard, and api subdomains. The active Electron admin still uses the control-plane admin session against its configured API origin.
  • services/platform-api/src/rosterscraper/config.py checks in localhost defaults, but CORS_ALLOWED_ORIGINS can now be supplied as a comma-separated list or JSON array for production origins such as www, dashboard, and admin.
  • In hosted mode, ad hoc discovery and run requests can resolve execution_target=auto to scrape-local when a healthy macOS node is advertising that queue; otherwise they fall back to scrape-cloud. Scheduled jobs stay cloud-oriented by default.

Secret ownership assumptions

  • Frontend-only public build vars such as NEXT_PUBLIC_* and VITE_* should live in app-specific Infisical paths.
  • Shared backend secrets such as WORKOS_*, SESSION_COOKIE_*, DATABASE_URL, REDIS_URL, and OBJECT_STORAGE_* should live in shared runtime paths and be imported into API/worker/scheduler scopes.
  • Build-only sourcemap credentials such as SENTRY_AUTH_TOKEN, SENTRY_ORG, and project-name overrides should stay separate from runtime secrets so frontend deploys can read them without widening backend access.

Verification and Operational Notes

  • services/platform-api/scripts/run_local_verification.py treats infra/docker-compose.local.yml as the shared dependency stack and exports host-side DATABASE_URL, REDIS_URL, OBJECT_STORAGE_*, and app URL variables before running backend and frontend verification.
  • services/platform-api/docs/local-verification.md documents an additional collision-resistant smoke path for the legacy embedded web shell on localhost:13000; that shell is useful for backend verification but is not part of the primary monorepo deployment picture.
  • DEPLOY.md is the current repo-level runbook for the split hosted stack, the VPS backend bundle, the scheduler tick loop, and the optional macOS scrape node that writes directly into the shared cloud state.
  • INFISICAL.md is the repo-level runbook for the Infisical project shape, path mapping, CLI workflow, and Vercel/Cloudflare Secret Sync setup.
  • infra/cloudflare/README.md is the repo-visible runbook for Cloudflare proxy, WAF/rate-limit, and Bot Fight Mode rollout across www, dashboard, and api.
  • infra/vps/README.md is the checked-in host runbook for Docker Compose, Nginx, systemd, Cloudflare Origin Certificates, and nightly Postgres backups to R2.
  • The docs site itself is verified with the workspace-level scripts: pnpm build:docs, pnpm lint:docs, and pnpm typecheck:docs.

On this page