Skip to main content
Cerbos can be deployed on Kubernetes using the official Helm chart, which supports both standalone service and sidecar deployment patterns.

Prerequisites

  • Kubernetes cluster version 1.23.0 or higher
  • Helm 3.x installed
  • kubectl configured to access your cluster

Installation

1
Add the Helm repository
2
helm repo add cerbos https://cerbos.github.io/helm-charts
helm repo update
3
Install Cerbos
4
helm install cerbos cerbos/cerbos --namespace cerbos --create-namespace
5
This installs Cerbos with default configuration values.
6
Verify the installation
7
kubectl get pods -n cerbos
kubectl get svc -n cerbos

Configuration

Default Ports

Cerbos exposes two service ports:
  • HTTP Port: 3592 - REST API and health checks
  • gRPC Port: 3593 - gRPC API

Service Configuration

The Helm chart creates a Kubernetes Service with configurable settings:
service:
  type: ClusterIP
  httpPort: 3592
  grpcPort: 3593
  annotations: {}
For external access, change the service type to LoadBalancer or NodePort.

Deployment Options

The chart supports two deployment types:
type: deployment
replicaCount: 3

Storage Backends

Disk Storage with Volume

Mount a volume containing policies:
volumes:
  - name: cerbos-policies
    hostPath:
      path: /data/cerbos-policies

volumeMounts:
  - name: cerbos-policies
    mountPath: /policies
    readOnly: true

cerbos:
  config:
    storage:
      driver: "disk"
      disk:
        directory: /policies
        watchForChanges: true

Git Repository Storage

Connect Cerbos to a Git repository for policy management:
1
Create GitHub token secret
2
export PAT=your_github_token
kubectl create secret generic cerbos-github-token \
  --from-literal=GITHUB_TOKEN=$PAT \
  -n cerbos
3
Configure Git storage
4
Create a values-git.yaml file:
5
cerbos:
  config:
    storage:
      driver: "git"
      git:
        protocol: https
        url: https://github.com/your-org/policies.git
        branch: main
        subDir: policies
        checkoutDir: /work
        updatePollInterval: 60s
        https:
          username: ${GITHUB_TOKEN}
          password: ""

envFrom:
  - secretRef:
      name: cerbos-github-token
6
Install with Git configuration
7
helm install cerbos cerbos/cerbos -f values-git.yaml -n cerbos

Cerbos Hub Storage

Connect to Cerbos Hub for centralized policy management:
1
Create Hub credentials secret
2
kubectl create secret generic cerbos-hub-credentials \
  --from-literal=CERBOS_HUB_CLIENT_ID=<your_client_id> \
  --from-literal=CERBOS_HUB_CLIENT_SECRET=<your_client_secret> \
  --from-literal=CERBOS_HUB_DEPLOYMENT_ID=<your_deployment_id> \
  -n cerbos
3
Configure Hub storage
4
cerbos:
  config:
    storage:
      driver: "hub"
      hub:
        remote:
          deploymentID: "${CERBOS_HUB_DEPLOYMENT_ID}"
    audit:
      enabled: true
      backend: "hub"
      hub:
        storagePath: /audit_logs

envFrom:
  - secretRef:
      name: cerbos-hub-credentials

volumes:
  - name: cerbos-audit-logs
    emptyDir: {}

volumeMounts:
  - name: cerbos-audit-logs
    mountPath: /audit_logs

TLS Configuration

Using cert-manager

The chart integrates with cert-manager for automatic certificate management:
certManager:
  certSpec:
    issuerRef:
      name: letsencrypt-prod
      kind: ClusterIssuer
    dnsNames:
      - cerbos.example.com

Using existing TLS secret

1
Create TLS secret
2
kubectl create secret tls cerbos-tls \
  --cert=path/to/tls.crt \
  --key=path/to/tls.key \
  -n cerbos
3
Configure TLS
4
cerbos:
  tlsSecretName: cerbos-tls

Health Checks

The deployment includes liveness and readiness probes:
livenessProbe:
  httpGet:
    path: /_cerbos/health
    port: http
    scheme: HTTP

readinessProbe:
  httpGet:
    path: /_cerbos/health
    port: http
    scheme: HTTP
The health endpoint returns a 200 status when Cerbos is ready.

Resource Limits

Configure resource requests and limits:
resources:
  limits:
    cpu: 1000m
    memory: 512Mi
  requests:
    cpu: 100m
    memory: 128Mi

Autoscaling

Enable horizontal pod autoscaling:
autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80
  targetMemoryUtilizationPercentage: 80
Autoscaling is only available when using type: deployment.

Sidecar Deployment

Deploy Cerbos as a sidecar container alongside your application:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      containers:
        - name: app
          image: my-app:latest
          env:
            - name: CERBOS_ADDRESS
              value: "localhost:3593"
        
        - name: cerbos
          image: ghcr.io/cerbos/cerbos:0.52.0
          args:
            - "server"
            - "--config=/config/.cerbos.yaml"
            - "--log-level=INFO"
          ports:
            - name: http
              containerPort: 3592
            - name: grpc
              containerPort: 3593
          livenessProbe:
            httpGet:
              path: /_cerbos/health
              port: http
          readinessProbe:
            httpGet:
              path: /_cerbos/health
              port: http
          volumeMounts:
            - name: config
              mountPath: /config
              readOnly: true
            - name: policies
              mountPath: /policies
              readOnly: true
      
      volumes:
        - name: config
          configMap:
            name: cerbos-config
        - name: policies
          configMap:
            name: cerbos-policies

Environment Variables

Add environment variables to the deployment:
env:
  - name: CERBOS_LOG_LEVEL
    value: "DEBUG"
  - name: CUSTOM_VAR
    valueFrom:
      secretKeyRef:
        name: my-secret
        key: custom-key

envFrom:
  - configMapRef:
      name: cerbos-env
  - secretRef:
      name: cerbos-secrets

Monitoring

Prometheus Integration

The chart automatically adds Prometheus annotations for service discovery:
cerbos:
  prometheusPodAnnotationsEnabled: true
This adds the following annotations to pods:
prometheus.io/scrape: "true"
prometheus.io/port: "3592"
prometheus.io/path: "/_cerbos/metrics"
prometheus.io/scheme: "http"
Metrics are available at: http://cerbos:3592/_cerbos/metrics

Advanced Configuration

Pod Security Context

podSecurityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000

securityContext:
  allowPrivilegeEscalation: false
  capabilities:
    drop:
      - ALL
  readOnlyRootFilesystem: true

Node Affinity and Tolerations

nodeSelector:
  workload: cerbos

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
              - key: app.kubernetes.io/name
                operator: In
                values:
                  - cerbos
          topologyKey: kubernetes.io/hostname

tolerations:
  - key: "workload"
    operator: "Equal"
    value: "cerbos"
    effect: "NoSchedule"

Topology Spread Constraints

topologySpreadConstraints:
  - topologyKey: topology.kubernetes.io/zone
    maxSkew: 1
    whenUnsatisfiable: ScheduleAnyway
  - topologyKey: kubernetes.io/hostname
    maxSkew: 1
    whenUnsatisfiable: DoNotSchedule

Complete Example

A production-ready values.yaml configuration:
replicaCount: 3

image:
  repository: ghcr.io/cerbos/cerbos
  tag: "0.52.0"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  httpPort: 3592
  grpcPort: 3593

cerbos:
  httpPort: 3592
  grpcPort: 3593
  logLevel: INFO
  prometheusPodAnnotationsEnabled: true
  tlsSecretName: cerbos-tls
  config:
    storage:
      driver: "git"
      git:
        protocol: https
        url: https://github.com/org/policies.git
        branch: main
        updatePollInterval: 60s
        https:
          username: ${GITHUB_TOKEN}
          password: ""

resources:
  limits:
    cpu: 1000m
    memory: 512Mi
  requests:
    cpu: 100m
    memory: 128Mi

autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

podSecurityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000

securityContext:
  allowPrivilegeEscalation: false
  capabilities:
    drop:
      - ALL
  readOnlyRootFilesystem: true

envFrom:
  - secretRef:
      name: cerbos-github-token

topologySpreadConstraints:
  - topologyKey: topology.kubernetes.io/zone
    maxSkew: 1
    whenUnsatisfiable: ScheduleAnyway
Install with this configuration:
helm install cerbos cerbos/cerbos \
  -f values.yaml \
  --namespace cerbos \
  --create-namespace

Upgrading

Upgrade an existing deployment:
# Update repository
helm repo update

# Upgrade release
helm upgrade cerbos cerbos/cerbos \
  -f values.yaml \
  -n cerbos

Uninstalling

Remove the Cerbos deployment:
helm uninstall cerbos -n cerbos
kubectl delete namespace cerbos