Docmost
Deploy Docmost on Kubernetes — an open-source collaborative wiki and documentation
platform. Supports bundled or external PostgreSQL and Redis, local PVC or S3 uploads storage, and scheduled
pg_dump backups.
If docmost.appUrl is empty, Docmost auto-detects the URL from the Ingress host. In production, always set it
explicitly (e.g. https://wiki.example.com). An incorrect appUrl causes password reset emails, invite links, and
OAuth redirects to reference the wrong address.
Upgrade to 0.96
Keep APP_SECRET stable: the new encryption service derives its AES-256-GCM
key from it. Back up PostgreSQL and uploaded files before upgrading. Connected
Helm upgrades preserve the generated Secret; explicitly manage
docmost.appSecret when rendering offline.
The release updates Node and collaboration services, adds page-version comparison
and attachments, fixes Redis ACL/URL/TLS handling, and includes security fixes.
Review the official notes.
The bundled dependency set now uses PostgreSQL 2.1.1 and Redis 3.1.0.
Key Features
- Collaborative wiki — real-time editing, spaces, pages, and permissions
- PostgreSQL + Redis — bundled subcharts or external connections
- Auto-bootstrap —
unaccentandpg_trgmextensions granted on first start - Storage modes — local PVC (single replica) or S3-compatible (scalable)
- pg_dump backup — scheduled CronJob to S3; database-only (uploads separate)
- JWT sessions — configurable
jwtTokenExpiresInwith auto-generated app secret - Explicit listener contract —
containerPorts.httpchanges the real Docmost process port - Least-privilege pod identity — Kubernetes API token mounting is disabled by default
Architecture and Runtime Port
The Kubernetes Service targets the named http container port.
containerPorts.http configures both that declared port and Docmost’s supported
PORT environment variable, so probes, runtime, and Service routing remain
aligned. service.port changes only the Kubernetes-facing port and does not
reconfigure the process listener.
PostgreSQL and Redis can be bundled or external. Uploads use a local PVC for a single replica or S3-compatible storage when replicas are scaled horizontally.
Installation
HTTPS repository:
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install docmost helmforge/docmost -f values.yaml
OCI registry:
helm install docmost oci://ghcr.io/helmforgedev/helm/docmost -f values.yaml
Deployment Examples
# values.yaml — Docmost with bundled PostgreSQL and Redis
docmost:
appUrl: 'https://wiki.example.com'
appSecret: 'generate-with-openssl-rand-hex-32'
postgresql:
enabled: true
auth:
database: docmost
username: docmost
password: 'strong-db-password'
standalone:
persistence:
enabled: true
size: 8Gi
redis:
enabled: true
standalone:
persistence:
enabled: true
size: 1Gi
storage:
mode: local
local:
enabled: true
size: 20Gi
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: wiki.example.com
paths:
- path: /
pathType: Prefix# values.yaml — Docmost with external PostgreSQL and Redis
# IMPORTANT: On the external PostgreSQL instance, run before installing:
# GRANT CREATE ON DATABASE docmost TO docmost;
# \connect docmost
# CREATE EXTENSION IF NOT EXISTS unaccent;
# CREATE EXTENSION IF NOT EXISTS pg_trgm;
docmost:
appUrl: 'https://wiki.example.com'
appSecret: 'generate-with-openssl-rand-hex-32'
postgresql:
enabled: false
database:
mode: external
external:
host: postgres.database.svc.cluster.local
port: 5432
name: docmost
username: docmost
existingSecret: docmost-db-credentials
existingSecretPasswordKey: database-password
redis:
enabled: false
external:
host: redis.cache.svc.cluster.local
port: 6379
existingSecret: docmost-redis-credentials
existingSecretPasswordKey: redis-password
storage:
mode: local
local:
enabled: true
size: 20Gi
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: wiki.example.com
paths:
- path: /
pathType: Prefix# values.yaml — Docmost with S3 uploads (enables horizontal scaling)
docmost:
appUrl: 'https://wiki.example.com'
appSecret: 'generate-with-openssl-rand-hex-32'
postgresql:
enabled: true
auth:
password: 'strong-db-password'
redis:
enabled: true
storage:
mode: s3 # no local PVC created; allows replicaCount > 1
s3:
region: us-east-1
bucket: docmost-uploads
endpoint: https://s3.amazonaws.com # or MinIO endpoint
forcePathStyle: true # required for MinIO and most S3-compatible providers
existingSecret: docmost-s3-credentials
existingSecretAccessKeyKey: access-key
existingSecretSecretKeyKey: secret-key
replicaCount: 2 # safe to scale with S3 storage# values.yaml — Full production Docmost with backup and TLS
docmost:
appUrl: 'https://wiki.example.com'
appSecret: 'generate-with-openssl-rand-hex-32'
jwtTokenExpiresIn: 30d
postgresql:
enabled: true
auth:
database: docmost
username: docmost
password: 'strong-db-password'
postgresPassword: 'strong-superuser-password'
standalone:
persistence:
enabled: true
size: 20Gi
redis:
enabled: true
auth:
enabled: true
password: 'strong-redis-password'
standalone:
persistence:
enabled: true
size: 1Gi
storage:
mode: local
local:
enabled: true
size: 50Gi
backup:
enabled: true
schedule: '0 3 * * *'
s3:
endpoint: https://s3.amazonaws.com
bucket: docmost-backups
existingSecret: docmost-backup-s3-credentials
resources:
requests:
memory: 256Mi
cpu: 200m
limits:
memory: 1Gi
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: wiki.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: docmost-tls
hosts:
- wiki.example.comConfiguration Reference
Core
| Parameter | Type | Default | Description |
|---|---|---|---|
replicaCount |
integer | 1 |
Pod replicas. Safe to increase only with storage.mode: s3. |
nameOverride |
string | "" |
Override the chart name. |
fullnameOverride |
string | "" |
Override the full release name. |
commonLabels |
object | {} |
Extra labels added to all resources. |
containerPorts.http |
integer | 3000 |
Docmost process listener and declared container port. |
Image
| Parameter | Type | Default | Description |
|---|---|---|---|
image.repository |
string | docker.io/docmost/docmost |
Docmost image. |
image.tag |
string | "0.96.0" |
Image tag. |
image.pullPolicy |
string | IfNotPresent |
Image pull policy. |
Docmost Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
docmost.appUrl |
string | "" |
Full public URL. Auto-detected from first Ingress host if empty. Set explicitly in production. |
docmost.appSecret |
string | "" |
Application secret key. Auto-generated if empty. Store in a stable secret for production. |
docmost.jwtTokenExpiresIn |
string | 30d |
JWT token expiration for user sessions. |
docmost.extraEnv |
array | [] |
Extra environment variables for the container. |
Database
Auto-detection precedence (database.mode: auto):
database.external.hostordatabase.external.existingSecret→ external PostgreSQLpostgresql.enabled: true→ bundled PostgreSQL subchart
| Parameter | Type | Default | Description |
|---|---|---|---|
database.mode |
string | auto |
Database mode: auto, external, or postgresql. |
database.external.host |
string | "" |
External PostgreSQL hostname. |
database.external.port |
integer | 5432 |
External PostgreSQL port. |
database.external.name |
string | docmost |
Database name. |
database.external.username |
string | docmost |
Database username. |
database.external.existingSecret |
string | "" |
Existing secret with the database password. |
database.external.existingSecretPasswordKey |
string | database-password |
Key for the password in the existing secret. |
When using an external PostgreSQL, the bundled bootstrap scripts do not run. Before installing Docmost, manually execute on the target database:
GRANT CREATE ON DATABASE docmost TO docmost;
\connect docmost
CREATE EXTENSION IF NOT EXISTS unaccent;
CREATE EXTENSION IF NOT EXISTS pg_trgm;PostgreSQL Subchart
| Parameter | Type | Default | Description |
|---|---|---|---|
postgresql.enabled |
boolean | true |
Deploy the bundled PostgreSQL subchart. |
postgresql.auth.database |
string | docmost |
Database name. |
postgresql.auth.username |
string | docmost |
Database username. |
postgresql.auth.password |
string | "" |
Database password. Auto-generated if empty. |
postgresql.auth.postgresPassword |
string | "" |
Superuser password. Auto-generated if empty. |
postgresql.standalone.persistence.size |
string | 8Gi |
PVC size for PostgreSQL. |
Redis Subchart / External
| Parameter | Type | Default | Description |
|---|---|---|---|
redis.enabled |
boolean | true |
Deploy the bundled Redis subchart. |
redis.auth.enabled |
boolean | true |
Enable Redis password authentication. |
redis.auth.password |
string | "" |
Redis password. Auto-generated if empty. |
redis.standalone.persistence.size |
string | 1Gi |
PVC size for Redis. |
redis.external.host |
string | "" |
External Redis hostname. |
redis.external.existingSecret |
string | "" |
Existing secret with external Redis password. |
Storage
With storage.mode: local, the uploads PVC uses ReadWriteOnce. Only one pod can mount it at a
time. The chart rejects replicaCount > 1 unless storage.mode: s3 is configured for horizontal scaling.
| Parameter | Type | Default | Description |
|---|---|---|---|
storage.mode |
string | local |
Storage mode: local (PVC) or s3. |
storage.local.enabled |
boolean | true |
Create a local PVC for uploads. |
storage.local.size |
string | 10Gi |
Uploads PVC size. |
storage.local.storageClass |
string | "" |
StorageClass for the uploads PVC. |
storage.local.existingClaim |
string | "" |
Use an existing PVC for uploads. |
storage.s3.region |
string | us-east-1 |
S3 region. |
storage.s3.bucket |
string | "" |
S3 bucket name. |
storage.s3.endpoint |
string | "" |
S3-compatible endpoint URL. |
storage.s3.forcePathStyle |
boolean | true |
Force path-style requests. Required for MinIO. |
storage.s3.existingSecret |
string | "" |
Existing secret with S3 credentials. |
storage.s3.existingSecretAccessKeyKey |
string | access-key |
Key for the S3 access key. |
storage.s3.existingSecretSecretKeyKey |
string | secret-key |
Key for the S3 secret key. |
Backup
The backup CronJob runs pg_dump and uploads the result to S3. Upload files are not included.
| Parameter | Type | Default | Description |
|---|---|---|---|
backup.enabled |
boolean | false |
Enable scheduled pg_dump S3 backup. |
backup.schedule |
string | "0 3 * * *" |
Cron schedule. |
backup.archivePrefix |
string | docmost |
Prefix for backup archive filenames. |
backup.images.postgresql |
string | postgres:18-alpine |
Image providing pg_dump. |
backup.s3.endpoint |
string | "" |
S3-compatible endpoint URL. |
backup.s3.bucket |
string | "" |
Target bucket name. |
backup.s3.existingSecret |
string | "" |
Existing secret with S3 credentials. |
Service and Ingress
| Parameter | Type | Default | Description |
|---|---|---|---|
service.type |
string | ClusterIP |
Service type. |
service.port |
integer | 80 |
Service port. |
ingress.enabled |
boolean | false |
Enable an Ingress resource. |
ingress.ingressClassName |
string | "" |
Ingress class name. |
ingress.annotations |
object | {} |
Ingress annotations (e.g. cert-manager). |
ingress.hosts |
array | [] |
Host and path rules. |
ingress.tls |
array | [] |
TLS configuration. |
Probes
All probes use /api/health as the HTTP path.
| Parameter | Type | Default | Description |
|---|---|---|---|
startupProbe.enabled |
boolean | true |
Enable startup probe. |
startupProbe.failureThreshold |
integer | 30 |
Startup probe failure threshold. |
livenessProbe.enabled |
boolean | true |
Enable liveness probe. |
readinessProbe.enabled |
boolean | true |
Enable readiness probe. |
Resources and Scheduling
| Parameter | Type | Default | Description |
|---|---|---|---|
resources |
object | {} |
CPU and memory requests/limits. |
terminationGracePeriodSeconds |
integer | 30 |
Termination grace period. |
nodeSelector |
object | {} |
Node selector for scheduling. |
tolerations |
array | [] |
Tolerations for scheduling. |
extraVolumes |
array | [] |
Extra volumes. |
extraVolumeMounts |
array | [] |
Extra volume mounts. |
extraManifests |
array | [] |
Extra Kubernetes manifests. |
serviceAccount.automountServiceAccountToken |
boolean | false |
Mount the Kubernetes API token into Docmost pods. |
Security and Production Boundaries
The default workload drops all Linux capabilities, denies privilege
escalation, uses RuntimeDefault seccomp, and does not mount the Kubernetes API
token. Enable serviceAccount.automountServiceAccountToken only for a concrete
integration that needs Kubernetes API credentials. The upstream image needs a
writable filesystem, so the chart does not claim immutable-root support.
The chart does not provision DNS, TLS issuers, routing controllers, Storage
Classes, external databases, Redis, S3, or External Secrets providers. For
production, preserve APP_SECRET, back up PostgreSQL and uploads separately,
and use storage.mode=s3 before increasing replicaCount.
Troubleshooting
- When probes fail after a port override, verify that
containerPorts.httprenders as both the container port and thePORTenvironment variable. - When encrypted data fails after restore, restore the original
APP_SECRETthroughdocmost.existingSecret. - When files differ between replicas, switch to S3 storage; a local PVC is a single-replica contract.
- For startup failures, inspect Docmost, PostgreSQL, and Redis logs together; the init containers only prove TCP reachability.
- For S3 errors, verify endpoint reachability, bucket policy, path-style mode, and both credential keys in the referenced Secret.