Platform Infrastructure
Detailed reference documentation for eSHARS infrastructure components.
What we’re building
eSHARS runs on Azure following the Microsoft Cloud Adoption Framework (CAF) hub-and-spoke pattern, in a single subscription, split into two tiers — nonprod (dev, qa, regression) and prod (uat, training, prod). Each tier has its own hub, its own spoke network, and its own set of shared services; the environments within a tier share that tier’s foundation.
The estate is described entirely as Terraform/OpenTofu “roots” (independent state units), layered so each builds on the one below it:
| Root | Scope | Owns |
|---|---|---|
| control-plane-core (hub) | per tier | Hub VNet, VPN gateway, control-plane Key Vault |
| control-plane-dns-zones | per tier | Global private DNS zones (blob, vaultcore, redis, azconfig) in rg-eshars-global-{tier} |
| control-plane-dns | per tier | The dnsmasq DNS forwarder VM |
| workload-network (spoke) | per tier | Spoke VNet + subnets (apps / private-endpoint / VMs / app-gateway), NSGs, peering to the hub, SQL private DNS zone |
| workload-core (shared services) | per tier | Tier resource groups, App Gateway, App Service Plan, Redis, tier automation account, ReportViewer tier Key Vault (created empty), staging storage |
| workload-core-secrets | per tier | The in-spoke data-plane writes into the RV KV (tier encryption key, ReportViewer SSL cert) |
| vms/ops | per tier | The ops VM — self-hosted GitHub runner + hybrid runbook worker |
| vms/report-server, vms/job-scheduler (+ optional VM roots) | per tier | SSRS VM, jobs VM; plus prod-only rns/tmhp-sftp and nonprod-only utility VMs |
| workload-env | per environment | Everything per-env: its own web + function app (no shared-app slots; only prod has a staging swap slot), SQL server + databases, per-env Key Vault, storage, private endpoints, DNS alias |
Key idea: the hub, spoke, shared services, and report server are built once
per tier; adding an environment (e.g. a new QA) is just another workload-env
on top of the tier that already exists.
graph TD
subgraph TIER["Each tier — nonprod / prod"]
CPC["control-plane-core<br/>hub: VNet, VPN gw, private DNS, DNS forwarder"]
WN["workload-network<br/>spoke VNet, subnets, peering"]
WC["workload-core<br/>tier RGs, App GW, web/func apps, Redis, KV, automation"]
RS["report-server<br/>SSRS VM"]
ENV1["workload-env: dev"]
ENV2["workload-env: qa"]
ENV3["workload-env: …"]
end
CPC --> WN
WN --> WC
WC --> RS
RS --> ENV1
RS --> ENV2
RS --> ENV3
WC -. "spoke peers to hub; private endpoints resolve via hub DNS" .-> CPC
For the exact order to stand a tier up (and the per-tier vs per-env distinction), see Deployment Order; for the GitHub Actions workflows that automate it end-to-end, see Stand-up Workflows. (The Shared Core Architecture page predates the 2026-06 rebuild — its RG names and zone ownership are historical.)
Architecture
| Document | Description |
|---|---|
| Shared Core Architecture | VNet, App Gateway WAF_v2, Private DNS, Landing Zone alignment |
| Application Infrastructure | OpenTofu modules for web app, function app, SQL, Redis, Key Vault |
| Terraform Modules — HISD Full-Stack | Full-stack module set for provisioning a complete HISD environment |
Virtual Machines
| Document | Description |
|---|---|
| VM Registry | Centralized inventory of all VMs in the eSHARS estate |
| TMHP SFTP VM | vm-tmhp-sftp-prod-cus — TMHP file exchange, NSG rules, KV/SQL connectivity |
| SFTP Server | SFTPGo VM (vm-sftp-prod-001) — LB config, fail2ban, cutover plan |
| Report Server (SSRS) | SSRS 2022 VM — install process, networking, troubleshooting |
Networking
| Document | Description |
|---|---|
| Workload Network | Workload spoke VNet (vnet-eshars-prod-cus) — peering, subnets, DNS links |
| Private Endpoints — Database | Non-prod DB private endpoint configuration |
| Private Endpoints — Storage | Non-prod storage private endpoint configuration |
Environment Provisioning
| Document | Description |
|---|---|
| Deployment Order | Which Terraform roots to apply, in what order, when standing up a tier or adding an environment |
| Stand-up Workflows | The Infra: 0–6 GitHub Actions workflows, the two OIDC deploy identities, and the Port self-service front door |
| Training Environment Setup | Deploying to the training environment, job migration |