Air-Gapped / Offline Deployment
Eparch is designed to run inside a regulated or classified boundary with no outbound network access. Nothing in the running system needs to reach the public internet.
Why it works with zero egress
| Concern | Default (SaaS) | Air-gapped setting |
|---|---|---|
| User login | WorkOS AuthKit (external) | AUTH_MODE=local — built-in email/password, no external IdP |
| Model inference | managed model gateway | self-hosted vLLM / Ollama / TGI on your network |
| State | Postgres, Redis, MinIO | all self-hosted (bundled) |
| Authorization | OPA (self-hosted) | bundled |
| Container images | pulled at deploy time | pre-loaded from the offline bundle |
There is no telemetry phone-home. OTEL_EXPORTER_OTLP_ENDPOINT is empty by
default; set it only to an OTLP collector inside your boundary.
1. Build the image bundle (on a connected host)
scripts/airgap-bundle.sh build ./airgap-bundle
This pulls the runtime dependency images (Postgres/pgvector, Redis, MinIO, OPA,
golang-migrate), builds the Eparch monolith + identity images, and writes a
single compressed tarball plus a manifest.txt and SHA-256 checksum.
2. Transfer
Move ./airgap-bundle/ across your air-gap boundary by whatever means your
environment allows (removable media, one-way diode, review gateway). Verify the
checksum on arrival:
cd airgap-bundle && sha256sum -c eparch-airgap-images.tar.sha256
3. Load + run (on the air-gapped host)
scripts/airgap-bundle.sh load airgap-bundle/eparch-airgap-images.tar.gz
cp deploy/.env.example deploy/.env
# Edit deploy/.env:
# - keep AUTH_MODE=local
# - set POSTGRES_PASSWORD / EPARCH_APP_PASSWORD / EPARCH_SECRET_KEY / JWT_RSA_PRIVATE_KEY
# - point LLM_GATEWAY_URL / LLM_EMBEDDING_URL at your in-boundary model server
docker compose -f deploy/docker-compose.monolith.yml --env-file deploy/.env up -d
The first user to register (via the UI or POST /auth/local/register) becomes
the tenant admin.
4. The model server (your responsibility)
The bundle does not include model weights — pre-stage those with your serving engine inside the boundary. Any OpenAI-compatible endpoint works:
- vLLM:
python -m vllm.entrypoints.openai.api_server --model /models/llama-3.3-70b→LLM_GATEWAY_URL=http://vllm:8000/v1/chat/completions - Ollama:
ollama servewith pre-pulled models →LLM_GATEWAY_URL=http://ollama:11434/v1/chat/completions
Register the exact model names you serve with LLM_MODELS (see
model-providers.md). An in-boundary model server on a
trusted network needs no upstream auth — leave LLM_API_KEY empty.
5. Updates
Rebuild the bundle on a connected host when a new Eparch version is released,
transfer it, load, then follow the upgrade steps in
operations.md (pull → run migrations job → restart).
Air-gap checklist
-
AUTH_MODE=local(no WorkOS egress) -
LLM_GATEWAY_URL/LLM_EMBEDDING_URLpoint at an in-boundary model server -
OTEL_EXPORTER_OTLP_ENDPOINTempty, or an in-boundary collector -
WORKOS_*unset - All images loaded from the bundle (
docker images | grep -E 'eparch|pgvector|opa') - Model weights staged with your serving engine