Skip to content

Network — infrastructure & VPC — N1 IT Landscape

N1 IT Landscape — The Blueprint · CF-Access internal

N1 IT Landscape · Owner: Arun Venkataraman · source of truth: markdown SSOT

N1 NETWORK ARCHITECTURE — FULL SPECIFICATION

Section titled “N1 NETWORK ARCHITECTURE — FULL SPECIFICATION”

Part of theN1 IT Landscape — the infrastructure/VPC network chapter. For who-calls-whom (service ports, stream topology, DB allow-lists) see the companion Network — service-to-service map. CURRENT-STATE as of 2026-06-09 , AWS account 191421493115, region us-east-2. Inventoried live (aws ec2/eks/rds/elasticache, Cloudflare API). All facts are verified except the two points explicitly marked (inferred).

This document is written so that a person or an AI can reconstruct N1’s network diagrams in full depth from the text alone. It gives, for each environment (staging and production):

N1 network overview: Internet traffic passes Cloudflare Access and Tunnels into separate staging and production VPCs, each with private cluster and database boundaries and NAT-only egress.
Trust-boundary overview; the environment-specific CIDR, routing, and edge tables below are authoritative. Download SVG source
  1. the layered topology (prose + ASCII),
  2. every VPC, subnet (ID, CIDR, AZ, tier), route table, gateway, peering link, and security group,
  3. the EKS networking, the data layer (Aurora + Valkey placement, endpoints, security groups),
  4. the exact ingress map (public hostname → in-cluster service:port) and the egress model,
  5. a diagram source record : an explicit node list and edge list with labels and trust-boundary groupings. It is retained as historical input for the versioned visual source, not as browser-rendered diagram code.

The published overview groups nodes by the trust boundaries in §1, places the Cloudflare edge above the cluster VPC and its private database VPC, and keeps staging and production as separate, non-connected graphs. The edge list remains the detailed source record.


1. Global model (applies to both environments)

Section titled “1. Global model (applies to both environments)”
  • One AWS account (191421493115), one region (us-east-2), three Availability Zones (us-east-2a/2b/2c). Staging and production are fully separate VPCs and never talk to each other.
  • Trust boundaries (use these as diagram groupings, outermost → innermost):
    1. Internet — users, clinicians, developers.
    2. Cloudflare edge — DNS, WAF (on n1.care), Access (Google IdP), WARP devices, the Tunnel.
    3. Cluster VPC — the EKS cluster; public/NAT subnet tier + private app subnet tier.
    4. Database VPC — isolated; Aurora + Valkey only; reachable from the cluster VPC over peering.
  • Ingress rule (critical): the only inbound path is a Cloudflare Tunnel. cloudflared pods inside the cluster open an outbound connection to Cloudflare; Cloudflare forwards request traffic down that connection to in-cluster ClusterIP services. Therefore AWS has no inbound ports, no public IPs on workloads, no load balancers, and no ACM certificates. TLS terminates at Cloudflare.
  • EKS API-server exception: the Kubernetes API-server endpoint is public (endpointPublicAccess = true, publicAccessCidrs = 0.0.0.0/0) and private; it is authenticated by AWS IAM/OIDC. This is a separate control-plane path from application traffic, used by kubectl, ArgoCD, Karpenter, CI.
  • Egress rule: pods reach the internet through a single NAT gateway per cluster VPC (in us-east-2a) → internet gateway. There are no VPC endpoints , so traffic to AWS APIs (S3, ECR, Secrets Manager, STS) and to external services (GCP Vertex AI, Stripe, Postmark, GitHub, Cloudflare R2, dhi.io) all egresses via NAT.
  • Subnet tiers (per cluster VPC): three large /18 private “app” subnets (one per AZ) host the EKS nodes/pods and route egress through NAT; three small /24 “NAT/public” subnets (one per AZ) carry the route to the internet gateway and host the NAT gateway. No subnet sets MapPublicIpOnLaunch (no workload gets a public IP).
  • Database VPC: three /24 private subnets (one per AZ); a route table sends the cluster-VPC CIDR back over the peering link; RDS and ElastiCache both live here in their own subnet groups.

INTERNET — users · developers
│ HTTPS
┌─────────────────────────────┴──────────────────────────────┐
│ CLOUDFLARE edge │
│ Access (Google IdP @n1.healthcare) · WARP · DNS │
│ Tunnel "EKS Staging" id=03dae21f (healthy, 8 conns) │
└─────────────────────────────┬──────────────────────────────┘
outbound tunnel (cloudflared dials OUT) — no inbound ports
┌──────── VPC n1-staging-cluster-vpc vpc-0e8b4e1cc854393cd 10.10.0.0/16 ────────┐
│ NAT/public tier (/24, route→IGW igw-0a9175f4684f99808): │
│ 2a subnet-0b6800f4ed3c6fb37 10.10.192.0/24 (NAT gw nat-0fa14ebecfd9b4311) │
│ 2b subnet-06b8b97c7a6e2346f 10.10.193.0/24 │
│ 2c subnet-0b3e7427f03afac8e 10.10.194.0/24 │
│ Private app tier (/18, route→NAT + peering→10.80): │
│ 2a subnet-0f79867baf12c5efe 10.10.0.0/18 │
│ 2b subnet-01c421077f2dbd594 10.10.64.0/18 │
│ 2c subnet-0c64caa054fcd318f 10.10.128.0/18 │
│ EKS n1-staging-cluster (k8s v1.35.4) — 12 Bottlerocket nodes, Karpenter │
│ cluster SG sg-04733424b4539086e · node SG sg-028257ce022982ce4 · │
│ control-plane ENI SG (eks-cluster-sg) sg-0017610cc00c6e9f8 │
│ cloudflared ×2 (kube-system) ─serves─▶ ClusterIP services (see ingress map) │
│ egress ─▶ NAT (2a) ─▶ IGW ─▶ internet (Vertex AI, Stripe, Postmark, GitHub, │
│ ECR, R2, dhi.io, AWS APIs) │
└───────────────────────────────────────┬─────────────────────────────────────────┘
peering pcx-0b0be34847a25cce8 (active)
┌───────────────────────────────────────▼──── VPC n1-staging-database vpc-08b5430d41c64a4e5 10.80.0.0/16 ──┐
│ Private subnets (/24): 2a 10.80.1.0/24 subnet-0d22f082a83393d05 · │
│ 2b 10.80.2.0/24 subnet-01545530e79cf6b90 · │
│ 2c 10.80.3.0/24 subnet-0040aab6f7695227b │
│ RDS SG sg-0ec302e948493a190 (n1-staging-database-rds-sg) · subnet group n1-staging-database-subnet-group│
│ Aurora PostgreSQL 17.7 Serverless v2 clusters (endpoint host …cluster-c3gc6ccoiwig.us-east-2.rds…): │
│ n1-staging-app · auth-staging · billing-staging · litellm-staging · forge-runner-staging (agno) │
│ ElastiCache Valkey 8.2.0 — replication group staging-valkey (2× cache.r7g.xlarge, auto-failover); │
│ subnet group "staging-valkey"; endpoint staging-valkey.zc3ep9.ng.0001.use2.cache.amazonaws.com │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Developer read-only access (WARP-enrolled @n1.healthcare devices only):
db.staging.n1 → (Cloudflare Gateway DNS override) → n1-staging-app.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com
redis.staging.n1 → (Cloudflare Gateway DNS override) → staging-valkey.zc3ep9.ng.0001.use2.cache.amazonaws.com
The DNS override returns the private RDS/Valkey host; the device reaches it over the tunnel's
private-network route into 10.80.0.0/16 (inferred).
VPC Route table Routes
cluster 10.10.0.0/16 rtb-0946754c442477fb7 (public/NAT tier) 10.10.0.0/16→local · 0.0.0.0/0→IGW igw-0a9175f4684f99808
cluster rtb-08750244c638b557e (private app tier) 10.10.0.0/16→local · 10.80.0.0/16→peering pcx-0b0be348 · 0.0.0.0/0→NAT nat-0fa14ebecfd9b4311
cluster rtb-06d7d8f31b18f8446 10.10.0.0/16→local (isolated)
database 10.80.0.0/16 rtb-081c9057abce4d76b 10.10.0.0/16→peering · 10.80.0.0/16→local
database rtb-0b48e600a87cd3a3d 10.80.0.0/16→local

vpc-0e8b4e1cc854393cd; control-plane subnets subnet-0f79867baf12c5efe, subnet-01c421077f2dbd594, subnet-0c64caa054fcd318f (the three /18); cluster SG sg-04733424b4539086e; cluster-created ENI SG sg-0017610cc00c6e9f8; endpoint public + private , public CIDR 0.0.0.0/0.

2.4 Ingress map (staging) — public hostname → in-cluster backend

Section titled “2.4 Ingress map (staging) — public hostname → in-cluster backend”
Public hostname Backend service.namespace:port Protocol
api-staging.n1.care api-websocket-proxy.staging:9999 WebSocket
api-staging.n1.care oathkeeper-proxy.staging:4455 HTTP (→ api-backend)
auth-staging.n1.care authentication-service.staging:9000 and kratos-public.staging:4433 HTTP
oauth-staging.n1.care hydra-public.staging:4444 HTTP
billing-staging.n1.care oathkeeper-proxy.staging:4455 HTTP
staging-admin.n1-research.com admin-dashboard.staging:3000 HTTP
argocd-staging.n1-research.com argocd-server-proxy.argocd:443 HTTPS
automated-testing.n1-research.com automated-testing.staging:8787 HTTP
litellm-staging.n1-research.com litellm.llmproxy:4000 HTTP

INTERNET — clinicians (app.n1.care)
│ HTTPS
┌─────────────────────────────┴──────────────────────────────┐
│ CLOUDFLARE edge │
│ WAF (n1.care: Managed + OWASP) · Access · WARP · DNS │
│ Tunnel "EKS Production" id=5a3b0a66 (healthy, 8 conns) │
└─────────────────────────────┬──────────────────────────────┘
outbound tunnel (cloudflared dials OUT) — no inbound ports
┌──────── VPC n1-production-cluster-vpc vpc-02bfbd3ac089cc6cc 10.30.0.0/16 ────────┐
│ NAT/public tier (/24, route→IGW igw-00af27c9514cf1077): │
│ 2a subnet-036709bb3487c205f 10.30.192.0/24 (NAT gw nat-0b0e21a37fb950920) │
│ 2b subnet-0efa880dd7c33ae39 10.30.193.0/24 │
│ 2c subnet-0481a253a6b8d06b7 10.30.194.0/24 │
│ Private app tier (/18, route→NAT + peering→10.70): │
│ 2a subnet-0f32faa0c3b22e0eb 10.30.0.0/18 │
│ 2b subnet-0b78705a0735f6ccb 10.30.64.0/18 │
│ 2c subnet-0c2d73517db3edfa6 10.30.128.0/18 │
│ EKS n1-production-cluster (k8s v1.35.4) — 10 Bottlerocket nodes, Karpenter │
│ cluster SG sg-078566499446bdb22 · node SG sg-09dbb3a8b57a373b8 · │
│ control-plane ENI SG (eks-cluster-sg) sg-07474adb47a3bf828 │
│ cloudflared ×2 (kube-system) ─serves─▶ ClusterIP services (see ingress map) │
│ egress ─▶ NAT (2a) ─▶ IGW ─▶ internet (Vertex AI, Stripe, Postmark, GitHub, │
│ ECR, R2, dhi.io, AWS APIs) │
└───────────────────────────────────────┬─────────────────────────────────────────┘
peering pcx-043ae3b00da8e9703 (active)
┌───────────────────────────────────────▼──── VPC n1-production-database vpc-039f3b070cb9de124 10.70.0.0/16 ┐
│ Private subnets (/24): 2a 10.70.1.0/24 subnet-0838b2e33986b75ff · │
│ 2b 10.70.2.0/24 subnet-0793491a194679826 · │
│ 2c 10.70.3.0/24 subnet-069819557be80e753 │
│ RDS SG sg-09a9f6eba199245f6 (n1-production-database-rds-sg) · subnet group n1-production-database-subnet-group
│ Aurora PostgreSQL 17.7 Serverless v2 clusters (endpoint host …cluster-c3gc6ccoiwig.us-east-2.rds…): │
│ n1-production-app · auth-production · billing-production (**Multi-AZ**) · litellm-production · │
│ forge-runner-production (agno) │
│ ElastiCache Valkey 8.2.0 — replication group production-valkey (2× cache.m7g.large, auto-failover); │
│ subnet group "production-valkey" │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Production databases are NOT exposed to developers (no WARP DNS override exists for production).
VPC Route table Routes
cluster 10.30.0.0/16 rtb-0aa3632231c49bd5c (public/NAT tier) 10.30.0.0/16→local · 0.0.0.0/0→IGW igw-00af27c9514cf1077
cluster rtb-0e99547a1c5367517 (private app tier) 10.30.0.0/16→local · 10.70.0.0/16→peering pcx-043ae3b0 · 0.0.0.0/0→NAT nat-0b0e21a37fb950920
cluster rtb-0200630a80c27991c 10.30.0.0/16→local (isolated)
database 10.70.0.0/16 rtb-0e7f3e63d6d309d14 10.30.0.0/16→peering · 10.70.0.0/16→local
database rtb-062940b2dd768da07 10.70.0.0/16→local

vpc-02bfbd3ac089cc6cc; control-plane subnets subnet-0f32faa0c3b22e0eb, subnet-0b78705a0735f6ccb, subnet-0c2d73517db3edfa6 (the three /18); cluster SG sg-078566499446bdb22; cluster-created ENI SG sg-07474adb47a3bf828; endpoint public + private , public CIDR 0.0.0.0/0.

3.4 Ingress map (production) — public hostname → in-cluster backend

Section titled “3.4 Ingress map (production) — public hostname → in-cluster backend”
Public hostname Backend service.namespace:port Protocol
api.n1.care / api-production.n1.care api-websocket-proxy.prod:9999 WebSocket
api.n1.care / api-production.n1.care oathkeeper-proxy.prod:4455 HTTP (→ api-backend)
auth.n1.care / auth-production.n1.care authentication-service.prod:9000 and kratos-public.prod:4433 HTTP
oauth.n1.care hydra-public.prod:4444 HTTP
billing.n1.care / billing-production.n1.care oathkeeper-proxy.prod:4455 HTTP
admin.n1-research.com admin-dashboard.prod:3000 HTTP
argocd.n1-research.com argocd-server-proxy.argocd:443 HTTPS
litellm-prod.n1-research.com litellm.llmproxy:4000 HTTP

This is the same topology expressed as a node/edge list, so a tool can lay it out automatically. Build two separate graphs (staging, production); they share shape, differing only in the values in §2/§3. Substitute {env} and the per-env IDs/CIDRs from above.

4.1 Nodes (per environment), grouped by trust boundary

Section titled “4.1 Nodes (per environment), grouped by trust boundary”
  • Boundary: Internetusers (clinicians/developers).
  • Boundary: Cloudflare edgecloudflare_dns, cloudflare_access (Google IdP), cloudflare_waf (production/n1.care only), warp_devices, tunnel ({EKS Staging|EKS Production}).
  • Boundary: Cluster VPC{cidr}
    • tier NAT/public : igw, nat_gw (in 2a), three /24 subnets {a,b,c}.
    • tier private app : three /18 subnets {a,b,c}.
    • eks_cluster (control plane, public+private API endpoint), karpenter, nodes (Bottlerocket).
    • workload group cloudflared (kube-system) and cluster_services (the ClusterIP services from the ingress map: api-websocket-proxy, oathkeeper, api-backend, authentication-service, kratos, hydra, admin-dashboard, phoenix-router, phoenix-parser, rosetta-grouper, forge-sentinel, forge-agents-api, litellm, mineru, otel, argocd, plus prod-only api-proxy/auth-proxy/billing-proxy, pdf-converter).
  • Boundary: Database VPC{cidr} — three /24 subnets, rds_sg, aurora (5 clusters), valkey (2-node replication group).
  • External egress targets (outside all boundaries): vertex_ai, stripe, postmark, github, ecr, r2, dhi_io, aws_apis.
  1. users → cloudflare_dns : HTTPS
  2. cloudflare_access → cloudflare_dns : gate (Google IdP, @n1.healthcare)
  3. cloudflare_waf → cloudflare_dns : WAF (Managed+OWASP, n1.care) (production)
  4. cloudflare_dns → tunnel : route hostname
  5. cloudflared → tunnel : outbound connection (cloudflared dials OUT)draw arrow from cluster to Cloudflare; no inbound ports
  6. tunnel → cluster_services : per ingress map, label each hostname → service:port/proto
  7. eks_cluster → users : public API-server endpoint (IAM/OIDC auth, 0.0.0.0/0) — control-plane path
  8. cluster_services → nat_gw : egress
  9. nat_gw → igw : ``
  10. igw → {vertex_ai, stripe, postmark, github, ecr, r2, dhi_io, aws_apis} : internet egress (no VPC endpoints)
  11. private_app_subnets → database VPC : VPC peering {pcx-id}
  12. cluster_services → aurora : PostgreSQL 5432 (via pgbouncer) across peering
  13. cluster_services → valkey : Valkey/Redis 6379 across peering
  14. warp_devices → aurora : db.staging.n1 (Gateway DNS override, WARP only, read-only) (staging only, inferred private route)
  15. warp_devices → valkey : redis.staging.n1 (Gateway DNS override, WARP only, read-only) (staging only, inferred)

The versioned SVG overview above is the published diagram. The node and edge lists in §§4.1–4.2 remain the complete implementation record.


  • Everything is verified live except: the WARP→database private-network route (the Gateway DNS override is verified; the underlying tunnel private-route that carries the connection is inferred).
  • No VPC endpoints exist , so all AWS-API and external egress is over NAT (this is a deliberate part of the picture, not an omission).
  • Security-group rules (allowed ports between SGs) were not enumerated here — only SG identities and purposes. The effective paths are: cluster nodes ↔ Aurora 5432 and ↔ Valkey 6379 across the peering link, gated by the database *-rds-sg security group.
  • The AI/development cluster (n1-ai-cluster, account 083636777616) is out of scope and not shown; it follows the same NAT-only-egress + Cloudflare-tunnel-ingress pattern.