Skip to main content

Kubernetes Deployment

Deploy Sentro on Kubernetes using the official Helm chart. Designed for production workloads with autoscaling, pod disruption budgets, Ingress, and Prometheus integration.

Prerequisites​

  • Kubernetes 1.26+
  • Helm 3.12+
  • kubectl configured for your cluster
  • x86-64 nodes — the images are published for x86-64 only, so ARM node pools (Graviton, Ampere) will fail to schedule
  • Access to the public images at ghcr.io/sentro-dev/platform

The chart has no external chart dependencies. PostgreSQL and Redis are deployed by the chart itself using the official upstream images, so helm dependency steps are not required.

Quick Start​

1. Get the chart​

git clone https://github.com/sentro-dev/self-hosted.git
cd self-hosted

2. Generate secrets​

export AUTH_SECRET=$(openssl rand -hex 32)
export ENCRYPTION_KEY=$(openssl rand -hex 32)
export ADMIN_SESSION_SECRET=$(openssl rand -hex 32)
export ADMIN_PASSWORD=$(openssl rand -base64 16 | tr -d '/+=')
export PG_PASSWORD=$(openssl rand -hex 16)
export REDIS_PASSWORD=$(openssl rand -hex 16)

3. Install​

helm install sentro ./helm/sentro \
--namespace sentro \
--create-namespace \
--set secrets.authSecret=$AUTH_SECRET \
--set secrets.encryptionKey=$ENCRYPTION_KEY \
--set secrets.adminSessionSecret=$ADMIN_SESSION_SECRET \
--set secrets.adminEmail=admin@yourcompany.com \
--set secrets.adminPassword=$ADMIN_PASSWORD \
--set postgresql.auth.password=$PG_PASSWORD \
--set redis.auth.password=$REDIS_PASSWORD \
--set config.authUrl=https://app.yourdomain.com \
--wait --timeout 10m
warning

secrets.adminSessionSecret, postgresql.auth.password, and redis.auth.password are mandatory. The install fails immediately with a clear message if any are missing.

4. Verify​

kubectl get pods -n sentro     # all Running, migration job Completed
kubectl get jobs -n sentro

Then reach the services:

kubectl port-forward -n sentro svc/sentro-app 3001:3001
curl http://localhost:3001/api/health # {"status":"ok","database":"ok"}

Architecture​

ComponentKindReplicasPort
sentro-appDeployment + Service1 (scalable)3001
sentro-adminDeployment + Service13002
sentro-apiDeployment + Service1 (scalable)4000
sentro-workerDeployment + Service1 (scalable)9464 (metrics)
sentro-migrateJob (Helm hook)1 (runs once)—
PostgreSQL 16StatefulSet + PVC15432
Redis 7StatefulSet + PVC16379

The migration job runs as a post-install and post-upgrade hook. It waits for the database to accept connections, applies pending schema migrations, then seeds the plan matching your license edition.

Optional resources (disabled by default):

  • Ingress — route external traffic to the services
  • HPA — autoscale app, api, and worker
  • PDB — pod disruption budgets for app and worker
  • ServiceMonitor — Prometheus Operator integration

Applying a License​

helm upgrade sentro ./helm/sentro --reuse-values \
--set secrets.licenseKey="eyJ2IjoxLC..."

The migration job re-runs on upgrade and moves every organisation onto the plan for the new edition. See Licensing.

Ingress and Hostnames​

config:
authUrl: 'https://app.yourdomain.com'
apiCorsOrigin: 'https://app.yourdomain.com,https://admin.yourdomain.com'

ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
app:
host: app.yourdomain.com
admin:
host: admin.yourdomain.com
api:
host: api.yourdomain.com
tls:
- secretName: sentro-tls
hosts:
- app.yourdomain.com
- admin.yourdomain.com
- api.yourdomain.com
warning

config.authUrl must match the hostname users actually open. The dashboard treats unrecognised hostnames as custom status-page domains and answers "Status page not found". When the app is reachable on more than one hostname, list them all in config.appHostnames.

Production Configuration​

values-production.yaml is a ready-made starting point:

helm install sentro ./helm/sentro \
--namespace sentro --create-namespace \
-f ./helm/sentro/values-production.yaml \
--set secrets.authSecret=$AUTH_SECRET \
--set secrets.encryptionKey=$ENCRYPTION_KEY \
--set secrets.adminSessionSecret=$ADMIN_SESSION_SECRET \
--set secrets.adminPassword=$ADMIN_PASSWORD \
--set postgresql.auth.password=$PG_PASSWORD \
--set redis.auth.password=$REDIS_PASSWORD

This enables 2 replicas for app, api, and worker; HPA autoscaling; pod disruption budgets; a Prometheus ServiceMonitor; and Ingress with TLS.

External Database​

The bundled PostgreSQL is a single pod with a persistent volume — fine for most self-hosted installs, but not highly available. For production, point at a managed database:

postgresql:
enabled: false

secrets:
externalDatabaseUrl: 'postgresql://user:pass@your-rds.region.rds.amazonaws.com:5432/sentro?sslmode=require'

External Redis​

redis:
enabled: false

secrets:
externalRedisUrl: 'redis://:password@your-redis.cache.amazonaws.com:6379'
danger

Any Redis you use must run with eviction disabled (maxmemory-policy noeviction). With eviction enabled, the queue silently drops scheduled checks and monitors stop running without any error. The bundled Redis is configured correctly out of the box; managed Redis often defaults to an eviction policy.

Single Sign-On​

Available on the Business and Enterprise editions. Up to five OpenID Connect providers:

config:
ssoEnforce: false # true hides password and social sign-in

secrets:
sso:
- name: Okta
issuer: https://example.okta.com
clientId: '...'
clientSecret: '...'

The redirect URI for the first provider is <authUrl>/api/auth/callback/sso-1, the second sso-2, and so on.

Monitoring​

Prometheus ServiceMonitor​

worker:
serviceMonitor:
enabled: true
interval: 15s
labels:
release: kube-prometheus-stack # match your Prometheus selector

Key metrics​

The worker exposes these on port 9464:

MetricTypeDescription
sentro_checks_totalCounterTotal checks executed
sentro_monitors_activeGaugeActive monitors
sentro_incidents_activeGaugeOpen incidents
sentro_check_durationHistogramCheck execution time
sentro_alerts_dispatchedCounterAlerts sent
sentro_queue_depthGaugeQueue size

Upgrading​

helm upgrade sentro ./helm/sentro \
--namespace sentro \
--reuse-values \
--set global.image.tag=v1.2.0 \
--wait --timeout 10m

Helm updates the deployment images, runs the migration job as a post-upgrade hook, and rolling-restarts the pods.

Uninstall​

helm uninstall sentro --namespace sentro
warning

This does not delete PVCs. To fully clean up (DATA LOSS):

kubectl delete pvc --all -n sentro
kubectl delete namespace sentro