Skip to content

Kubernetes Deployment

Deploy GOTRS on Kubernetes using Helm for production-grade scalability and high availability.

Getting Started

First steps with GOTRS - installation, initial setup, and your first ticket.

Deployment

Production deployment guides for Docker, Kubernetes, and air-gapped environments.

Admin Guide

Configure queues, users, groups, automation, and system settings.

API Reference

REST API documentation for integrations and custom development.

Migration Guide

Moving from OTRS to GOTRS - import your existing data and configuration.

FAQ

Frequently asked questions and common troubleshooting tips.

Kubernetes Deployment with Helm

Deploy GOTRS on Kubernetes for production-grade scalability, high availability, and enterprise features.

Prerequisites

  • Kubernetes 1.25+
  • Helm 3.12+
  • Ingress controller (nginx-ingress recommended)
  • PV provisioner support in the cluster
  • kubectl configured for your cluster

Quick Start

Install from OCI Registry

The chart is published to GitHub Container Registry with tags that mirror container image tags:

# Create namespace
kubectl create namespace gotrs

# Install latest release
helm install gotrs oci://ghcr.io/gotrs-io/charts/gotrs \
  --namespace gotrs \
  --version latest

# Install specific version (deploys matching container images)
helm install gotrs oci://ghcr.io/gotrs-io/charts/gotrs \
  --namespace gotrs \
  --version v0.6.0

Tag Mirroring: The chart’s appVersion matches the tag, so --version v0.6.0 automatically deploys :v0.6.0 container images.

Install from Cloned Repository

# Clone the repository
git clone https://github.com/gotrs-io/gotrs-ce.git
cd gotrs-ce

# Update Helm dependencies
helm dependency update charts/gotrs

# Install with default values (MySQL)
helm install gotrs ./charts/gotrs --namespace gotrs --create-namespace

# Install with PostgreSQL
helm install gotrs ./charts/gotrs \
  --namespace gotrs \
  --create-namespace \
  -f charts/gotrs/values-postgresql.yaml

Production Configuration

Ingress with TLS

# values-production.yaml
ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  hosts:
    - host: gotrs.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: gotrs-tls
      hosts:
        - gotrs.example.com

External Database (RDS, Cloud SQL, etc.)

For production, use a managed database service:

# values-production.yaml
database:
  type: mysql  # or postgresql
  external:
    enabled: true
    host: "your-rds-endpoint.amazonaws.com"
    port: "3306"
    database: "gotrs"
    existingSecret: "gotrs-db-credentials"  # Secret with keys: username, password

Create the secret:

kubectl create secret generic gotrs-db-credentials \
  --namespace gotrs \
  --from-literal=username=gotrs \
  --from-literal=password=your-secure-password

External Valkey/Redis (ElastiCache, etc.)

# values-production.yaml
valkey:
  enabled: false

externalValkey:
  enabled: true
  host: "your-elasticache-endpoint"
  port: 6379
  existingSecret: "gotrs-valkey-credentials"

Autoscaling

# values-production.yaml
backend:
  replicaCount: 3
  autoscaling:
    enabled: true
    minReplicas: 3
    maxReplicas: 10
    targetCPUUtilizationPercentage: 70
    targetMemoryUtilizationPercentage: 80

  resources:
    requests:
      cpu: "500m"
      memory: "512Mi"
    limits:
      cpu: "2"
      memory: "2Gi"

Complete Production Example

helm install gotrs oci://ghcr.io/gotrs-io/charts/gotrs \
  --namespace gotrs \
  --create-namespace \
  --version latest \
  -f values-production.yaml \
  --set secrets.appSecretKey=$(openssl rand -hex 32)

Cloud Provider Integration

AWS EKS with IRSA

serviceAccount:
  annotations:
    eks.amazonaws.com/role-arn: "arn:aws:iam::123456789:role/gotrs"

backend:
  serviceAnnotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"

GKE with Workload Identity

serviceAccount:
  annotations:
    iam.gke.io/gcp-service-account: "[email protected]"

Azure AKS

serviceAccount:
  annotations:
    azure.workload.identity/client-id: "your-client-id"

backend:
  podLabels:
    azure.workload.identity/use: "true"

Observability

Prometheus Metrics

backend:
  podAnnotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "9090"
    prometheus.io/path: "/metrics"

Istio Service Mesh

backend:
  podAnnotations:
    sidecar.istio.io/inject: "true"
  podLabels:
    app: gotrs
    version: v1

Database Selection

MySQL/MariaDB (Default)

database:
  type: mysql
  mysql:
    rootPassword: ""  # Use existingSecret in production
    existingSecret: "gotrs-mysql-secret"
    storage:
      size: 20Gi
    config:
      maxConnections: 200
      innodbBufferPoolSize: "1G"

PostgreSQL

database:
  type: postgresql
  postgresql:
    existingSecret: "gotrs-postgres-secret"
    storage:
      size: 20Gi
    config:
      maxConnections: 200
      sharedBuffers: "1GB"

Extra Resources

Define arbitrary Kubernetes resources with Helm templating:

extraResources:
  # PodDisruptionBudget for high availability
  - apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      name: "{{ .Release.Name }}-backend-pdb"
    spec:
      minAvailable: 2
      selector:
        matchLabels:
          app.kubernetes.io/name: gotrs
          app.kubernetes.io/component: backend

  # Scheduled cleanup job
  - apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: "{{ .Release.Name }}-cleanup"
    spec:
      schedule: "0 2 * * *"
      jobTemplate:
        spec:
          template:
            spec:
              containers:
                - name: cleanup
                  image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag | default .Chart.AppVersion }}"
                  command: ["/app/gotrs", "cleanup"]
              restartPolicy: OnFailure

Upgrading

# Update to latest version
helm upgrade gotrs oci://ghcr.io/gotrs-io/charts/gotrs \
  --namespace gotrs \
  --version latest \
  -f values-production.yaml

# Or from local chart
helm upgrade gotrs ./charts/gotrs --namespace gotrs -f values-production.yaml

Uninstalling

helm uninstall gotrs --namespace gotrs

Note: PVCs are retained by default. To remove all data:

kubectl delete pvc -l app.kubernetes.io/instance=gotrs -n gotrs

Troubleshooting

Check Pod Status

kubectl get pods -n gotrs -l app.kubernetes.io/instance=gotrs
kubectl describe pod <pod-name> -n gotrs
kubectl logs <pod-name> -n gotrs

Database Connection Issues

# Check database pod logs
kubectl logs -n gotrs -l app.kubernetes.io/component=database

# Test connectivity from backend
kubectl exec -it -n gotrs <backend-pod> -- nc -zv <db-service> 3306

Valkey Connection Issues

# Check valkey pods
kubectl get pods -n gotrs -l app.kubernetes.io/name=valkey

# Test connectivity
kubectl exec -it -n gotrs <backend-pod> -- nc -zv <valkey-service> 6379

View Helm Release Info

helm status gotrs -n gotrs
helm get values gotrs -n gotrs
helm history gotrs -n gotrs

Configuration Reference

ParameterDescriptionDefault
backend.replicaCountNumber of backend replicas2
backend.autoscaling.enabledEnable HPAfalse
database.typeDatabase type: mysql or postgresqlmysql
database.external.enabledUse external databasefalse
valkey.enabledDeploy Valkey subcharttrue
ingress.enabledEnable ingressfalse
config.logLevelApplication log levelinfo

See the full values.yaml for all configuration options.

Next Steps