Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.trynebula.ai/llms.txt

Use this file to discover all available pages before exploring further.

The Compose deploy is the right path for air-gapped, single-VM, and POC / evaluation deployments — anywhere standing up a Kubernetes cluster is overkill or impossible. The bundle is identical regardless of which path you choose: same application binaries, same database schema, same release-contract attestations. Migrating from Compose to EKS later does not require a data re-import.

Prereqs

  • Linux host with docker (24+) and docker compose (v2.30+, ideally v2.40+ for healthcheck and profile semantics)
  • ~50 GB free disk (graph-engine WAL + compactor scratch + Postgres + RabbitMQ)
  • 16 GB RAM minimum, 32 GB recommended for production
  • At least one LLM provider key (OpenAI, Anthropic, or Azure OpenAI). For air-gapped deploys with no cloud LLM, use the compose.vllm.yaml overlay (below)
If you’re on AWS and want to back the durable state to RDS + S3 instead of running Postgres / MinIO in-stack, follow Managed AWS resources. enterprise/bootstrap.sh auto-detects which in-stack services to skip based on the *_HOST values in your .env.enterprise.

Install

tar -xzf nebula-enterprise-<version>.tar.gz
cd nebula-enterprise-<version>/
sha256sum -c checksums.txt

# Preflight: docker/compose present, default published ports free,
# disk + memory headroom.
./scripts/preflight.sh

# Side-load every pinned image; no registry pull required.
docker load -i images.tar

# Generate the secrets section of .env.enterprise (random keys, RSA
# keypair for JWT signing, MinIO root credentials).
./enterprise/generate-secrets.sh

# Edit env/.env.enterprise: populate at least one LLM provider key.
# For RDS + S3, see /enterprise/managed-resources.

# Bring everything up. Idempotent on re-run.
./enterprise/bootstrap.sh

# Verify
curl -fsS http://localhost:7272/v1/health
The bootstrap script orders the infrastructure (Postgres, MinIO, Hatchet) → migrations → token derivation → application services. Catalog-bootstrap runs Alembic, creates the pgvector extension, and applies the catalog contract. End-to-end first boot takes 2-4 minutes; subsequent re-runs are a no-op if everything is already healthy.

What runs in the stack

ServiceRoleExternalizable?
nebulaAPI + ingest pipeline
nebula-workerHatchet worker pool
graph-engineRust graph + vector store
postgresNebula application databaseYes → RDS
hatchet-postgresHatchet workflow databaseYes → RDS (same instance, separate DB)
minio + minio-initS3-compatible object storageYes → S3
hatchet-engine + hatchet-dashboardHatchet control planeNo
hatchet-rabbitmqHatchet task queueNo
See Managed AWS resources for the externalization knobs.

Air-gapped: local LLM with vLLM

For deployments with no internet egress, stack the compose.vllm.yaml overlay on top of compose.enterprise.yaml by passing --overlay to bootstrap.sh:
./enterprise/bootstrap.sh --overlay compose.vllm.yaml
Running through bootstrap.sh (rather than calling docker compose -f compose.enterprise.yaml -f compose.vllm.yaml up -d directly) is required so the in-stack postgres, hatchet-postgres, and minio services activate via COMPOSE_PROFILES — those services are profile-gated and won’t start under a raw docker compose up. The overlay runs an in-stack OpenAI-compatible vLLM server and flips every Nebula service to NEBULA_CONFIG_NAME=onprem_local, which routes all completion and embedding calls to http://vllm:8000/v1. No OPENAI_API_KEY required.
The default nebula-enterprise-<version>.tar.gz bundle does not include the vllm/vllm-openai image — it’s ~10 GB and most customers route to a cloud LLM provider (OpenAI / Anthropic / Azure) instead. Two options to obtain it:
  1. Request a vLLM-inclusive bundle from support. We can produce nebula-enterprise-<version>-vllm.tar.gz (built with bundle.sh --include-vllm) and ship it via the encrypted-delivery path. Use this for truly air-gapped hosts with no public-registry egress.
  2. Side-load the vLLM image yourself. If you have a separate host that can reach Docker Hub, pull and save the image there, transfer the tarball, and load on the air-gapped host:
    # On a connected host:
    docker pull vllm/vllm-openai:v0.20.2
    docker save -o vllm.tar vllm/vllm-openai:v0.20.2
    # Transfer vllm.tar to the air-gapped host via your usual mechanism, then:
    docker load -i vllm.tar
    
The exact vllm/vllm-openai tag the overlay expects is pinned in compose.vllm.yaml; check that file for the version to pull.
GPU prereqs: NVIDIA Container Toolkit installed on the host; a GPU with at least 24 GB VRAM for the default Qwen3-VL model.

Upgrade

# Extract the new bundle alongside the old one.
tar -xzf nebula-enterprise-<new-version>.tar.gz
cd nebula-enterprise-<new-version>/

# Reuse the existing env file (your secrets carry forward).
cp ../nebula-enterprise-<old-version>/env/.env.enterprise env/
cp -R ../nebula-enterprise-<old-version>/secrets/ ./

# Load new images.
docker load -i images.tar

# Update NEBULA_VERSION in env/.env.enterprise to the new version.
# Re-run bootstrap; it picks up the new image tags.
./enterprise/bootstrap.sh
Single-host restart; ~30s downtime on the API tier while pods cycle. Catalog-bootstrap re-runs Alembic to apply any new migrations before the API is back in service.

Stopping the stack

# Keep state (volumes preserved):
docker compose -f compose.enterprise.yaml down

# Wipe state (volumes deleted — data loss):
docker compose -f compose.enterprise.yaml down -v

Troubleshooting

enterprise/generate-secrets.sh didn’t run, or env/.env.enterprise is missing the secrets section. Re-run ./enterprise/generate-secrets.sh ./env/.env.enterprise and try again. The script refuses to overwrite an existing file, so delete it first if you intend to regenerate (warning: this rotates every secret).
The bundled pgvector/pgvector:0.8.0-pg16 image always carries the extension, so this only happens if you’ve pointed at an external Postgres that doesn’t have pgvector enabled. On RDS, add vector to rds.extensions in the parameter group; on a vanilla Postgres, install the extension package on the server.
For in-stack MinIO: check that AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in .env.enterprise match MINIO_ROOT_USER and MINIO_ROOT_PASSWORD. generate-secrets.sh populates all four to the same value; if you edited any of them manually, restore the match.
The Hatchet engine takes 30-60s to fully start after migrations. Wait for docker compose -f compose.enterprise.yaml logs -f hatchet-engine to show successfully booted, then refresh.