Installation Script mode
This page describes the Installation Script deployment mode for Omada Identity Cloud Private – the recommended and fully supported path for first-time and standard deployments. For an overview of deployment modes and shared prerequisites, see the Deployment guide.
Overview
A single installation script (install.sh) orchestrates the entire deployment end-to-end:
- Preflight validation: OS, disk space, network connectivity checks.
- Toolchain bootstrap: Installs Azure CLI, Terraform, Helm, kubectl, ODBC Driver 18, Python, and Ansible automatically.
- Infrastructure provisioning: Terraform backend, shared global infrastructure, and workspace-specific resources.
- Artifact publishing: Container images to ACR and release artifacts to blob storage.
- Configuration validation: Key Vault certificate and secret checks before compute provisioning.
- Node setup: Ansible playbooks for AKS configuration and application deployment.
- Health check: Automated post-deployment readiness check.
Before starting, make sure the Installation Script prerequisites and Networking prerequisites are in place.
Step 1: Extract the installation package
You will receive a secure link to download the Omada Identity Cloud Private installation package from the Omada Community.
Extract it and navigate to the installation directory:
Tool: Bash shell
unzip oicp_install_<version>.zip
cd oicp_install_<version>/scripts/install
Step 2: Configure deployment-config.json
The deployment-config.json file in the installation directory is the single configuration input for the entire deployment. Edit it with your environment-specific values before running the script.
You can create multiple named copies of this file (for example, for different environments) and pass the desired one via the optional --config parameter, described later.
Key parameters to configure:
| Section | Parameter | Description |
|---|---|---|
azure | subscription_id | Azure subscription GUID. |
azure | tenant_id | Azure AD (Microsoft Entra ID) tenant GUID. |
azure | location | Azure region (for example, swedencentral). |
deployment | workspace_prefix | Workspace identifier – 2 lowercase letters + 4 digits (for example, ab0001). |
deployment | project_name | Project name for resource naming (for example, oicp). |
deployment | omada_license_string | Omada license key – provided by Omada. |
deployment | update_private_dns_records | Whether to update private DNS records automatically. Defaults to true. |
backend | storage_account_name | Storage account for Terraform state. |
backend | container_name | Blob container name for state files. |
backend | key | Terraform state file name. Defaults to terraform.tfstate; the shared-infrastructure state is stored as <key>.shared. |
release | package_url | Secure URL to the Cloud Private release package – provided by Omada. |
release | checksum_url | Optional URL to the release package SHA-256 checksum. If omitted (and no local release-package.sha256 exists), checksum verification is skipped with a warning. |
security | entra_admin_group.login / object_id | Existing Entra ID admin group. Leave both empty to have the script create the group for you (it will prompt, unless you pass --auto-create-groups). |
security | sql_admin_group.login / object_id | Existing Entra ID SQL admin group. Same create-or-provide behavior as entra_admin_group. |
shared | dns_zone_name | Public DNS zone for Cloud Private custom domains (for example, mycompany.example.com). Required – it names the zone whether the zone is referenced or created (see create_dns_zone). With create_dns_zone set to false, the zone must already exist in Azure – the installer validates this and fails if not found. |
shared | create_dns_zone | Whether the installer creates the DNS zone. Defaults to false, meaning the zone named in dns_zone_name must already exist. Set to true to have the installer create it. |
shared | dns_zone_resource_group | Resource group of the existing DNS zone. |
shared | certificate_secret_name | Name of the Azure Key Vault certificate. This certificate must be uploaded manually to the "Certificates" section of Key Vault before running the script. |
shared | certificate_file | Optional path to a certificate file (.pfx or .pem) on the machine running the installer. When set and the Key Vault certificate is missing, the installer imports it. The certificate password is read from the OMADA_CERT_PASSWORD environment variable, never from the config file. |
infrastructure | aks_system_node_size | VM SKU for AKS system node pool (current automation default: Standard_D2s_v5). |
infrastructure | aks_app_node_size | VM SKU for AKS application node pool (current automation default: Standard_D8s_v5). |
infrastructure | cag_vm_size | VM SKU for the Cloud Application Gateway VM (current automation default: Standard_D2s_v5). |
infrastructure | aks_linux_node_size | VM SKU for the AKS Linux node pool (default: Standard_D4s_v5). This node pool is shared with Linux CAG workloads. |
secrets | aks-extCertBase64, aks-extKeyBase64, aks-pfxCertificate, aks-pfxPassword, etc. | Optional. Base64-encoded certificates and keys can be supplied here to pre-populate Key Vault; otherwise add them manually before the secrets_validate phase runs. The aks-containerRegistryDockerConfigJson secret is also required by validation but is generated automatically from the container registry credentials if not supplied. |
Example deployment-config.json
The following example shows a fully filled-in deployment-config.json for a development environment.
{
"azure": {
"subscription_id": "00000000-0000-0000-0000-000000000000", // Your Azure subscription GUID
"tenant_id": "00000000-0000-0000-0000-000000000000", // Your Microsoft Entra ID tenant GUID
"location": "swedencentral" // Azure region for all resources
},
"deployment": {
"workspace_prefix": "ab0001", // 2 lowercase letters + 4 digits, e.g. ab0001
"project_name": "oicp", // Used to derive resource names; keep short and lowercase
"omada_license_string": "<provided-by-omada>",
"update_private_dns_records": true // Set to false to manage DNS records manually
},
"backend": {
"storage_account_name": "tfstateoicp", // Storage account for Terraform state; must be globally unique
"container_name": "tfstate", // Blob container name; "tfstate" is a safe default
"key": "terraform.tfstate" // State file name; default is "terraform.tfstate"
},
"release": {
"package_url": "<secure-url-provided-by-omada>",
"checksum_url": "<checksum-url-provided-by-omada>" // Optional; omit to skip checksum verification
},
"security": {
"entra_admin_group": {
"login": "omada-admins", // Display name of the Entra ID admin group
"object_id": "", // Leave empty to have the script create the group
"tenant_id": "" // Leave empty to use the tenant from azure.tenant_id
},
"sql_admin_group": {
"login": "omada-sql-admins", // Display name of the SQL admin group
"object_id": "", // Leave empty to have the script create the group
"tenant_id": "" // Leave empty to use the tenant from azure.tenant_id
}
},
"shared": {
"dns_zone_name": "omada.mycompany.com", // Required; the zone to reference or create
"create_dns_zone": false, // false: zone must already exist; true: installer creates it
"dns_zone_resource_group": "my-dns-rg", // Resource group containing the DNS zone
"certificate_secret_name": "omada-tls-cert", // Name of the certificate in Key Vault
"certificate_file": "" // Optional local .pfx/.pem to import if the certificate is missing
},
"infrastructure": {
"aks_system_node_size": "Standard_D2s_v5", // AKS system node pool VM SKU
"aks_app_node_size": "Standard_D8s_v5", // AKS application node pool VM SKU
"aks_linux_node_size": "Standard_D4s_v5", // AKS Linux node pool VM SKU (optional)
"cag_vm_size": "Standard_D2s_v5", // Cloud Application Gateway VM SKU
"enable_private_endpoints": false, // Set to true to enable Azure Private Link
"enable_public_access": true, // Set to false for fully private deployments
"allowed_ip_addresses": ["203.0.113.10"], // IPs allowed to reach AKS; auto-detected if empty
"logging_level": "minimal", // "minimal" (default) or "full"
"application_insights_sampling_percentage": 100 // Telemetry sampling rate (0–100)
},
"secrets": {
"aks-extCertBase64": "", // Base64-encoded external TLS certificate (.crt)
"aks-extKeyBase64": "", // Base64-encoded external TLS private key (.key)
"aks-pfxCertificate": "", // Base64-encoded PFX certificate
"aks-pfxPassword": "" // PFX certificate password
}
}
How to fill in this file:
You do not need to populate every field before running the script. As a starting point:
-
Fill in first (
azure,deployment,backend,release, andshared.certificate_secret_name): these are required; the script will not start without them. -
Confirm prerequisites exist (
shared): the Key Vault certificate must already be in place in Azure before you run the script – and so must the DNS zone, unless you setcreate_dns_zonetotrueto have the installer create it. -
Choose your approach (
security): leaveobject_idempty to let the script create your Entra ID admin groups automatically, or fill them in to use existing groups.noteIf
entra_admin_groupandsql_admin_groupare left without anobject_id, the script checks whether a group with the configured (or default) name already exists, and prompts to create it if not. When running with--non-interactive, you must either pre-populate both groups'object_idvalues or pass--auto-create-groups; otherwise the script will fail at this step rather than prompt. -
Leave as-is unless you have specific requirements (
infrastructure): the defaults work for most standard deployments. -
Optional shortcut (
secrets): supply base64-encoded certificates here to let the script push them to Key Vault automatically. If left empty, upload them to Key Vault manually before the script reaches thesecrets_validatephase.
-
Comments (prefixed
//) are included for reference and must be removed from your actual file before use. -
Workspace naming: The
workspace_prefixmust follow the format 2 lowercase letters + 4 digits exactly (for example,ab0001). -
Key Vault secrets: Before running the full installer, you can validate Key Vault secrets independently using
validate-secrets.sh --vault-name <name>(or--listto see required secrets without checking values). This catches missing certificates before committing to a full multi-phase run.
Infrastructure sizing
The default VM SKUs are configured in deployment-config.json via the aks_system_node_size, aks_app_node_size, and cag_vm_size parameters. For sizing profiles, SKU recommendations, and cost optimization guidance, see Azure infrastructure sizing in the Omada Identity Cloud Private overview.
Monitor CPU and memory usage in Azure portal after initial deployment to determine if scaling is needed.
Logging level
The logging_level field in the deployment-config.json file controls the verbosity of AKS cluster controller logs.
AKS cluster controller logs record the activity of Kubernetes controllers – the automated systems that manage cluster health and state. This includes pod restarts, node status checks, resource allocation decisions, and other routine cluster maintenance operations.
| Value | Description |
|---|---|
minimal | Default. Logs essential cluster events only. Recommended for most deployments. |
full | Logs all controller activity, including routine checks and updates. This mode generates high-volume logs and can rapidly fill the Log Analytics workspace. |
Logging verbosity is separate from telemetry sampling, which is controlled by application_insights_sampling_percentage in the same section.
Step 3: Azure login
Authenticate with Azure CLI and verify you are on the correct subscription:
Tool: Bash shell
az login --tenant <your-tenant-id>
az account set --subscription <your-subscription-id>
az account show
Ensure your account has the Azure roles described in Identity – Contributor (or Owner) and User Access Administrator (or Owner) at subscription scope.
Step 4: Run the installation script
From the installation directory, run:
Tool: Bash shell
./install.sh --config ./deployment-config.json
The ./deployment-config.json is the default value for --config, so this is equivalent to running ./install.sh with no arguments. It is provided here for full reference.
The script runs through all phases automatically and logs progress to the following (where <project> is your project_name and <workspace> is your workspace_prefix):
Deployment_OICP_<version>/run-<project>-<workspace>/logs/install-<timestamp>.log
In the interactive mode, progress is shown live in the terminal. To monitor progress live in the non-interactive mode, execute:
Tool: Bash shell
tail -f Deployment_OICP_<version>/run-<project>-<workspace>/logs/install-*.log
The script pauses for confirmation at several points during a fresh installation, typically:
- At startup, after configuration is loaded (press Enter to continue).
- Before creating Terraform backend resources (resource group, storage account, container), if they don't already exist.
- Before publishing release artifacts to blob storage, and again before publishing container images to the registry.
- Before each
terraform apply(once for shared infrastructure, once for workspace-specific infrastructure). - If your detected OS version differs from Ubuntu 24.04.
- If some of the requested VM sizes are not available in the selected Azure region (continuing may cause the deployment to fail).
- During certificate validation (
secrets_validatephase): if a required certificate is missing or invalid, the script presents a menu to retry, import a certificate file interactively, or quit. Have your certificate files (.pfx or .pem) accessible before running the script.
Answer y at each prompt to proceed.
Run the script in a regular interactive terminal session – not piped, backgrounded, or invoked from automation – so these prompts can be answered.
In --non-interactive mode, each prompt resolves to its default instead of pausing:
- Prompts that default to Yes (the startup pause, Terraform backend resource creation, the two artifact-publish confirmations, and each
terraform apply) are accepted automatically. A non-interactive run therefore creates backend resources and applies Terraform changes without pausing for review. - Prompts that default to No (the OS-mismatch confirmation and the VM-size availability warning) fail the run immediately.
The certificate validation menu does not block unattended runs – it automatically quits, failing the phase, if a certificate is missing.
Resuming an interrupted installation
If the installation is interrupted or a phase fails, resume from the last completed phase:
Tool: Bash shell
./install.sh --config ./deployment-config.json --resume
To clear all checkpoints and restart the entire installation:
Tool: Bash shell
./install.sh --config ./deployment-config.json --force
-
Each phase records its completion as a
<phase_id>.donefile containing the UTC timestamp of when it ran, stored inDeployment_OICP_<version>/run-<project>-<workspace>/. Deleting a phase's.donefile will cause that phase to be re-executed the next time--resumeis run. -
--forceclears all checkpoints but does not destroy Azure resources. To tear down infrastructure, use Azure portal orterraform destroy.
Common options
| Flag | Description |
|---|---|
--resume | Skip completed phases and continue from the last failure. |
--force | Clear all checkpoints and re-run all phases. |
--verbose, -v | Enable debug output. |
--dry-run | Simulate Ansible execution without making changes (Ansible --check mode). |
--skip-tools | Skip tool installation phase. |
--skip-terraform | Skip both Terraform phases. |
--skip-ansible | Skip the Ansible configuration phase. |
--skip-cag | Skip the CAG VM configuration phase (runs by default otherwise). |
--tags <tags> | Restrict Ansible execution to specific tags (comma-separated). Useful for re-running a narrow slice of configuration, for example --tags dns_records. |
--non-interactive | Disable interactive prompts; fail on missing input (CI/CD mode). |
--auto-create-groups | Create Entra ID groups automatically without prompting. |
--entra-group-name <name> | Override the default Entra admin group name (omada-admins). |
--sql-group-name <name> | Override the default SQL admin group name (omada-sql-admins). |
--update-config | Write newly created Entra/SQL group IDs back into deployment-config.json. |
--workspace <prefix> | Override deployment.workspace_prefix from the command line. |
--no-cache | Force re-download of the release package instead of reusing a cached copy. |
During Ansible phases, you may see deprecation warnings related to ansible.module_utils._text imports (to_bytes, to_native, to_text). These warnings come from the Azure Ansible collection and do not affect task execution with the current pinned Ansible Core version. For details, see Known issue: Ansible module deprecation warnings.
Stage dependency overview
The installer runs the following phases in order, with each phase checkpointed on success. When using --resume, the script skips all checkpointed phases and continues from the first incomplete one – including resuming partway through the Ansible stage, since each Ansible sub-phase has its own checkpoint.
| Order | Stage | Purpose |
|---|---|---|
| 1 | preflight | OS, disk, network checks. |
| 2 | config | Load and validate deployment-config.json. |
| 3 | tools | Install toolchain (Terraform, Ansible, kubectl, etc.). |
| 4 | azure | Azure auth, RBAC and quota checks, Entra/SQL group provisioning. |
| 5 | terraform_backend | Create or validate Terraform state storage. |
| 6 | release | Download and extract Cloud Private release package. |
| 7 | terraform_iac_shared | Provision shared global infrastructure. |
| 8 | artifacts_publish_blob | Publish release artifacts to blob storage. |
| 9 | artifacts_publish_acr | Publish container images to ACR. |
| 10 | tfvars_sync | Sync release-derived values into Terraform variables. |
| 11 | secrets_validate | Validate Key Vault certificates and secrets. |
| 12 | terraform_iac | Provision workspace-specific infrastructure. |
| 13 | ansible_db_preaks | Tier 1 – pre-AKS database setup. |
| 14 | ansible_deploy_aks | Phase 1 – deploy AKS cluster, ES pod, Timer pod, and DNS records. |
| 15 | ansible_cag | CAG VM pre-configuration (skipped with --skip-cag). |
| 16 | ansible_configure_es | Tier 2+3 – ES configuration (changeset import, provisioning, connectivity). |
| 17 | ansible_deploy_aks_phase2 | Phase 2 – deploy RoPE and CagOps pods. |
| 18 | health_check | Automated post-deployment health check. Detailed documentation: Post-deployment health check. |
Completed phases are marked with checkpoint files under Deployment_OICP_<version>/run-<project>-<workspace>/.
Review the installation log for the health_check phase result and address any reported issues before handing over the environment. For the full validation checklist, see Deployment validation checklist in the Deployment guide.
If the health check reports failures or warnings and you need to troubleshoot further, see Collecting debug logs to gather diagnostic data for analysis or to send to Omada Support.