Ir al contenido
HitKeep
Seleccionar idioma
Seleccionar tema
GitHub
Empezar gratis en Cloud

Desplegar HitKeep en Kubernetes con Helm

Despliega HitKeep en tu clúster de Kubernetes con el chart oficial de Helm si el clúster ya usa Helm. El chart crea un StatefulSet, un Service ClusterIP, un Service headless para el clúster, un Ingress opcional y almacenamiento persistente para los archivos de DuckDB y los recursos locales de HitKeep.

Usa el manifiesto sencillo que aparece más adelante si no utilizas Helm o quieres ver todos los objetos de Kubernetes en un único archivo.

El chart se publica como artefacto OCI en GitHub Container Registry:

Ventana de terminal
helm show values oci://ghcr.io/pascalebeier/charts/hitkeep --version 2.14.1

Crea un namespace y guarda el secreto para firmar JWT antes de instalar:

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

Guarda lo siguiente como 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

Instala el chart:

Ventana de terminal
helm install hitkeep oci://ghcr.io/pascalebeier/charts/hitkeep --namespace analytics --version 2.14.1 -f hitkeep-values.yaml
kubectl -n analytics rollout status statefulset/hitkeep

Si tu clúster no tiene un controlador de Ingress, conserva ingress.enabled como false y publica el Service siguiendo el patrón habitual de tu clúster.

Confirma que el StatefulSet ha completado el despliegue y que la reclamación de volumen persistente está enlazada:

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

Mientras el reenvío de puerto esté activo, comprueba ambos endpoints desde otra terminal:

Terminal window
curl --fail http://localhost:8080/healthz
curl --fail http://localhost:8080/readyz

/healthz confirma que el proceso está activo. /readyz confirma que la base de datos compartida y todas las bases de datos de tenants abiertas están listas.

ValorPredeterminadoUso
image.repositoryghcr.io/pascalebeier/hitkeepRepositorio de la imagen de contenedor.
image.tagversión de la aplicación del chart, sin la v inicialCámbialo únicamente si quieres ejecutar deliberadamente una imagen de la aplicación distinta de la versión del chart.
env.HITKEEP_PUBLIC_URLhttp://localhost:8080URL visible en el navegador para acceder a HitKeep. Defínela en producción.
extraEnv[]Valores respaldados por secretos, como HITKEEP_JWT_SECRET, credenciales SMTP o S3 y tokens de proveedores de IA.
persistence.enabledtrueCrea una plantilla de reclamación de volumen del StatefulSet para el directorio de datos de HitKeep.
persistence.mountPath/var/lib/hitkeep/dataPunto de montaje persistente usado por los valores predeterminados del chart que aparecen a continuación.
ingress.enabledfalseCrea un Ingress para el controlador de Ingress del clúster.
customTrackingDomains.enabledfalseConfigura los ajustes de ejecución de HitKeep para dominios de seguimiento personalizados.
customTrackingDomains.ingress.enabledfalseCrea un Ingress independiente, limitado al seguimiento, para hostnames estáticos del tracker.
service.typeClusterIPUsa LoadBalancer o NodePort solo si encaja con tu clúster.
replicaCount1Usa 2 o más únicamente si quieres un clúster de HitKeep.

El chart define estas rutas salvo que las sobrescribas en env:

Variable de entornoValor predeterminado 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 estos valores, el mismo PVC almacena la base de datos DuckDB compartida, las bases de datos DuckDB de los tenants, los recursos gráficos de códigos QR en assets/qr-codes, los archivos y la caché local opcional del filtro de spam.

El chart de Helm admite dominios de seguimiento personalizados sin incluir un controlador de Ingress. Usa el mismo flujo del panel que en otras instalaciones autogestionadas: añade el dominio en los ajustes del equipo, publica el registro TXT de propiedad, dirige el DNS al destino del Ingress y verifica cuando TLS esté listo.

Con controladores de Ingress habituales de Kubernetes, usa el modo TLS externo:

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

El chart emite un Ingress de seguimiento independiente cuyo nombre deriva de la instalación de Helm, por ejemplo hitkeep-tracking. Solo enruta /hk.js, /hk-vitals.js, /ingest, /ingest/event y /ingest/web-vitals hacia HitKeep. El panel, la API, la autenticación, los enlaces compartidos, MCP, QR y las rutas alternativas de la SPA no forman parte de ese Ingress. HitKeep también aplica internamente este límite para los hosts de seguimiento.

Para TLS bajo demanda de Caddy, despliega Caddy por separado y conserva el token de consulta en un Secret de Kubernetes:

Terminal window
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 el listener externo de Caddy con ask http://hitkeep.analytics.svc.cluster.local/internal/caddy/on-demand-tls/<token>. Caddy envía ?domain= a esa URL antes de emitir un certificado y HitKeep solo permite dominios de seguimiento personalizados activados y verificados mediante DNS.

Conserva hitkeep-values.yaml bajo control de versiones o en tu sistema de despliegue. Actualiza juntos el chart y la imagen de la aplicación cambiando únicamente la versión del chart:

Ventana de terminal
helm upgrade hitkeep oci://ghcr.io/pascalebeier/charts/hitkeep --namespace analytics --version 2.14.1 -f hitkeep-values.yaml
kubectl -n analytics rollout status statefulset/hitkeep

Revisa las notas de la versión antes de actualizar entre versiones con funcionalidades distintas, sobre todo si usas integraciones opcionales como MCP, configuración de modelos de IA, Google Search Console, SMTP o copias de seguridad en S3.

MCP y las funcionalidades del producto basadas en IA permanecen desactivadas hasta que las habilites y configures. Usa env para ajustes no sensibles y extraEnv para 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

Consulta Servidor MCP oficial y Configuración de modelos de IA antes de activarlos en producción.

Usa este manifiesto si no utilizas Helm. Mantiene las rutas de ejecución de HitKeep alineadas con el chart oficial.

Guárdalo como 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.14.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

Aplícalo:

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

Añade tu recurso Ingress o un Service externo de acuerdo con el controlador de Ingress o el balanceador de carga habitual del clúster.

Comprobaciones de actividad y disponibilidad

Section titled “Comprobaciones de actividad y disponibilidad”

HitKeep expone dos endpoints de comprobación para Kubernetes:

EndpointFinalidad
GET /healthzActividad. El proceso está en ejecución.
GET /readyzDisponibilidad. La base de datos compartida y todas las bases de datos de tenants abiertas están en buen estado.

Estos endpoints siguen disponibles en la raíz local aunque HITKEEP_PUBLIC_URL incluya un prefijo de ruta.

Durante la recuperación de la base de datos, /healthz sigue respondiendo correctamente para que kubelet no termine un proceso que está realizando una recuperación segura. /readyz responde con 503, Retry-After: 5 y un motivo JSON como database_recovering o database_needs_attention, por lo que el pod queda fuera de servicio hasta que la base de datos vuelva a estar en buen estado.

Si tu clúster usa un controlador de Ingress como nginx-ingress, Traefik o AWS ALB, configura los CIDR de proxies de confianza para usar las IP reales de clientes en la analítica y los límites de solicitudes:

env:
HITKEEP_TRUSTED_PROXIES: "10.0.0.0/8"

Consulta Proxies de confianza para obtener más información.

Crea copias de toda la ruta de datos persistente. Con los valores predeterminados del chart de Helm y el manifiesto sencillo anterior, las rutas de ejecución importantes son:

  • /var/lib/hitkeep/data/hitkeep.db para los datos compartidos del plano de control
  • /var/lib/hitkeep/data/tenants/*/hitkeep.db para los datos de analítica de los equipos no predeterminados
  • /var/lib/hitkeep/data/assets/qr-codes/* para los recursos gráficos de códigos QR
  • /var/lib/hitkeep/data/archive para los archivos locales
  • /var/lib/hitkeep/data/backups si defines HITKEEP_BACKUP_PATH con esa ruta local
  • /var/lib/hitkeep/data/recovery para paquetes de recuperación automática y marcadores reanudables con permisos restringidos, salvo que sobrescribas HITKEEP_DB_RECOVERY_PATH

Para activar instantáneas automáticas locales en el mismo PVC:

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

Para almacenar copias fuera del clúster, usa una URL s3:// en HITKEEP_BACKUP_PATH y configura las variables de entorno S3 en un Secret de Kubernetes. Consulta Copias de seguridad en S3 para ver ejemplos.

¿Ejecutas HitKeep en Kubernetes pero no quieres administrar StatefulSets, PVC ni actualizaciones del clúster? Compara HitKeep Cloud.