Files

Joplin Server Helm Chart

A Helm chart for deploying Joplin Server on Kubernetes.

Introduction

This chart deploys Joplin Server, the synchronization server for the Joplin note-taking application, on a Kubernetes cluster. Joplin Server allows syncing notes across devices and supports filesystem or S3 storage, email notifications, and an optional AI transcription service.

Source code: https://github.com/rtomik/helm-charts/tree/main/charts/joplin-server

Prerequisites

  • Kubernetes 1.19+
  • Helm 3.0+
  • External PostgreSQL database (required — Joplin Server does not support SQLite)
  • PV provisioner support (if using filesystem storage)

Installing the Chart

helm repo add rtomik https://rtomik.github.io/helm-charts
helm install joplin-server rtomik/joplin-server

Important

: Configure PostgreSQL database settings before installation.

Uninstalling the Chart

helm uninstall joplin-server

Configuration Examples

Minimal Installation

Important

: Health check probes require a Host header matching your ingress domain. Update probes.*.httpHeaders accordingly.

postgresql:
  external:
    enabled: true
    host: "postgresql.example.com"
    port: 5432
    database: "joplin"
    user: "joplin"
    password: "secure-password"

env:
  APP_BASE_URL: "https://joplin.example.com"

probes:
  liveness:
    httpHeaders:
      - name: Host
        value: joplin.example.com
  readiness:
    httpHeaders:
      - name: Host
        value: joplin.example.com

joplin:
  admin:
    email: "admin@example.com"
    password: "admin-password"
  server:
    enableUserRegistration: true

ingress:
  enabled: true
  hosts:
    - host: joplin.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - hosts:
        - joplin.example.com
      secretName: joplin-tls

Production with Existing Secrets

postgresql:
  external:
    enabled: true
    host: "postgres-cluster-pooler.dbs.svc.cluster.local"
    port: 5432
    database: "joplin-server"
    existingSecret: "joplin-db-credentials"
    userKey: "username"
    passwordKey: "password"

joplin:
  admin:
    existingSecret: "joplin-admin-secret"
    emailKey: "email"
    passwordKey: "password"

S3 Storage

joplin:
  storage:
    driver: "s3"
    s3:
      bucket: "joplin-notes"
      region: "us-east-1"
      existingSecret: "joplin-s3-secret"
      accessKeyIdKey: "access-key-id"
      secretAccessKeyKey: "secret-access-key"

# No persistence needed when using S3
persistence:
  enabled: false

Email Notifications

joplin:
  email:
    enabled: true
    host: "smtp.example.com"
    port: 587
    fromEmail: "joplin@example.com"
    fromName: "Joplin Server"
    secure: true
    existingSecret: "joplin-email-secret"
    usernameKey: "username"
    passwordKey: "password"

Transcribe Service (AI Transcription)

transcribe:
  enabled: true
  api:
    existingSecret: "joplin-transcribe-secret"
    keyName: "api-key"
  database:
    host: "postgresql.example.com"
    port: 5432
    database: "transcribe"
    user: "transcribe"
    existingSecret: "transcribe-db-secret"
    userKey: "username"
    passwordKey: "password"
  persistence:
    enabled: true
    size: 5Gi

Parameters

Global Parameters

Name Description Default
nameOverride Override the release name ""
fullnameOverride Fully override the release name ""

Image Parameters

Name Description Default
image.repository Joplin Server image repository joplin/server
image.tag Image tag 3.4.2
image.pullPolicy Image pull policy IfNotPresent

Deployment Parameters

Name Description Default
replicaCount Number of replicas 1
revisionHistoryLimit Revisions to retain 3
podSecurityContext.runAsNonRoot Run as non-root true
podSecurityContext.runAsUser User ID 1001
podSecurityContext.fsGroup Filesystem group ID 1001
nodeSelector Node selector {}
tolerations Tolerations []
affinity Affinity rules {}

Service Parameters

Name Description Default
service.type Service type ClusterIP
service.port Service port 22300

Ingress Parameters

Name Description Default
ingress.enabled Enable ingress false
ingress.className Ingress class name ""
ingress.annotations Ingress annotations See values.yaml
ingress.hosts Ingress hosts See values.yaml
ingress.tls TLS configuration See values.yaml

PostgreSQL Configuration (Required)

Name Description Default
postgresql.external.enabled Use external PostgreSQL true
postgresql.external.host PostgreSQL host ""
postgresql.external.port PostgreSQL port 5432
postgresql.external.database Database name joplin
postgresql.external.user Username joplin
postgresql.external.password Password ""
postgresql.external.existingSecret Existing secret name ""
postgresql.external.userKey Key for username in secret username
postgresql.external.passwordKey Key for password in secret password
postgresql.external.hostKey Key for host in secret (optional) ""
postgresql.external.portKey Key for port in secret (optional) ""
postgresql.external.databaseKey Key for database in secret (optional) ""

Admin Settings

Name Description Default
joplin.admin.email Admin user email ""
joplin.admin.password Admin user password ""
joplin.admin.existingSecret Existing secret for admin credentials ""
joplin.admin.emailKey Key for email in secret admin-email
joplin.admin.passwordKey Key for password in secret admin-password

Server Settings

Name Description Default
joplin.server.maxRequestBodySize Max request body size 200mb
joplin.server.sessionTimeout Session timeout (seconds) 86400
joplin.server.enableUserRegistration Enable user registration false
joplin.server.enableSharing Enable sharing true
joplin.server.enablePublicNotes Enable public notes true

Storage Settings

Name Description Default
joplin.storage.driver Storage driver (filesystem, s3, azure) filesystem
joplin.storage.filesystemPath Filesystem storage path /var/lib/joplin
joplin.storage.s3.bucket S3 bucket name ""
joplin.storage.s3.region S3 region ""
joplin.storage.s3.endpoint S3 endpoint (for S3-compatible services) ""
joplin.storage.s3.accessKeyId S3 access key ID ""
joplin.storage.s3.secretAccessKey S3 secret access key ""
joplin.storage.s3.existingSecret Existing secret for S3 credentials ""
joplin.storage.s3.accessKeyIdKey Key for access key in secret access-key-id
joplin.storage.s3.secretAccessKeyKey Key for secret access key in secret secret-access-key

Email Settings

Name Description Default
joplin.email.enabled Enable email false
joplin.email.host SMTP host ""
joplin.email.port SMTP port 587
joplin.email.username SMTP username ""
joplin.email.password SMTP password ""
joplin.email.fromEmail From email address ""
joplin.email.fromName From name Joplin Server
joplin.email.secure Use TLS/SSL true
joplin.email.existingSecret Existing secret for credentials ""
joplin.email.usernameKey Key for username in secret email-username
joplin.email.passwordKey Key for password in secret email-password

Logging Settings

Name Description Default
joplin.logging.level Log level (error, warn, info, debug) info
joplin.logging.target Log target (console, file) console

Persistence Parameters

Name Description Default
persistence.enabled Enable persistence true
persistence.storageClass Storage class ""
persistence.accessMode Access mode ReadWriteOnce
persistence.size PVC size 10Gi
persistence.annotations PVC annotations {}

Transcribe Service

Name Description Default
transcribe.enabled Enable transcribe service false
transcribe.image.repository Transcribe image repository joplin/transcribe
transcribe.image.tag Transcribe image tag latest
transcribe.api.key Shared API key ""
transcribe.api.existingSecret Existing secret for API key ""
transcribe.api.keyName Key name in secret transcribe-api-key
transcribe.service.type Transcribe service type ClusterIP
transcribe.service.port Transcribe service port 4567
transcribe.database.host Transcribe DB host ""
transcribe.database.port Transcribe DB port 5432
transcribe.database.database Transcribe DB name transcribe
transcribe.database.user Transcribe DB user transcribe
transcribe.database.password Transcribe DB password ""
transcribe.database.existingSecret Existing secret for transcribe DB ""
transcribe.database.userKey Key for username in secret username
transcribe.database.passwordKey Key for password in secret password

Security Settings

Name Description Default
security.httpsRedirect Enable HTTPS redirect false
security.tls.enabled Enable custom TLS certificate false
security.tls.existingSecret Secret with TLS certificate ""
security.tls.certificateKey Key for TLS certificate in secret tls.crt
security.tls.privateKeyKey Key for TLS private key in secret tls.key

Resource Parameters

Name Description Default
resources Resource limits and requests {}

Health Check Parameters

Name Description Default
probes.liveness.enabled Enable liveness probe true
probes.liveness.path Liveness probe path /api/ping
probes.liveness.initialDelaySeconds Liveness initial delay 60
probes.liveness.periodSeconds Liveness period 30
probes.liveness.httpHeaders Liveness HTTP headers Host matching ingress
probes.readiness.enabled Enable readiness probe true
probes.readiness.path Readiness probe path /api/ping
probes.readiness.initialDelaySeconds Readiness initial delay 30
probes.readiness.periodSeconds Readiness period 10
probes.readiness.httpHeaders Readiness HTTP headers Host matching ingress

Autoscaling Parameters

Name Description Default
autoscaling.enabled Enable HPA false
autoscaling.minReplicas Min replicas 1
autoscaling.maxReplicas Max replicas 3
autoscaling.targetCPUUtilizationPercentage Target CPU 80
autoscaling.targetMemoryUtilizationPercentage Target memory 80

Troubleshooting

Health Check Failures / "No Available Server"

Health checks require the correct Host header matching your ingress domain:

probes:
  liveness:
    httpHeaders:
      - name: Host
        value: your-joplin-domain.com
  readiness:
    httpHeaders:
      - name: Host
        value: your-joplin-domain.com

Database Connection Issues

Verify PostgreSQL credentials, network connectivity, and that env.APP_BASE_URL matches your ingress host.

Origin Validation Errors

Ensure env.APP_BASE_URL matches your ingress hostname exactly.

Debugging

kubectl logs -f deployment/joplin-server
kubectl describe pod -l app.kubernetes.io/name=joplin-server