version bump norish

This commit is contained in:
Richard Tomik
2026-04-13 16:15:48 +02:00
parent 839d5ce530
commit 256f7e6807
11 changed files with 2058 additions and 2421 deletions

View File

@ -1,266 +1,40 @@
# Joplin Server Helm Chart
A Helm chart for deploying Joplin Server on Kubernetes - Note-taking and synchronization server.
A Helm chart for deploying [Joplin Server](https://github.com/laurent22/joplin) on Kubernetes.
## Introduction
This chart deploys [Joplin Server](https://github.com/laurent22/joplin) on a Kubernetes cluster using the Helm package manager. Joplin Server is the synchronization server for Joplin, allowing you to sync your notes across devices.
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 can be found here:
- https://github.com/rtomik/helm-charts/tree/main/charts/joplin-server
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 in production)
- PV provisioner support in the underlying infrastructure (if persistence is needed for file storage)
- **External PostgreSQL database** (required Joplin Server does not support SQLite)
- PV provisioner support (if using filesystem storage)
## Installing the Chart
To install the chart with the release name `joplin-server`:
```bash
$ helm repo add joplin-chart https://rtomik.github.io/helm-charts
$ helm install joplin-server joplin-chart/joplin-server
helm repo add rtomik https://rtomik.github.io/helm-charts
helm install joplin-server rtomik/joplin-server
```
> **Important**: You must configure PostgreSQL database settings before installation.
> **Important**: Configure PostgreSQL database settings before installation.
## Uninstalling the Chart
To uninstall/delete the `joplin-server` deployment:
```bash
$ helm uninstall joplin-server
helm uninstall joplin-server
```
## Parameters
### Global parameters
| Name | Description | Value |
|------------------------|------------------------------------------------|-------|
| `nameOverride` | String to partially override the release name | `""` |
| `fullnameOverride` | String to fully override the release name | `""` |
### Image parameters
| Name | Description | Value |
|-------------------------|-----------------------------------|--------------------|
| `image.repository` | Joplin Server image repository | `joplin/server` |
| `image.tag` | Joplin Server image tag | `latest` |
| `image.pullPolicy` | Joplin Server image pull policy | `IfNotPresent` |
### Deployment parameters
| Name | Description | Value |
|--------------------------------------|-----------------------------------------------|-----------|
| `replicaCount` | Number of Joplin Server replicas | `1` |
| `revisionHistoryLimit` | Number of revisions to retain for rollback | `3` |
| `podSecurityContext.runAsNonRoot` | Run containers as non-root user | `true` |
| `podSecurityContext.runAsUser` | User ID for the container | `1001` |
| `podSecurityContext.fsGroup` | Group ID for the container filesystem | `1001` |
| `containerSecurityContext` | Security context for the container | See values.yaml |
| `nodeSelector` | Node labels for pod assignment | `{}` |
| `tolerations` | Tolerations for pod assignment | `[]` |
| `affinity` | Affinity for pod assignment | `{}` |
### Service parameters
| Name | Description | Value |
|----------------|-----------------------|-------------|
| `service.type` | Kubernetes Service type | `ClusterIP` |
| `service.port` | Service HTTP port | `22300` |
### Ingress parameters
| Name | Description | Value |
|-------------------------|-------------------------------------------|-----------------|
| `ingress.enabled` | Enable ingress record generation | `false` |
| `ingress.className` | IngressClass name | `""` |
| `ingress.annotations` | Additional annotations for the Ingress | See values.yaml |
| `ingress.hosts` | Array of host and path objects | See values.yaml |
| `ingress.tls` | TLS configuration | See values.yaml |
### Environment variables
| Name | Description | Value |
|---------------------------|-----------------------------------------------|--------------------------|
| `env.APP_PORT` | Application port | `22300` |
| `env.APP_BASE_URL` | Base URL for the application | `http://localhost:22300` |
| `env.DB_CLIENT` | Database client (always pg for PostgreSQL) | `pg` |
### PostgreSQL configuration (Required)
| Name | Description | Value |
|----------------------------------------|-----------------------------------------------|-----------|
| `postgresql.external.enabled` | Use external PostgreSQL database (required) | `true` |
| `postgresql.external.host` | PostgreSQL host | `""` |
| `postgresql.external.port` | PostgreSQL port | `5432` |
| `postgresql.external.database` | PostgreSQL database name | `joplin` |
| `postgresql.external.user` | PostgreSQL username | `joplin` |
| `postgresql.external.password` | PostgreSQL password | `""` |
| `postgresql.external.existingSecret` | Name of existing secret with PostgreSQL credentials | `""` |
| `postgresql.external.userKey` | Key in the secret for username | `username` |
| `postgresql.external.passwordKey` | Key in the secret for password | `password` |
| `postgresql.external.hostKey` | Key in the secret for host (optional) | `""` |
| `postgresql.external.portKey` | Key in the secret for port (optional) | `""` |
| `postgresql.external.databaseKey` | Key in the secret for database name (optional) | `""` |
### Joplin Server Configuration
#### Admin Settings
| Name | Description | Value |
|----------------------------------------|-----------------------------------------------|-----------|
| `joplin.admin.email` | First admin user email | `""` |
| `joplin.admin.password` | First admin user password | `""` |
| `joplin.admin.existingSecret` | Name of existing secret with admin credentials | `""` |
| `joplin.admin.emailKey` | Key in the secret for admin email | `admin-email` |
| `joplin.admin.passwordKey` | Key in the secret for admin password | `admin-password` |
#### Server Settings
| Name | Description | Value |
|-------------------------------------------|-----------------------------------------------|-----------|
| `joplin.server.maxRequestBodySize` | Maximum request body size | `200mb` |
| `joplin.server.sessionTimeout` | Session timeout in seconds | `86400` |
| `joplin.server.enableUserRegistration` | Enable/disable user registration | `false` |
| `joplin.server.enableSharing` | Enable/disable sharing | `true` |
| `joplin.server.enablePublicNotes` | Enable/disable public notes | `true` |
#### Storage Settings
| Name | Description | Value |
|-------------------------------------------|-----------------------------------------------|--------------|
| `joplin.storage.driver` | Storage driver (filesystem, s3, azure) | `filesystem` |
| `joplin.storage.filesystemPath` | Path for filesystem storage | `/var/lib/joplin` |
##### S3 Storage (Optional)
| Name | Description | Value |
|---------------------------------------------|---------------------------------------------|-----------|
| `joplin.storage.s3.bucket` | S3 bucket name | `""` |
| `joplin.storage.s3.region` | S3 region | `""` |
| `joplin.storage.s3.accessKeyId` | S3 access key ID | `""` |
| `joplin.storage.s3.secretAccessKey` | S3 secret access key | `""` |
| `joplin.storage.s3.endpoint` | S3 endpoint (for S3-compatible services) | `""` |
| `joplin.storage.s3.existingSecret` | Name of existing secret with S3 credentials | `""` |
| `joplin.storage.s3.accessKeyIdKey` | Key in the secret for access key ID | `access-key-id` |
| `joplin.storage.s3.secretAccessKeyKey` | Key in the secret for secret access key | `secret-access-key` |
#### Email Settings (Optional)
| Name | Description | Value |
|----------------------------------------|-----------------------------------------------|-----------|
| `joplin.email.enabled` | Enable email notifications | `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` | Name of existing secret with email credentials | `""` |
| `joplin.email.usernameKey` | Key in the secret for SMTP username | `email-username` |
| `joplin.email.passwordKey` | Key in the secret for SMTP password | `email-password` |
#### Logging Settings
| Name | Description | Value |
|--------------------------------|--------------------------------------|-----------|
| `joplin.logging.level` | Log level (error, warn, info, debug) | `info` |
| `joplin.logging.target` | Log target (console, file) | `console` |
### Persistence settings (for filesystem storage)
| Name | Description | Value |
|-------------------------------|----------------------------------|-----------------|
| `persistence.enabled` | Enable persistence using PVC | `true` |
| `persistence.storageClass` | PVC Storage Class | `""` |
| `persistence.accessMode` | PVC Access Mode | `ReadWriteOnce` |
| `persistence.size` | PVC Size | `10Gi` |
| `persistence.annotations` | Annotations for PVC | `{}` |
### Transcribe Service (Optional AI Transcription)
| Name | Description | Value |
|-------------------------------------------|-----------------------------------------------|--------------|
| `transcribe.enabled` | Enable transcribe service | `false` |
| `transcribe.image.repository` | Transcribe image repository | `joplin/transcribe` |
| `transcribe.image.tag` | Transcribe image tag | `latest` |
| `transcribe.image.pullPolicy` | Transcribe image pull policy | `IfNotPresent` |
| `transcribe.api.key` | Shared secret between Joplin and Transcribe | `""` |
| `transcribe.api.existingSecret` | Name of existing secret with transcribe API key | `""` |
| `transcribe.api.keyName` | Key in the secret for transcribe API key | `transcribe-api-key` |
| `transcribe.service.type` | Transcribe service type | `ClusterIP` |
| `transcribe.service.port` | Transcribe service port | `4567` |
| `transcribe.htr.imagesFolder` | HTR images folder path | `/app/images` |
#### Transcribe Database (Separate from main database)
| Name | Description | Value |
|---------------------------------------------|---------------------------------------------|-------------|
| `transcribe.database.host` | Transcribe database host | `""` |
| `transcribe.database.port` | Transcribe database port | `5432` |
| `transcribe.database.database` | Transcribe database name | `transcribe` |
| `transcribe.database.user` | Transcribe database username | `transcribe` |
| `transcribe.database.password` | Transcribe database password | `""` |
| `transcribe.database.existingSecret` | Name of existing secret with transcribe DB credentials | `""` |
| `transcribe.database.userKey` | Key in the secret for username | `username` |
| `transcribe.database.passwordKey` | Key in the secret for password | `password` |
### Resource Configuration
| Name | Description | Value |
|-------------|--------------------------------------|-------|
| `resources` | Resource limits and requests | `{}` |
### Health Checks
| Name | Description | Value |
|-------------------------------------------|------------------------------------------|-------|
| `probes.liveness.enabled` | Enable liveness probe | `true` |
| `probes.liveness.initialDelaySeconds` | Initial delay for liveness probe | `60` |
| `probes.liveness.periodSeconds` | Period for liveness probe | `30` |
| `probes.liveness.timeoutSeconds` | Timeout for liveness probe | `10` |
| `probes.liveness.failureThreshold` | Failure threshold for liveness probe | `3` |
| `probes.liveness.successThreshold` | Success threshold for liveness probe | `1` |
| `probes.liveness.path` | Path for liveness probe | `/api/ping` |
| `probes.liveness.httpHeaders` | HTTP headers for liveness probe | `[{"name": "Host", "value": "joplin.domain.com"}]` |
| `probes.readiness.enabled` | Enable readiness probe | `true` |
| `probes.readiness.initialDelaySeconds` | Initial delay for readiness probe | `30` |
| `probes.readiness.periodSeconds` | Period for readiness probe | `10` |
| `probes.readiness.timeoutSeconds` | Timeout for readiness probe | `5` |
| `probes.readiness.failureThreshold` | Failure threshold for readiness probe | `3` |
| `probes.readiness.successThreshold` | Success threshold for readiness probe | `1` |
| `probes.readiness.path` | Path for readiness probe | `/api/ping` |
| `probes.readiness.httpHeaders` | HTTP headers for readiness probe | `[{"name": "Host", "value": "joplin.domain.com"}]` |
### Autoscaling
| Name | Description | Value |
|---------------------------------------------|------------------------------------------|---------|
| `autoscaling.enabled` | Enable horizontal pod autoscaling | `false` |
| `autoscaling.minReplicas` | Minimum number of replicas | `1` |
| `autoscaling.maxReplicas` | Maximum number of replicas | `3` |
| `autoscaling.targetCPUUtilizationPercentage`| Target CPU utilization percentage | `80` |
| `autoscaling.targetMemoryUtilizationPercentage`| Target memory utilization percentage | `80` |
### Security Settings
| Name | Description | Value |
|-----------------------------------|--------------------------------------|---------|
| `security.httpsRedirect` | Enable/disable HTTPS redirect | `false` |
| `security.tls.enabled` | Enable custom TLS certificate | `false` |
| `security.tls.existingSecret` | Name of existing secret with TLS cert| `""` |
| `security.tls.certificateKey` | Key in the secret for TLS certificate| `tls.crt` |
| `security.tls.privateKeyKey` | Key in the secret for TLS private key| `tls.key` |
## Configuration Examples
### Basic Installation with PostgreSQL
### Minimal Installation
> **Important**: Health check probes require a `Host` header matching your ingress domain. Update `probes.*.httpHeaders` accordingly.
```yaml
postgresql:
@ -272,22 +46,9 @@ postgresql:
user: "joplin"
password: "secure-password"
ingress:
enabled: true
hosts:
- host: joplin.example.com
paths:
- path: /
pathType: Prefix
tls:
- hosts:
- joplin.example.com
secretName: joplin-tls
env:
APP_BASE_URL: "https://joplin.example.com"
# IMPORTANT: Update health check host headers to match your domain
probes:
liveness:
httpHeaders:
@ -304,30 +65,22 @@ joplin:
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
```
### Using Kubernetes Secrets
### Production with Existing Secrets
#### Full Secret Configuration
```yaml
postgresql:
external:
enabled: true
existingSecret: "joplin-postgresql-secret"
hostKey: "host"
portKey: "port"
databaseKey: "database"
userKey: "username"
passwordKey: "password"
joplin:
admin:
existingSecret: "joplin-admin-secret"
emailKey: "email"
passwordKey: "password"
```
#### Mixed Configuration (Host in values, credentials in secret)
```yaml
postgresql:
external:
@ -338,10 +91,15 @@ postgresql:
existingSecret: "joplin-db-credentials"
userKey: "username"
passwordKey: "password"
# hostKey, portKey, databaseKey left empty - using values above
joplin:
admin:
existingSecret: "joplin-admin-secret"
emailKey: "email"
passwordKey: "password"
```
### S3 Storage Configuration
### S3 Storage
```yaml
joplin:
@ -359,7 +117,7 @@ persistence:
enabled: false
```
### Email Notifications Setup
### Email Notifications
```yaml
joplin:
@ -375,7 +133,7 @@ joplin:
passwordKey: "password"
```
### Transcribe Service (AI Features)
### Transcribe Service (AI Transcription)
```yaml
transcribe:
@ -396,65 +154,234 @@ transcribe:
size: 5Gi
```
## First-time Setup
## Parameters
1. **Configure PostgreSQL**: Ensure your PostgreSQL database is accessible and credentials are configured
2. **Admin User**: Set admin email/password or access the web interface to create the first admin user
3. **User Registration**: Configure whether users can self-register or admin approval is required
4. **Storage**: Choose between filesystem (requires persistence) or cloud storage (S3/Azure)
### Global Parameters
## Security Considerations
| Name | Description | Default |
|------|-------------|---------|
| `nameOverride` | Override the release name | `""` |
| `fullnameOverride` | Fully override the release name | `""` |
For production deployments:
### Image Parameters
1. Use external secrets for all sensitive information (database passwords, admin credentials, etc.)
2. Enable TLS/SSL for all communications
3. Configure proper RBAC and network policies
4. Use dedicated databases with proper access controls
5. Disable user registration if not needed
6. Use cloud storage for better scalability and backup
| 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
Common issues and solutions:
### Health Check Failures / "No Available Server"
1. **Health Check Issues / "No Available Server"**:
- Ensure `probes.*.httpHeaders` includes the correct Host header matching your domain
- Health checks use `/api/ping` endpoint which requires proper host validation
- Example fix:
```yaml
probes:
liveness:
httpHeaders:
- name: Host
value: your-joplin-domain.com
readiness:
httpHeaders:
- name: Host
value: your-joplin-domain.com
```
Health checks require the correct `Host` header matching your ingress domain:
2. **Database connection issues**: Verify PostgreSQL credentials and network connectivity
3. **Storage permissions**: Check filesystem permissions for persistent volumes
4. **First admin user**: If no admin configured, access the web interface to create one
5. **Transcribe issues**: Verify Docker socket access and separate database configuration
6. **Origin validation errors**: Make sure `env.APP_BASE_URL` matches your ingress host
```yaml
probes:
liveness:
httpHeaders:
- name: Host
value: your-joplin-domain.com
readiness:
httpHeaders:
- name: Host
value: your-joplin-domain.com
```
For detailed troubleshooting, check the application logs:
### 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
```bash
kubectl logs -f deployment/joplin-server
```
Check pod status and events:
```bash
kubectl describe pod -l app.kubernetes.io/name=joplin-server
```
## Backing Up
## Links
- **Database**: Use PostgreSQL backup tools (pg_dump, etc.)
- **File Storage**:
- Filesystem: Backup the PVC data
- S3: Files are already stored in S3 (ensure proper S3 backup policies)
- **Configuration**: Backup your Kubernetes secrets and config
- [Joplin GitHub](https://github.com/laurent22/joplin)
- [Chart Source](https://github.com/rtomik/helm-charts/tree/main/charts/joplin-server)