# Kubernetes installation

Starting from Ontopic Suite 2026.1.0

Kubernetes is the recommended platform for production deployments. Deployment is based on Helm (opens new window) charts. The chart source code is available on GitHub (opens new window).

# Requirements

You need to install:

Prerequisites

Please contact us for obtaining the license key and the credentials for accessing the image registry. Contact Us (opens new window)

# Limitations

  • The embedded Git repository (Gitea) is not provided.

# Create and connect to a cluster

Ontopic Suite can be installed on any standard Kubernetes cluster. This guide documents two options:

  • Azure Kubernetes Service for production deployment in the Azure cloud
  • K3D for deployment on a virtual machine or laptop, primarily for testing and development

# On Azure Kubernetes Service

We recommend following this official tutorial (opens new window) for creating and connecting to an AKS cluster.

As a starting point, we recommend using a single node with the Standard D4ds v5 (4 vCPUs, 16 GB memory) (opens new window) virtual machine size.

# On a VM with K3D

# DNS resolving for the cluster

To access locally the cluster with the domain name ontopic.local, you should modify your /etc/hosts file with:

127.0.0.1  ontopic.local

# Create the cluster

If using a VM, first connect to it using SSH.

Install K3D (opens new window)

Get the cluster configuration:

wget https://raw.githubusercontent.com/ontopic-vkg/ontopic-helm/refs/heads/main/samples/k3d/ontopic-cluster.yaml

This configuration opens two public ports: 8080 for HTTP and 4300 for the PostgreSQL port of the semantic SQL endpoints. Feel free to edit the ontopic-cluster.yaml file if you want to use different ports.

Create the cluster:

k3d cluster create -c ontopic-cluster.yaml

# Create the namespace

Here is how you can create the namespace ontopic and set it as the current context:

kubectl create namespace ontopic
kubectl config set-context --current --namespace=ontopic

Note: You can use a different namespace if preferred.

# Add the repository

Add the repository as follows:

helm repo add ontopic https://charts.ontopic.ai/

If you have already added this repository, run helm repo update to retrieve the latest package versions. You can then run helm search repo ontopic to see the available charts.

# Create a custom values.yaml file

Ontopic Suite must be configured with a custom values.yaml file. An example is provided that can be adapted to your scenario.

Get the sample file and copy it as values.yaml:

wget https://raw.githubusercontent.com/ontopic-vkg/ontopic-helm/main/values.example.yaml
cp values.example.yaml values.yaml

# Add the credentials for the image registry as a secret

Create the secret using the credentials you received by email, substituting the values <USERNAME> and <DEPLOY_TOKEN>:

kubectl create secret docker-registry regcred --docker-server=registry.gitlab.com  --docker-username=<USERNAME> --docker-password=<DEPLOY_TOKEN>

# Add the license as a secret

Create a secrets directory:

mkdir -p secrets

Add the provided Ontopic Suite license as a secret. Place the license in a file named user-license in the secrets directory.

Create the secret from the user-license file:

kubectl create secret generic user-license-file --from-file=user-license=./secrets/user-license

# Configure the ingress

The ingress controller manages incoming HTTP(S) traffic. We support three solutions:

  1. Traefik for cost-efficient production deployment
  2. Azure Application Gateway Ingress Controller (AGIC) for native Azure integration (relatively expensive)
  3. K3D default ingress controller

# Solution 1: Traefik

The Traefik controller manages both HTTP(S) traffic (Layer 7) and TCP traffic to the PostgreSQL port of the semantic SQL endpoints (Layer 4). The same domain name and IP addresses can be used for all these ports.

# Install Traefik

Add the Traefik Helm repository:

helm repo add traefik https://traefik.github.io/charts
helm repo update

First, create a static public IP. On Azure, use the following commands:

# Use the AKS node resource group (starts with MC_)
RESOURCE_GROUP="MC_<your-rg>_<your-aks-cluster>_<region>"
IP_NAME="traefik-public-ip"
LOCATION="westeurope"
# Create the static IP
az network public-ip create \
  --resource-group $RESOURCE_GROUP \
  --name $IP_NAME \
  --sku Standard \
  --allocation-method Static \
  --location $LOCATION
# Get the IP address
az network public-ip show \
  --resource-group $RESOURCE_GROUP \
  --name $IP_NAME \
  --query ipAddress -o tsv

Register this static public IP with your DNS provider using the name <YOUR_DOMAIN_NAME>.

Then install Traefik with the static IP:

STATIC_IP="<your-static-ip>"
helm install traefik traefik/traefik \
  --namespace traefik \
  --create-namespace \
  --set service.spec.loadBalancerIP=$STATIC_IP \
  --set ports.postgres.port=4300 \
  --set ports.postgres.expose.default=true \
  --set ports.postgres.exposedPort=4300 \
  --set ports.postgres.protocol=TCP

This configures Traefik with:

  • Default HTTP (port 80) and HTTPS (port 443) entrypoints
  • A custom postgres entrypoint on port 4300 for the PostgreSQL wire protocol
  • A static IP for stable DNS configuration

Verify the installation:

kubectl get pods -n traefik
kubectl get svc -n traefik

# Configure Ingress for HTTP

Update your values.yaml to use Traefik:

ingress:
  host: <YOUR_DOMAIN_NAME>
  className: traefik

# Expose Postgres service with Traefik IngressRouteTCP

After deploying the Helm chart, create an IngressRouteTCP resource to expose PostgreSQL through Traefik. Save the following to postgres-ingressroute.yaml:

apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: ontopic-postgres
spec:
  entryPoints:
    - postgres
  routes:
    - match: HostSNI(`*`)
      services:
        - name: ontopic-server-postgres
          port: 4300

Apply the resource:

kubectl apply -f postgres-ingressroute.yaml

Clients can then connect to PostgreSQL at <YOUR_DOMAIN_NAME>:4300 for Semantic SQL queries.

# Solution 2: AGIC

Azure Application Gateway Ingress Controller (AGIC) (opens new window) provides native integration with Azure infrastructure and manages HTTP(S) traffic (Layer 7) through Azure Application Gateway. However, it does not support TCP routing for the PostgreSQL wire protocol. Therefore, AGIC is used for web traffic and a separate Azure Load Balancer for PostgreSQL connections on port 4300.

In the Azure portal (opens new window), go to Kubernetes services, open your Kubernetes service, navigate to Settings > Networking > Virtual network integration, and in the Application Gateway ingress controller section, click on Manage. Enable Ingress controller and click on Save.

It may take up to 15 minutes for the ingress controller to start. Once ready, you will see it appear in the Application Gateway ingress controller section. Click on it, then click on Frontend public IP address and copy the IP address field. This is the public IP address for HTTP(S) traffic. Assign <YOUR_DOMAIN_NAME> to this IP address.

Next, create a static public IP in Azure for the PostgreSQL port:

# Use the AKS node resource group (starts with MC_)
RESOURCE_GROUP="MC_<your-rg>_<your-aks-cluster>_<region>"
IP_NAME="pg-public-ip"
LOCATION="<region>"
# Create the static IP
az network public-ip create \
  --resource-group $RESOURCE_GROUP \
  --name $IP_NAME \
  --sku Standard \
  --allocation-method Static \
  --location $LOCATION
# Get the IP address
az network public-ip show \
  --resource-group $RESOURCE_GROUP \
  --name $IP_NAME \
  --query ipAddress -o tsv

Assign the domain name <YOUR_DOMAIN_NAME_FOR_PG> to this IP.

Edit the values.yaml file:

ingress:
  host: <YOUR_DOMAIN_NAME>
  className: azure-application-gateway
ontopic-server:
  postgresService:
    type: LoadBalancer
    host: <YOUR_DOMAIN_NAME_FOR_PG>
    annotations:
      service.beta.kubernetes.io/azure-pip-name: pg-public-ip

# Solution 3: K3D default ingress controller

With K3D, edit the values.yaml file to assign the domain name (e.g. ontopic.local for a local installation) as host and set a load balancer for the postgres service:

ingress:
  host: <YOUR_DOMAIN_NAME>
ontopic-server:
  postgresService:
    type: LoadBalancer

Both the Postgres service (port 4300) and HTTP (port 8080) will be available at <YOUR_DOMAIN_NAME>.

# Configure the internal database

Ontopic Suite requires a PostgreSQL database for internal storage. Choose one of the following options:

  1. Use the built-in database (default): Automatically deploys a PostgreSQL chart to the cluster
  2. Use an external database: Connect to your own PostgreSQL instance

# Option 1: Built-in database

By default, the Helm chart deploys a PostgreSQL database in the cluster. No additional configuration is required.

# Option 2: External database

To use your own PostgreSQL database, configure the connection parameters in your values.yaml file:

db:
  deployedInCluster: false
  host: <db_host>
  port: <db_port>
  name: <db_name>
  user: <db_user>

# Create the database password secret

Before deploying Ontopic Suite with an external database, create the database-password secret manually:

# Create secrets directory if it doesn't exist
mkdir -p ./secrets
# Save the password to a file
echo -n "<your-db-password>" > ./secrets/database-password
# Create the Kubernetes secret
kubectl create secret generic database-password \
  --from-file=database-password=./secrets/database-password

# What's next

To further configure Ontopic Suite, you can:

Afterwards, start Ontopic Suite.