๐Ÿ›ก๏ธ Interven

Self-hosting

Run Interven on your own infrastructure (single-VPS docker-compose).

Most customers use the hosted SaaS at https://api.intervensecurity.com. If you need to keep traffic on-prem (regulated environment, air-gapped deploy, or you just want control), the same stack runs on a single VPS via docker-compose.

Stack

  • Gateway (Fastify, port 4000)
  • Telemetry (Fastify, port 4100, internal-only)
  • Console (Express + React, port 3100)
  • Postgres โ€” Neon hosted or local
  • Redis โ€” Upstash or local (only used for rate limiting; optional)

Quick start

git clone https://github.com/intervensecurity/aif
cd aif
cp .env.example .env
# fill in DATABASE_URL, AIF_CONSOLE_SECRET, INTERVEN_API_KEYS_ADMIN_SECRET, etc.

# apply migrations
DATABASE_URL=$(grep ^DATABASE_URL= .env | cut -d= -f2-) ./infra/fly/apply-migrations.sh

# start the stack
./infra/scripts/rolling-deploy.sh

Required env vars

VarPurpose
DATABASE_URLPostgres connection string
REDIS_URLOptional. Falls back to in-memory rate limiting (single-node only โ€” set this on multi-node deploys)
AIF_CONSOLE_SECRET32+ char hex, JWT signing key (must match across telemetry + console)
ADMIN_USER / ADMIN_PASSFirst-login bootstrap for the console
INTERVEN_API_KEYS_ADMIN_SECRETBearer for the admin /v1/keys endpoint
INTERVEN_INTERNAL_SECRETService-to-service auth between console / gateway / telemetry
INTERVEN_CREDENTIAL_ENCRYPTION_KEY64-char hex, encrypts tool credentials at rest

Generate any 32-char secret with openssl rand -hex 32. The credential encryption key needs openssl rand -hex 32 too (32 bytes = 64 hex chars).

Optional: OIDC SSO

Both Google and Microsoft OIDC are supported. Set per-provider env vars; the Console exposes the matching sign-in buttons automatically.

VarPurpose
GOOGLE_OIDC_CLIENT_ID / GOOGLE_OIDC_CLIENT_SECRETGoogle Workspace SSO
MICROSOFT_OIDC_CLIENT_ID / MICROSOFT_OIDC_CLIENT_SECRET / MICROSOFT_OIDC_TENANT_IDMicrosoft Entra ID SSO
OIDC_REDIRECT_URIMust match what you configured in the provider โ€” usually https://your-console-domain/api/auth/oidc/callback

SAML / SCIM are not implemented today โ€” on the Enterprise roadmap.

Optional: Alert channels

Multi-channel alerts route DENY / REQUIRE_APPROVAL / INCIDENT events to your team. Configure under Console โ†’ Alerts โ†’ Add channel:

  • Slack โ€” incoming webhook + signing secret (enables interactive Approve/Deny buttons)
  • Discord โ€” incoming webhook (one-way alerts)
  • Microsoft Teams โ€” incoming webhook
  • Telegram โ€” bot token + chat ID
  • SIEM โ€” HTTP webhook accepting CEF or OCSF payloads (Splunk HEC, Datadog, custom)

TLS + custom domain

Interven doesn't terminate TLS itself โ€” point Cloudflare Tunnel (or any reverse proxy) at localhost:4000 for the gateway and localhost:3100 for the console.

Rolling deploy

./infra/scripts/rolling-deploy.sh                # build + sequential restart
./infra/scripts/rolling-deploy.sh --no-build     # restart only
./infra/scripts/rolling-deploy.sh gateway        # only redeploy gateway

Each service is health-gated; the script aborts if any service fails to come up within 200 seconds.

Backups

Postgres is the only stateful component. Use whatever backup mechanism your DB provider gives you (Neon point-in-time, RDS snapshots, pg_dump cron). Tool credentials are AES-256-GCM encrypted with INTERVEN_CREDENTIAL_ENCRYPTION_KEY โ€” keep that key in a secrets manager and back it up separately from the DB.

Reference backup setup

For a single-VPS deployment the included infra/scripts/backup.sh runs a daily pg_dump to /var/backups/interven/. Off-site mirroring is up to you โ€” common options:

  • rsync over SSH to a separate machine (lowest setup; encrypt the destination).
  • Cron to S3 (aws s3 cp) with versioned + server-side-encrypted bucket.
  • Restic to any S3-compatible target with deduplication.

Test restore at least quarterly: a backup you can't restore is not a backup.

Monitoring

We recommend Sentry for error monitoring on the gateway, telemetry, and console services. Set SENTRY_DSN and SENTRY_ENVIRONMENT per service; only 5xx errors and uncaught exceptions are reported (no request bodies).