Self-Hosted / On-Premise

Deploy AgentWatch on Your Cluster

Run AgentWatch entirely inside your own infrastructure. Agent telemetry, guardrail logs, and run data never leave your servers. Supports AWS EKS, GCP GKE, Azure AKS, and bare-metal on-prem clusters.

< 15 min
Deploy time
8 GB
Min RAM
4 vCPU
Min CPU
60 GB
Storage

What gets deployed

AgentWatch runs as four services inside a dedicated agentwatch namespace. Nothing else is modified in your cluster.

agentwatch-api
:8000
FastAPI backend — ingests runs, steps, guardrails, Gate
agentwatch-dashboard
:3000
Next.js operator console — runs, analytics, guardrails UI
postgres (TimescaleDB)
:5432
Time-series store for runs, steps, anomalies, Gate events
redis
:6379
Live dashboard updates (Socket.IO) and job queue

Prerequisites

RequirementMinimumRecommended (production)
Kubernetes version1.24+1.28+
Node RAM8 GB16–32 GB
Node CPU4 vCPU8–16 vCPU
Persistent storage60 GB200 GB+ (SSD)
kubectlv1.24+matches cluster version
Helm (optional)3.12+3.14+
nginx-ingress-controllerAny versionv1.8+
cert-manager (for TLS)v1.12+v1.13+

Quickstart — Helm (recommended)

Fastest path. Creates the namespace, generates secrets, and deploys all four services from the chart in this repo (helm/agentwatch/). Images are pulled from GHCR.

1

Install prerequisites

nginx-ingress-controller and cert-manager handle traffic routing and TLS.

terminal
bash
1# nginx-ingress-controller
2kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml
3
4# cert-manager
5kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
6
7# Wait for cert-manager to be ready
8kubectl wait --for=condition=ready pod -l app=cert-manager -n cert-manager --timeout=90s
2

Create image pull secret

AgentWatch images are on a private GHCR registry. Your cluster needs read credentials.

Get your pull token
After an on-prem license, email agentwatchsupport@gmail.com for a read-only token for ghcr.io/chinmaynayar.
bash
1kubectl create namespace agentwatch
2
3kubectl create secret docker-registry ghcr-credentials \
4 --docker-server=ghcr.io \
5 --docker-username=YOUR_USERNAME \
6 --docker-password=YOUR_READ_TOKEN \
7 --namespace agentwatch
3

Create cert-manager ClusterIssuer

Automatic TLS via Let's Encrypt.

cluster-issuer.yaml
yaml
1apiVersion: cert-manager.io/v1
2kind: ClusterIssuer
3metadata:
4 name: letsencrypt-prod
5spec:
6 acme:
7 server: https://acme-v02.api.letsencrypt.org/directory
8 email: YOUR_EMAIL@company.com
9 privateKeySecretRef:
10 name: letsencrypt-prod
11 solvers:
12 - http01:
13 ingress:
14 class: nginx
bash
1kubectl apply -f cluster-issuer.yaml
4

Deploy with Helm

Replace YOUR_DOMAIN with the parent domain (e.g. acme.com → app.acme.com + api.acme.com).

Save the generated secrets
Store the printed values in Vault / AWS Secrets Manager / equivalent. You will need them for upgrades and disaster recovery. CONNECTOR_ENCRYPTION_KEY is required in production or the API exits on boot.
bash
1# Generate secrets (copy and save these)
2PG_PASS=$(openssl rand -hex 20)
3API_KEY=$(openssl rand -hex 16)
4INT_SECRET=$(openssl rand -hex 32)
5FERNET_KEY=$(python3 -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())')
6NEXT_SECRET=$(openssl rand -base64 32 | tr -d '\n')
7
8echo "POSTGRES_PASSWORD=$PG_PASS"
9echo "AGENTWATCH_DEV_API_KEY=$API_KEY"
10echo "INTERNAL_AUTH_SECRET=$INT_SECRET"
11echo "CONNECTOR_ENCRYPTION_KEY=$FERNET_KEY"
12echo "NEXTAUTH_SECRET=$NEXT_SECRET"
13
14# Clone + deploy the chart from this repo
15git clone https://github.com/chinmayNayar/agentwatch.git
16cd agentwatch
17
18helm install agentwatch helm/agentwatch/ \
19 --namespace agentwatch --create-namespace \
20 --set global.domain="YOUR_DOMAIN" \
21 --set secrets.postgresPassword="$PG_PASS" \
22 --set secrets.agentwatchDevApiKey="$API_KEY" \
23 --set secrets.internalAuthSecret="$INT_SECRET" \
24 --set secrets.connectorEncryptionKey="$FERNET_KEY" \
25 --set secrets.nextauthSecret="$NEXT_SECRET" \
26 --set imagePullSecret="ghcr-credentials"
5

Point DNS to your cluster

Get the ingress IP and create two DNS records.

bash
1# Get the ingress external IP (may take 2–3 minutes after deploy)
2kubectl get svc -n ingress-nginx ingress-nginx-controller \
3 -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

Create two A records pointing to that IP (on AWS NLB use CNAMEs to the hostname instead):

app.YOUR_DOMAIN → INGRESS_IP
api.YOUR_DOMAIN → INGRESS_IP
6

Verify the installation

bash
1# Watch pods come up (takes 3–5 minutes)
2kubectl get pods -n agentwatch -w
3
4# All should show: STATUS=Running, READY=1/1
5
6# Health check
7kubectl port-forward svc/api-service 8000:8000 -n agentwatch &
8curl http://localhost:8000/health
9# Expected: {"status":"ok","db":true,"redis":true}
Success
Once you see {"status":"ok","db":true,"redis":true}, AgentWatch is live. Open https://app.YOUR_DOMAIN for the console. For a custom domain, rebuild the dashboard image — see Customer dashboard image.

Alternative — kubectl / Kustomize

If your team prefers raw manifests, apply the Kustomize overlay in k8s/. Secrets are a template and are not included in kustomization.yaml.

bash
1# Clone the manifests
2git clone https://github.com/chinmayNayar/agentwatch.git
3cd agentwatch
4
5# Create namespace + image pull secret (same as Helm step 2)
6kubectl create namespace agentwatch
7kubectl create secret docker-registry ghcr-credentials \
8 --docker-server=ghcr.io --docker-username=YOUR_USERNAME \
9 --docker-password=YOUR_READ_TOKEN --namespace agentwatch
10
11# Fill in secrets (copy template, fill values, apply, then delete local copy)
12cp k8s/secrets/agentwatch-secrets.yaml /tmp/aw-secrets.yaml
13# Edit /tmp/aw-secrets.yaml with real values — never commit them
14kubectl apply -f /tmp/aw-secrets.yaml && rm /tmp/aw-secrets.yaml
15
16# Edit domain (placeholders are RFC 1123: example.com, not CUSTOMER_DOMAIN)
17sed -i '' 's/app.example.com/app.YOUR_DOMAIN/g' k8s/ingress/ingress.yaml
18sed -i '' 's/api.example.com/api.YOUR_DOMAIN/g' k8s/ingress/ingress.yaml
19# Linux: drop the '' after -i
20
21# Deploy everything
22kubectl apply -k k8s/
23kubectl get pods -n agentwatch -w

Storage Classes & PVCs

AgentWatch uses two PersistentVolumeClaims. Both use ReadWriteOnce (RWO) — they attach to a single node, which is correct for databases. You do not need ReadWriteMany (RWX).

PVCAccess ModeDefault sizeWhy
postgres-pvcRWO50 GiTimescaleDB data + WAL. SSD required. Grows ~3–5GB/month at 10M steps/mo.
redis-pvcRWO5 GiRedis AOF-style persistence. Rarely exceeds 1GB.
Why not RWX?
ReadWriteMany lets multiple nodes mount the same volume — useful for shared filesystems. Postgres and Redis are single-instance and manage their own concurrency. RWO is correct, faster, and supported by every cloud storage class. RWX (NFS, EFS, Filestore) adds latency with no benefit for these databases.

StorageClass by cloud

Use gp3 (faster and cheaper than gp2). Install the EBS CSI driver if it is not already present.

bash
1# Install EBS CSI driver (required for EKS 1.23+)
2eksctl create addon --name aws-ebs-csi-driver --cluster YOUR_CLUSTER --region YOUR_REGION
3
4# Create a gp3 StorageClass and set as default
5kubectl apply -f - <<EOF
6apiVersion: storage.k8s.io/v1
7kind: StorageClass
8metadata:
9 name: gp3
10 annotations:
11 storageclass.kubernetes.io/is-default-class: "true"
12provisioner: ebs.csi.aws.com
13parameters:
14 type: gp3
15 iops: "3000"
16 throughput: "125"
17 encrypted: "true"
18volumeBindingMode: WaitForFirstConsumer
19reclaimPolicy: Retain
20allowVolumeExpansion: true
21EOF
bash
1helm install agentwatch helm/agentwatch/ \
2 --namespace agentwatch --create-namespace \
3 --set postgres.storageClass="gp3" \
4 --set redis.storageClass="gp3"
Use WaitForFirstConsumer
EBS volumes are AZ-specific. WaitForFirstConsumer creates the PVC in the same AZ as the pod. Without it, pods can fail with volume node affinity conflict.

AWS EKS — Full Deployment Guide

bash
1# 1. Create EKS cluster (if you don't have one)
2eksctl create cluster \
3 --name agentwatch-prod \
4 --region us-east-1 \
5 --nodegroup-name standard \
6 --node-type m5.xlarge \
7 --nodes 2 \
8 --nodes-min 2 \
9 --nodes-max 4 \
10 --managed
11
12# 2. Install EBS CSI driver
13eksctl create addon \
14 --name aws-ebs-csi-driver \
15 --cluster agentwatch-prod \
16 --region us-east-1
17
18# 3. Install nginx-ingress (AWS NLB mode)
19helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
20helm install ingress-nginx ingress-nginx/ingress-nginx \
21 --namespace ingress-nginx --create-namespace \
22 --set controller.service.annotations."service\.beta\.kubernetes\.io/aws-load-balancer-type"="nlb"
23
24# 4. Install cert-manager
25kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
26
27# 5. Get NLB hostname (use this for DNS CNAME, not A record)
28kubectl get svc -n ingress-nginx ingress-nginx-controller \
29 -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
30
31# 6. Deploy AgentWatch (from a clone of this repo)
32helm install agentwatch helm/agentwatch/ \
33 --namespace agentwatch --create-namespace \
34 --set global.domain="agentwatch.company.com" \
35 --set postgres.storageClass="gp3" \
36 --set redis.storageClass="gp3" \
37 --set imagePullSecret="ghcr-credentials" \
38 --set secrets.postgresPassword="$(openssl rand -hex 20)" \
39 --set secrets.agentwatchDevApiKey="$(openssl rand -hex 16)" \
40 --set secrets.internalAuthSecret="$(openssl rand -hex 32)" \
41 --set secrets.connectorEncryptionKey="$(python3 -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())')" \
42 --set secrets.nextauthSecret="$(openssl rand -base64 32 | tr -d '\n')"

GCP GKE — Full Deployment Guide

bash
1# 1. Create GKE cluster
2gcloud container clusters create agentwatch-prod \
3 --region us-central1 \
4 --machine-type n2-standard-4 \
5 --num-nodes 2 \
6 --enable-autoscaling --min-nodes 2 --max-nodes 4 \
7 --workload-pool=$(gcloud config get-value project).svc.id.goog
8
9# 2. Get credentials
10gcloud container clusters get-credentials agentwatch-prod --region us-central1
11
12# 3. Install nginx-ingress
13helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
14helm install ingress-nginx ingress-nginx/ingress-nginx \
15 --namespace ingress-nginx --create-namespace
16
17# 4. Install cert-manager
18kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
19
20# 5. Get ingress IP
21kubectl get svc -n ingress-nginx ingress-nginx-controller \
22 -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
23# → Create A records: app.YOUR_DOMAIN → IP, api.YOUR_DOMAIN → IP
24
25# 6. Deploy AgentWatch
26helm install agentwatch helm/agentwatch/ \
27 --namespace agentwatch --create-namespace \
28 --set global.domain="agentwatch.company.com" \
29 --set postgres.storageClass="pd-ssd" \
30 --set redis.storageClass="pd-ssd" \
31 --set imagePullSecret="ghcr-credentials" \
32 --set secrets.postgresPassword="$(openssl rand -hex 20)" \
33 --set secrets.agentwatchDevApiKey="$(openssl rand -hex 16)" \
34 --set secrets.internalAuthSecret="$(openssl rand -hex 32)" \
35 --set secrets.connectorEncryptionKey="$(python3 -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())')" \
36 --set secrets.nextauthSecret="$(openssl rand -base64 32 | tr -d '\n')"

Azure AKS — Full Deployment Guide

bash
1# 1. Create resource group and AKS cluster
2az group create --name agentwatch-rg --location eastus
3az aks create \
4 --resource-group agentwatch-rg \
5 --name agentwatch-prod \
6 --node-count 2 \
7 --node-vm-size Standard_D4s_v3 \
8 --enable-cluster-autoscaler \
9 --min-count 2 --max-count 4 \
10 --generate-ssh-keys
11
12# 2. Get credentials
13az aks get-credentials --resource-group agentwatch-rg --name agentwatch-prod
14
15# 3. Install nginx-ingress
16helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
17helm install ingress-nginx ingress-nginx/ingress-nginx \
18 --namespace ingress-nginx --create-namespace
19
20# 4. Install cert-manager
21kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
22
23# 5. Get ingress IP
24kubectl get svc -n ingress-nginx ingress-nginx-controller \
25 -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
26
27# 6. Deploy AgentWatch
28helm install agentwatch helm/agentwatch/ \
29 --namespace agentwatch --create-namespace \
30 --set global.domain="agentwatch.company.com" \
31 --set postgres.storageClass="managed-csi-premium" \
32 --set redis.storageClass="managed-csi-premium" \
33 --set imagePullSecret="ghcr-credentials" \
34 --set secrets.postgresPassword="$(openssl rand -hex 20)" \
35 --set secrets.agentwatchDevApiKey="$(openssl rand -hex 16)" \
36 --set secrets.internalAuthSecret="$(openssl rand -hex 32)" \
37 --set secrets.connectorEncryptionKey="$(python3 -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())')" \
38 --set secrets.nextauthSecret="$(openssl rand -base64 32 | tr -d '\n')"

On-Prem / Bare Metal — Full Deployment Guide

k3s recommended for bare metal
k3s is a lightweight Kubernetes distribution for bare-metal and edge. It includes containerd and CoreDNS and installs in under a minute. Disable Traefik if you will use nginx-ingress.
bash
1# 1. Install k3s on your server (single-node)
2curl -sfL https://get.k3s.io | sh -s - \
3 --disable traefik \
4 --write-kubeconfig-mode 644
5
6export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
7
8# 2. Install local-path-provisioner (storage)
9kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.26/deploy/local-path-storage.yaml
10kubectl patch storageclass local-path \
11 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
12
13# 3. Install nginx-ingress
14helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
15helm install ingress-nginx ingress-nginx/ingress-nginx \
16 --namespace ingress-nginx --create-namespace \
17 --set controller.service.type=NodePort \
18 --set controller.service.nodePorts.http=80 \
19 --set controller.service.nodePorts.https=443
20
21# 4. Install cert-manager
22kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
23
24# 5. Point DNS to your server's public IP
25# app.YOUR_DOMAIN → SERVER_IP
26# api.YOUR_DOMAIN → SERVER_IP
27
28# 6. Deploy AgentWatch
29helm install agentwatch helm/agentwatch/ \
30 --namespace agentwatch --create-namespace \
31 --set global.domain="agentwatch.company.com" \
32 --set imagePullSecret="ghcr-credentials" \
33 --set secrets.postgresPassword="$(openssl rand -hex 20)" \
34 --set secrets.agentwatchDevApiKey="$(openssl rand -hex 16)" \
35 --set secrets.internalAuthSecret="$(openssl rand -hex 32)" \
36 --set secrets.connectorEncryptionKey="$(python3 -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())')" \
37 --set secrets.nextauthSecret="$(openssl rand -base64 32 | tr -d '\n')"

Secrets Reference

Pass these via Helm --set secrets.* or fill k8s/secrets/agentwatch-secrets.yaml (kustomize). Never commit real values.

VariableRequiredPurpose & how to generate
POSTGRES_PASSWORDYesPostgres superuser password. openssl rand -hex 20
AGENTWATCH_DEV_API_KEYYesAPI key for SDK + curl. openssl rand -hex 16
INTERNAL_AUTH_SECRETYesDashboard → API auth. openssl rand -hex 32
CONNECTOR_ENCRYPTION_KEYYesFernet key for Gate secrets. python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
NEXTAUTH_SECRETYesNextAuth session signing. openssl rand -base64 32
RESEND_API_KEYNoOptional. Email alerts and Book-a-Demo notifications.
GOOGLE_API_KEYNoOptional. Agora (AI copilot) and Arena.
STRIPE_*NoOptional. Billing if you enable Stripe on that install.
Production auth
Keep LOCAL_NO_AUTH=false and AGENTWATCH_ENV=production. The API will not boot in production without CONNECTOR_ENCRYPTION_KEY.

Ingress & TLS

The chart and kustomize overlay both expect nginx-ingress plus a cert-manager ClusterIssuer named letsencrypt-prod. Hosts are app.YOUR_DOMAIN and api.YOUR_DOMAIN. Helm sets these from global.domain. Kustomize ships placeholders app.example.com / api.example.com — Kubernetes rejects a host like app.CUSTOMER_DOMAIN.

bash
1# Confirm ingress + cert
2kubectl get ingress -n agentwatch
3kubectl describe certificate -n agentwatch
4kubectl get clusterissuer letsencrypt-prod

Customer dashboard image

Dashboard NEXT_PUBLIC_* values are baked in at image build time. The stock ghcr.io/chinmaynayar/agentwatch-dashboard:latest image points at agentwatch.in. For your domain, rebuild:

bash
1# GitHub → Actions → "Build Customer Image" → Run workflow
2# customer_slug: acme-bank
3# api_url: https://api.YOUR_DOMAIN
4# app_url: https://app.YOUR_DOMAIN
5#
6# Then:
7helm upgrade agentwatch helm/agentwatch/ \
8 --namespace agentwatch \
9 --reuse-values \
10 --set dashboard.imageTag="acme-bank-latest"
Blank dashboard / wrong API host
If the console loads but cannot reach your API, the dashboard image was built for a different domain. Rebuild with the workflow above — do not only change runtime env vars.

Air-Gapped Clusters

For clusters with no outbound internet (defence, regulated banking), transfer images offline, then point Helm at your internal registry.

Air-gapped deployments require the Enterprise license
Email agentwatchsupport@gmail.com for the offline image bundle and install support.
bash
1# On a machine WITH internet access:
2
3docker pull ghcr.io/chinmaynayar/agentwatch-api:latest
4docker pull ghcr.io/chinmaynayar/agentwatch-dashboard:latest
5docker pull timescale/timescaledb:latest-pg15
6docker pull redis:7-alpine
7docker pull postgres:15-alpine # API init container (pg_isready)
8docker pull curlimages/curl:latest # dashboard init container
9
10docker save ghcr.io/chinmaynayar/agentwatch-api:latest | gzip > agentwatch-api.tar.gz
11docker save ghcr.io/chinmaynayar/agentwatch-dashboard:latest | gzip > agentwatch-dashboard.tar.gz
12docker save timescale/timescaledb:latest-pg15 | gzip > timescaledb.tar.gz
13docker save redis:7-alpine | gzip > redis.tar.gz
14docker save postgres:15-alpine | gzip > postgres-init.tar.gz
15docker save curlimages/curl:latest | gzip > curl-init.tar.gz
16
17# Transfer to the air-gapped node (USB, SCP to bastion, etc.)
18scp *.tar.gz admin@airgapped-node:/tmp/
19
20# On the air-gapped node:
21docker load < /tmp/agentwatch-api.tar.gz
22docker load < /tmp/agentwatch-dashboard.tar.gz
23docker load < /tmp/timescaledb.tar.gz
24docker load < /tmp/redis.tar.gz
25docker load < /tmp/postgres-init.tar.gz
26docker load < /tmp/curl-init.tar.gz
27
28# Push to your internal registry
29docker tag ghcr.io/chinmaynayar/agentwatch-api:latest registry.internal/agentwatch-api:latest
30docker push registry.internal/agentwatch-api:latest
31# Repeat for dashboard, timescaledb, redis, postgres:15-alpine, curlimages/curl
32
33# Deploy pointing at the internal registry
34helm install agentwatch helm/agentwatch/ \
35 --namespace agentwatch --create-namespace \
36 --set global.domain="YOUR_DOMAIN" \
37 --set global.registry="registry.internal" \
38 --set postgres.image="registry.internal/timescaledb:latest-pg15" \
39 --set redis.image="registry.internal/redis:7-alpine" \
40 --set imagePullPolicy="IfNotPresent"

Verifying the Installation

bash
1# 1. All pods must be Running 1/1
2kubectl get pods -n agentwatch
3# NAME READY STATUS RESTARTS
4# postgres-0 1/1 Running 0
5# redis-xxx 1/1 Running 0
6# agentwatch-api-xxx 1/1 Running 0
7# agentwatch-api-yyy 1/1 Running 0
8# agentwatch-dashboard-xxx 1/1 Running 0
9
10# 2. API health (db AND redis must be true)
11kubectl port-forward svc/api-service 8000:8000 -n agentwatch &
12curl http://localhost:8000/health
13# {"status":"ok","db":true,"redis":true}
14
15# 3. Create a test run to confirm end-to-end
16API_KEY=$(kubectl get secret agentwatch-secrets -n agentwatch \
17 -o jsonpath='{.data.AGENTWATCH_DEV_API_KEY}' | base64 -d)
18
19RUN=$(curl -s -X POST http://localhost:8000/runs \
20 -H "x-api-key: $API_KEY" \
21 -H "Content-Type: application/json" \
22 -d '{"agent_name":"install-verify"}')
23echo $RUN | python3 -m json.tool
24# Should show run_id, status: running
25
26# 4. Open the dashboard
27echo "Console: https://app.YOUR_DOMAIN"
All green?
If all pods are Running and health returns db:true, redis:true, the install is complete. The dashboard at https://app.YOUR_DOMAIN shows the login page.

Upgrading

bash
1# Check current release
2helm list -n agentwatch
3
4# Pull latest chart + images, keep existing values
5git pull
6helm upgrade agentwatch helm/agentwatch/ \
7 --namespace agentwatch \
8 --reuse-values
9
10# Watch the rollout
11kubectl rollout status deployment/agentwatch-api -n agentwatch
12kubectl rollout status deployment/agentwatch-dashboard -n agentwatch
13
14# Verify after upgrade
15kubectl port-forward svc/api-service 8000:8000 -n agentwatch &
16curl http://localhost:8000/health

Backup & Restore

bash
1# Backup Postgres (from any machine with kubectl access)
2kubectl exec -n agentwatch postgres-0 -- \
3 pg_dump -U agentwatch agentwatch_db | gzip > agentwatch-backup-$(date +%Y%m%d).sql.gz
4
5# Restore (to a fresh install)
6gunzip -c agentwatch-backup-20260912.sql.gz | \
7 kubectl exec -i -n agentwatch postgres-0 -- \
8 psql -U agentwatch agentwatch_db
Automate daily backups
Add a Kubernetes CronJob that runs pg_dump and uploads to S3 / GCS / Azure Blob. Email us for a sample CronJob manifest.

Troubleshooting

SymptomLikely causeFix
Pod stuck in PendingNo StorageClass / PVC cannot bindkubectl describe pod → Events. Install a StorageClass for your cluster type.
ErrImagePull / ImagePullBackOffPull secret missing or wrongkubectl describe pod. Recreate ghcr-credentials with a valid read:packages token.
"db": false in /healthPostgres not ready or wrong DATABASE_URLkubectl logs -n agentwatch postgres-0. Check POSTGRES_PASSWORD in the secret.
"redis": false in /healthRedis pod not runningkubectl get pods -n agentwatch. Check redis logs.
Ingress 404 / no route to hostDNS not pointing to ingress IPkubectl get svc -n ingress-nginx. Confirm A/CNAME records match the LB.
TLS cert pending / not issuedClusterIssuer missing or HTTP-01 failingkubectl describe certificate -n agentwatch. Confirm letsencrypt-prod exists.
Dashboard blank / wrong APINEXT_PUBLIC_API_URL baked for another domainRebuild the dashboard image with the Build Customer Image workflow.
volume node affinity conflictEBS PVC in the wrong AZ (AWS)Use WaitForFirstConsumer on the StorageClass.

Need help with your deployment?

Our team will deploy AgentWatch in your cluster, verify health, and hand it off ready to use. Included with all on-prem licenses.

Book a deployment session →