Skip to content

NHC Architecture Decisions — DA-15 Brief · 2026-03-31

DA-15 — Architecture Update · Phase 3 Complete

Internal brief · 31 March 2026

AWS Account 794248400165 (NHC prod)
Region us-east-2 (Ohio)
Critical gaps 0 — ENC-003 closed
Compliance 55% — 11/20 controls

🔄 What Changed — Phase 3 Complete

✅ HTTPS Enforcement Live — Last Critical Gap Closed

ALB + WAF deployed and verified. Both ALBs serve HTTPS only (HTTP redirects to 443). AWS WAF v2 attached to Django ALB with managed rule sets and rate limiting at 2,000 req/5min. CloudWatch log group captures WAF events (90-day retention). ENC-003 closed.

✅ DNS Verified

All three staging domains resolve correctly via dig. Cloudflare CNAMEs point to ALB endpoints. Django API uses grey cloud (DNS-only — PHI must not traverse Cloudflare). WP CMS uses orange cloud (proxied — Cloudflare WAF + CDN).

ℹ️ Staging Domains Active

staging-django-api.novavirtual.site · staging-portals.novavirtual.site · staging-wp-cms.novavirtual.site
ACM certs issued and attached. Django cert is a SAN cert covering both the API and Portals subdomains.


📊 Compliance Status Post Phase 3

Metric Value Notes
Critical Gaps 0 Was 1 (ENC-003). Now closed.
High Gaps Remaining 4 ⚠️ Access controls + screenshot PHI
Controls Done 11 / 20 55% — up from 45% at Phase 2
Phases Complete 3 / 6 1 Encryption · 2 App infra · 3 HTTPS+WAF

🏗️ Settled Hosting Architecture

Django API + Portals — HIPAA path (AWS only)

User → Cloudflare DNS only (grey cloud) → ACM + ALB (HTTPS, TLS 1.2–1.3) → AWS WAF v2 → EC2 Django (private subnet)

PHI never leaves AWS network. Cloudflare is DNS-only — no traffic interception.

WP CMS — non-HIPAA

User → Cloudflare (proxied — WAF + CDN) → ALB (HTTPS) → EC2 App (private subnet)

Gatsby + Astro (3 sites) — static, non-HIPAA

User → Cloudflare Pages (CDN + WAF)

GitLab Runner (ec2-app) → wrangler pages deploy → Cloudflare Pages project

No S3, no CloudFront, no ACM certs needed. Cloudflare handles HTTPS + CDN + WAF. Phase 4 = GitLab CI config only.

Hosting Summary Table

App PHI / HIPAA? Hosting WAF Status
Django API staging-django-api.novavirtual.site ❗ Yes — full HIPAA EC2 private + ALB (AWS only, no CF proxy) AWS WAF v2 ✅ Live — Phase 3
Portals staging-portals.novavirtual.site ⚠️ Auth sessions — in scope Shared EC2 Django + ALB (must stay AWS) AWS WAF v2 (inherited) ✅ Live — Phase 3
WP CMS staging-wp-cms.novavirtual.site ✅ No PHI EC2 private + ALB + Cloudflare proxy Cloudflare ✅ Live — Phase 3
Gatsby staging-gatsby.novavirtual.site ✅ No PHI Cloudflare Pages (built on ec2-app) Cloudflare 🟡 Phase 4 — CI config only
Astro (×3 sites) staging-essential · staging-caringforyou · staging-vital ✅ No PHI Cloudflare Pages (built on ec2-app) Cloudflare 🟡 Phase 4 — CI config only

Note: Astro monorepo has 4 sites but one org stopped operations — 3 active staging domains.


✅ Deployed Infrastructure — Full Inventory

Resource ID / Endpoint Notes
ec2-app i-0880310086620ce5e · 10.1.10.241 WP CMS + Gatsby/Astro builds, GitLab Runner, 4GB swap
ec2-django i-0341906c41c45d520 · 10.1.11.178 Django API + Portals, GitLab Runner, 4GB swap
rds-django prod-nhc-django (MySQL 8.0) Private subnet, KMS encrypted, PHI-tagged, 7-day backups
ALB — Django prod-nhc-django-alb-1713854905.us-east-2.elb.amazonaws.com HTTPS only, WAF attached, health check /health/
ALB — WP CMS prod-nhc-wordpress-alb-1502175647.us-east-2.elb.amazonaws.com HTTPS only, Cloudflare proxied in front
WAF — Django prod-nhc-django-waf Managed rules + rate limit 2,000/5min, logs → CloudWatch 90d
ACM cert — Django ad4f0d27-051e-4dc6-811a-c71c83944383 SAN: staging-django-api + staging-portals.novavirtual.site
ACM cert — WP CMS be7a98d6-28c3-476d-8e8a-a1212d24dbf7 staging-wp-cms.novavirtual.site

All EC2s: Debian 13, Docker CE + Compose, GitLab Runner, deploy user. Access via SSM Session Manager only — no SSH port open anywhere.


🗺️ Roadmap — What's Next

✅ Phase 1 — Security Baseline (Complete)

  • KMS CMKs (EBS, S3, RDS, CloudTrail, Backup)
  • VPC — private subnets, NAT GW, VPC endpoints, flow logs
  • CloudTrail, GuardDuty, Config (HIPAA pack), Security Hub (NIST 800-53)
  • AWS Backup vault — 30-day retention
  • IAM baseline — SSM instance profile, Access Analyzer, password policy

✅ Phase 2 — App Infrastructure (Complete)

  • EC2 × 2 (ec2-app + ec2-django) — Debian 13, encrypted EBS, SSM-only
  • RDS MySQL 8.0 — KMS encrypted, private subnet, PHI-tagged
  • Ansible bootstrap — Docker CE, GitLab Runner, deploy user, swap

✅ Phase 3 — HTTPS + WAF (Complete — ENC-003 closed)

  • ALB module — HTTPS-only, HTTP→HTTPS redirect, TLS 1.2+1.3
  • AWS WAF v2 — managed rules + rate limiting on Django ALB
  • ACM certs issued and attached (both ALBs)
  • DNS verified — all 3 staging domains resolving

🟡 Phase 4 — Static Site CI/CD (Next — No AWS infra needed)

  • Register GitLab Runner on ec2-app (needs registration token)
  • Create Cloudflare Pages projects (Gatsby × 1, Astro × 3)
  • Write .gitlab-ci.yml: build → wrangler pages deploy
  • Store CLOUDFLARE_API_TOKEN in GitLab CI/CD variables

⏳ Phase 5 — Hardening & State (Pending)

  • S3 + DynamoDB remote state backend
  • TerraformDeployRole via IaC — restore assume_role in provider
  • Cross-region backup DR vault (us-west-2)
  • VPC Flow Logs + SSM Parameter Store IAM policy on instance profiles
  • Import Ansible SSM bucket into tofu state

⏳ Go-Live — Production Promotion (After MWE data handover)

  • Paolo updates stage = "prod" in terraform.tfvars, runs tofu apply to retag
  • MWE prod database + S3 migrated in — real PHI now in scope
  • True staging account created from scratch post go-live

🚧 Current Blockers — Phase 4

Blocker Needed For Owner
GitLab Runner registration token Phase 4 — register runner on ec2-app GitLab admin / Paolo
Cloudflare Pages projects created (4 sites) Phase 4 — deploy targets for wrangler Paolo
Cloudflare API token (Pages deploy scope) Phase 4 — GitLab CI variable for wrangler Paolo
MWE prod data handover date Go-live — stage promotion + PHI migration MWE / Stakeholder

DA-15 — NHC HIPAA-Compliant Infrastructure · Phase 3 Complete · 2026-03-31 · DevOps