Aller au contenu
Démarrer avec HitKeep Cloud

Deploy HitKeep on Kubernetes with Helm

Ce contenu n’est pas encore disponible dans votre langue.

Deploy HitKeep in your Kubernetes cluster with the official Helm chart when your cluster already uses Helm. The chart creates a StatefulSet, a ClusterIP Service, a headless Service for clustering, optional Ingress, and persistent storage for HitKeep’s DuckDB files and local assets.

Use the plain manifest later on this page if you do not use Helm or want every Kubernetes object visible in one file.

The chart is published as an OCI artifact on GitHub Container Registry:

Terminal window
helm show values oci://ghcr.io/pascalebeier/charts/hitkeep --version 2.8.1

Create a namespace and store the JWT signing secret before installing:

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

Save this as 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

Install the chart:

Terminal window
helm install hitkeep oci://ghcr.io/pascalebeier/charts/hitkeep \
--namespace analytics \
--version 2.8.1 \
-f hitkeep-values.yaml
kubectl -n analytics rollout status statefulset/hitkeep

If your cluster does not have an ingress controller, leave ingress.enabled as false and expose the Service through your normal cluster pattern.

Value Default Use
image.repository ghcr.io/pascalebeier/hitkeep Container image repository.
image.tag chart app version, without a leading v Override only when you intentionally run a different app image from the chart version.
env.HITKEEP_PUBLIC_URL http://localhost:8080 Browser-visible URL where HitKeep is reached. Set this for production.
extraEnv [] Secret-backed values such as HITKEEP_JWT_SECRET, SMTP credentials, S3 credentials, or AI provider tokens.
persistence.enabled true Creates a StatefulSet volume claim template for HitKeep’s data directory.
persistence.mountPath /var/lib/hitkeep/data Persistent mount used by the chart defaults below.
ingress.enabled false Creates an Ingress for your cluster ingress controller.
service.type ClusterIP Use LoadBalancer or NodePort only when that matches your cluster.
replicaCount 1 Set to 2 or more only when you want HitKeep clustering.

The chart sets these paths unless you override them in env:

Environment variable Chart default
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

With those defaults, the same PVC stores the shared DuckDB database, tenant DuckDB databases, QR Code graphic assets under assets/qr-codes, archive files, and the optional local spam-filter cache.

Keep your hitkeep-values.yaml under source control or in your deployment system. Upgrade the chart and app image together by changing only the chart version:

Terminal window
helm upgrade hitkeep oci://ghcr.io/pascalebeier/charts/hitkeep \
--namespace analytics \
--version 2.8.1 \
-f hitkeep-values.yaml
kubectl -n analytics rollout status statefulset/hitkeep

Review release notes before upgrading across feature releases, especially when you use optional integrations such as MCP, AI model configuration, Google Search Console, SMTP, or S3 backups.

MCP and AI-backed product features are disabled until you enable and configure them. Use env for non-secret settings and extraEnv for tokens.

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

See Official MCP Server and AI Model Configuration before enabling these in production.

Use this manifest if you do not use Helm. It keeps HitKeep’s runtime paths aligned with the official chart.

Save it as 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.8.1
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

Apply it:

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

Add your Ingress resource or external Service according to your cluster’s normal ingress controller or load-balancer setup.

HitKeep exposes two probe endpoints for Kubernetes:

Endpoint Purpose
GET /healthz Liveness. The process is running.
GET /readyz Readiness. The database connection is healthy.

These endpoints stay available at the local root even when HITKEEP_PUBLIC_URL includes a path prefix.

If your cluster uses an ingress controller such as nginx-ingress, Traefik, or AWS ALB, configure trusted proxy CIDRs so real client IPs are used for analytics and rate limiting:

env:
HITKEEP_TRUSTED_PROXIES: "10.0.0.0/8"

See Trusted Proxies for details.

Back up the full persistent data path. With the Helm chart defaults and the plain manifest above, the important runtime paths are:

  • /var/lib/hitkeep/data/hitkeep.db for shared control-plane data
  • /var/lib/hitkeep/data/tenants/*/hitkeep.db for non-default team analytics data
  • /var/lib/hitkeep/data/assets/qr-codes/* for QR Code graphic assets
  • /var/lib/hitkeep/data/archive for local archive artifacts
  • /var/lib/hitkeep/data/backups if you set HITKEEP_BACKUP_PATH to that local path

To enable local automatic backup snapshots on the same PVC:

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

For off-cluster backup storage, use an s3:// HITKEEP_BACKUP_PATH and configure the S3 environment variables in a Kubernetes Secret. See S3 Backups for examples.

Running HitKeep in Kubernetes but do not want to manage StatefulSets, PVCs, and cluster upgrades? HitKeep Cloud handles the infrastructure in your chosen managed region.