Data Quality Detect. Quantify. Resolve.
← Back to download

AltitudeIQ Pre-Install Checklist

Audience: your Azure / Cloud Ops team. Run through this before the scheduled install window (ideally 2–3 business days ahead) so anything that needs a ticket filed has time to clear.

Target: one Azure subscription, one region of your choice.

Installer: Zero-dependency Go binary run from any machine with az access to the target subscription.

Each item below lists: what to check, how to check, pass criteria, and if it fails, what to do. Items are ordered by likelihood of being a blocker in a typical enterprise Azure tenant.


1. Subscription + RBAC

1.0 Target subscription designated for AltitudeIQ

Check: your Azure / Cloud Ops team has designated which Azure subscription will host AltitudeIQ. This can be an existing subscription with a dedicated resource group, or a net-new subscription stood up specifically for this install.

Pass: a subscription has been agreed by your cloud governance team and the subscription ID is in hand.

Fail (no subscription yet): if your tenant doesn't already have a suitable subscription, your procurement / EA team needs to provision one through the Microsoft EA portal (or your Cloud Solution Provider partner) before install day. New EA subscription provisioning typically takes 1–5 business days, so file the request at least a week ahead of the agreed install window.

Recommendation: a dedicated subscription gives the cleanest operational boundary for AltitudeIQ — distinct cost reporting, simpler RBAC scoping, and a one-command teardown path (az group delete against the install RG, no risk of touching neighbouring workloads). A shared subscription with a dedicated resource group is also fine; the installer scopes everything to the RG it creates.

1.1 Target subscription is named and accessible

Check: you know the exact subscription ID that will host AltitudeIQ, and you can list resource groups in it.

az account show --subscription <SUB_ID> --query '{name:name, id:id, tenantId:tenantId}' -o json
az group list --subscription <SUB_ID> -o table | head -5

Pass: subscription name and ID match expectations; az group list returns without a permission error.

Fail: you may be signed into the wrong tenant (az login --tenant <TENANT_ID>) or missing at least Reader role on the subscription.

1.2 Installer-running user has Owner (or Contributor + User Access Administrator) at the subscription scope

The installer creates a new resource group and grants a user-assigned managed identity two roles on that RG: Contributor (to provision resources) and Role Based Access Control Administrator (to grant the Container Apps environment AcrPull on the customer's ACR at runtime). That second role assignment requires the installer to hold Owner OR User Access Administrator at the subscription scope at run time.

az role assignment list \
  --subscription <SUB_ID> \
  --assignee <YOUR_AAD_UPN> \
  --all \
  --query "[?scope=='/subscriptions/<SUB_ID>'].{role:roleDefinitionName, scope:scope}" -o table

Pass: Owner OR (Contributor + User Access Administrator) at the subscription scope.

Fail: ask your Azure admin to grant one of the above for the duration of the install window. After install completes, you can downgrade to Reader; the managed identity owns the RG-scoped operations going forward.

1.3 No subscription-level deny-assignment blocks our scope

Large org subscriptions sometimes carry deny assignments from Azure Blueprints or Management Group policy that override role assignments.

az deployment sub list --subscription <SUB_ID> --query "[?contains(name, 'denyAssignment')]" -o table
az lock list --subscription <SUB_ID> -o table | head

Pass: no deny assignments that block Microsoft.Resources/resourceGroups/write, Microsoft.Authorization/roleAssignments/write, or Microsoft.App/*.

Fail: open a ticket with the Azure policy team. We can work around most deny assignments by targeting a specific subscription they've already approved, but the scope has to be provided explicitly.


2. Azure Policy

2.1 No policy blocks our resource types in the target region

AltitudeIQ provisions:

Check:

az policy state list --subscription <SUB_ID> --filter "complianceState eq 'NonCompliant'" --query "[].{policy:policyDefinitionName, resource:resourceType}" -o table | head -20
az policy assignment list --subscription <SUB_ID> --query "[].{name:displayName, scope:scope}" -o table

Pass: no deny policies on the resource types above for region East US 2 (or the agreed region).

Fail: usually fixable by either (a) adding an exemption for the AltitudeIQ RG once it exists, or (b) adjusting the Bicep parameters to match policy requirements (e.g. if policy requires tags, we parameterise tags).

2.2 No policy blocks public ingress on Container Apps

The dashboard, backend API, and frontend are served from Container Apps with public ingress (HTTPS-only, TLS terminated by Azure). Some tenants have a policy blocking public ingress on Container Apps or requiring VNet integration.

Pass: either public ingress is allowed, OR you have a private-endpoint pattern we can adapt to (in which case please flag so we can plan).

Fail for Standard tiers: Tiers below Enterprise uses public ingress by default. If policy requires private-only, escalate to the Enterprise tier conversation — it has VNet integration and private ingress.

2.3 Key Vault purge protection policy is compatible

AltitudeIQ provisions Key Vaults with enablePurgeProtection: true and 90-day soft-delete retention. Some tenants have stricter retention (180 / 365 days).

Pass: policy allows >= 90 days soft-delete retention. Stricter is fine.

Fail: none expected — Key Vault compliance policies typically only require purge protection to be on, which matches.


3. Quotas

3.1 Container Apps, PostgreSQL, and Managed Identity quotas in the target region

# Container Apps environments — default quota is 15 per subscription, 5 per region
az rest --method GET \
  --uri "https://management.azure.com/subscriptions/<SUB_ID>/providers/Microsoft.App/locations/eastus2/usages?api-version=2024-03-01" \
  --query "value[].{name:name.value, current:currentValue, limit:limit}" -o table

# PostgreSQL Flexible Server quota — GeneralPurpose vCores
az postgres flexible-server list-skus --location eastus2 --query "[].name" -o tsv | head -5

Pass: at least 1 Container Apps environment slot free, 1 PG Flexible Server slot free, 8 vCores of GeneralPurpose quota.

Fail: file a quota increase at least 3 business days ahead — Microsoft often takes 1–3 business days to approve PG quota in East US 2.

3.2 Multi-Zone HA quota (informational — not blocking for Standard tiers)

Tiers below Enterprise currently ship with HA = Disabled. We've filed a Multi-Zone HA quota request with Azure; it's pending and has been declined once due to capacity constraints in some regions. First customer installs proceed with single-zone HA; zone-redundant HA will be enabled on a later update when the quota clears.

No action needed from your team.


4. Outbound networking

4.1 Hostnames reachable from the AltitudeIQ resource group

During bootstrap the reconciler pulls container images from GHCR, registers with the AltitudeIQ Control Plane, and streams telemetry:

Hostname Port Why
ghcr.io 443 Image pull during bootstrap + updates
*.pkg.github.com 443 GHCR layer storage (redirect target for ghcr.io)
cp.altitudeiq.ai 443 Control Plane registration, heartbeat, telemetry
*.azurecr.io (customer's own) 443 Internal — images land here after GHCR import
*.vault.azure.net (customer's own) 443 Internal — reconciler reads its secrets
*.postgres.database.azure.com (customer's own) 5432 Internal — app → DB
*.blob.core.windows.net (customer's own) 443 Internal — app → object storage
*.azurecontainerapps.io (customer's own) 443 Internal — backend ↔ frontend ↔ matching-service
dc.services.visualstudio.com 443 Application Insights ingestion
*.applicationinsights.azure.com 443 Application Insights (regional)
*.in.applicationinsights.azure.com 443 Application Insights ingestion (regional)

Check: if you use Azure Firewall / NSG-based outbound filtering, confirm the hostnames above are allowlisted. The *.altitudeiq.ai and ghcr.io entries are the only non-Azure destinations.

Pass: outbound HTTPS to the list above is permitted from the AltitudeIQ resource group.

Fail: file the firewall change at least 3 business days ahead. We can run a pre-install connectivity probe if you want confirmation before install day.

4.2 No tenant-level egress restriction that would block GHCR

Some enterprise tenants route all outbound through a tenant-level egress proxy that strips non-allowlisted TLS. If you use one, confirm ghcr.io and cp.altitudeiq.ai are in the proxy's allowlist.

Fail: this is the single most common last-minute blocker. File the change ahead of time.


5. Conditional Access

5.1 The installer-running user can complete OAuth from the install workstation

The installer authenticates via az login (browser or device code). If you have a Conditional Access policy requiring a compliant device, specific location, or MFA for management plane operations, the workstation running the installer must satisfy it.

Check: on the install workstation, run:

az login
az account set --subscription <SUB_ID>
az group create --name delete-me-preinstall-probe --location eastus2 --tags temporary=true
az group delete --name delete-me-preinstall-probe --yes

Pass: all four commands succeed without MFA loops, device-compliance denials, or "AADSTS" errors.

Fail: the error codes (e.g. AADSTS53000 for non-compliant device, AADSTS50158 for MFA) tell you which policy tripped. File a temporary exception for the install workstation, or run the installer from a device that already satisfies policy.

5.2 Service-principal-free install confirmed

The installer does not require creating a service principal. It uses your interactive login for the lifetime of the install. After install, only the installer-provisioned managed identity operates on the resource group — no long-lived user credential is stored anywhere.

No action needed from your team, but confirm this with your identity team if they ask.


6. Naming + tagging conventions

6.1 Resource group naming

The installer creates a resource group named rg-{appName} where {appName} is supplied via --app-name. Set --app-name to whatever resource group naming your Azure team prefers (the installer prepends rg-).

Fail: if your naming policy requires a specific prefix or suffix (e.g. rg-prod-pharma-altitudeiq-001), please confirm ahead so we set --app-name accordingly. Length limit: 3–20 chars, lowercase, alphanumeric + hyphens.

6.2 Mandatory tags

Many enterprise policies deny resource creation without specific tags (Cost Center, Owner, Environment, Data Classification, etc.).

Check: list any Azure Policy assignments that deny based on tags:

az policy assignment list --subscription <SUB_ID> --query "[?contains(displayName, 'tag') || contains(displayName, 'Tag')].displayName" -o tsv

Pass: no tag-required deny policies, OR the required tags are documented and we can pass them as installer parameters.

Fail: send us the tag names + values; we'll plumb them through the Bicep. This is a ~5-line change on our side.


7. Backup / DR readiness

7.1 Geo-redundant backup region is accessible

Standard tiers use geo-redundant PostgreSQL backup (paired region depends on the region you chose). No action required from your team unless your tenant has policy blocking cross-region resource data residency.

Pass: the paired region for your chosen region is acceptable for PostgreSQL backups.

Fail: if your organization requires in-region backup only, we can switch to locally-redundant backup at install time — please flag ahead.

7.2 Subscription or RG delete-lock policy

Some enterprise subscriptions auto-apply CanNotDelete locks at the RG level. This doesn't block install, but it does prevent the teardown-and-retry flow if something goes wrong on install day.

Check:

az lock list --subscription <SUB_ID> -o table

Pass: no locks on the (yet-to-be-created) RG name. Locks at subscription-level that permit write-and-create are fine.

Fail: if the lock will be applied automatically post-creation, let us know so we can plan the mitigation path (usually: install, then lock, then re-installs need the lock lifted first).


8. SAP / Oracle connectivity (if either data source is in scope for v1)

Covered in the main customer guide section "Data Source Connectivity". Confirm the following ahead of install day:

8.1 SAP ECC / S/4HANA

8.2 Oracle

8.3 Target systems not in scope for v1

If either SAP or Oracle is out of v1 scope, skip that subsection. Can be added later — both integrations are additive.


9. Day-of-install window

9.1 Expected duration: 30–45 minutes

Phase Expected time
Installer bootstrap Bicep 10–15 min (PG Flexible Server is the long pole)
Reconciler provisions application layer 10–15 min
Health verification (5 checks) <5 min

Fail modes during the window are usually:

9.2 Rollback plan

If the install fails unrecoverably, teardown is az group delete --name rg-<appName> --yes. Destructive; cleans up everything the installer created. No customer data risk because no customer data has been loaded yet.

Retry after teardown is safe — the reconciler has a self-heal path that handles Azure's 90-day Key Vault soft-delete recovery cleanly, so a same-day retry with the same --app-name works without intervention.


10. Green-light signal

Once items 1.1 through 4 pass, your team can green-light the install window. Items 5, 6, 7.2, 8 are common tripwires — resolve those before install day, not during it. Item 7.1 is informational.

Confirmation back to AltitudeIQ on the day of:

We'll be on call during the install window to troubleshoot any surprises.