Skip to main content

Self-Hosted Proxy

Self-hosted mode runs the same knoxcall/proxy Docker image on your infrastructure. Live API traffic — request bodies, response bodies, injected secrets — stays entirely within your VPC. Only routing metadata, tenant config, and re-encrypted secrets flow from the control plane over TLS.
Requires an Enterprise subscription with byoAgentEnabled (the same flag gates the Go Agent). Reach out if you need to pilot — we can provision a sandbox agent.

Why Self-Host

  • Data-residency regulation: HIPAA, FedRAMP-adjacent, EU-residency, sovereign-cloud contracts that require payload data to stay on-prem.
  • Air-gapped environments: systems without outbound internet except to a single control-plane endpoint.
  • Latency-sensitive workloads: proxy sits in the same VPC as your apps and upstream APIs.
  • Compliance audits: every byte of customer data remains under your audit log.

How It Works

  • Control plane at knoxcall.com holds route config and MASTER_KEY-wrapped secrets.
  • Your container pulls a signed session bundle every hour.
  • Request flow: your app → knoxcall/proxy (your infra) → upstream API. Control-plane hop only happens during session-bundle refresh.

Prerequisites

  1. Credentials: create a server-mode agent under Automation → Agents with mode: server. Copy the kc_agent_xxx ID and secret (shown only once).
  2. Local Postgres + Redis: one of each, reachable from the container. SQLite is not supported.
  3. Local MASTER_KEY_B64: generate a 32-byte base64 key locally (openssl rand -base64 32). Do NOT share this with KnoxCall; it stays on your infrastructure and wraps integration credentials at rest.
  4. Outbound HTTPS to knoxcall.com (for session-bundle refresh + metrics reporting).
  5. Public HTTPS endpoint (typically https://proxy.yourdomain.com) behind your preferred TLS terminator.

Install

Docker Compose

Before bringing anything up, generate two strong secrets and place them in a local .env file (never commit):
Create .env alongside the compose file:
Then the compose file:
docker compose up -d, then point your TLS terminator (Caddy, Nginx, Cloudflare Tunnel, ALB) at :8080.

Health Checks

Once running, the container exposes:
  • GET /healthz — readiness probe. Returns 503 until the first control-plane sync succeeds, then 200 with sync stats. Returns 503 again if the bundle goes stale (control plane unreachable for >1 hour).
  • GET /livez — liveness probe. Always 200 while the process is responsive.
Point your orchestrator’s readiness probe at /healthz so a container with a dead control-plane link is depooled automatically.

Session Bundles

Every hour the container POSTs to /agent/v1/session with its agent credentials and receives a bundle containing:
  • Routes merged with their production-environment config
  • Secrets re-encrypted with an HKDF-derived session key (decrypts locally)
  • Tenant metadata (slug)
  • Environments and API keys
The session key never leaves the container. The MASTER_KEY_B64 on the control plane is never sent — secrets are re-encrypted per-window so even a packet capture during refresh yields nothing useful past the current hour.

Field actions are not available on a self-hosted proxy

A route configured with Relay field actions (tokenize, detokenize, encrypt, decrypt on selected JSON fields) is refused by a self-hosted container, with 503 and "code": "relay_unavailable". It is not served with the transform skipped. Field actions resolve against the vault and ECDH key material held by the control plane, so a container cannot execute one. Forwarding the request anyway would send the exact value the action exists to remove — a card number, a national ID — upstream in the clear, and answer the upstream’s normal 200. Refusing is the only safe answer, and each refusal writes an audit row and pages KnoxCall operations. If you need field actions on a route today, serve that route from the KnoxCall cloud data plane. Routes without field actions are unaffected.
Adding a field action to a route that a self-hosted container serves takes that route out of service on that container from the next hourly bundle refresh. Remove the action to restore it.

Local Integrations

The control plane never pushes KnoxCall’s own integration credentials (SMTP, Twilio, S3, Anthropic) to a self-hosted container. You configure your own under Settings → Integrations. Required minimum for a functional self-hosted deployment:
  • Email provider — otherwise alerts, invitations, and password resets fail silently.
Optional:
  • S3 — for response-body archival
  • Anthropic — for AI anomaly detection on your alerts
  • Twilio — for SMS alerts

Tamper Seal

Every knoxcall/proxy image is built with a two-pass build_sig:
  1. Compile the image with a placeholder signature.
  2. Hash the compiled dist/ contents.
  3. HMAC-SHA256 of hash:version with a CI-only secret.
  4. Rebuild with the real signature baked in.
The control plane validates this on every session refresh. In strict mode (KNOXCALL_STRICT_TAMPER_CHECK=true), an unknown signature = session refused. Default mode logs a tamper event but still issues the session so you have time to investigate.

Next Steps