Deploy Guide
Enterprise Deployment Guide

Gateway Deployment.
VPC / Docker / Terraform.

Production deployment reference for the RGX Compliant Multi-Tenant AI Integration Gateway. All three deployment targets — cloud-managed, Docker self-hosted, and VPC-dedicated — covered with real configuration at every step. No placeholder values.

Docker image: ghcr.io/rgxsystems/gateway:latest
Runtime: Node.js 20 LTS
Database: PostgreSQL 15+
TLS 1.3 required
AES-256-GCM at rest
Architecture
Choose Your Deployment Target
Three deployment modes cover the full spectrum from managed SaaS to air-gapped VPC. All three run identical API code — the mode controls where data persists, whether outbound RGX licensing calls are made, and what isolation guarantees apply.
ModeInfrastructureData ResidencyBest For
Cloud Managed RGX-operated Render + managed Postgres. Zero ops burden. RGX infrastructure (SOC 2 Type II). US region by default. VAR pilots, SMB deployments, fast time-to-production.
Docker Self-Hosted Your server or VM. Single docker compose up. Your datacenter or cloud account. You own the database. On-prem requirements, custom data residency, hybrid setups.
VPC Dedicated ECS Fargate, AKS, or bare-metal in your VPC. No shared resources with other tenants. Fully within your cloud account. Air-gap compatible. HIPAA covered entities, regulated finance, government, CISO-mandated isolation.

All modes use identical API endpoints and response schemas. Switching from Cloud Managed to VPC Dedicated requires only a DNS update and environment variable change — no application code changes.

Cloud Managed
Quick Start — Cloud Gateway
Cloud Managed nodes are provisioned at rgxsystems.com/demo. Your API key is issued immediately. No infrastructure to configure — call the API directly.
Verify your node is live — GET /api/v1/health
curl https://rgxsystems.com/api/v1/health \ -H "X-Api-Key: rgx_live_your_key_here"
200 OKResponse
{ "status": "ok", "node_id": "vn_01j9x...", "deployment_mode": "cloud", "api_version": "v1", "systems": { "compliance_engine": "operational", "tenant_isolation": "operational", "seat_metering": "operational" } }
Your base URL is https://rgxsystems.com/api/v1. Every request passes your API key as X-Api-Key. For full endpoint reference see API Reference →

Self-Hosted — Docker
Docker Deployment
The gateway image is published to GitHub Container Registry. A single docker compose up starts the gateway plus a managed Postgres instance. Suitable for on-prem servers, bare-metal, or single-VM cloud deployments.
Pull the gateway image
docker pull ghcr.io/rgxsystems/gateway:latest # Pin to a specific release for production (recommended): docker pull ghcr.io/rgxsystems/gateway:2.4.1
docker-compose.yml — gateway + postgres
version: '3.9' services: gateway: image: ghcr.io/rgxsystems/gateway:latest restart: unless-stopped ports: - "443:3000" environment: DEPLOYMENT_MODE: dedicated DATABASE_URL: postgresql://rgx:${DB_PASSWORD}@postgres:5432/rgx ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} LICENSE_KEY: ${LICENSE_KEY} RGX_NODE_ID: ${RGX_NODE_ID} JWT_SECRET: ${JWT_SECRET} SEAT_AUTH_MODE: jwt PORT: 3000 LOG_LEVEL: info depends_on: postgres: condition: service_healthy postgres: image: postgres:15-alpine restart: unless-stopped environment: POSTGRES_DB: rgx POSTGRES_USER: rgx POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U rgx"] interval: 10s retries: 5 volumes: pgdata:
.env — secrets file (never commit)
DB_PASSWORD=strong_random_password_here ANTHROPIC_API_KEY=sk-ant-api03-... LICENSE_KEY=eyJhbGciOiJSUzI1NiJ9... RGX_NODE_ID=vn_01j9x_your_node_id JWT_SECRET=64_byte_random_hex_string
Start the gateway
docker compose --env-file .env up -d # Wait for the health endpoint to return 200 before routing traffic: curl http://localhost:3000/api/v1/health
!

TLS termination is your responsibility in self-hosted mode. Place an nginx or Caddy reverse proxy in front of the gateway container that terminates TLS 1.3 and forwards to port 3000. Do not expose port 3000 directly to the internet.

Self-Hosted — AWS
AWS Deployment — ECS Fargate + RDS
The Terraform module provisions ECS Fargate (auto-scaled), RDS PostgreSQL (Multi-AZ), an Application Load Balancer with ACM certificate, Secrets Manager for all credentials, and a dedicated security group that permits only HTTPS inbound. No SSH access to gateway tasks.
Provision AWS infrastructure via Terraform
git clone https://github.com/rgxsystems/deploy.git cd deploy/terraform/aws terraform init terraform apply \ -var "aws_region=us-east-1" \ -var "license_key=${LICENSE_KEY}" \ -var "anthropic_api_key=${ANTHROPIC_API_KEY}" \ -var "db_password=${DB_PASSWORD}" \ -var "jwt_secret=${JWT_SECRET}" \ -var "rgx_node_id=${RGX_NODE_ID}" \ -var "domain=rgx.yourdomain.com" \ -var "seat_auth_mode=oidc"
OutputsTerraform apply complete
alb_dns_name = "rgx-alb-1234567890.us-east-1.elb.amazonaws.com" gateway_url = "https://rgx.yourdomain.com" rds_endpoint = "rgx-prod.cluster-xyz.us-east-1.rds.amazonaws.com:5432" ecs_cluster_arn = "arn:aws:ecs:us-east-1:123456789012:cluster/rgx-gateway" secrets_prefix = "arn:aws:secretsmanager:us-east-1:..."
The module creates the following AWS resources:
ResourceTypeNotes
ECS ClusterFargateAuto-scaling 1–10 tasks based on CPU/memory. Task definition pinned to gateway image digest.
Application Load BalancerHTTPS/443TLS 1.3 policy. ACM certificate auto-provisioned for your domain. HTTP/80 permanently redirected.
RDS PostgreSQLMulti-AZ db.t3.mediumAES-256 encryption at rest. Automated backups 7-day retention. Point-in-time recovery enabled.
Secrets ManagerKMS-encryptedStores LICENSE_KEY, ANTHROPIC_API_KEY, JWT_SECRET, DB_PASSWORD. Injected into Fargate task at runtime.
Security GroupsLeast privilegeALB: 443 inbound from 0.0.0.0/0. ECS task: 3000 from ALB SG only. RDS: 5432 from ECS SG only.
CloudWatchLog group + alarmsStructured JSON logs. Alarms on 5xx rate >1% and p99 latency >2s.
Self-Hosted — Azure
Azure Deployment — AKS Helm / ACI
Two Azure paths are supported: AKS via Helm chart for clusters that already exist, and Azure Container Instances for single-container deployments without orchestration overhead. Both use Azure Database for PostgreSQL Flexible Server and Key Vault for secrets.
Option A — AKS via Helm chart
# Add the RGX Helm repository helm repo add rgxsystems https://charts.rgxsystems.com helm repo update # Create namespace and secrets kubectl create namespace rgx-gateway kubectl create secret generic rgx-secrets \ --namespace rgx-gateway \ --from-literal=licenseKey="${LICENSE_KEY}" \ --from-literal=anthropicApiKey="${ANTHROPIC_API_KEY}" \ --from-literal=jwtSecret="${JWT_SECRET}" \ --from-literal=databaseUrl="${DATABASE_URL}" # Deploy gateway helm install rgx-gateway rgxsystems/gateway \ --namespace rgx-gateway \ --set deploymentMode=dedicated \ --set rgxNodeId="${RGX_NODE_ID}" \ --set seatAuthMode=oidc \ --set oidcIssuer="https://login.microsoftonline.com/${TENANT_ID}/v2.0" \ --set oidcAudience="api://rgx-gateway" \ --set ingress.enabled=true \ --set ingress.host="rgx.yourdomain.com" \ --set ingress.tls=true \ --set replicaCount=2
Option B — Azure Container Instances (single container)
# Create resource group az group create --name rgx-gateway --location eastus # Deploy ACI container az container create \ --resource-group rgx-gateway \ --name rgx-gateway \ --image ghcr.io/rgxsystems/gateway:latest \ --cpu 2 --memory 4 \ --dns-name-label rgx-gateway \ --ports 3000 \ --environment-variables \ DEPLOYMENT_MODE=dedicated \ RGX_NODE_ID="${RGX_NODE_ID}" \ SEAT_AUTH_MODE=oidc \ PORT=3000 \ LOG_LEVEL=info \ --secure-environment-variables \ LICENSE_KEY="${LICENSE_KEY}" \ ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" \ DATABASE_URL="${DATABASE_URL}" \ JWT_SECRET="${JWT_SECRET}" # Place Azure Application Gateway (WAF v2) in front for TLS 1.3 termination

Azure AD / Entra ID OIDC is the recommended seat auth mode for Azure deployments. Set OIDC_ISSUER=https://login.microsoftonline.com/<tenant_id>/v2.0, OIDC_AUDIENCE=api://<your_app_registration_id>, and OIDC_JWKS_URI is auto-discovered from the issuer metadata endpoint. Bearer tokens from Entra ID are validated on every request without any per-request network call — JWKS keys are cached with automatic rotation.

Self-Hosted — Kubernetes
Kubernetes — Any Cluster
The Helm chart works with EKS, GKE, AKS, or any conformant K8s cluster. It creates a Deployment, HorizontalPodAutoscaler, Service, Ingress, and a Secret (from the values you provide). PodDisruptionBudget ensures zero-downtime rolling deploys.
values.yaml — production Helm values
replicaCount: 2 image: repository: ghcr.io/rgxsystems/gateway tag: "2.4.1" pullPolicy: IfNotPresent env: DEPLOYMENT_MODE: dedicated SEAT_AUTH_MODE: oidc LOG_LEVEL: info PORT: "3000" secrets: existingSecret: rgx-secrets # kubectl secret with all sensitive vars resources: requests: { cpu: 500m, memory: 512Mi } limits: { cpu: 2000m, memory: 2Gi } autoscaling: enabled: true minReplicas: 2 maxReplicas: 10 targetCPUUtilizationPercentage: 70 ingress: enabled: true className: nginx host: rgx.yourdomain.com tls: true certManager: true podDisruptionBudget: minAvailable: 1

Configuration
Environment Variable Reference
All configuration is driven by environment variables. Required variables must be set before startup — the gateway exits with a clear error if any required variable is absent.
VariableRequiredDescription
DEPLOYMENT_MODE required cloud | dedicated. Cloud mode phones home for billing; dedicated mode is fully offline per-request.
DATABASE_URL required PostgreSQL connection string. Format: postgresql://user:pass@host:5432/dbname. SSL mode enforced.
ANTHROPIC_API_KEY required Your Anthropic API key. The gateway routes all AI calls through this key. Never exposed in logs or API responses.
LICENSE_KEY required (dedicated) RS256 JWT issued by RGX CA. Verified offline at startup. Claims: node_id, expiry, allowed_seats. Contact licensing@rgxsystems.com.
RGX_NODE_ID required (dedicated) Node identifier issued with your license. Must match node_id claim in LICENSE_KEY. Format: vn_01j9x...
JWT_SECRET required 64-byte hex string. Signs RGX-issued HS256 seat JWTs. Generate with openssl rand -hex 64.
SEAT_AUTH_MODE optional jwt | oidc | saml | header. Default: jwt. All four modes are auto-detected from request headers when not set.
OIDC_ISSUER oidc only OIDC issuer URL. Example: https://dev-123.okta.com/oauth2/default. JWKS fetched from {issuer}/.well-known/jwks.json.
OIDC_AUDIENCE oidc only Expected aud claim value. Example: api://default (Okta) or api://rgx-gateway (Azure AD).
OIDC_JWKS_URI oidc only Override the auto-discovered JWKS URI. Required for air-gapped deployments where the IdP metadata endpoint is not reachable.
SAML_ENTRY_POINT saml only IdP SSO URL. Example: https://yourcompany.okta.com/app/rgx/sso/saml
SAML_CERT saml only PEM-encoded IdP signing certificate (base64, no headers). Obtained from your IdP's SAML metadata XML.
PORT optional HTTP listen port. Default: 3000. TLS termination handled upstream by ALB, nginx, or Application Gateway.
LOG_LEVEL optional error | warn | info | debug. Default: info. Structured JSON. PHI/PII never appears in logs at any level.
Enterprise SSO
OIDC and SAML Seat Authentication
The gateway validates inbound seat identity tokens on every request. Four modes are supported and auto-detected from request headers — no configuration flag required beyond setting the right environment variables.
ModeTriggerCompatible IdPs
RGX JWTHS256 Authorization: Bearer <hs256_jwt> Issued by your own back-end using JWT_SECRET. Payload must contain { tenant_id, seat_id }.
OIDCRS256 / ES256 Authorization: Bearer <id_token> Okta, Azure AD / Entra ID, Google Workspace, Auth0, Ping Identity.
SAML 2.0 X-Saml-Assertion: <base64 SAMLResponse> Azure AD SAML, Okta SAML, ADFS, Ping Identity.
Header / Body X-Seat-Id: <user_id> or body { "seat_id": "..." } Server-side VAR calls where you control both ends. No token signing required.
OIDC configuration — Okta example (.env)
SEAT_AUTH_MODE=oidc OIDC_ISSUER=https://dev-123456.okta.com/oauth2/default OIDC_AUDIENCE=api://default # OIDC_JWKS_URI is auto-discovered from the issuer metadata endpoint. # Override only in air-gapped environments: # OIDC_JWKS_URI=https://internal-idp.corp/oauth2/v1/keys
OIDC configuration — Azure AD / Entra ID (.env)
SEAT_AUTH_MODE=oidc OIDC_ISSUER=https://login.microsoftonline.com/{tenant_id}/v2.0 OIDC_AUDIENCE=api://rgx-gateway # In the Azure app registration, expose the API with scope "gateway.access" # and add rgx-gateway as the Application ID URI.
SAML configuration — ADFS / Azure AD SAML (.env)
SEAT_AUTH_MODE=saml SAML_ENTRY_POINT=https://yourcompany.okta.com/app/rgxgateway/sso/saml SAML_CERT=MIICpDCCAYwCCQD... # from IdP metadata XML, base64 only (no PEM headers) # seat_id extracted from SAMLResponse NameID by default. # Override with SAML_SEAT_ID_ATTRIBUTE for custom attributes: # SAML_SEAT_ID_ATTRIBUTE=http://schemas.microsoft.com/identity/claims/objectidentifier
On each authenticated request, the gateway auto-provisions the seat in var_client_seats on first appearance and populates req.seatContext with { seatId, tenantId, nodeId, autoProvisioned, idpMode }. Usage is metered against that seat for per-seat billing.
Enterprise
Dedicated / Air-Gapped Deployment
Set DEPLOYMENT_MODE=dedicated to activate full offline operation. In this mode, the gateway makes zero outbound network calls to RGX infrastructure per request. License validation, seat provisioning, usage metering, and audit logging all run locally within your VPC. No data leaves your network boundary.

Dedicated mode requires a LICENSE_KEY JWT. Contact licensing@rgxsystems.com. The JWT is RS256-signed by RGX CA and verified offline at gateway startup against a hardcoded public key baked into the image. No license server call is ever made. Set it as LICENSE_KEY in your environment.

LICENSE_KEY JWT ClaimTypeDescription
node_idstringMust match RGX_NODE_ID. Gateway refuses to start if they differ.
expiryunix timestampLicense hard expiry. Gateway logs a warning at 30 days out and enters read-only mode at expiry.
allowed_seatsintegerMaximum concurrent active seats. Provisioning new seats above this limit returns HTTP 402.
industriesstring[]Allowed industry values. Requests with unlicensed industry fields return HTTP 403.
Verify dedicated mode is active — GET /api/v1/health
curl https://rgx.internal/api/v1/health \ -H "X-Api-Key: YOUR_KEY"
200 OKDedicated mode confirmed
{ "status": "ok", "deployment_mode": "dedicated", "license": { "valid": true, "node_id": "vn_01j9x...", "allowed_seats": 500, "expires": "2027-01-01T00:00:00Z" }, "outbound_rgx_calls": "disabled" }
!

In dedicated mode, admin and VAR portal routes are disabled. The node bootstraps from the LICENSE_KEY claims on first start — no manual provisioning step is needed. Billing runs locally against your Postgres instance. Stripe is never contacted.


Hardening
Production Security Checklist
Run through this checklist before routing production traffic to a self-hosted gateway. All items are required for HIPAA-compliant and regulated-finance deployments.
  • TLS 1.3 enforced at the load balancer. Disable TLS 1.0 and 1.1. Use ELBSecurityPolicy-TLS13-1-2-2021-06 on AWS ALB or the equivalent Azure / GCP policy. The gateway container itself speaks plain HTTP internally — TLS lives at the LB.
  • AES-256-GCM encryption enabled on PostgreSQL at rest. AWS RDS: StorageEncrypted: true with KMS key. Azure: Transparent Data Encryption (TDE) enabled. GCP: CMEK on Cloud SQL.
  • No secrets in environment variable logs. Confirm your container orchestrator filters LICENSE_KEY, ANTHROPIC_API_KEY, JWT_SECRET, DATABASE_URL from log streams. AWS Secrets Manager and Azure Key Vault inject at runtime without environment variable leakage.
  • API keys stored as SHA-256 hashes only. Plaintext API keys are never persisted to the database. The gateway hashes inbound keys on each request and compares against stored hashes. This is the default behavior — verify with SELECT * FROM api_keys LIMIT 1; and confirm the key_hash column starts with a 64-char hex string, not rgx_live_.
  • Raw PII/PHI never written to central logs. The gateway's compliance engine tokenizes regulated data before any logging occurs. Confirm by sending a test request with dummy PHI and verifying CloudWatch / Log Analytics shows {{REDACTED_PHI_1}} tokens, not the original values.
  • Database connection uses SSL mode=require. Confirm DATABASE_URL includes ?sslmode=require or the equivalent DSN parameter. The gateway will refuse to connect to a non-SSL database in dedicated mode.
  • Security groups / NSGs restrict database access to gateway tasks only. Postgres port 5432 must not be reachable from the public internet or any other security group. Verify inbound rules on your RDS instance or VM firewall.
  • HSTS header configured at load balancer. Set Strict-Transport-Security: max-age=31536000; includeSubDomains on all HTTPS responses. Prevents protocol downgrade attacks.
  • JWT_SECRET is at least 64 bytes of random entropy. Generate with openssl rand -hex 64. Do not reuse across environments. Rotate quarterly or on suspected compromise.
  • Health endpoint is not publicly accessible. GET /api/v1/health requires a valid API key. If your ALB health check calls it unauthenticated, create a separate internal ALB target group or use the /internal/health endpoint (authenticated by source IP restriction, not API key).
Operations
Health, Readiness, and Log Endpoints
The gateway exposes standard health endpoints for orchestrator integration. Use /health for liveness and readiness probes. Use /api/v1/usage to monitor seat consumption and billing position.
Kubernetes liveness + readiness probe configuration
livenessProbe: httpGet: path: /api/v1/health port: 3000 httpHeaders: - name: X-Api-Key value: $(RGX_HEALTH_KEY) initialDelaySeconds: 15 periodSeconds: 30 failureThreshold: 3 readinessProbe: httpGet: path: /api/v1/health port: 3000 httpHeaders: - name: X-Api-Key value: $(RGX_HEALTH_KEY) initialDelaySeconds: 10 periodSeconds: 10
Check active seat count and billing position — GET /api/v1/usage
curl https://rgx.yourdomain.com/api/v1/usage \ -H "X-Api-Key: YOUR_KEY"
200 OKUsage + billing summary
{ "period": "2026-07", "active_seats": 47, "allowed_seats": 500, "compliance_events_this_month": 18241, "base_fee_usd": 2000, "seat_fee_per_seat_usd": 20, "seat_charges_usd": 940, "estimated_invoice_usd": 2940, "deployment_mode": "dedicated" }
Need help or a dedicated deployment license?

For licensing and dedicated VPC deployments: licensing@rgxsystems.com
For deployment support: support@rgxsystems.com
Full API reference: API Reference →  |  Security architecture: Security Overview →  |  Data flow diagram: Zero-Leakage Architecture →