Skip to content

Karakeep

AI-powered bookmark manager. Karakeep saves links with full-text content archival, automatic screenshots via a headless Chromium browser, full-text search via Meilisearch, and optional AI-driven automatic tagging. All data is stored in SQLite on a single persistent volume.

Architecture

Karakeep runs as a single pod with optional sidecars sharing the same PVC:

  • karakeep — main application (Next.js)
  • meilisearch (optional) — full-text search engine, indexes archived content
  • chromium (optional) — headless browser for web page screenshots and archiving
Chromium and Meilisearch require significant resources

With both sidecars enabled (the default), the pod requires at least 1.5–2 GB RAM to operate stably. The Chromium sidecar alone needs ~500 MB on startup. On resource-constrained clusters (e.g. Raspberry Pi), disable one or both sidecars and set explicit resources limits for the remaining containers.

Key Features

  • Meilisearch sidecar — optional full-text search across bookmarks and archived content
  • Chromium sidecar — optional headless browser for automatic web page screenshots
  • AI tagging — automatic categorization via OpenAI or Ollama (configured via extraEnv)
  • SQLite storage — embedded database, no external database required
  • Persistent storage — single PVC shared by all containers
  • Ingress support — TLS via cert-manager with configurable ingress class
  • External Secrets — optional ESO projection for auth and Meilisearch credentials

Operational Patterns

The examples below cover the supported Karakeep operating modes: full sidecar mode, lightweight mode, AI tagging, explicit resource limits, TLS ingress, Gateway API, and External Secrets Operator credentials. The playground exposes the same high-impact settings so operators can generate a focused values file without starting from the complete values contract.

Security Scan

Security Scan: Kubescape on rendered default manifests.

Framework Score
MITRE 100.00%
NSA 60.00%
SOC2 80.00%
Aggregate 80.00%

Default findings map to controls that should be set by production values or the platform: resource limits, container hardening context, service account token policy, and namespace network policy.

Installation

HTTPS repository:

helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install karakeep helmforge/karakeep

OCI registry:

helm install karakeep oci://ghcr.io/helmforgedev/helm/karakeep

Deployment Examples

# values.yaml — Karakeep with Meilisearch and Chromium (default)
karakeep:
  nextAuthUrl: 'https://karakeep.example.com'

meilisearch:
  enabled: true

chromium:
  enabled: true

persistence:
  enabled: true
  size: 10Gi

ingress:
  enabled: true
  ingressClassName: traefik
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: karakeep.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: karakeep-tls
      hosts:
        - karakeep.example.com
# values.yaml — Lightweight mode without sidecars
# Suitable for resource-constrained environments (ARM, Raspberry Pi)
# Full-text search and automatic screenshots will be unavailable.
karakeep:
  nextAuthUrl: 'https://karakeep.example.com'

meilisearch:
  enabled: false

chromium:
  enabled: false

persistence:
  enabled: true
  size: 5Gi

resources:
  requests:
    memory: 256Mi
    cpu: 100m
  limits:
    memory: 512Mi
    cpu: 500m

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: karakeep.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Karakeep with OpenAI automatic tagging
karakeep:
  nextAuthUrl: 'https://karakeep.example.com'
  extraEnv:
    # OpenAI integration for automatic AI tagging
    - name: OPENAI_API_KEY
      valueFrom:
        secretKeyRef:
          name: karakeep-ai-secret
          key: openai-api-key
    - name: OPENAI_BASE_URL
      value: 'https://api.openai.com/v1'

    # Alternative: use Ollama for local AI inference
    # - name: OLLAMA_BASE_URL
    #   value: 'http://ollama.ollama.svc:11434'
    # - name: INFERENCE_TEXT_MODEL
    #   value: 'llama3.2'

meilisearch:
  enabled: true

chromium:
  enabled: true

persistence:
  enabled: true
  size: 10Gi

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: karakeep.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Production setup with explicit resource limits per container
karakeep:
  nextAuthUrl: 'https://karakeep.example.com'

meilisearch:
  enabled: true
  resources:
    requests:
      memory: 256Mi
      cpu: 100m
    limits:
      memory: 512Mi
      cpu: 500m

chromium:
  enabled: true
  resources:
    requests:
      memory: 512Mi
      cpu: 250m
    limits:
      memory: 1Gi
      cpu: 1000m

resources:
  requests:
    memory: 256Mi
    cpu: 100m
  limits:
    memory: 512Mi
    cpu: 500m

persistence:
  enabled: true
  size: 10Gi

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: karakeep.example.com
      paths:
        - path: /
          pathType: Prefix

Configuration Reference

Core

Parameter Type Default Description
nameOverride string "" Override the chart name.
fullnameOverride string "" Override the full release name.
commonLabels object {} Extra labels added to all resources.

Image

Parameter Type Default Description
image.repository string ghcr.io/karakeep-app/karakeep Karakeep container image.
image.tag string "0.32.0" Image tag.
image.pullPolicy string IfNotPresent Image pull policy.
imagePullSecrets array [] Pull secrets for private registries.

Karakeep Configuration

Parameter Type Default Description
karakeep.nextAuthUrl string "" Public URL of the instance. Used as NEXTAUTH_URL for authentication callbacks.
karakeep.browserConnectOnDemand bool true Connect to Chromium only when crawling needs it.
karakeep.existingSecret string "" Existing secret with nextauth-secret and meili-master-key.
karakeep.existingSecretNextAuthKey string nextauth-secret Key for NEXTAUTH_SECRET.
karakeep.existingSecretMeiliMasterKey string meili-master-key Key for MEILI_MASTER_KEY.
karakeep.extraEnv array [] Extra environment variables for AI integration and advanced configuration.
nextAuthUrl must match your exact public URL

Karakeep uses Next.js authentication (NextAuth). The NEXTAUTH_URL must exactly match the URL your users use to access the app — including the scheme (https://) and without a trailing slash. A mismatch causes login redirects to fail or sessions to be rejected.

Enable AI tagging via extraEnv

Karakeep supports automatic AI-powered tagging using OpenAI or a local Ollama instance. Configure the integration by setting OPENAI_API_KEY (and optionally OPENAI_BASE_URL) or OLLAMA_BASE_URL and INFERENCE_TEXT_MODEL via karakeep.extraEnv. See the Karakeep AI documentation for the full list of supported variables.

Meilisearch Sidecar

Parameter Type Default Description
meilisearch.enabled boolean true Enable the Meilisearch sidecar for full-text search.
meilisearch.image.repository string docker.io/getmeili/meilisearch Meilisearch container image.
meilisearch.image.tag string "v1.41.0" Meilisearch image tag.
meilisearch.image.pullPolicy string IfNotPresent Meilisearch image pull policy.
meilisearch.resources object {} CPU and memory requests and limits for Meilisearch.

Chromium Sidecar

Parameter Type Default Description
chromium.enabled boolean true Enable the Chromium sidecar for screenshots and archiving.
chromium.port integer 9222 Internal Chromium sidecar HTTP port.
chromium.image.repository string ghcr.io/browserless/chromium Chromium container image.
chromium.image.tag string "v2.46.0" Chromium image tag.
chromium.image.pullPolicy string IfNotPresent Chromium image pull policy.
chromium.resources object {} CPU and memory requests and limits for Chromium.

Persistence

All containers in the pod share the same PVC. SQLite database, Meilisearch index, and uploaded files are all stored within this volume.

Parameter Type Default Description
persistence.enabled boolean true Enable a PVC for application data, search index, and uploads.
persistence.size string 10Gi PVC size.
persistence.storageClass string "" StorageClass for the PVC.
persistence.accessModes array ["ReadWriteOnce"] PVC access modes.
persistence.existingClaim string "" Use an existing PVC instead of creating one.

Service

Parameter Type Default Description
service.type string ClusterIP Kubernetes service type.
service.port integer 80 Service port exposed to the cluster.
service.annotations object {} Annotations for the Service.
service.ipFamilyPolicy string null Service IP family policy.
service.ipFamilies array [] Ordered Service IP families.

Ingress

Parameter Type Default Description
ingress.enabled boolean false Enable an Ingress resource.
ingress.ingressClassName string traefik Ingress class name.
ingress.annotations object {} Annotations for the Ingress (e.g. cert-manager).
ingress.hosts array [] Ingress host and path rules.
ingress.tls array [] TLS configuration (secret name and hosts).

Gateway API

Use gatewayAPI.enabled to render a native Kubernetes Gateway API HTTPRoute for Karakeep. Ingress stays disabled by default and can coexist with the route during migrations.

gatewayAPI:
  enabled: true
  parentRefs:
    - name: shared-gateway
      namespace: gateway-system
      sectionName: https
  hostnames:
    - karakeep.example.com
  paths:
    - type: PathPrefix
      value: /
Parameter Type Default Description
gatewayAPI.enabled boolean false Render an HTTPRoute.
gatewayAPI.parentRefs array [] Parent Gateway references.
gatewayAPI.hostnames array [] HTTPRoute hostnames.
gatewayAPI.paths array [{ type: PathPrefix, value: "/" }] HTTPRoute path matches.
gatewayAPI.annotations object {} HTTPRoute annotations.

Dual-Stack Networking

Karakeep’s Service supports Kubernetes dual-stack networking through optional service.ipFamilyPolicy and service.ipFamilies values. Defaults omit both fields so existing installs inherit cluster defaults.

service:
  ipFamilyPolicy: PreferDualStack

Probes

Parameter Type Default Description
probes.startup.enabled boolean true Enable startup probe.
probes.startup.initialDelaySeconds integer 5 Startup probe initial delay.
probes.startup.periodSeconds integer 5 Startup probe period.
probes.startup.timeoutSeconds integer 3 Startup probe timeout.
probes.startup.failureThreshold integer 30 Startup probe failure threshold.
probes.liveness.enabled boolean true Enable liveness probe.
probes.liveness.initialDelaySeconds integer 0 Liveness probe initial delay.
probes.liveness.periodSeconds integer 15 Liveness probe period.
probes.liveness.timeoutSeconds integer 5 Liveness probe timeout.
probes.liveness.failureThreshold integer 3 Liveness probe failure threshold.
probes.readiness.enabled boolean true Enable readiness probe.
probes.readiness.initialDelaySeconds integer 0 Readiness probe initial delay.
probes.readiness.periodSeconds integer 10 Readiness probe period.
probes.readiness.timeoutSeconds integer 5 Readiness probe timeout.
probes.readiness.failureThreshold integer 3 Readiness probe failure threshold.

Resources and Security

These values apply to the main Karakeep container. Set meilisearch.resources and chromium.resources separately for the sidecars.

Parameter Type Default Description
resources object {} CPU and memory requests and limits for Karakeep.
podSecurityContext object {} Pod-level security context.
securityContext object {} Container-level security context.

Service Account

Parameter Type Default Description
serviceAccount.create boolean false Create a dedicated ServiceAccount.
serviceAccount.name string "" Override the ServiceAccount name.
serviceAccount.annotations object {} Annotations for the ServiceAccount.

Scheduling

Parameter Type Default Description
nodeSelector object {} Node selector for scheduling.
tolerations array [] Tolerations for scheduling.
affinity object {} Affinity rules.
topologySpreadConstraints array [] Topology spread constraints.
priorityClassName string "" PriorityClass for the pod.
terminationGracePeriodSeconds integer 30 Termination grace period.
podLabels object {} Extra labels for the pod.
podAnnotations object {} Extra annotations for the pod.

Extra

Parameter Type Default Description
extraVolumes array [] Extra volumes to attach to the pod.
extraVolumeMounts array [] Extra volume mounts for the container.
extraManifests array [] Extra Kubernetes manifests deployed alongside the chart.

External Secrets

Karakeep can render an External Secrets Operator ExternalSecret that projects NEXTAUTH_SECRET and MEILI_MASTER_KEY into the Kubernetes Secret configured by karakeep.existingSecret.

karakeep:
  existingSecret: karakeep-app-secret

externalSecrets:
  enabled: true
  secretStoreRef:
    name: platform-secrets
    kind: ClusterSecretStore
  data:
    - secretKey: nextauth-secret
      remoteRef:
        key: karakeep/credentials
        property: nextauth-secret
    - secretKey: meili-master-key
      remoteRef:
        key: karakeep/credentials
        property: meili-master-key
Parameter Type Default Description
externalSecrets.enabled boolean false Render an ExternalSecret.
externalSecrets.secretStoreRef.name string "" SecretStore or ClusterSecretStore.
externalSecrets.secretStoreRef.kind string SecretStore Secret store kind.
externalSecrets.refreshInterval string "0" ExternalSecret refresh interval.
externalSecrets.data array [] Remote key mappings for Secret data.

Common Issues

Pod OOMKilled with both sidecars enabled

If the pod is killed shortly after startup with OOMKilled, the Chromium sidecar is most likely the cause. Set explicit chromium.resources.limits.memory (at least 1Gi) and meilisearch.resources.limits.memory (at least 512Mi). Check kubectl describe pod for which container was killed.

Bookmarks saved but no screenshots appearing

Screenshots require the Chromium sidecar to be running. Verify that chromium.enabled: true and check the Chromium container logs: kubectl logs <pod> -c chromium. On ARM64 nodes, ensure the Chromium image has an ARM64 variant available for your tag.

More Information