Dolibarr
Open-source ERP and CRM platform for small and medium businesses. Dolibarr covers invoicing, order management, stock, CRM contacts, project tracking, HR, and 500+ optional modules — all in a single PHP application backed by MySQL.
The built-in S3 backup CronJob runs mysqldump against the MySQL database. The two persistent volumes
(persistence.documents and persistence.custom) — which contain uploaded files, generated documents (invoices,
proposals, delivery notes), and custom PHP modules — are not included in this backup. Implement a separate backup
strategy (e.g. Velero PVC snapshots) for both volumes.
Key Features
- Unattended installation —
DOLI_*environment variables configure the full setup on first boot - Module selection — enable specific Dolibarr modules at install time via
enableModules - Dual PVC storage — separate volumes for generated documents and custom PHP modules
- MySQL backend — bundled HelmForge MySQL subchart or external MySQL/MariaDB
- PHP tuning — configurable
memory_limit,upload_max_filesize,post_max_size, andmax_execution_time - Secret preservation — admin and runtime secrets survive upgrades via
existingSecret - S3 backup — scheduled
mysqldumpCronJob to S3-compatible storage
Installation
HTTPS repository:
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install dolibarr helmforge/dolibarr
OCI registry:
helm install dolibarr oci://ghcr.io/helmforgedev/helm/dolibarr
Deployment Examples
# values.yaml — Dolibarr with bundled MySQL and core ERP modules
dolibarr:
siteUrl: 'https://erp.example.com'
companyName: 'Acme Corp'
companyCountryCode: 'US'
timezone: 'America/New_York'
installAuto: true
prod: true
# Enable core ERP modules on first boot
enableModules: 'societe,produit,service,propal,commande,facture'
admin:
login: admin
password: 'change-me-now'
mysql:
enabled: true
auth:
password: 'change-me-now'
standalone:
persistence:
size: 20Gi
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
persistence:
documents:
enabled: true
size: 8Gi
custom:
enabled: true
size: 2Gi
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: erp.example.com
paths:
- path: /
pathType: Prefix# values.yaml — Production Dolibarr with TLS, S3 backup, and secret management
dolibarr:
siteUrl: 'https://erp.example.com'
companyName: 'Acme Corp'
companyCountryCode: 'US'
timezone: 'America/Sao_Paulo'
installAuto: true
prod: true
initDemo: false # never enable in production
enableModules: 'societe,produit,service,propal,commande,facture,stock,projet'
admin:
existingSecret: dolibarr-admin-secret
existingSecretPasswordKey: admin-password
mysql:
enabled: true
auth:
password: 'mysql-password'
persistence:
documents:
enabled: true
size: 20Gi
custom:
enabled: true
size: 2Gi
backup:
enabled: true
schedule: '0 3 * * *'
s3:
endpoint: https://s3.amazonaws.com
bucket: my-dolibarr-backups
prefix: dolibarr
existingSecret: dolibarr-s3-credentials
resources:
requests:
memory: 256Mi
cpu: 100m
limits:
memory: 1Gi
cpu: 500m
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: erp.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: dolibarr-tls
hosts:
- erp.example.com# values.yaml — Dolibarr with external managed MySQL or MariaDB
dolibarr:
siteUrl: 'https://erp.example.com'
companyName: 'Acme Corp'
companyCountryCode: 'BR'
database:
mode: external
external:
host: mysql.database.svc.cluster.local
port: 3306
name: dolibarr
username: dolibarr
existingSecret: dolibarr-db-credentials
existingSecretPasswordKey: database-password
mysql:
enabled: false
persistence:
documents:
enabled: true
size: 20Gi
custom:
enabled: true
size: 2Gi
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: erp.example.com
paths:
- path: /
pathType: Prefix# values.yaml — PHP limits tuned for large document and spreadsheet imports
# Default PHP upload_max_filesize is 2MB — insufficient for ERP use.
dolibarr:
siteUrl: 'https://erp.example.com'
companyName: 'Acme Corp'
companyCountryCode: 'US'
php:
memoryLimit: '512M'
uploadMaxFilesize: '64M'
postMaxSize: '64M'
maxExecutionTime: '120'
mysql:
enabled: true
auth:
password: 'mysql-password'
persistence:
documents:
enabled: true
size: 20Gi
custom:
enabled: true
size: 2GiConfiguration 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 | docker.io/dolibarr/dolibarr |
Dolibarr container image. |
image.tag |
string | "23.0.3" |
Image tag. |
image.pullPolicy |
string | IfNotPresent |
Image pull policy. |
imagePullSecrets |
array | [] |
Pull secrets for private registries. |
Dolibarr Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
dolibarr.siteUrl |
string | "" |
Full public URL. Auto-detected from Ingress when empty. |
dolibarr.companyName |
string | Dolibarr |
Company name used in the unattended installation. |
dolibarr.companyCountryCode |
string | US |
ISO country code for the company. |
dolibarr.auth |
string | dolibarr |
Authentication method. |
dolibarr.enableModules |
string | "" |
Comma-separated list of modules to enable on first boot. Empty = no modules. |
dolibarr.installAuto |
boolean | true |
Enable unattended installation via DOLI_* environment variables. |
dolibarr.initDemo |
boolean | false |
Load demo data on first boot. Never use true in production. |
dolibarr.prod |
boolean | true |
Production mode. Disables debug output and developer warnings. |
dolibarr.timezone |
string | UTC |
PHP timezone. Affects date/time display and report generation. |
dolibarr.extraEnv |
array | [] |
Extra environment variables for the container. |
dolibarr.enableModules accepts a comma-separated list of internal module names. Common modules: societe
(companies), produit (products), service (services), propal (proposals), commande (orders), facture
(invoices), stock (inventory), projet (projects). If left empty, no modules are activated and the installation
will appear empty — all modules must then be enabled manually from the UI.
Admin Credentials
| Parameter | Type | Default | Description |
|---|---|---|---|
admin.login |
string | admin |
Admin username created on first install. |
admin.password |
string | "" |
Admin password. Auto-generated if empty. |
admin.existingSecret |
string | "" |
Existing secret containing the admin password. |
admin.existingSecretPasswordKey |
string | admin-password |
Key inside the existing secret for the admin password. |
Runtime Secret
| Parameter | Type | Default | Description |
|---|---|---|---|
runtime.existingSecret |
string | "" |
Existing secret for the runtime instance unique ID. |
runtime.existingSecretInstanceUniqueIdKey |
string | instance-unique-id |
Key inside the existing secret. |
runtime.instanceUniqueId |
string | "" |
Explicit instance unique ID. Auto-generated if empty. |
Database
| Parameter | Type | Default | Description |
|---|---|---|---|
database.mode |
string | auto |
Database mode: auto, external, or mysql. |
database.external.host |
string | "" |
External MySQL/MariaDB hostname. |
database.external.port |
integer | 3306 |
External database port. |
database.external.name |
string | dolibarr |
Database name on the external server. |
database.external.username |
string | dolibarr |
Username for the external database. |
database.external.password |
string | "" |
Password for the external database (prefer existingSecret). |
database.external.existingSecret |
string | "" |
Existing secret containing the database password. |
database.external.existingSecretPasswordKey |
string | database-password |
Key inside the existing secret. |
database.external.ssl |
boolean | false |
Enable SSL for external database connections. |
MySQL Subchart
| Parameter | Type | Default | Description |
|---|---|---|---|
mysql.enabled |
boolean | true |
Deploy the bundled MySQL subchart. |
mysql.architecture |
string | standalone |
MySQL architecture. |
mysql.auth.database |
string | dolibarr |
Database name created by the subchart. |
mysql.auth.username |
string | dolibarr |
Database user created by the subchart. |
mysql.auth.password |
string | "" |
Database password. Auto-generated if empty. |
mysql.auth.rootPassword |
string | "" |
MySQL root password. Auto-generated if empty. |
mysql.standalone.persistence.enabled |
boolean | true |
Enable persistence for MySQL data. |
mysql.standalone.persistence.size |
string | 8Gi |
PVC size for MySQL data. |
mysql.standalone.resources.requests.cpu |
string | 100m |
MySQL CPU request. |
mysql.standalone.resources.requests.memory |
string | 256Mi |
MySQL memory request. |
mysql.standalone.resources.limits.cpu |
string | 500m |
MySQL CPU limit. |
mysql.standalone.resources.limits.memory |
string | 768Mi |
MySQL memory limit. |
mysql.startupProbe.initialDelaySeconds |
integer | 30 |
MySQL startup probe delay for first bootstrap. |
Older mysql.primary.* values are rejected by the chart so persistence and resource settings are not silently
ignored. Migrate those values to mysql.standalone.* before upgrading.
Persistence
Dolibarr uses two separate PVCs. Both must be preserved in backups independently of the database.
| Parameter | Type | Default | Description |
|---|---|---|---|
persistence.documents.enabled |
boolean | true |
Enable PVC for /var/www/documents (generated files and uploads). |
persistence.documents.size |
string | 8Gi |
Documents PVC size. Grows with invoices, proposals, and attachments. |
persistence.documents.storageClass |
string | "" |
StorageClass for the documents PVC. |
persistence.documents.accessMode |
string | ReadWriteOnce |
PVC access mode. |
persistence.documents.existingClaim |
string | "" |
Use an existing PVC for documents. |
persistence.custom.enabled |
boolean | true |
Enable PVC for /var/www/html/custom (custom PHP modules). |
persistence.custom.size |
string | 2Gi |
Custom modules PVC size. |
persistence.custom.storageClass |
string | "" |
StorageClass for the custom PVC. |
persistence.custom.accessMode |
string | ReadWriteOnce |
PVC access mode. |
persistence.custom.existingClaim |
string | "" |
Use an existing PVC for custom modules. |
PHP Configuration
PHP defaults (upload_max_filesize: 2M, post_max_size: 8M) prevent uploading large spreadsheets, PDF contracts, and
bulk imports. Set php.uploadMaxFilesize and php.postMaxSize to at least 32M for typical ERP workloads. Also
increase php.maxExecutionTime for large import operations.
| Parameter | Type | Default | Description |
|---|---|---|---|
php.memoryLimit |
string | "" |
PHP memory limit (e.g. 512M). Empty = PHP default. |
php.uploadMaxFilesize |
string | "" |
Maximum upload file size (e.g. 64M). Empty = 2M. |
php.postMaxSize |
string | "" |
Maximum POST body size (e.g. 64M). Empty = 8M. |
php.maxExecutionTime |
string | "" |
Maximum script execution time in seconds. Empty = 30. |
Backup
| Parameter | Type | Default | Description |
|---|---|---|---|
backup.enabled |
boolean | false |
Enable scheduled MySQL S3 backup CronJob. |
backup.schedule |
string | "0 3 * * *" |
Cron schedule for backups. |
backup.suspend |
boolean | false |
Suspend the CronJob without deleting it. |
backup.concurrencyPolicy |
string | Forbid |
CronJob concurrency policy. |
backup.successfulJobsHistoryLimit |
integer | 3 |
Successful job records to keep. |
backup.failedJobsHistoryLimit |
integer | 3 |
Failed job records to keep. |
backup.backoffLimit |
integer | 1 |
Job retry limit. |
backup.archivePrefix |
string | dolibarr |
Prefix for backup archive filenames. |
backup.images.mysql |
string | docker.io/library/mysql:8.4 |
Image for mysqldump. |
backup.images.uploader |
string | docker.io/helmforge/mc:1.0.0 |
Image for S3 upload. |
backup.resources |
object | {} |
Resources for backup containers. |
backup.database.mysqldumpArgs |
string | --single-transaction --routines --triggers |
Extra args passed to mysqldump. |
backup.s3.endpoint |
string | "" |
S3-compatible endpoint URL. |
backup.s3.bucket |
string | "" |
Target bucket name. |
backup.s3.prefix |
string | dolibarr |
Key prefix within the bucket. |
backup.s3.createBucketIfNotExists |
boolean | true |
Create the bucket if it does not exist. |
backup.s3.existingSecret |
string | "" |
Existing secret with S3 access and secret keys. |
backup.s3.existingSecretAccessKeyKey |
string | access-key |
Key for the S3 access key. |
backup.s3.existingSecretSecretKeyKey |
string | secret-key |
Key for the S3 secret key. |
backup.s3.accessKey |
string | "" |
Inline S3 access key (ignored when existingSecret is set). |
backup.s3.secretKey |
string | "" |
Inline S3 secret key (ignored when existingSecret is set). |
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. |
Ingress
| Parameter | Type | Default | Description |
|---|---|---|---|
ingress.enabled |
boolean | false |
Enable an Ingress resource. |
ingress.ingressClassName |
string | "" |
Ingress class name. Must be set explicitly. |
ingress.annotations |
object | {} |
Annotations for the Ingress (e.g. cert-manager). |
ingress.hosts |
array | [] |
Ingress host and path rules. |
ingress.tls |
array | [] |
TLS configuration. |
Gateway API
| Parameter | Type | Default | Description |
|---|---|---|---|
gateway.enabled |
boolean | false |
Enable an HTTPRoute instead of Ingress. |
gateway.annotations |
object | {} |
Annotations for the HTTPRoute. |
gateway.parentRefs |
array | [] |
Gateway parent references. |
gateway.hostnames |
array | [] |
Hostnames matched by the HTTPRoute. |
gateway.path |
string | / |
Path prefix routed to the Service. |
gateway.pathType |
string | PathPrefix |
Gateway API path match type. |
External Secrets
| Parameter | Type | Default | Description |
|---|---|---|---|
externalSecrets.enabled |
boolean | false |
Enable an ExternalSecret for admin credentials. |
externalSecrets.apiVersion |
string | external-secrets.io/v1 |
External Secrets API version. |
externalSecrets.refreshInterval |
string | 0 |
Secret refresh interval. |
externalSecrets.secretStoreRef.name |
string | "" |
SecretStore or ClusterSecretStore name. |
externalSecrets.secretStoreRef.kind |
string | ClusterSecretStore |
Secret store kind. |
externalSecrets.target.creationPolicy |
string | Owner |
Target Secret ownership policy. |
externalSecrets.data |
array | [] |
Remote reference mappings for admin password. |
Probes
| Parameter | Type | Default | Description |
|---|---|---|---|
startupProbe.enabled |
boolean | true |
Enable startup probe. |
startupProbe.initialDelaySeconds |
integer | 70 |
Startup probe initial delay. |
startupProbe.periodSeconds |
integer | 10 |
Startup probe period. |
startupProbe.timeoutSeconds |
integer | 5 |
Startup probe timeout. |
startupProbe.failureThreshold |
integer | 30 |
Startup probe failure threshold. |
livenessProbe.enabled |
boolean | true |
Enable liveness probe. |
livenessProbe.initialDelaySeconds |
integer | 0 |
Liveness probe initial delay. |
livenessProbe.periodSeconds |
integer | 20 |
Liveness probe period. |
livenessProbe.timeoutSeconds |
integer | 5 |
Liveness probe timeout. |
livenessProbe.failureThreshold |
integer | 3 |
Liveness probe failure threshold. |
readinessProbe.enabled |
boolean | true |
Enable readiness probe. |
readinessProbe.initialDelaySeconds |
integer | 0 |
Readiness probe initial delay. |
readinessProbe.periodSeconds |
integer | 10 |
Readiness probe period. |
readinessProbe.timeoutSeconds |
integer | 5 |
Readiness probe timeout. |
readinessProbe.failureThreshold |
integer | 3 |
Readiness probe failure threshold. |
Resources and Security
| Parameter | Type | Default | Description |
|---|---|---|---|
resources.requests.cpu |
string | 100m |
Application CPU request. |
resources.requests.memory |
string | 256Mi |
Application memory request. |
resources.limits.cpu |
string | 500m |
Application CPU limit. |
resources.limits.memory |
string | 768Mi |
Application memory limit. |
podSecurityContext.seccompProfile.type |
string | RuntimeDefault |
Pod seccomp profile. |
securityContext |
object | {} |
Container-level security context. |
The official Dolibarr image performs first-run file ownership and Apache setup as root. The chart keeps
securityContext empty by default and applies pod-level RuntimeDefault seccomp; operators can add stricter
container security after validating their image and storage combination.
Security Scan
| Framework | Score |
|---|---|
| MITRE + NSA + SOC2 | 87.878784% |
| MITRE | 100.00% |
| NSA | 82.50% |
| SOC2 | 90.00% |
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. |