# Azure

This guide explains how to deploy the full **Nected Platform** on **Microsoft Azure** using Terraform. The Terraform configuration provisions networking, an AKS cluster, databases, caching, logging infrastructure, DNS, SSL certificates, and all runtime services required for a production-grade Nected setup. Every step below prepares your system for a deterministic and reproducible deployment.

#### Prerequisites

Install the following tools on your machine and verify that each one runs correctly.

| Requirement | Version | Purpose                                                            |
| ----------- | ------- | ------------------------------------------------------------------ |
| Terraform   | ≥ 1.6   | Infrastructure as Code (IaC) tool for provisioning Azure resources |
| Azure CLI   | ≥ 2.60  | Command-line tool for interacting with Azure services              |
| kubectl     | Latest  | Kubernetes command-line tool for cluster management                |
| Helm        | Latest  | Kubernetes package manager for deploying applications              |
| Git         | Latest  | Version control system for cloning the repository                  |

Terraform manages Azure resources, the Azure CLI handles authentication and cluster access, kubectl interacts with AKS, and Helm deploys Nected’s workloads.

**Azure Resources & Nected license key**

To successfully deploy the infrastructure, ensure you have:

* **An active Azure Subscription** and its **Subscription ID**
* **One Azure DNS Hosted Zone**, which will be used for:
  * Creating CNAME records for all Nected services
  * Adding DNS entries required for SSL certificate validation
  * **Important:** To issue an SSL certificate using Cert-Manager, the domain must have a public DNS zone for verification.
* **One Azure Resource Group** where the entire infrastructure will be created.
  * The **Hosted Zone** can be in the *same* Resource Group or a *different* one.
* **Nected License Key** required for installing the full Nected service
  * Remove it from `terraform.tfvars` if you want to use the free & limited version

#### Authentication

Authenticate your environment with Azure.

Login:

```bash
az login
```

Select the correct subscription:

```bash
az account set --subscription "<YOUR_SUBSCRIPTION_ID>"
```

Confirm your context:

```bash
az account show
```

Terraform uses these credentials to communicate with Azure Resource Manager APIs.\
If authentication fails, no resource can be created. Always verify this step before proceeding.

#### Repository Setup and Installation Steps

Clone the Terraform deployment repository from GitHub. These files contain all resource definitions, Terraform modules, and environment-specific variables.

Clone the repository:

```bash
git clone https://github.com/nected/nected-terraform.git
```

Move into the project directory:

```bash
cd nected-terraform
```

Spend a moment reviewing the folder layout. Understanding which module controls which resource helps you troubleshoot or extend the deployment later.

#### Configuration

You must create a `terraform.tfvars` file to supply the environment-specific values. Terraform loads this file automatically and merges it into your configuration.

**Example `terraform.tfvars`**

```hcl
# Prerequisites
subscription_id     = "<YOUR_SUBSCRIPTION_ID>"
resource_group_name = "<YOUR_RESOURCE_GROUP>"
base_domain         = "<YOUR_BASE_DOMAIN>"

# Set false if base_domain hosted zone is not available
# If az_hosted_zone = false
#  - Manual DNS mapping required post deployement
#  - Required key_vault_name for SSL
az_hosted_zone      = true

# set hosted_zone_rg if base_domain hosted zone is in different resource group
# default: "null" and expect hosted zone in resource_group_name
# hosted_zone_rg    = "<HOSTED_ZONE_RESOURCE_GROUP>"

# SSL certificates, provide vault name & certificate name
# default: "null" and generate using Let's Encrypt
# key_vault_name = "<KEY_VAULT_NAME>"
# key_vault_certificate_name = "<KEY_VAULT_CERTIFICATE_NAME>"

# Nected License (uncomment to use paid version)
# default: free key with limited usage
# nected_pre_shared_key = "<NECTED_LICENSE_KEY>"

# Project Information
project             = "nected"
environment         = "dev"

# Network Configuration
vnet_address_space = "10.50.0.0/16"

# AKS Configuration
kubernetes_version = "1.33"
aks_node_count     = 2
aks_min_node_count = 2
aks_max_node_count = 4
aks_vm_size        = "Standard_D4s_v6"

# Application Gateway private ip
# default public ip
agic_internal = false

# PostgreSQL
pg_version      = 17
pg_admin_user   = "psqladmin"
pg_admin_passwd = "<password>"
pg_sku_name     = "GP_Standard_D4ds_v5"
pg_disk_size    = 262144       # 256 GB
pg_backup_retention = 7

# Redis (use Azure Redis Cache)
# default redis via datastore helm chart
use_managed_redis = false

# Elasticsearch
elasticsearch_version        = "8.12.0"
elasticsearch_vm_size        = "Standard_D2ds_v4"
elasticsearch_admin_username = "elastic"
elasticsearch_admin_password = "<password>"

# Application variables
# Chart versions
nected_chart_version = "0.4.35"

# Domain Configuration
ui_domain_prefix      = "ui"
backend_domain_prefix = "backend"
router_domain_prefix  = "router"

# Serivices env configs
nected_env_overrides = {
  "nalanda" = {
    # notifications setiings
    SEND_EMAIL         = "false"
    EMAIL_PROVIDER     = "smtp"
    SENDER_EMAIL       = ""
    SENDER_NAME        = ""
    EMAIL_INSECURE_TLS = ""
    EMAIL_HOST         = ""
    EMAIL_PORT         = ""
    EMAIL_USERNAME     = ""
    EMAIL_PASSWORD     = ""

    # to restrict signup/invite user email domain
    SIGNUP_DOMAINS = ""
  }
}

# Console Access
# username is always an email and password should be alphanumeric at least 8 characters
console_signup_domains = ""
console_user_email    = "<<user email>>"
console_user_password = "<<password>>"
```

> ⚠️ Do not commit terraform.tfvars to version control. Add it to .gitignore.

#### Remote Terraform State (Optional)

If you want to use **remote Terraform state** in **Azure Blob Storage**, create the following:

1. **Azure Storage Account**
2. **Blob Container** inside the storage account
3. Update your `backend.tf` file with the correct values.

Example `backend.tf` configuration:

```hcl
terraform {
  backend "azurerm" {
    resource_group_name  = "<RESOURCE_GROUP>"
    storage_account_name = "<STORAGE_ACCOUNT_NAME>"
    container_name       = "<CONTAINER_NAME>"
    key                  = "<TFSTATE_FILE_NAME>.tfstate"
  }
}
```

Ensure these resources are created **before** running `terraform init`.

Each variable directly influences the resources deployed on Azure.\
For example:

* `vnet_address_space` defines the private network boundary for all Nected services.
* `aks_vm_size` decides the compute capacity of each AKS worker node.
* `base_domain` combined with domain prefixes produces all public URLs for UI, API, and router.
* `nected_pre_shared_key` activates your Nected license inside the cluster.

Always verify that your values comply with Azure’s constraints—especially VM SKUs, PostgreSQL SKUs, and address spaces.

#### Deployment Steps

Execute the commands below from inside the repository directory. Terraform will detect modules, providers, and variable files automatically.

**Step 1: Initialize the Terraform Workspace**

```bash
terraform init
```

Terraform downloads provider plugins, prepares the backend, and scans the modules.\
This process ensures all components needed for deployment are present.

**Step 2: Validate the Configuration**

```bash
terraform validate
```

This step checks your file structure and ensures that Terraform syntax, variable types, and references are correct.\
It prevents many common errors before provisioning.

**Step 3: Preview the Changes**

```bash
terraform plan -out=tfplan
```

The plan lists all Azure resources Terraform will create, modify, or remove.\
Read the output carefully because Azure resources incur cost.\
This step provides visibility before making irreversible changes.

**Step 4: Apply the Deployment**

```bash
terraform apply tfplan
```

Terraform provisions:

* The Azure Resource Group
* The Virtual Network and all subnets
* The AKS cluster using your specified VM size and scaling configuration
* A PostgreSQL Flexible Server
* A Redis Cache instance
* An Elasticsearch VM-based cluster
* DNS entries, routing rules, and SSL certificates
* Helm deployments that install Nected services inside AKS

Azure typically takes several minutes to create managed services.\
The AKS cluster and PostgreSQL server are usually the slowest resources.

{% hint style="warning" %}
The Deployment Process might take \~25 minutes to complete
{% endhint %}

#### Post-Deployment Tasks

Once Terraform finishes, retrieve the outputs:

```bash
terraform output
```

This returns critical information for operations:

* The AKS cluster name
* Resource group names
* Fully qualified domain names for all Nected services
* PostgreSQL and Redis endpoints
* Elasticsearch connection details
* Admin console credentials
* kubeconfig contents (if enabled)

Use these values to connect to your environment.

**Access AKS**

Fetch Kubernetes credentials:

```bash
az aks get-credentials \
  --resource-group <resource_group> \
  --name <aks_name>
```

Check cluster access:

```bash
kubectl get nodes
```

You should see your AKS worker node pool listed.\
If access fails, confirm that your Azure user has the correct RBAC role.

**Alternative kubeconfig extraction**

If you want to use the kubeconfig file generated by Terraform:

```bash
terraform output -raw kube_config > /tmp/kubeconfig
export KUBECONFIG=/tmp/kubeconfig
```

This method is useful in CI systems or non-interactive environments.

**Retrieving encryption key**

Ensure the following secret is retrieved and backed up:

```bash
kubectl get secret encryption-at-rest-secret -o yaml > encryption-at-rest-secret
```

#### Upgrade Nected apps

**Upgrade using Terraform**

Update `terraform.tfvars`:

```hcl
nected_chart_version = "<version-number>"
```

Apply the upgrade:

```bash
terraform apply
```

**Upgrade using Helm**

```bash
helm get values nected > nected-values.yaml
helm upgrade -i nected nected/nected -f nected-values.yaml --version <version-number>
```

#### Destroying the Environment

Remove all resources created by Terraform:

```bash
terraform destroy
```

Terraform deletes the VNet, AKS, databases, Redis, Elasticsearch, and DNS records.\
Azure may take a few minutes to release large managed services.\
Run this only when the environment is no longer required.

#### Accessing the Nected Application

Your deployed instance becomes available at:

* UI: `https://<ui_domain_prefix>.<base_domain>`
* Backend: `https://<backend_domain_prefix>.<base_domain>`
* Router: `https://<router_domain_prefix>.<base_domain>`

Login using the credentials defined in `terraform.tfvars`:

* Email: `console_user_email`
* Password: `console_user_password`

Once logged in, verify UI connectivity, API responsiveness, webhook endpoints, and rule execution.

#### Terraform Azure: Public Domain vs Private Domain Configuration

This section explains how domain configuration behaves in Azure-based Terraform deployments and what changes when you deploy Nected using a public domain versus a private domain.

**Public Domain Deployment (Azure DNS / Public Access)**

When you deploy Nected on a **public domain**, Terraform provisions the Application Gateway and related resources for internet-facing access.

Key characteristics:

* Application endpoints are exposed using the **public IP of the Azure Application Gateway**
* DNS records are created in **Azure DNS (Public Zone)**
* If `az_hosted_zone = false`, manual DNS mapping is required after deployment

Required `terraform.tfvars` configuration:

* Set `agic_internal = false`

This is the default configuration. Use this setup when Nected must be accessible over the public internet using a public IP address.

**Private Domain Deployment (VNet / Internal Access Only)**

When you deploy Nected on a **private domain**, all application traffic remains within your Azure virtual network.

Key characteristics:

* Application endpoints use the **private IP of the Azure Application Gateway**
* DNS records are created in **Azure DNS Private Zones** mapped to private IP addresses
* Access is limited to internal networks, VPN, or private connectivity

Required `terraform.tfvars` configuration:

* Set `agic_internal = true`

Use this configuration for regulated environments or deployments that require network isolation and restricted access.

***

**Summary**

| Deployment Type | Public Domain | Private Domain |
| --------------- | ------------- | -------------- |
| Internet Access | Yes           | No             |
| Domain Mapping  | Public IP     | Private IP     |

Select the deployment model based on your access and security requirements before running `terraform apply`.

#### Terraform Azure: Managed Redis vs Redis in AKS

This section explains how Redis is provisioned in Azure-based Terraform deployments and when to use managed Azure Redis Cache versus Redis deployed inside AKS.

**Default: Redis Deployed in AKS (Recommended)**

By default, Terraform deploys Redis using the **Nected datastore Helm chart** inside the AKS cluster.

Key characteristics:

* Redis runs as a Kubernetes workload inside AKS
* Used only for **caching**, not for persistent storage
* Faster overall deployment time
* No additional network latency between AKS and Redis

This setup is recommended for most deployments.

**Optional: Azure Managed Redis Cache**

If you choose to use **Azure Redis Cache**, Terraform provisions a managed Redis instance instead of deploying Redis in AKS.

Required `terraform.tfvars` configuration:

* Set `use_managed_redis = true`

Important considerations:

* Adds approximately **20 minutes** to the deployment time
* Introduces additional network latency compared to in-cluster Redis
* Suitable when organizational policies mandate the use of managed cloud services

Use this option only when managed Redis is explicitly required by your infrastructure or compliance standards.

#### JMeter Load testing

Update the following placeholders in the configuration:

* \[RULE\_ID]
* \[RULE\_DOMAIN]
* \[RULE\_DOMAIN\_IP] (optional)
* \[NECTED\_API\_KEY]
* \[RULE\_PAYLOAD] {"environment": "production", "params": {"a": 1}}

**Run JMeter**

```bash
kubectl create ns jmeter
kubectl apply -f jmeter-test/jmeter-k8s.yaml
kubectl -n jmeter get pods
kubectl -n jmeter logs -f jmeter-master
```

**Retrieve JMeter Report**

To copy the generated JMeter report after the test completes:

```bash
kubectl -n jmeter cp jmeter-master:/test/output .
```

> Default configuration supports approximately 25 RPS.

#### Support

For deployment questions or feedback:

* Read our documentation
* Join the conversation on [LinkedIn](https://www.linkedin.com/company/nected-ai/)
* Email: [**support@nected.ai**](mailto:support@nected.ai)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.nected.ai/nected-docs/self-hosting/new-installation/terraform/azure.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
