1.2 Infrastructure
Outcome
Azure resources for the master DB, tenant DB server, Service Bus (Premium with Private
Endpoint), blob storage with SFTP, Key Vault, App Service backends, Front Door, and
Static Web Apps are provisioned and reachable from your workstation. In practice this
is done via the Terraform under infra/terraform/envs/dev (and prod) — the manual
az commands below are reproduced for understanding only.
Prerequisites
- 1.1 Prerequisites complete.
Architecture
Provisioning sequence
Two important notes that drive the rest of this guide:
- Service Bus is Premium with Private Endpoint (hardcoded in Terraform). The Standard tier is not supported — message size and topic scale require Premium.
- Backends run on App Service (Linux) with slot-based blue-green deploys, not
Container Apps. The dev workflows under
.github/workflows/deploy-dev-*.ymlpush to slots and then trigger a swap.
Steps
Create the resource group
az group create \--name rg-rcm-prod-eastus2 \--location eastus2 \--tags env=prod app=rcmProvision the master Postgres flexible server
az postgres flexible-server create \--resource-group rg-rcm-prod-eastus2 \--name pg-rcm-master-prod \--location eastus2 \--tier Burstable --sku-name Standard_B2ms \--version 16 --storage-size 64 \--admin-user rcm_master_admin \--admin-password "$(openssl rand -base64 24)" \--high-availability Disabled \--public-access 0.0.0.0Capture the admin password — store it directly in Key Vault in step 5 (don't save it to a file).
Provision the first tenant DB server
az postgres flexible-server create \--resource-group rg-rcm-prod-eastus2 \--name pg-rcm-tenant-eastus2-01 \--location eastus2 \--tier GeneralPurpose --sku-name Standard_D2s_v3 \--version 16 --storage-size 128 \--admin-user rcm_tenant_admin \--admin-password "$(openssl rand -base64 24)"You'll register this in master DB as a
db_serverrow in 1.4 Master DB.Provision Key Vault, Service Bus, Storage, and Static Web Apps
# Key Vaultaz keyvault create \--resource-group rg-rcm-prod-eastus2 \--name kv-rcm-prod-eastus2 \--location eastus2 \--enable-rbac-authorization true# Service Bus — Premium tier required (Private Endpoint, larger msg size)az servicebus namespace create \--resource-group rg-rcm-prod-eastus2 \--name sb-rcm-prod-eastus2 \--location eastus2 --sku Premium --capacity 1# Storage account with SFTP enabledaz storage account create \--resource-group rg-rcm-prod-eastus2 \--name strcmprodeastus2 \--location eastus2 \--sku Standard_LRS \--enable-hierarchical-namespace true \--enable-sftp true# Static Web Apps for docs (one per docs subdomain — see Phase 1 step 6)for site in admin-docs docs edi-docs; doaz staticwebapp create \--resource-group rg-rcm-prod-eastus2 \--name swa-rcm-${site}-prod \--location eastus2 \--sku Standard \--source https://github.com/medsuite/eligibility-rcm \--branch main --app-location "apps/docs-${site##*-}" --output-location builddoneStash credentials in Key Vault
az keyvault secret set \--vault-name kv-rcm-prod-eastus2 \--name pg-master-admin-password \--value '<paste the master DB password from step 2>'az keyvault secret set \--vault-name kv-rcm-prod-eastus2 \--name pg-tenant-eastus2-01-admin-password \--value '<paste the tenant DB password from step 3>'The platform code reads these via the
@medsuite/key-vaultpackage usingDefaultAzureCredential(managed identity in production, your CLI login locally).Allow your workstation IP for one-time bootstrap access
MY_IP=$(curl -s https://api.ipify.org)for server in pg-rcm-master-prod pg-rcm-tenant-eastus2-01; doaz postgres flexible-server firewall-rule create \--resource-group rg-rcm-prod-eastus2 \--name "$server" --rule-name bootstrap-from-laptop \--start-ip-address "$MY_IP" --end-ip-address "$MY_IP"doneRemove these rules after 1.7 Smoke tests — the deployed services reach Postgres via private endpoint or VNet integration in production.
Validation
# Master DB reachable
psql "host=pg-rcm-master-prod.postgres.database.azure.com user=rcm_master_admin dbname=postgres sslmode=require" -c "SELECT now();"
# Tenant DB server reachable
psql "host=pg-rcm-tenant-eastus2-01.postgres.database.azure.com user=rcm_tenant_admin dbname=postgres sslmode=require" -c "SELECT now();"
# Key Vault accessible
az keyvault secret list --vault-name kv-rcm-prod-eastus2 -o table
# Service Bus reachable
az servicebus namespace show -g rg-rcm-prod-eastus2 -n sb-rcm-prod-eastus2 --query "status"
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
psql: connection refused | No firewall rule for your IP | Re-run step 6. |
az keyvault secret list returns 403 | RBAC not propagated | Add yourself as Key Vault Administrator: az role assignment create --role "Key Vault Administrator" --assignee $(az ad signed-in-user show --query id -o tsv) --scope $(az keyvault show -n kv-rcm-prod-eastus2 --query id -o tsv) |
| Storage SFTP not enabled | --enable-sftp true requires hierarchical namespace | Recreate with --enable-hierarchical-namespace true. |