Azure RaaS — New Customer Configuration + Initial Terraform Deploy (Ops Playbook)
Audience: Junior Cloud Engineers
Covers: New customer YAML → PR → publish workflow → initial Terraform modules (base account, then base connectivity).
Does NOT cover: Full module rollout beyond initial phases, full VM/bootstrap behavior, and post-deploy validation.
Systems and repos involved
-
RAAS-azure-customer-configs(source of truth; Deploy Lens reads from here) -
RAAS-azure-terraform-v2(Terraform execution repo; publish workflow generates/updates changes here) -
RAAS-azure-ansible-v2(bootstrap/Ansible repo; publish workflow generates/updates changes here) -
Deploy Lens (reads customer-configs)
-
Rhapsody SaaS Platform Portal → Cosmos DB (customer map/secrets/IP allocation etc.; typically Seniors)
Inputs you must have before you start
Collect these before you touch the repos:
-
Customer code (e.g.,
CCAD) -
Tenant name (usually
RAAS, sometimesM42) -
Salesforce customer number (if available)
-
Environments (dev/dev2/test/stage/prod, etc.)
-
Sizing per environment (VM size, disk size/type)
-
OS image choice (AlmaLinux, shared image gallery, use latest)
-
Any optional “extra modules” (VPN/SIFs/ExpressRoute/peering/monitoring/diagnostics)
-
Networking requirements (VPN details, remote VNet IDs/locations, etc.)
-
Rhapsody/Ansible version targets + any rhapsody.properties overrides
High-level flow (for awareness)
-
Create/update customer YAML in
raas-azure-customer-configs -
Raise PR (preferably via Copilot in VS Code)
-
Merge PR to
main -
Run GitHub Action “publish customer config” on
main(tenant + customer inputs) -
Verify downstream updates in Terraform V2 + Ansible V2
-
Senior reviews/merges downstream changes
-
Confirm Cosmos DB customer map/secrets/IP allocation exists (Seniors typically)
-
Terraform Unified Workflow: PLAN/ APPLY
base account, then PLAN/ APPLYbase connectivity
Part 1 — Customer config + Publish workflow
Step 1 — Clone the customer config repo
-
Clone and open in VS Code:
github.com/Rhapsody-health/RAAS-azure-customer-configs
Expected result: You can browse customers/ and see tenant folders.
Step 2 — Create the customer folder + YAML
-
Navigate to
customers/(contains a folder per tenant). -
Choose the correct tenant folder:
RAASis typical for RaaS customers;M42exists for M42 tenant customers.
-
Create a new folder:
customers/<TENANT>/<CUSTOMER_CODE>/
-
Create the YAML:
customers/<TENANT>/<CUSTOMER_CODE>/<CUSTOMER_CODE>.yaml
-
Recommended: copy an existing YAML from the same tenant as your starting template.
Step 3 — Update the “must change” YAML fields
In your new customer YAML, verify:
-
tenant:matches where the customer lives (RAASvsM42). -
customer_code:is updated everywhere. -
Add Salesforce customer number if provided.
-
Modules rule: do not list default modules as “extra”; only genuinely optional modules belong under
modules.extra.-
Default modules typically include base account, base core, env-raas, base-snapshots, base connectivity.
-
Examples of extra modules: VPN, SIFs, ExpressRoute, peering, monitoring, diagnostics.
-
-
Module versions are now tags (example discussed:
v3.0.0) rather than commit SHAs.
Step 4 — Define environments (raas_config)
-
Create one environment entry per required env (dev/dev2/test/stage/prod, etc.).
-
Set
alt_nameper environment (tag used so support can identify instances). -
Set compute/disk sizing per environment (example discussed: “medium” with ~512GB disk).
-
Disk redundancy: direction discussed was moving back to ZRS as default.
-
Image: AlmaLinux from shared image gallery, use “latest”.
Step 5 — Add optional config blocks (only if required)
Only include these blocks if the customer needs them:
-
Ansible version target (example discussed:
7.5.1— verify per ticket/customer). -
Host mappings (domain → on-prem IP via VPN) if needed for local name resolution.
-
rhapsody.propertiesoverrides requested by the customer (appended during bootstrap). -
Per-environment overrides where needed; keep a default “catch-all” for shared values.
Step 6 — Networking + cost-sensitive defaults (do not “improve” these)
-
Firewall SKU: keep basic unless explicitly approved.
-
VPN gateway SKU: keep VpnGw1 unless higher throughput/many tunnels required.
-
VPNs: you can define multiple VPNs by copying/repeating the block; include crypto parameters.
- Note: some PFS groups (e.g., 14) may not appear in the portal but can still be valid in config.
-
Peerings: set remote VNet IDs/locations and ensure VNet access/forwarded traffic options are correct (especially with VPN).
Step 7 — Create branch/commit/push/PR using GitHub Copilot (VS Code)
-
In VS Code Copilot Chat, switch agent/context to Cloud (not Local).
-
Ask Copilot to create a new branch, commit, and push your changes.
-
Ask Copilot to create a PR for that branch.
-
Review the diff carefully before “Ready for Review”.
-
Watch for accidental inclusion of generated dirs like
out/; remove and ensure it’s ignored.
Step 8 — Merge the customer-config PR
-
Get review/approval per team process.
-
Merge to
main. -
Confirm
maincontains the new customer folder/YAML.
Step 9 — Run GitHub Action: “publish customer config”
-
In
raas-azure-customer-configson GitHub: Actions → “publish customer config”. -
Run workflow from the
mainbranch. -
Enter inputs:
-
Tenant
-
Customer code
-
-
Decide: dry run vs create downstream changes:
-
Set “render only / only render” true to preview without creating branches/PRs
-
Set it false to create downstream branches/PRs
-
-
Monitor workflow logs until completion.
Step 10 — Verify downstream outputs (Terraform + Ansible)
-
In Terraform V2 repo, confirm a new branch and/or PR was created/updated for the customer.
-
In Ansible V2 repo, confirm a PR was created/updated for bootstrap config.
-
If something looks incorrect (stale/broken branch from previous attempts), delete/close old branch/PR and re-run publish workflow.
Step 11 — Handoff
-
Ask a Senior (Lee/Cole/Emily) to review and merge downstream PRs/branches.
-
Once merged, proceed to Part 2 (Terraform deploy).
Part 2 — Deploy initial customer infRAAStructure with Terraform Unified Workflow
Rule: Always run PLAN before APPLY.
Step 12 — Confirm prerequisites
Before running any Terraform workflow:
-
Customer config was published from
RAAS-azure-customer-configs. -
Downstream changes are merged to
mainin Terraform V2 + Ansible V2 (Senior typically merges). -
Customer exists in Cosmos DB customer map (secrets/subscription/CIDR/snapshots/etc.).
-
You know tenant + customer code.
-
You know which IaC env you’re targeting (typically
prod;sandboxfor safe testing only when explicitly requested).
Step 13 — Cosmos DB customer map awareness (usually Seniors)
Where: Rhapsody SaaS platform portal → search “Cosmos” → Cosmos DB → Data Explorer → credentials → items.
Confirm tenant item exists (e.g., RAAS) and that the customer entry exists under customer map.
Typical fields include customer code/name, firewall address, DNS overrides (optional), CIDR allocation (commonly /24, can be /22), subscription ID, timezone, snapshot schedule.
Important: snapshot schedule start date/time must be in the future.
If you don’t have access, get a Senior to confirm before you run Terraform.
Step 14 — Terraform Unified Workflow: Base account (PLAN)
-
Go to Terraform V2 repo → Actions → Terraform Unified Workflow → Run workflow.
-
Set:
-
Branch:
main -
Action:
plan -
Tenant: customer tenant (e.g.,
RAAS) -
Customer: customer code (e.g.,
CCAD) -
IaC environment: typically
prod(sandboxonly if explicitly requested) -
Terraform module:
base account(always first for new customer)
-
-
Optional security scans (Trivy/AI remediation): leave defaults unless instructed otherwise.
Stop condition: If plan output looks wrong, do not proceed.
Step 15 — Terraform Unified Workflow: Base account (APPLY)
-
Only after plan is correct, rerun workflow with action =
apply(same tenant/customer/env/module). -
Expected outcome: foundational resources such as App Configuration, Key Vault, Log Analytics workspace, Storage Account.
Step 16 — Verify Base account resources in Azure
-
Confirm resources were created under the shared Management subscription in a customer-specific RG.
-
RG naming pattern includes customer code, region (example shown:
UAEN), and “BA base account”. -
In the RG you should see:
-
App Configuration
-
Key Vault
-
Log Analytics workspace
-
Storage Account (linked to workspace for logging/telemetry)
-
Step 17 — Terraform Unified Workflow: Base connectivity (PLAN)
-
Run the workflow again:
-
Action =
plan -
Module =
base connectivity -
Tenant/customer/env unchanged
-
-
If plan fails due to module-level issues: escalate to a Senior (do not guess-fix production module code).
Step 18 — Terraform Unified Workflow: Base connectivity (APPLY)
-
After a clean plan, rerun workflow with action =
apply. -
Note: base connectivity creates the firewall and it can take several minutes.
Step 19 — Verify connectivity resources
-
Connectivity resources (VPNs, firewall, ExpressRoute, peerings, etc.) live in Management subscription under a customer/region connectivity RG.
-
During apply, firewall may sit in “Creating” for a long time — this is normal.
Step 20 — Continue modules in order (as required)
After base account + base connectivity, continue modules in order:
base counter → base core → base-diagnostics (optional) → env-raas → base-snapshots
Rule of thumb: PLAN then APPLY for each module, one at a time, in order.
Step 21 — Day-2 rerun guidance
Once deployed, you typically do not rerun: base account, base counter, base connectivity, base core.
Most day-2 changes are handled by rerunning env-raas or VPN-related modules.
Quick checklists
Before you raise the PR
-
Correct tenant folder selected (RAAS vs M42)
-
Customer code updated everywhere
-
Salesforce customer number added (if provided)
-
Only extra modules listed under
modules.extra -
Firewall SKU is basic; VPN gateway SKU is 1 unless approved
-
No generated directories (e.g.,
out/) in commit
Before you run “publish customer config”
-
Customer-config PR merged to
main -
You know exact tenant + customer code
-
You decided: dry run (render only) vs create branches/PRs
After publish workflow
-
Terraform repo has new customer branch/updates
-
Ansible repo has new/updated PR
-
Senior notified to review/merge
Before Terraform Unified Workflow (Part 2)
-
Downstream changes merged to main (Terraform + Ansible)
-
CosmosDB customer map/secrets exist (or Senior confirmed)
-
You will PLAN first (never APPLY blind)
-
Correct tenant/customer/IaC env selected; start with base account then base connectivity
Appendix — YAML starter skeleton (illustrative)
Use an existing in-tenant customer YAML as your source of truth; this is just to help you recognize sections.
# customers/<TENANT>/<CUSTOMER_CODE>/<CUSTOMER_CODE>.yaml
tenant: <TENANT> # e.g., RAAS or M42
customer_code: <CUSTOMER_CODE> # e.g., CCAD
salesforce_customer_number: <SF_NUMBER> # optional but recommended
modules:
extra:
- <OPTIONAL_MODULE_ID> # e.g., base_vpn, base_sifs, base_express_route
RAAS_config:
environments:
dev:
alt_name: <CUSTOMER>-Rhapsody-dev
instance_type: <VM_SIZE>
disk_size_gb: <DISK_SIZE>
disk_type: <ZRS_or_other>
image: <image_gallery_latest>
rhapsody_properties:
- key: <property.name>
value: <value>
prod:
alt_name: <CUSTOMER>-Rhapsody-prod
# ...same pattern...
networking:
firewall_sku: basic
vpn_gateway_sku: VpnGw1
peerings: []
vpns: []