---
title: "HitKeep mit Helm auf Kubernetes bereitstellen | HitKeep"
description: "Stelle HitKeep mit dem offiziellen Helm-Chart oder einem StatefulSet auf Kubernetes bereit und speichere DuckDB-Daten, QR-Assets, Archive und Backups persistent."
canonical: "https://hitkeep.com/de/guides/installation/kubernetes/"
---

# HitKeep mit Helm auf Kubernetes bereitstellen

Stelle HitKeep mit dem offiziellen Helm-Chart in deinem Kubernetes-Cluster bereit, wenn dein Cluster bereits Helm nutzt. Der Chart erstellt ein StatefulSet, einen ClusterIP-Service, einen Headless-Service für das Clustering, optionalen Ingress und persistenten Speicher für HitKeeps DuckDB-Dateien und lokale Assets.

Verwende das einfache Manifest weiter unten, wenn du Helm nicht nutzt oder alle Kubernetes-Objekte sichtbar in einer Datei haben möchtest.

## Schnellstart

### Mit Helm installieren

Der Chart wird als OCI-Artefakt in der GitHub Container Registry veröffentlicht:

```
helm show values oci://ghcr.io/pascalebeier/charts/hitkeep --version 2.13.18
```

Erstelle vor der Installation einen Namespace und speichere das JWT-Signaturgeheimnis:

```
kubectl create namespace analytics
kubectl -n analytics create secret generic hitkeep-secrets \
  --from-literal=jwt-secret="$(openssl rand -hex 32)"
```

Speichere Folgendes als `hitkeep-values.yaml`:

```
domain: analytics.example.com

ingress:
  enabled: true
  className: ""

persistence:
  enabled: true
  size: 10Gi
  accessMode: ReadWriteOnce

env:
  HITKEEP_PUBLIC_URL: "https://analytics.example.com"

extraEnv:
  - name: HITKEEP_JWT_SECRET
    valueFrom:
      secretKeyRef:
        name: hitkeep-secrets
        key: jwt-secret
```

Installiere den Chart:

```
helm install hitkeep oci://ghcr.io/pascalebeier/charts/hitkeep --namespace analytics --version 2.13.18 -f hitkeep-values.yaml

kubectl -n analytics rollout status statefulset/hitkeep
```

Wenn dein Cluster keinen Ingress-Controller besitzt, lasse `ingress.enabled` auf `false` und veröffentliche den Service nach dem üblichen Muster deines Clusters.

## Installation prüfen

Prüfe, ob das StatefulSet vollständig ausgerollt und der PersistentVolumeClaim gebunden ist:

```
kubectl -n analytics rollout status statefulset/hitkeep
kubectl -n analytics get pods,pvc
kubectl -n analytics port-forward service/hitkeep 8080:80
```

Prüfe bei laufendem Port-Forward beide Endpunkte in einem weiteren Terminal:

```
curl --fail http://localhost:8080/healthz
curl --fail http://localhost:8080/readyz
```

`/healthz` bestätigt, dass der Prozess läuft. `/readyz` bestätigt, dass die gemeinsame Datenbank und jede geöffnete Mandantendatenbank bereit sind.

## Zu prüfende Chart-Werte

| Wert | Standard | Verwendung |
| --- | --- | --- |
| image.repository | ghcr.io/pascalebeier/hitkeep | Repository des Container-Images. |
| image.tag | App-Version des Charts ohne führendes v | Nur überschreiben, wenn du bewusst ein anderes App-Image als die Chart-Version ausführst. |
| env.HITKEEP_PUBLIC_URL | http://localhost:8080 | Im Browser sichtbare URL für HitKeep. Für den Produktivbetrieb festlegen. |
| extraEnv | [] | Aus Secrets bezogene Werte wie HITKEEP_JWT_SECRET, SMTP- oder S3-Zugangsdaten und KI-Provider-Token. |
| persistence.enabled | true | Erstellt eine VolumeClaimTemplate des StatefulSets für HitKeeps Datenverzeichnis. |
| persistence.mountPath | /var/lib/hitkeep/data | Persistenter Mount für die folgenden Chart-Standardwerte. |
| ingress.enabled | false | Erstellt einen Ingress für den Ingress-Controller deines Clusters. |
| customTrackingDomains.enabled | false | Konfiguriert HitKeeps Laufzeiteinstellungen für eigene Tracking-Domains. |
| customTrackingDomains.ingress.enabled | false | Erstellt einen separaten reinen Tracking-Ingress für statische Tracker-Hostnamen. |
| service.type | ClusterIP | Nutze LoadBalancer oder NodePort nur, wenn das zu deinem Cluster passt. |
| replicaCount | 1 | Setze den Wert nur dann auf 2 oder höher, wenn du HitKeep-Clustering benötigst. |

Der Chart setzt diese Pfade, sofern du sie nicht unter `env` überschreibst:

| Umgebungsvariable | Chart-Standardwert |
| --- | --- |
| HITKEEP_DB_PATH | /var/lib/hitkeep/data/hitkeep.db |
| HITKEEP_DATA_PATH | /var/lib/hitkeep/data |
| HITKEEP_ARCHIVE_PATH | /var/lib/hitkeep/data/archive |
| HITKEEP_SPAM_FILTER_PATH | /var/lib/hitkeep/data/spam-filter.json |

Mit diesen Standardwerten speichert derselbe PVC die gemeinsame DuckDB-Datenbank, die DuckDB-Datenbanken der Mandanten, QR-Code-Grafiken unter `assets/qr-codes`, Archivdateien und den optionalen lokalen Spamfilter-Cache.

## Eigene Tracking-Domains

Der Helm-Chart unterstützt [eigene Tracking-Domains](https://hitkeep.com/guides/tracking/custom-tracking-domains/), ohne einen Ingress-Controller mitzuliefern. Nutze denselben Dashboard-Ablauf wie bei anderen selbst gehosteten Installationen: Füge die Domain in den Team-Einstellungen hinzu, veröffentliche den TXT-Eigentumsnachweis, richte DNS auf das Ingress-Ziel und verifiziere die Domain, sobald TLS bereit ist.

Nutze für übliche Kubernetes-Ingress-Controller den externen TLS-Modus:

```
customTrackingDomains:
  enabled: true
  tlsMode: external
  # Empty defaults to the host from env.HITKEEP_PUBLIC_URL.
  # Set this when tracker domains point at a separate ingress hostname or IP.
  dnsTarget: ""
  ingress:
    enabled: true
    className: nginx
    annotations:
      cert-manager.io/cluster-issuer: letsencrypt-prod
    hosts:
      - host: tracker.customer-one.example
      - host: tracker.customer-two.example
    tls:
      - hosts:
          - tracker.customer-one.example
          - tracker.customer-two.example
        secretName: hitkeep-tracking-tls
```

Der Chart erzeugt einen separaten Tracking-Ingress, der nach dem Helm-Release benannt ist, beispielsweise `hitkeep-tracking`. Er leitet ausschließlich `/hk.js`, `/hk-vitals.js`, `/ingest`, `/ingest/event` und `/ingest/web-vitals` an HitKeep weiter. Dashboard-, API-, Auth-, Share-, MCP-, QR- und SPA-Fallback-Routen gehören nicht zu diesem Ingress. HitKeep setzt die Beschränkung auf Tracking-Hosts zusätzlich intern durch.

Stelle Caddy für On-Demand-TLS separat bereit und speichere das Ask-Token in einem Kubernetes-Secret:

```
kubectl -n analytics create secret generic hitkeep-caddy-ask \
  --from-literal=token="$(openssl rand -hex 32)"
```

```
customTrackingDomains:
  enabled: true
  tlsMode: caddy-on-demand
  caddyAskToken:
    existingSecret: hitkeep-caddy-ask
    existingSecretKey: token
  ingress:
    enabled: false
```

Konfiguriere den externen Caddy-Listener mit `ask http://hitkeep.analytics.svc.cluster.local/internal/caddy/on-demand-tls/<token>`. Caddy sendet `?domain=` an diese URL, bevor es ein Zertifikat ausstellt. HitKeep erlaubt nur aktivierte, per DNS verifizierte eigene Tracking-Domains.

## Upgrade

Bewahre deine `hitkeep-values.yaml` in der Versionsverwaltung oder deinem Bereitstellungssystem auf. Aktualisiere Chart und App-Image gemeinsam, indem du ausschließlich die Chart-Version änderst:

```
helm upgrade hitkeep oci://ghcr.io/pascalebeier/charts/hitkeep --namespace analytics --version 2.13.18 -f hitkeep-values.yaml

kubectl -n analytics rollout status statefulset/hitkeep
```

Lies vor Upgrades über Feature-Releases hinweg die Release Notes, insbesondere wenn du optionale Integrationen wie MCP, KI-Modellkonfiguration, Google Search Console, SMTP oder S3-Backups nutzt.

## Optionale MCP- und KI-Konfiguration

MCP und KI-gestützte Produktfunktionen bleiben deaktiviert, bis du sie aktivierst und konfigurierst. Nutze `env` für nicht geheime Einstellungen und `extraEnv` für Token.

```
env:
  HITKEEP_MCP_ENABLED: "true"
  HITKEEP_MCP_PATH: "/mcp"
  HITKEEP_MCP_MAX_RANGE_DAYS: "366"
  HITKEEP_AI_ENABLED: "true"
  HITKEEP_AI_PROVIDER: "openai-compatible"
  HITKEEP_AI_MODEL: "opportunities-json"

extraEnv:
  - name: HITKEEP_AI_API_KEY
    valueFrom:
      secretKeyRef:
        name: hitkeep-ai
        key: api-key
```

Lies vor der Aktivierung im Produktivbetrieb [Offizieller MCP-Server](https://hitkeep.com/guides/integrations/mcp/) und [KI-Modellkonfiguration](https://hitkeep.com/guides/admin/ai-model-configuration/).

## Einfaches Kubernetes-Manifest

Nutze dieses Manifest, wenn du Helm nicht verwendest. Die HitKeep-Laufzeitpfade entsprechen denen des offiziellen Charts.

Speichere es als `hitkeep.yaml`:

```
apiVersion: v1
kind: Namespace
metadata:
name: analytics
---
apiVersion: v1
kind: Secret
metadata:
name: hitkeep-secrets
namespace: analytics
type: Opaque
stringData:
jwt-secret: "change-me-to-a-long-random-string"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: hitkeep-data
namespace: analytics
spec:
accessModes: ["ReadWriteOnce"]
resources:
  requests:
    storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: hitkeep-headless
namespace: analytics
spec:
clusterIP: None
publishNotReadyAddresses: true
selector:
  app: hitkeep
ports:
  - name: gossip-tcp
    port: 7946
    protocol: TCP
    targetPort: gossip-tcp
  - name: gossip-udp
    port: 7946
    protocol: UDP
    targetPort: gossip-udp
---
apiVersion: v1
kind: Service
metadata:
name: hitkeep
namespace: analytics
spec:
type: ClusterIP
selector:
  app: hitkeep
ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: http
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: hitkeep
namespace: analytics
spec:
serviceName: hitkeep-headless
replicas: 1
selector:
  matchLabels:
    app: hitkeep
template:
  metadata:
    labels:
      app: hitkeep
  spec:
    securityContext:
      runAsNonRoot: true
      runAsUser: 65532
      runAsGroup: 65532
      fsGroup: 65532
    containers:
      - name: hitkeep
        image: ghcr.io/pascalebeier/hitkeep:2.13.18
        imagePullPolicy: IfNotPresent
        ports:
          - containerPort: 8080
            name: http
          - containerPort: 7946
            name: gossip-tcp
            protocol: TCP
          - containerPort: 7946
            name: gossip-udp
            protocol: UDP
        env:
          - name: HITKEEP_HTTP_ADDR
            value: ":8080"
          - name: HITKEEP_PUBLIC_URL
            value: "https://analytics.example.com"
          - name: HITKEEP_DB_PATH
            value: "/var/lib/hitkeep/data/hitkeep.db"
          - name: HITKEEP_DATA_PATH
            value: "/var/lib/hitkeep/data"
          - name: HITKEEP_ARCHIVE_PATH
            value: "/var/lib/hitkeep/data/archive"
          - name: HITKEEP_SPAM_FILTER_PATH
            value: "/var/lib/hitkeep/data/spam-filter.json"
          - name: HITKEEP_JWT_SECRET
            valueFrom:
              secretKeyRef:
                name: hitkeep-secrets
                key: jwt-secret
        volumeMounts:
          - mountPath: /var/lib/hitkeep/data
            name: data
        livenessProbe:
          httpGet:
            path: /healthz
            port: http
          initialDelaySeconds: 10
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /readyz
            port: http
          initialDelaySeconds: 5
          periodSeconds: 10
    volumes:
      - name: data
        persistentVolumeClaim:
          claimName: hitkeep-data
```

Wende es an:

```
kubectl apply -f hitkeep.yaml
kubectl -n analytics rollout status statefulset/hitkeep
```

Ergänze deine Ingress-Ressource oder einen externen Service passend zum üblichen Ingress-Controller- oder Load-Balancer-Aufbau deines Clusters.

## Zustands- und Bereitschaftsprüfungen

HitKeep stellt zwei Prüfendpunkte für Kubernetes bereit:

| Endpunkt | Zweck |
| --- | --- |
| GET /healthz | Liveness: Der Prozess läuft. |
| GET /readyz | Readiness: Die gemeinsame Datenbank und jede aktuell geöffnete Mandantendatenbank sind fehlerfrei. |

Diese Endpunkte bleiben am lokalen Root verfügbar, auch wenn `HITKEEP_PUBLIC_URL` ein Pfadpräfix enthält.

Während einer Datenbankwiederherstellung bleibt `/healthz` erfolgreich, damit der Kubelet keinen Prozess beendet, der gerade sichere Wiederherstellungsarbeiten ausführt. `/readyz` antwortet mit `503`, `Retry-After: 5` und einem JSON-Grund wie `database_recovering` oder `database_needs_attention`. Dadurch wird der Pod aus dem Service genommen, bis die Datenbank wieder fehlerfrei ist.

## Vertrauenswürdige Proxys

Wenn dein Cluster einen Ingress-Controller wie nginx-ingress, Traefik oder AWS ALB nutzt, konfiguriere vertrauenswürdige Proxy-CIDRs, damit echte Client-IPs für Webanalyse und Ratenbegrenzung verwendet werden:

```
env:
  HITKEEP_TRUSTED_PROXIES: "10.0.0.0/8"
```

Weitere Einzelheiten findest du unter [Vertrauenswürdige Proxys](https://hitkeep.com/guides/installation/trusted-proxies/).

## Backup

Sichere den vollständigen persistenten Datenpfad. Bei den Standardwerten des Helm-Charts und des einfachen Manifests oben sind diese Laufzeitpfade wichtig:

- `/var/lib/hitkeep/data/hitkeep.db` für gemeinsame Control-Plane-Daten
- `/var/lib/hitkeep/data/tenants/*/hitkeep.db` für Analysedaten von Teams außerhalb des Standardmandanten
- `/var/lib/hitkeep/data/assets/qr-codes/*` für QR-Code-Grafiken
- `/var/lib/hitkeep/data/archive` für lokale Archivartefakte
- `/var/lib/hitkeep/data/backups`, wenn du `HITKEEP_BACKUP_PATH` auf diesen lokalen Pfad setzt
- `/var/lib/hitkeep/data/recovery` für zugriffsgeschützte automatische Wiederherstellungspakete und fortsetzbare Marker, sofern du `HITKEEP_DB_RECOVERY_PATH` nicht überschreibst

Aktiviere lokale automatische Backup-Snapshots auf demselben PVC so:

```
env:
  HITKEEP_BACKUP_PATH: "/var/lib/hitkeep/data/backups"
  HITKEEP_BACKUP_INTERVAL: "60"
  HITKEEP_BACKUP_RETENTION: "24"
```

Nutze für Backup-Speicher außerhalb des Clusters einen `s3://`-Wert für `HITKEEP_BACKUP_PATH` und konfiguriere die S3-Umgebungsvariablen in einem Kubernetes-Secret. Beispiele findest du unter [S3-Backups](https://hitkeep.com/guides/data/s3-backups/).

## Verwandte Themen

- [Docker-Compose-Installation](https://hitkeep.com/de/guides/installation/docker-compose/)
- [Vertrauenswürdige Proxys](https://hitkeep.com/guides/installation/trusted-proxies/)
- [Backups und Wiederherstellung](https://hitkeep.com/guides/data/backups-and-restore/)
- [S3-Backups](https://hitkeep.com/guides/data/s3-backups/)
- [Konfigurationsreferenz](https://hitkeep.com/reference/configuration/)
- [Architektur](https://hitkeep.com/reference/architecture/)

Du betreibst HitKeep auf Kubernetes, möchtest aber StatefulSets, PVCs und Cluster-Upgrades nicht selbst verwalten? [HitKeep Cloud](https://hitkeep.com/de/pricing/) übernimmt die Infrastruktur in der von dir gewählten verwalteten Region.

[Vorherige Seite Docker Compose](https://hitkeep.com/de/guides/installation/docker-compose/)[Nächste Seite Trusted proxies](https://hitkeep.com/de/guides/installation/trusted-proxies/)
