---
title: "Distribuire HitKeep su Kubernetes con Helm | HitKeep"
description: "Distribuisci HitKeep su Kubernetes con il chart Helm ufficiale o uno StatefulSet, conservando dati DuckDB, risorse QR, archivi e backup su storage persistente."
canonical: "https://hitkeep.com/it/guides/installation/kubernetes/"
---

# 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.

## Avvio rapido

### Installa con Helm

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

```
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:

```
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:

```
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.

## Verifica

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

```
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:

```
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.

## Valori del chart da controllare

| Valore | Predefinito | Utilizzo |
| --- | --- | --- |
| image.repository | ghcr.io/pascalebeier/hitkeep | Repository dell’immagine container. |
| image.tag | versione app del chart, senza v iniziale | Sovrascrivi solo per eseguire intenzionalmente un’immagine diversa dalla versione del chart. |
| env.HITKEEP_PUBLIC_URL | http://localhost:8080 | URL visibile nel browser. Impostalo in produzione. |
| extraEnv | [] | Valori da Secret, come HITKEEP_JWT_SECRET, credenziali SMTP/S3 o token del provider AI. |
| persistence.enabled | true | Crea un volume claim template nello StatefulSet. |
| persistence.mountPath | /var/lib/hitkeep/data | Mount persistente usato dai valori predefiniti. |
| ingress.enabled | false | Crea un Ingress per l’ingress controller del cluster. |
| customTrackingDomains.enabled | false | Configura i domini di tracciamento personalizzati. |
| customTrackingDomains.ingress.enabled | false | Crea un Ingress separato, limitato al tracciamento, per hostname statici. |
| service.type | ClusterIP | Usa LoadBalancer o NodePort solo se coerente con il cluster. |
| replicaCount | 1 | Imposta 2 o più solo per il clustering HitKeep. |

Il chart imposta questi percorsi salvo sovrascrittura in `env`:

| Variabile d’ambiente | Valore 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.

## Domini di tracciamento personalizzati

Il chart supporta i [domini di tracciamento personalizzati](https://hitkeep.com/guides/tracking/custom-tracking-domains/) 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:

```
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.

## Aggiornamento

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

```
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.

## Configurazione opzionale di MCP e AI

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](https://hitkeep.com/guides/integrations/mcp/) e [Configurazione del modello AI](https://hitkeep.com/guides/admin/ai-model-configuration/) prima di abilitarli in produzione.

## Manifest Kubernetes semplice

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:

```
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.

## Sonde di integrità e disponibilità

| Endpoint | Scopo |
| --- | --- |
| GET /healthz | Liveness: il processo è in esecuzione. |
| GET /readyz | Readiness: 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.

## Proxy attendibili

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](https://hitkeep.com/guides/installation/trusted-proxies/).

## Backup

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](https://hitkeep.com/guides/data/s3-backups/).

## Pagine correlate

- [Installazione con Docker Compose](https://hitkeep.com/it/guides/installation/docker-compose/)
- [Proxy attendibili](https://hitkeep.com/guides/installation/trusted-proxies/)
- [Backup e ripristino](https://hitkeep.com/guides/data/backups-and-restore/)
- [Backup S3](https://hitkeep.com/guides/data/s3-backups/)
- [Riferimento di configurazione](https://hitkeep.com/reference/configuration/)
- [Architettura](https://hitkeep.com/reference/architecture/)

Esegui HitKeep su Kubernetes ma non vuoi gestire StatefulSet, PVC e aggiornamenti del cluster? [HitKeep Cloud](https://hitkeep.com/it/pricing/) gestisce l’infrastruttura nella regione scelta.

[Indietro Docker Compose](https://hitkeep.com/it/guides/installation/docker-compose/)[Avanti Trusted proxies](https://hitkeep.com/it/guides/installation/trusted-proxies/)
