§ DOCUMENTATION
Self-hosted deployment
Run the full Execlave governance platform on your own infrastructure using the published Docker images and a license key. Your data never leaves your network — the only thing that crosses the boundary is a license heartbeat (a fingerprint and a timestamp, no customer data).
Data privacy: no external AI API calls by default
The default self-hosted deployment sends zero prompts, traces, or model inputs to any external AI provider. Semantic classification and policy generation run against a local LLM (Ollama or any OpenAI-compatible endpoint) configured via LOCAL_LLM_URL. If that endpoint is unreachable, those features gracefully degrade to deterministic heuristics — enforcement keeps working, you just lose the advisory classifications.
What this means for procurement reviews
- Prompts and traces never leave your VPC.
- No API keys for Anthropic, OpenAI, Google, or any other external LLM provider are required — or accepted — in the default configuration.
- If you want to plug in an external provider for a specific workflow (e.g. using a hosted LLM for the policy-generation UI), you are responsible for the data-transfer compliance implications.
- Optional product telemetry (PostHog, Accoil) is off by default. Leave the corresponding env vars blank to keep all analytics on-prem.
Prerequisites
- Linux host (any cloud or bare metal) with 4 CPU, 8 GB RAM minimum
- Docker 24+ and Docker Compose v2
- A PostgreSQL 15 instance — included in the compose file, or bring your own
- A Redis 7 instance — included in the compose file, or bring your own
- A license key (request one at /get-license)
- Outbound HTTPS to
license.execlave.comfor heartbeat (air-gapped mode available — see §08)
Quickstart
curl -O https://get.execlave.com/docker-compose.ymlexport LICENSE_KEY=exe_lic_<your-key>docker compose up -dopen http://localhost:3000Four commands. The stack comes up in ~45 seconds on a modern host. Log in with the admin credentials printed in the startup output, or configure Logto.
Get a license key
Free and paid self-hosted licenses are issued manually at this stage. Request one at /get-license.
- Free plan: license arrives within 1 business hour
- Paid plans: we reach out to set up payment first
- Enterprise: we book a 30-min call
The license key is a JWT signed by our license server. The same key can be used on multiple instances up to the plan's instance limit (each distinct host fingerprint counts as one instance).
Architecture
Everything runs inside your network. The only outbound traffic is the license heartbeat.
+-------------------------------------------------+| Your infrastructure || || +---------+ +---------+ +-----------+ || | Next.js |-->| Express |-->| Postgres | || | (3000) | | (4000) | | (5432) | || +---------+ +---------+ +-----------+ || | || v || +---------+ +-----------+ || | Worker |-->| Redis | || | (BullMQ)| | (6379) | || +---------+ +-----------+ || || +-------------------+ || | Processing | || | (Python/FastAPI) | || +-------------------+ |+-------------------------------------------------+ | | outbound HTTPS only (heartbeat) v+-----------------------------+| license.execlave.com || (fingerprint + timestamp) |+-----------------------------+Configuration
Required environment variables
| Variable | Description |
|---|---|
LICENSE_KEY | The JWT license key we email you |
DEPLOYMENT_MODE | Set to self-hosted (controls license-client activation) |
DATABASE_URL | PostgreSQL connection string |
REDIS_URL | Redis connection string |
LOGTO_ENDPOINT | Logto endpoint (backend) |
LOGTO_APP_ID | Logto dashboard client app ID (backend) |
LOGTO_APP_SECRET | Logto dashboard client app secret (backend) |
NEXT_PUBLIC_LOGTO_ENDPOINT | Logto endpoint (frontend) |
NEXT_PUBLIC_LOGTO_APP_ID | Logto dashboard client app ID (frontend) |
Optional environment variables
| Variable | Default | Description |
|---|---|---|
LICENSE_SERVER_URL | https://license.execlave.com/api | Override for air-gapped proxies |
LICENSE_CACHE_PATH | ~/.execlave/ | Where the license client caches the validated license |
LICENSE_HEARTBEAT_INTERVAL_MS | 86400000 | How often to check in with the license server (default 24h) |
LOCAL_LLM_URL | unset | URL for local LLM service for semantic classification + policy generation |
STRIPE_SECRET_KEY | unset | Not used in self-hosted mode |
SENTRY_DSN | unset | Optional error tracking |
License keys: how they work
The license key is a signed JWT. When your instance starts:
- Startup validation — the license client verifies the JWT signature against our public key (bundled in the image) and checks the plan, expiry, and instance limits.
- Instance registration — your instance's host fingerprint (hash of hostname + MAC + Docker-Compose project name) is registered with the license server.
- Cached offline mode — the validated license is cached locally so the instance can boot even if the license server is unreachable.
- Heartbeat — every 24 hours, the instance sends a heartbeat containing its fingerprint and a timestamp. No customer data is included.
- Grace period — if the license server is unreachable for 14 consecutive days, the instance enters grace mode and logs a warning. After 21 days, enforcement is paused pending reconnection.
{fingerprint, timestamp, license_id, version}Updating, backups, and air-gapped mode
Updating
Pull the latest images and restart:
docker compose pulldocker compose up -dDatabase migrations run automatically on startup. Always take a backup first.
Backups
Back up the Postgres volume and the license cache:
docker compose exec postgres pg_dump -U execlave execlave > backup.sqldocker cp $(docker compose ps -q backend):/root/.execlave/ ./license-cacheRestoring from a backup regenerates the host fingerprint on first boot and re-registers with the license server.
Air-gapped mode
If your environment cannot reach license.execlave.com:
- Contact us to request an offline license bundle — a JWT with a longer offline grace window (typically 1 year).
- Set
LICENSE_SERVER_URLto an internal proxy that queues heartbeats and replays them during a periodic sync window, OR - Drop heartbeat altogether with
LICENSE_HEARTBEAT_INTERVAL_MS=0if you have an offline license.
Offline bundles are gated on a signed support agreement; email support@execlave.com for details.
Troubleshooting
- Confirm
LICENSE_KEYis set correctly in the environment - Check the JWT hasn't expired:
echo $LICENSE_KEY | cut -d. -f2 | base64 -d - Verify outbound HTTPS to
license.execlave.comis allowed
- Your license plan caps the number of concurrent host fingerprints
- Delete stale instances via the license server or upgrade your plan
- This is expected during the 14-day grace period — a warning is logged
- Check
docker compose logs backend | grep -i licensefor the exact error
- The stack runs all pending migrations on boot. If a migration fails, restore from your backup and contact support.
Support
- Documentation: execlave.com/docs
- Email: support@execlave.com
- Request a license: /get-license