Salta ai contenuti
Inizia gratis in Cloud

Distribuire HitKeep su Kubernetes con Helm

Distribuisci HitKeep nel tuo cluster Kubernetes con il chart Helm ufficiale se usi già Helm. Il chart crea uno StatefulSet, un Service ClusterIP, un Service headless per il clustering, un Ingress opzionale e storage persistente per i file DuckDB e le risorse locali di HitKeep.

Se non usi Helm o vuoi vedere ogni oggetto Kubernetes in un singolo file, usa il manifest semplice più avanti nella pagina.

Il chart è pubblicato come artefatto OCI su GitHub Container Registry:

Finestra del terminale
helm show values oci://ghcr.io/pascalebeier/charts/hitkeep --version 2.13.18

Crea un namespace e salva il segreto di firma JWT prima dell’installazione:

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

Salva questo file come 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

Installa il chart:

Finestra del terminale
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

Se il cluster non dispone di un ingress controller, lascia ingress.enabled su false ed esponi il Service secondo lo schema abituale del cluster.

Controlla che il rollout dello StatefulSet sia completato e che il persistent volume claim sia associato:

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

Mentre il port forwarding è attivo, interroga entrambe le sonde da un altro terminale:

Finestra del terminale
curl --fail http://localhost:8080/healthz
curl --fail http://localhost:8080/readyz

/healthz conferma che il processo è attivo. /readyz conferma che il database condiviso e tutti i database dei tenant aperti sono pronti.

ValorePredefinitoUtilizzo
image.repositoryghcr.io/pascalebeier/hitkeepRepository dell’immagine container.
image.tagversione app del chart, senza v inizialeSovrascrivi solo per eseguire intenzionalmente un’immagine diversa dalla versione del chart.
env.HITKEEP_PUBLIC_URLhttp://localhost:8080URL visibile nel browser. Impostalo in produzione.
extraEnv[]Valori da Secret, come HITKEEP_JWT_SECRET, credenziali SMTP/S3 o token del provider AI.
persistence.enabledtrueCrea un volume claim template nello StatefulSet.
persistence.mountPath/var/lib/hitkeep/dataMount persistente usato dai valori predefiniti.
ingress.enabledfalseCrea un Ingress per l’ingress controller del cluster.
customTrackingDomains.enabledfalseConfigura i domini di tracciamento personalizzati.
customTrackingDomains.ingress.enabledfalseCrea un Ingress separato, limitato al tracciamento, per hostname statici.
service.typeClusterIPUsa LoadBalancer o NodePort solo se coerente con il cluster.
replicaCount1Imposta 2 o più solo per il clustering HitKeep.

Il chart imposta questi percorsi salvo sovrascrittura in env:

Variabile d’ambienteValore predefinito del chart
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

Con questi valori lo stesso PVC contiene database DuckDB condiviso e dei tenant, risorse grafiche dei QR Code in assets/qr-codes, archivi e cache opzionale del filtro spam.

Il chart supporta i domini di tracciamento personalizzati senza includere un ingress controller. Segui lo stesso flusso della dashboard: aggiungi il dominio in Team Settings, pubblica il record TXT di proprietà, punta il DNS al target dell’Ingress e verifica quando TLS è pronto.

Con gli ingress controller Kubernetes standard usa la modalità TLS esterna:

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

Il chart crea un Ingress di tracciamento separato, per esempio hitkeep-tracking, che inoltra solo /hk.js, /hk-vitals.js, /ingest, /ingest/event e /ingest/web-vitals. Dashboard, API, autenticazione, condivisioni, MCP, QR e route fallback SPA non ne fanno parte. HitKeep applica lo stesso confine anche internamente.

Per TLS on-demand con Caddy, distribuisci Caddy separatamente e conserva il token ask in un Secret Kubernetes:

Finestra del terminale
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

Configura Caddy con ask http://hitkeep.analytics.svc.cluster.local/internal/caddy/on-demand-tls/<token>. Prima di emettere un certificato Caddy aggiunge ?domain=; HitKeep consente solo domini abilitati e verificati via DNS.

Mantieni hitkeep-values.yaml nel controllo versione o nel sistema di distribuzione. Aggiorna chart e immagine insieme modificando soltanto la versione del chart:

Finestra del terminale
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

Leggi le note di rilascio prima di attraversare release di funzionalità, soprattutto se usi integrazioni opzionali come MCP, modelli AI, Google Search Console, SMTP o backup S3.

MCP e le funzionalità basate su AI restano disabilitati finché non li configuri. Usa env per impostazioni non sensibili ed extraEnv per i 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

Consulta Server MCP ufficiale e Configurazione del modello AI prima di abilitarli in produzione.

Se non usi Helm, salva il seguente manifest come hitkeep.yaml. I percorsi di runtime restano allineati al chart ufficiale:

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

Applicalo:

Finestra del terminale
kubectl apply -f hitkeep.yaml
kubectl -n analytics rollout status statefulset/hitkeep

Aggiungi un Ingress o un Service esterno secondo lo schema del tuo ingress controller o bilanciatore di carico.

EndpointScopo
GET /healthzLiveness: il processo è in esecuzione.
GET /readyzReadiness: il database condiviso e tutti i database tenant aperti sono integri.

Gli endpoint restano disponibili alla radice locale anche quando HITKEEP_PUBLIC_URL contiene un prefisso. Durante il recupero del database, /healthz continua a rispondere correttamente per evitare che kubelet interrompa un recupero sicuro. /readyz restituisce 503, Retry-After: 5 e un motivo JSON come database_recovering o database_needs_attention, rimuovendo il pod dal servizio finché il database non è integro.

Se il cluster usa nginx-ingress, Traefik, AWS ALB o un altro ingress controller, configura i CIDR dei proxy affinché analytics e rate limiting usino gli IP reali:

env:
HITKEEP_TRUSTED_PROXIES: "10.0.0.0/8"

Consulta Proxy attendibili.

Esegui il backup dell’intero percorso dati persistente. Con i valori predefiniti del chart e il manifest precedente, i percorsi importanti sono:

  • /var/lib/hitkeep/data/hitkeep.db per i dati condivisi del control plane;
  • /var/lib/hitkeep/data/tenants/*/hitkeep.db per i dati analytics dei team non predefiniti;
  • /var/lib/hitkeep/data/assets/qr-codes/* per le risorse grafiche QR Code;
  • /var/lib/hitkeep/data/archive per gli archivi locali;
  • /var/lib/hitkeep/data/backups se HITKEEP_BACKUP_PATH usa quel percorso;
  • /var/lib/hitkeep/data/recovery per bundle e marker di recupero con permessi limitati, salvo modifica di HITKEEP_DB_RECOVERY_PATH.

Per abilitare snapshot automatici locali sullo stesso PVC:

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

Per backup esterni al cluster, usa un HITKEEP_BACKUP_PATH s3:// e conserva le variabili S3 in un Secret Kubernetes. Consulta Backup S3.

Esegui HitKeep su Kubernetes ma non vuoi gestire StatefulSet, PVC e aggiornamenti del cluster? HitKeep Cloud gestisce l’infrastruttura nella regione scelta.