Skip to main content

FrootAI — AmpliFAI your AI Ecosystem Get Started

FAI Orchard — Self-Host Guide

FAI Orchard — Self-Host Guide

Run the same v1.0 MCP server you'd get from npm or PyPI as a signed, multi-arch Docker image. Air-gap friendly. Supply-chain hardened. Multi-region tenancy supported.

ℹ️ TL;DR: `docker pull ghcr.io/frootai/mcp-orchard:1.0.0` and run. Image is non-root, HEALTHCHECK-wired, multi-arch, cosign-signed, with CycloneDX SBOM + SLSA L3 provenance attached.


§1 — Pull and verify

```bash docker pull ghcr.io/frootai/mcp-orchard:1.0.0

Verify the cosign keyless OIDC signature (always pin to image@digest):

cosign verify ghcr.io/frootai/mcp-orchard:1.0.0 \ --certificate-identity-regexp 'https://github.com/frootai/frootai/.github/workflows/publish-orchard-docker.yml@refs/tags/orchard-v.*-mcp$' \ --certificate-oidc-issuer https://token.actions.githubusercontent.com

Verify the CycloneDX 1.5 SBOM attestation:

cosign verify-attestation --type cyclonedx ghcr.io/frootai/mcp-orchard:1.0.0 ```

End-to-end runbook (verifies npm + PyPI + Docker + SLSA all at once):

```bash node frootai-core/scripts/orchard/verify-supply-chain.js \ --tag orchard-v1.0.0-mcp --json ```


§2 — Run

```bash docker run --rm \ -p 3000:3000 \ -e FROOTAI_REGION=us-east \ -e LOG_LEVEL=info \ ghcr.io/frootai/mcp-orchard:1.0.0 ```

SettingValue
BaseAlpine (multi-stage)
Usernon-root (UID 1001)
Port3000 (`EXPOSE 3000`)
HealthcheckNode built-in fetch on `/health` every 30s
Architectures`linux/amd64`, `linux/arm64`
Image size< 80 MiB (no `npm install` at runtime)

§3 — Health endpoint contract

`GET /health` returns:

```json { "status": "ok", "draining": false, "in_flight": 0, "started_at": "2026-05-28T10:00:00Z", "version": "1.0.0", "region": "us-east" } ```

During graceful shutdown (`SIGTERM`), the server enters `draining: true` state and `/health` returns `503` with a `Retry-After` header so rolling deploys land cleanly. The drain window is configurable via `closeGraceful({drainMs})` in code or `FROOTAI_DRAIN_MS` env var.


§4 — Multi-region tenancy

Pin a region at startup via `FROOTAI_REGION`:

RegionValue
US East`us-east` (default)
EU West`eu-west`
Asia Pacific South`ap-south`

Cross-region READ requires the `cross-region:read` entitlement (auto-granted to enterprise tier). Cross-region WRITE is locked to DENY even with maximal entitlements — enforced as a test invariant.


§5 — Rate-limiter backend (Redis adapter)

The default in-memory limiter is fine for single-instance deployments. For multi-instance (load-balancer behind a fleet), wire the Redis adapter:

```bash docker run --rm \ -p 3000:3000 \ -e FROOTAI_RATE_LIMITER_BACKEND=redis \ -e FROOTAI_REDIS_URL=redis://your-redis:6379 \ ghcr.io/frootai/mcp-orchard:1.0.0 ```

The adapter is generic (RESP-2 wire protocol). Tested against `ioredis`, `@upstash/redis` (with the RESP-2 shim), and an in-process RESP-2 stub for CI.


§6 — Audit-log export to customer-owned bucket

For enterprise tier, audit-log segments compact atomically and export to your S3, Azure Blob, or local FS bucket:

```bash docker run --rm \ -p 3000:3000 \ -e FROOTAI_AUDIT_BACKEND=s3 \ -e FROOTAI_AUDIT_S3_BUCKET=my-bucket \ -e FROOTAI_AUDIT_S3_REGION=us-east-1 \ -e AWS_ACCESS_KEY_ID=... \ -e AWS_SECRET_ACCESS_KEY=... \ ghcr.io/frootai/mcp-orchard:1.0.0 ```

Hive-partitioned object keys: `<bucket>/region=<R>/tenant=<T>/dt=<YYYY-MM-DD>/segment-<NNN>.jsonl`. SHA-256 manifests verify against actual file bytes — manifest spoofing is detectable.


§7 — Telemetry pipeline

Errors are sampled at `FROOTAI_TELEMETRY_SAMPLE_RATE` (default `0.1`) and shaped for the Slack webhook on the alert path. Set `DO_NOT_TRACK=1` to suppress every event (hard override).


§8 — Verify it's running

```bash curl http://localhost:3000/health ```

Should return `{ "status": "ok", ... }`.