Skip to main content

Azure Kubernetes Service (AKS) provisioner backend

Provision Nora agents into Azure Kubernetes Service (AKS) using Nora’s generic Kubernetes adapter and Admin cluster registry.
AKS uses the same Kubernetes adapter as every Kubernetes provider. Nora stores provider, namespace, exposure, and load-balancer settings on the Admin cluster row; docker-compose.kubernetes.yml only mounts kubeconfig files into the control-plane containers.

Step-by-step setup

1. Prerequisites

  • Azure subscription with permission to create AKS clusters.
  • An existing AKS cluster (or create one — Azure Portal → Kubernetes servicesCreate).
Use the cluster Overview blade to confirm the AKS cluster name and resource group before running the CLI commands below.
AKS cluster overview

Azure Portal — AKS cluster overview (cluster name and resource group)

2. Install and log in with Azure CLI

Install the Azure CLI on the host that runs Nora, then authenticate against the Azure subscription that owns the AKS cluster. Azure Cloud Shell already includes az, but the kubeconfig file still needs to be saved on the Nora host.
After installation, confirm the CLI is available and sign in:
For other package managers or locked-down hosts, use Microsoft’s Azure CLI install guide and Azure CLI authentication guide.

3. Install kubectl

Install kubectl on the same host where you will run Nora setup and verification commands. For AKS, the shortest path is Azure CLI’s Kubernetes tool installer:
If you prefer an OS package manager:
For other Linux distributions or direct binary installs, use the official Kubernetes kubectl install guide.

4. Create the kubeconfig

You can copy this command directly from the cluster’s Connect blade in the Azure Portal.
AKS Connect blade

Azure Portal — Cluster → Connect: copy the get-credentials command

5. Verify access from the host

6. Configure Nora

Set the generic Kubernetes mount variable in .env:
For two or more AKS clusters, put each kubeconfig under NORA_KUBECONFIGS_DIR and use Admin paths such as /kubeconfigs/aks-eastus2 and /kubeconfigs/aks-westus2.

7. Start the stack

This smoke-mode command is for the local nginx config (NGINX_CONFIG_FILE=nginx.conf, usually NGINX_HTTP_PORT=8080). If your .env already points to the public TLS config (NGINX_CONFIG_FILE=nginx.public.conf), include the tracked infra/docker-compose.public-tls.yml layer as shown in Promote to production; otherwise nginx will not mount /etc/letsencrypt and Cloudflare can return 521 because the origin web server is down.

8. Register this cluster in Admin

Open Admin -> Kubernetes, click Add cluster, and use these values: Do not put ./.secrets/aks-kubeconfig in the Admin Kubeconfig path when Nora runs in Docker Compose. That is the host-side path; the containers see files from NORA_KUBECONFIGS_DIR under /kubeconfigs.

9. Deploy test agents

Open the dashboard at http://127.0.0.1:8080, sign in, and create an OpenClaw agent with the AKS cluster label you registered. To validate Hermes on AKS, create a second agent with Runtime = Hermes and the same AKS execution target.
Backend picker

Nora deploy wizard — Backend dropdown showing Kubernetes on AKS

Kubernetes selected

Nora deploy wizard — Kubernetes on AKS selected

Agent detail K8s

Agent detail — status running with the AKS LoadBalancer address

AKS Service options

For a public load balancer, leave Service annotations JSON empty and restrict access with Source ranges when possible. For an internal AKS load balancer:
Confirm the LoadBalancer SKU in the Azure Portal under Settings → Networking matches what your subnet policies allow.
AKS networking settings

Azure Portal — Cluster → Settings → Networking (LoadBalancer SKU)

Do not set the Admin Runtime host to the AKS API server address. Nora uses the Kubernetes API through kubeconfig, and agent gateway/runtime traffic uses the per-agent Service address.

Verification

For real e2e, enable the Kubernetes matrix cell:
Agent logs K8s

Logs tab — worker-provisioner output during a successful AKS deploy

Automated smoke

Once your AKS kubeconfig is in place, run the shared lifecycle smoke. The AKS script deploys both OpenClaw and Hermes by default:
This script is operator-run only — it provisions real workloads against a live AKS cluster and is not part of CI. Set K8S_SMOKE_RUNTIME_FAMILIES=openclaw for a single-runtime check, K8S_SMOKE_CELLS=openclaw:nemoclaw plus NVIDIA_API_KEY for a NemoClaw run, or KEEP_ENV=true to leave the stack running after the script finishes.

Promote to production

Once the smoke is green, switch from the dev-mode stack to the prod-mode stack. The only changes vs the testing setup are nginx (public config + TLS) and Compose mode (infra/docker-compose.public-tls.yml for prod Dockerfiles, TLS mounts, public ports, and restart policies).

1. Tighten the LoadBalancer source ranges

Replace the smoke-time <nora-control-plane-egress-cidr> placeholder with your production control plane’s actual egress CIDR (e.g. the public IP of the host running Nora). Combine with internal-LB annotations if you’re keeping agents on a private subnet.

2. Switch nginx to public + TLS

In .env:
Provision Let’s Encrypt certs once:

3. Stop the smoke-mode stack

4. Start the prod-mode stack

5. Confirm

Deploy a real agent from the UI and confirm it reaches running and the AKS LoadBalancer assigns an external IP.

See also

  • Kind — local Kubernetes for development
  • K3s — self-hosted production K8s
  • GKE — Google Kubernetes Engine
  • EKS — Amazon EKS