Skip to content

Deployment

Nexivo runs on a single-node MicroK8s cluster per environment. All platform services are deployed via Helm. Secrets are applied manually with kubectl. Databases are self-hosted.


Environments

Environment Purpose Kubeconfig
dev Development & integration testing ~/dok8s/dev_tunnel.yaml
uat User acceptance testing ~/dok8s/uat.yaml
live Production (UK) ~/dok8s/live-uk-kubeconfig.yaml
# dev
export KUBECONFIG=~/dok8s/dev_tunnel.yaml

# uat
export KUBECONFIG=~/dok8s/uat.yaml

# live
export KUBECONFIG=~/dok8s/live-uk-kubeconfig.yaml

Useful aliases for your shell profile:

alias kdev='KUBECONFIG=~/dok8s/dev_tunnel.yaml kubectl'
alias kuat='KUBECONFIG=~/dok8s/uat.yaml kubectl'
alias klive='KUBECONFIG=~/dok8s/live-uk-kubeconfig.yaml kubectl'

Cluster Layout

Services are split across two primary namespaces:

Namespace Contents
nexivo All platform microservices, frontends, datastores
livekit LiveKit server, SIP gateway, Kamailio SBC, Atlas, Herald, KEDA
keycloak Keycloak authentication service
ingress-nginx NGINX ingress controller
cert-manager TLS certificate management
cnpg-system CloudNativePG operator
minio MinIO object storage
monitoring kube-state-metrics

Deployment Diagram

graph TB
    Internet((Internet))

    subgraph Ingress["ingress-nginx"]
        NG[NGINX Ingress\nTLS termination]
    end

    subgraph KeycloakNS["keycloak"]
        KC[Keycloak\nauth.nexivo.corecognitics.cc]
    end

    subgraph LiveKitNS["livekit namespace"]
        LK_SRV[livekit-server\nvoice.nexivo.corecognitics.cc]
        LK_SIP[livekit-sip-gateway\nsip.nexivo.corecognitics.cc]
        KAMA[kamailio-sbc\nSIP Session Border Controller]
        ATLAS[livekit-multi-agent-service\nAtlas · 2–10 pods KEDA]
        MEDIAB[livekit-communication-service\nMedia Bot · 8 pods]
        HERALD[text-multi-agent-service\nHerald · 1 pod]
        OE[orchestrator-engine\n3 pods]
        EGRESS[livekit-egress\n1–6 pods KEDA]
        LK_VK[(livekit-valkey\n1 primary + 3 replicas)]
    end

    subgraph NexivoNS["nexivo namespace"]
        subgraph Frontends["Frontends"]
            PORTAL[nexivo-portal\napp.nexivo.corecognitics.cc]
            ADMIN[nexivo-admin\nadmin.nexivo.corecognitics.cc]
            WIDGET[nexivo-widget\n5 pods]
            INSIGHTS_FE[call-insights-frontend\ninsights.nexivo.corecognitics.cc]
            REPORTS[nexivo-reports\nreports.nexivo.corecognitics.cc]
            DASHBOARD[nexivo-dashboard\nops.nexivo.corecognitics.cc]
            CAMPAIGN_HUB[campaign-hub\ncampaign.nexivo.corecognitics.cc]
        end

        subgraph CoreSvcs["Core Services"]
            CS[call-service · 3]
            WAS[whatsapp-service · 1]
            BL[billing-service · 3]
            AC[app-connect · 1]
            COMPASS[ai-provisioning-service\nCompass · 1]
            MCP_SRV[app-mcp-server · 1]
            TMS[tool-management-service · 2]
            NOTIF[notification-service · 3]
        end

        subgraph CommSvcs["Communication Services"]
            CHAT[chat-service · 3]
            EMAIL[email-service · 3]
            CAMP[campaign-service · 3]
            SCHED[communication-scheduler · 3]
            MSG[message-service · 1]
            CONTACT[contact-service · 3]
            PHONE[phone-number-service · 3]
            TRANSCRIPT[transcript-service · 3]
            INSIGHTS_SVC[call-insights-service · 1]
            WIDGET_SVC[communication-widget-service · 3]
        end

        subgraph DataStores["Datastores"]
            PG[(nexivo-db-cluster\nCloudNativePG · 2 nodes · 10 Gi each)]
            REDIS[(nexivo-redis · 8 Gi)]
            VALKEY[(nexivo-valkey\n1 primary + 3 replicas · 8 Gi each)]
            QDRANT[(nexivo-qdrant\nVector DB · 10 Gi)]
            CH[(ClickHouse\nReporting · 2 shards · 20 Gi each)]
        end
    end

    Internet --> NG
    NG --> PORTAL & ADMIN & INSIGHTS_FE & REPORTS & DASHBOARD & CAMPAIGN_HUB
    NG --> KC
    NG --> LK_SRV & LK_SIP

    LK_SIP --> KAMA
    LK_SRV --> ATLAS & MEDIAB
    CS --> LK_SRV
    WAS --> HERALD

    CoreSvcs --> PG
    CommSvcs --> PG
    CoreSvcs --> REDIS
    CoreSvcs --> VALKEY
    QDRANT -.->|vector search| COMPASS
    CH -.->|analytics| INSIGHTS_SVC

Services by Namespace

nexivo namespace — Platform Services

Core

Deployment Replicas Image Ingress
call-service 3 communication-services/call-service
whatsapp-service 1 communication-services/whatsapp-service
billing-service 3 communication-services/billing-service
app-connect 1 service-gateway/app-connect
ai-provisioning-service (Compass) 1 intento/tenantator/compass
app-mcp-server 1 intento/mcp-servers/intento-rest-api-services
tool-management-service 2 intento/tool-management-service
notification-service 3 communication-services/notification-service
conductor 1 common-services/conductor
communication-ai-service 2 communication-services/ai-service
feedback-service 2 communication-services/feedback-service feedback.nexivo.corecognitics.cc
opportunity-service 1 communication-services/opportunity-service

Communication

Deployment Replicas Image
chat-service 3 communication-services/chat-service
email-service 3 communication-services/email-service
campaign-service 3 campaign-services/campaign-service
communication-scheduler 3 communication-services/communication-scheduler
message-service 1 communication-services/message-service
contact-service 3 communication-services/contact-service
contact-status-service 2 communication-services/contact-status-service
phone-number-service 3 communication-services/phone-number-service
transcript-service 3 communication-services/transcript-service
call-insights-service 1 communication-services/call-insights-service
communication-widget-service 3 communication-services/widget-service
hls-s3-proxy 2 intento/hls-s3-proxy

Frontends

Deployment Replicas URL
nexivo-portal 1 app.nexivo.corecognitics.cc
nexivo-admin 1 admin.nexivo.corecognitics.cc
nexivo-widget 5
nexivo-dashboard 1 ops.nexivo.corecognitics.cc
nexivo-reports 1 reports.nexivo.corecognitics.cc
call-insights-frontend 1 insights.nexivo.corecognitics.cc
campaign-hub 1 campaign.nexivo.corecognitics.cc

Datastores (nexivo namespace)

Resource Type Size
nexivo-db-cluster CloudNativePG — 2 instances (1 primary, 1 standby) 10 Gi each
nexivo-redis-master Redis StatefulSet 8 Gi
nexivo-valkey-primary + 3 replicas Valkey StatefulSet 8 Gi each
nexivo-qdrant Qdrant vector DB 10 Gi
chi-clickhouse-reporting ClickHouse — 2 shards + 3 Keeper nodes 20 Gi each shard

livekit namespace — Voice & Text AI

Deployment Replicas Notes
livekit-server 1 voice.nexivo.corecognitics.cc
livekit-sip-gateway 1 sip.nexivo.corecognitics.cc
kamailio-sbc 1 SIP session border controller
livekit-multi-agent-service (Atlas) 2–10 KEDA autoscale · mem req 3.5 Gi
livekit-communication-service (Media Bot) 8 Fixed replica count
text-multi-agent-service (Herald) 1 mem req 1 Gi
orchestrator-engine 3 AI orchestration layer
livekit-egress 1–6 KEDA autoscale · mem req 2 Gi
livekit-valkey-primary + 3 replicas Valkey StatefulSet 8 Gi each

KEDA autoscaling is active in the livekit namespace:

ScaledObject Min Max Trigger
livekit-multi-agent-service 2 10 Active
livekit-egress 1 6

CI/CD Pipeline

Every service follows the same pattern (GitLab CI):

build  →  deploy (main only)  →  notify Teams
  1. build — Docker image built, pushed to registry.freston.io tagged with $CI_COMMIT_SHORT_SHA
  2. deployhelm upgrade --install against target cluster, then kubectl rollout status
  3. notify — Teams Adaptive Card on success or failure

Deploy only runs on main. Feature branches build the image but do not deploy.


Deploying a Service

Standard Helm deploy

export KUBECONFIG=~/dok8s/uat.yaml   # or dev / live

helm upgrade --install <release-name> ./helm \
  --namespace nexivo \
  --set image.tag=<commit-sha> \
  --values helm/values.<env>.yaml

Roll a new image manually

kubectl set image deployment/<name> <container>=registry.freston.io/<path>/<service>:<sha> -n nexivo
kubectl rollout status deployment/<name> -n nexivo --timeout=120s

livekit namespace services

kubectl set image deployment/livekit-multi-agent-service \
  livekit-multi-agent-service=registry.freston.io/intento/tenantator/atlas:<sha> \
  -n livekit

Secrets

Secrets are applied manually with kubectl and are not stored in Git.

kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: <secret-name>
  namespace: nexivo     # or livekit
type: Opaque
stringData:
  KEY: "value"
EOF
# List secrets
kubectl get secrets -n nexivo
kubectl get secrets -n livekit

# Update a single key
kubectl patch secret <name> -n nexivo \
  --type='json' \
  -p='[{"op":"replace","path":"/data/KEY","value":"'$(echo -n "newvalue" | base64)'"}]'

Warning

Update secrets before rolling out a deployment that depends on them. Pods pick up secret changes only on restart.


Database

CloudNativePG (PostgreSQL)

The nexivo-db-cluster CloudNativePG cluster runs in the nexivo namespace with 2 instances (1 primary, 1 standby replica).

# Check cluster health
kubectl get clusters.postgresql.cnpg.io -n nexivo

# Connect to primary (port-forward)
kubectl port-forward svc/nexivo-db-cluster-rw 5432:5432 -n nexivo
# psql -h localhost -U <user> -d <dbname>

# Connect to read-only replica
kubectl port-forward svc/nexivo-db-cluster-ro 5432:5432 -n nexivo

ClickHouse (Reporting)

ClickHouse runs as a 2-shard cluster with 3 ClickHouse Keeper nodes for coordination, managed by the Altinity ClickHouse Operator.

kubectl get chi -n nexivo          # list ClickHouse installations
kubectl get pods -n nexivo -l app=clickhouse

Qdrant (Vector DB)

kubectl get pods -n nexivo -l app=nexivo-qdrant
kubectl port-forward svc/nexivo-qdrant 6333:6333 -n nexivo

Rollback

# Roll back to a specific image
kubectl set image deployment/<name> \
  <container>=registry.freston.io/<path>/<service>:<previous-sha> \
  -n nexivo

# Roll back to previous Kubernetes revision
kubectl rollout undo deployment/<name> -n nexivo

# Check rollout history
kubectl rollout history deployment/<name> -n nexivo

Previous image SHAs are in GitLab under Registry → Container Registry for each project, or from pipeline history.


Useful Commands

# All pods across both main namespaces
kuat get pods -n nexivo
kuat get pods -n livekit

# Tail logs
kuat logs deployment/call-service -n nexivo --tail=100 -f
kuat logs deployment/livekit-multi-agent-service -n livekit --tail=100 -f

# Check ingresses
kuat get ingress -n nexivo
kuat get ingress -n livekit

# KEDA scaling status
kuat get scaledobject -n livekit

# CloudNativePG cluster health
kuat get clusters.postgresql.cnpg.io -n nexivo