Install Tembo Self Hosted on Azure

Installing Tembo Self Hosted on Azure

This guide describes the steps to install Tembo Self Hosted on Azure, enabling you to deploy a high-performance, fully-extensible managed Postgres service within an Azure Kubernetes Service (AKS) cluster.

Step 1: Obtain prerequisites

Before starting this tutorial, you must install and configure the following tools and resources necessary to create and manage Tembo Self Hosted on an Azure AKS cluster.

Step 2: Choose and set up a base domain

For the Tembo services, you will need to select a base domain, such as

Once you have chosen your base domain, ensure you have the capacity to add and modify DNS records for it.

With this setup, your users will be able to access various subdomains to manage, monitor, and run Postgres on the platform:

  • Software UI:
  • Backend requests:
  • Tembo Dataplane:

Step 3: Create an AKS control plane and a Kubernetes cluster

To create an AKS cluster named tembo-cluster with a minimum of three nodes, run the following command:

export RESOURCE_GROUP=yourResourceGroup
export CLUSTER_NAME=your-cluster-name

az aks create --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --node-count 3 --node-vm-size Standard_D4s_v3 --enable-managed-identity --enable-disk-driver --location eastus

Feel free to adjust the parameters as needed to suit your requirements.

For further information, see Quickstart: Deploy an Azure Kubernetes Service (AKS) cluster.

Step 4: Install Helm dependencies

1. Install cert-manager

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.14.4 --set installCRDs=true

1.1. Verify cert-manager installation

$ k get pods -n cert-manager

NAME                                      READY   STATUS    RESTARTS   AGE
cert-manager-6dc66985d4-vm2p8             1/1     Running   0          3d
cert-manager-cainjector-c7d4dbdd9-r96lv   1/1     Running   0          3d
cert-manager-webhook-847d7676c9-vg2c7     1/1     Running   0          3d

2. Configure Traefik

Firstly, create the traefik namespace:

kubectl create namespace traefik || true

To configure which connections Traefik should accept, create a ConfigMap. If you want to accept all connections, use a ConfigMap similar to the one below:

apiVersion: v1
kind: ConfigMap
  name: postgres-catch-all
  namespace: traefik
  postgres-catch-all.yaml: |
            - "postgresql"
          rule: "HostSNI(`*`)"
          service: empty
            servers: {}

Now, apply the ConfigMap you desire to use. If the accept-all configuration was chosen (as shown above), run:

kubectl apply -f traefik-postgres-catch-all.yaml

We now need to configure Traefik to handle Postgres connections appropriately. See the example values for reference.

Finally, install Traefik:

helm install traefik traefik/traefik --namespace traefik --version 20.8.0 -f traefik-values.yaml

Step 5: Configure DNS for Traefik’s Load Balancer

To properly route traffic to your Traefik load balancer, you need to configure a DNS CNAME record through your DNS provider. Follow the steps below to create a wildcard CNAME record, which is essential because each PostgreSQL instance has its own subdomain for its connection string.

Step 5.1: Set up a DNS Zone in Azure Portal

Create a DNS zone for your chosen Tembo Self Hosted subdomain, e.g.

For more information, see Create a DNS Zone.

Step 5.2: Identify Traefik’s Load Balancer external IP

kubectl get svc -n traefik
NAME      TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                       AGE
traefik   LoadBalancer  1234:56789/TCP,80:12345/TCP   45m

In the example above, the Load Balancer’s external IP would be

Step 5.3: Create an A record to re-route traffic to Traefik’s Load Balancer

# Must have previously set this DNS Zone up in the Azure Portal
export DNS_ZONE_NAME=""
export RECORD_SET_NAME="*"
# EXTERNAL-IP as shown in `k get svc -n traefik` 

az network dns zone create --resource-group $RESOURCE_GROUP_NAME --name $DNS_ZONE_NAME

az network dns record-set a add-record --resource-group $RESOURCE_GROUP_NAME --zone-name $DNS_ZONE_NAME --record-set-name $RECORD_SET_NAME --ipv4-address $LOAD_BALANCER_PUBLIC_IP

For more detailed information, refer to Create a DNS zone and record using the Azure portal.

Step 5.4. Verify DNS settings

After creating the CNAME record, verify that the DNS settings are correctly propagating and resolving.

You can use nslookup to check if your DNS settings are working correctly:


Non-authoritative answer:

Step 6: Add ipAllowList to the Traefik’s CRD

To middlewaretcps in, add:

                description: |-
                  IPAllowList defines the IPAllowList middleware configuration.
                  This middleware accepts/refuses connections based on the client IP.
                  More info:
                    description: SourceRange defines the allowed IPs (or ranges of
                      allowed IPs by using CIDR notation).
                      type: string
                    type: array
                type: object

Step 7: Configure permissions for the CSI driver

In order to use the premium-ssd-enc StorageClass (defined in the next step), we need to configure some permissions. This step assumes that the cluster is using a SystemAssigned or UserAssigned identity (rather than ServicePrincipal).

# Identify the object ID for this identity
export OBJECT_ID=$(az aks show --resource-group $RESOURCE_GROUP_NAME --name $AKS_CLUSTER_NAME --query identityProfile.kubeletidentity.objectId -o tsv)

8.1. Granting permissions

Create the role assignment:

export SUBSCRIPTION_ID="your-subscription-id"
export RESOURCE_GROUP_NAME="your-resource-group-name"
export OBJECT_ID="your-object-id"  # Retrieved from the above script

az role assignment create --assignee $OBJECT_ID --role Contributor --scope /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME

Verify the role assignment:

az role assignment list --assignee $OBJECT_ID --scope /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME

Step 8: Create the premium-ssd-enc StorageClass

Apply premium-ssd-enc-storage.yaml.

kubectl apply -f premium-ssd-enc-storage.yaml

Step 9: Install the Tembo Self Hosted Helm chart

Clone the Tembo Self Hosted repository:

git clone

Now, within the cloned tembo-self-hosted directory, create a file my-values.yaml with the following content:

  monitoringEnabled: true
  conductorEnabled: false
      - name: STRIPE_SECRET_KEY
        value: <secret-key>
        value: <signing-secret>

The base domain should be the same one created in Step 2.

Now, let’s install the Tembo Self Hosted Helm chart in your AKS cluster:

helm install tembo . -f my-values.yaml -n tembo --create-namespace

Let’s now enable the conductor component:

  monitoringEnabled: true
  conductorEnabled: true

Upgrade the Self Hosted Helm chart so that changes take effect:

helm upgrade tembo . -f my-values.yaml -n tembo

Step 10: Deploy a Tembo Postgres instance through mahout

Access and create a Postgres instance through the Tembo UI.


chevron right arrow


Tembo self hosted