Skip to main content

Migrating Between Cloud and Self-Hosted

This page covers switching a KnoxCall tenant between Cloud and self-hosted deployment modes. If you’re looking to migrate secrets from AWS Secrets Manager, Azure Key Vault, or GCP Secret Manager into KnoxCall, see the Secret Store Migrations section instead.
Switching a tenant between deployment modes is an in-place operation on tenants.deployment_mode. Cloud → self-hosted is gated by a readiness checklist; the reverse direction is always permitted.

Switch Flow

  1. Set up the self-hosted proxy on your infrastructure per the self-hosted guide. Container must be reachable over HTTPS.
  2. Configure the self-hosted proxy URL under Settings → Deployment.
  3. Run the readiness checks — all four must go green:
    • Proxy reachable (HTTPS GET /healthz returns 200)
    • Server-agent heartbeat healthy (under 2 minutes since last heartbeat)
    • Shadow tests (24h) — at least one successful, zero mismatches
    • Email provider configured (alerts, invitations, password resets)
  4. Confirm switch — the button is disabled until the checklist passes or you explicitly force it.
  5. DNS cutover — flip your client DNS from tenant.knoxcall.com to proxy.yourdomain.com. A 7-day cloud fallback is left warm in case you need to revert.

Shadow Testing

Shadow mode lets you compare the cloud and self-hosted proxies side-by-side before cutover:
  • Settings → Deployment → Shadow test fires a synthetic probe at both data planes and diffs the responses.
  • Each run is recorded in migration_diffs (30-day retention).
  • The readiness dashboard aggregates the last 24 hours of matches vs divergences.
Run several shadow tests covering the routes that matter most — auth routes, high-volume endpoints, routes with large request bodies — before flipping.
The first-cut shadow test pings /healthz on both sides. Route-level body comparison (sending the same authenticated request through both proxies and byte-diffing the response) is planned for a future release.

Readiness Gates

The “Switch to Self-hosted” button is enabled only when all of these hold: If you need to override (you’ve validated through another mechanism), the API accepts { force: true } — the UI surfaces this as a “Force switch” confirm button when readiness is red.

During Migration

Once you’ve confirmed the switch:
  • tenants.deployment_mode flips to self_hosted.
  • The cloud proxy starts returning 404 for any request addressed to this tenant.
  • Your self-hosted proxy begins answering traffic.
  • DNS change propagates (TTL-dependent — usually minutes).
  • The cloud tenant record remains so control-plane operations (managing routes, viewing analytics) continue to work.

Rolling Back

The reverse direction is one click:
  1. Settings → Deployment → Switch to KnoxCall Cloud
  2. DNS cutover from proxy.yourdomain.com back to tenant.knoxcall.com
There’s no readiness gate on the reverse switch — the cloud proxy is always available for active tenants.

Rate Limits

Shadow tests are rate-limited to 10 per minute per tenant to protect the cloud proxy and your self-hosted container from admin-triggered load. Exceeding it returns 429 with a Retry-After header.

Troubleshooting

  • Readiness check stays red despite reachable proxy: confirm the public URL is what the control plane sees. A NAT or load-balancer rewriting paths will break /healthz.
  • session_denied: tamper_detected in container logs: your knoxcall/proxy image’s build_sig isn’t in agent_versions. Pull knoxcall/proxy:latest and restart.
  • Alerts stopped after cutover: check Settings → Integrations → Email. The self-hosted container doesn’t inherit the cloud’s email provider — you must configure your own.
  • “Bundle stale” 503 responses: the container can’t reach knoxcall.com. Check firewall / egress rules; the only outbound endpoint needed is knoxcall.com:443.