Security model

How we isolate customer workloads, protect the control plane, and produce evidence trails compliant with India’s DPDP Act.

Workload isolation

Each customer VM is a fully-isolated KVM guest under Proxmox VE. Workloads share neither kernel nor userspace with other tenants — we don’t use containers as a tenancy boundary.

  • Per-VM CPU pinning + memory ballooning under host control.
  • Per-VM private bridge in the 10.10.0.0/24 range; no L2 between customers.
  • Per-VM iptables rules in dedicated chains (CLOUDNX-DNAT, CLOUDNX-FWD) so cross-tenant packet leaks would require kernel-level escape.

Control-plane authentication

Every protected API call is gated by an RS256-signed JWT issued by the auth service. Public verification key is mounted into compute and storage as a Docker secret — services never touch the private key.

  • Access tokens: 15 min TTL.
  • Refresh tokens: 30 days, rotated on every refresh.
  • Tokens carry sub (root user_id) plus optional iam_uid + iam_acct when authenticated as an IAM user.

Programmatic access (SigV4)

IAM access keys use AWS SigV4-compatible request signing — the secret never leaves the client process, only an HMAC of the canonical request travels over the wire. The cloudnx CLI does this automatically.

# Headers a signed request includes:
Authorization: AWS4-HMAC-SHA256 Credential=AKIA…/20260503/in-mum/cloudnx/aws4_request, …
X-Amz-Date: 20260503T120000Z
X-Amz-Content-Sha256: …

Replay protection: a 5-minute clock-skew window via X-Amz-Date. Reject requests outside the window.

Multi-factor authentication

TOTP-based MFA is supported on root users and IAM users. Login flow:

  1. Submit credentials → server returns {requires_2fa: true, pending_token} instead of the access token.
  2. Submit OTP + pending token → server validates against the stored secret and a 5-minute Redis pending key.
  3. Pending tokens are single-use and consumed on success.

Reused TOTP codes are detected via a totp_used:<user>:<code> Redis key with a 90-second TTL — covers the 30-second window the code is valid in plus prev/next windows.

Audit logging (DPDP Act)

Every state-changing HTTP request is logged to audit_logs with: actor user_id, account_id, service, method, path, status code, IP, user-agent, request-ID, and duration. Read-only requests (GET, HEAD) are skipped.

Owners can read their own org’s audit trail at /audit-logs or via GET /auth/audit-logs. Logs are retained for 12 months minimum to satisfy DPDP’s record-of-processing requirement.

Encryption

  • In transit: TLS 1.2+ on every public endpoint via Cloudflare (cloudnx.in) and Let’s Encrypt at the host nginx for direct-IP / customer hostnames.
  • At rest: Postgres on full-disk encrypted volumes; MinIO with server-side encryption keyed by the per-bucket access key.
  • Secrets: JWT private key + SMTP / Razorpay credentials live in Docker secrets, mounted read-only into containers. IAM access-key secrets are AES-GCM-encrypted in DB.

Backups

  • Postgres: nightly pg_dump --format=custom at 02:30 IST → MinIO + optional offsite (Hetzner Storage Box / Backblaze B2). 14-day retention.
  • VMs: nightly Proxmox live snapshots, 7-day retention. Customers can also take on-demand snapshots from the dashboard.

Incident response

Email [email protected] for vulnerability reports. We acknowledge within 24 hours and patch in-band; coordinated-disclosure window is 90 days.

Status page (planned): status.cloudnx.in— runs on GitHub Pages, hosted independently of our infrastructure so it’s reachable during platform incidents.