Skip to content

Deployment Overview

Nothing runs on the host. Every service is a container publishing a host port, and the Cloudflare tunnel targets that host port directly — there is no reverse proxy in the path on either estate.

graph TD
  GH[GitHub · Deployd-io<br/>push to main] -->|polled every 60s| W[deploy watcher<br/>systemd, dev VM]
  W -->|POST /api/deploy| C[management console<br/>management.logrite.ai]
  C --> B[build on the dev host]
  B --> R[registry<br/>127.0.0.1:5000]
  R --> P[pin the tag]
  P --> D[docker compose up -d]
  D --> DEV[(dev VM<br/>dev-*.logrite.ai)]
  C -.->|promote · human only| PR[(prod VM<br/>*.logrite.ai)]
  R -.->|same image, over an ssh tunnel| PR

The dotted edges are the whole difference between the estates: a push reaches dev automatically and never reaches prod. Prod moves when a person clicks Promote, which copies the image already tested on dev rather than rebuilding the commit.

One instance of each service per VM — prod and dev are separate machines, so there is no main + dev pair sharing a box. Two host ports differ from the container port, and the analyzer’s differs between estates.

ServiceproddevHost port
Frontendapp.logrite.aidev-app.logrite.ai3000
Backendleapfrogapi.deployd.iodev-leapfrogapi.logrite.ai9800 → 8080
Analyzeranalyzer.logrite.aidev-analyzer.logrite.ai9000 prod / 9001 dev
OpenSearch APIanalyticsapi.logrite.aidev-analyticsapi.logrite.ai9200 (https)
OpenSearch Dashboardsanalytics.logrite.aidev-analytics.logrite.ai5601
Semantic Searchsearch.logrite.aidev-search.logrite.ai9100
AI Serviceaiservice.logrite.aidev-aiservice.logrite.ai9300
AI Warden relaywarden.logrite.aidev-warden.logrite.ai9600
Collector ingest shimingest.logrite.aidev-ingest.logrite.ai9700
MCP Servermcp.logrite.aidev-mcp.logrite.ai9500
Webhook receiverwebhook.logrite.aidev-webhook.logrite.ai9999
Uptime trackerdowntime.logrite.aione board, both estates8765
Dev docsdevdocs.logrite.aidev-devdocs.logrite.ai3067 → 3000
JobSearchjobsearch.logrite.aidev-jobsearch.logrite.ai9081
OTEL traces / logstraces / logs.logrite.aidev- prefixed21890 / 21891

There is nothing to install to deploy — builds happen on the target host inside Docker, driven by the console. The list below is for running a service locally.

Terminal window
node --version # 20+
java --version # 17+ for the backend; 21 for OpenSearch 3.x
mvn --version # 3.8+, backend build
python3 --version # 3.10+, MCP server
docker --version # everything on both VMs is a container
gh --version && gh auth login
  • Every service repo has main and nothing else.
  • A push to main is polled by the deploy watcher and deployed to the dev host, served at dev-*.logrite.ai.
  • It is never deployed to production by a push.
  • Prod is a separate VM running the same branch.
  • It moves only when a human promotes from the management console, which copies the exact image tested on dev into prod’s registry and deploys that — so prod runs the bits that were tested, not a rebuild of the same commit.
  • Prod has no deploy key and builds nothing from source.
  • One instance per host; the two hosts do not share one.
  • Must be running before most services start.
  • start-all waits for OpenSearch health (up to 60 seconds).