Dedicated tree-docs guidebook under vibe/guidebooks/erp/ for the lab's most data-critical app, cross-linked from the applications hub (bidirectional): - README.md : Dolibarr 22.0.4 on Postgres; data-criticality; overview diagram; the Vault-unseal-before-scale recovery ordering (CAUTION). - deployment.md : upstream image + custom entrypoint (MySQL->psql), the 50Gi Longhorn RWX documents PVC, Vault CRDs + the shared app_roles iac, init scripts (conf.php creds, table-ownership), ingress, CI. - backup-and-recovery.md: the Ansible CronJob pg_dump (daily 04:00, 15-day retention) + restore Job (scale-0 -> restore -> scale-1); the cluster recovery ordering (Longhorn -> Vault unseal -> erp scale-up). - operations.md : the read-only bin/arcodange CLI, static/company.json, Deno+Playwright tests, day-2 ops. erp code via full gitea URLs; CLUSTER_RECOVERY.md by name; 2 mermaid diagrams MCP-validated; zero dead links. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
vibe > Guidebooks > ERP
ERP
Status: ✅ Active Last Updated: 2026-06-23 Upstream: Applications hub · 01 · factory Downstream: Deployment · Backup & recovery · Operations Related: tools secrets-and-vso · factory postgres-iac · storage concept · factory recover playbooks · safe-prod-like-environment ADR
This guidebook maps erp — the lab's Dolibarr 22.0.4 accounting/business ERP and its single most data-critical application. It is a PHP/Apache workload built from the upstream dolibarr/dolibarr image, served internally at erp.arcodange.lab (Traefik websecure + localIp@file + a letsencrypt-resolver cert). Everything a reader needs to deploy it, keep its data safe, and operate it lives in the three child pages below; this page is the orientation map.
What makes erp special
erp is the complex sibling of the webapp / url-shortener archetypes. It carries the same four-ingredient app pattern (Dockerfile-less reuse of an upstream image, a chart/, an iac/, .gitea/workflows) but layers several things on top that the archetypes do not:
| Trait | erp specifics | Why it matters |
|---|---|---|
| Upstream image | dolibarr/dolibarr:22.0.4 — not a repo-built image |
No custom Dockerfile; the chart adapts the upstream container at runtime |
| Postgres, not MySQL | Dolibarr classically assumes MySQL; erp runs on PostgreSQL (DOLI_DB_TYPE: pgsql) |
A custom entrypoint rewrites the upstream docker-run.sh mysql invocation into psql before launch |
| DB path | pod → pgbouncer.tools:5432 → the erp Postgres database on pi2 |
Shares the tools pgbouncer pooler like the webapp archetype |
| Vault wiring | dynamic rotating DB creds (postgres/creds/erp) + static KV config (kvv2 erp/config) via the shared app_roles module |
The pod cannot start without VSO-injected DOLI_DB_USER / DOLI_DB_PASSWORD |
| Document persistence | a 50Gi Longhorn RWX PVC (storageClassName: longhorn, accessModes: ReadWriteMany, helm.sh/resource-policy: keep) mounting /var/www/documents, /var/www/html/custom, and /var/backups |
Uploaded invoices/PDFs/attachments are real business records — losing them is the worst case |
| Backup + ops | its own backup/restore subsystem plus a read-only ops CLI (bin/arcodange) |
Data-criticality demands both an escape hatch for restores and a safe way to inspect live state |
Overview — how erp is wired
%%{init: {'theme': 'base'}}%%
flowchart LR
classDef src fill:#2563eb,stroke:#1e40af,color:#fff
classDef proc fill:#059669,stroke:#047857,color:#fff
classDef store fill:#7c3aed,stroke:#6d28d9,color:#fff
classDef net fill:#b45309,stroke:#92400e,color:#fff
CI["factory / erp CI<br>tofu apply (iac/)"]:::src
VAULT["Vault<br>postgres/creds/erp (dynamic)<br>kvv2 erp/config (static)"]:::store
ARGO["ArgoCD<br>syncs chart/ (ns erp)"]:::proc
POD["Dolibarr pod<br>dolibarr/dolibarr:22.0.4<br>custom entrypoint → psql"]:::proc
VSO["VSO<br>VaultAuth + VaultDynamicSecret<br>+ VaultStaticSecret"]:::proc
PGB["pgbouncer.tools:5432"]:::net
PG["Postgres erp db<br>(pi2)"]:::store
PVC["50Gi Longhorn RWX PVC<br> /var/www/documents"]:::store
BK["backup CronJob / runner<br>pg_dump → documents/admin/backup"]:::proc
CI --> VAULT
ARGO --> POD
VAULT -. "creds + config" .-> VSO
VSO -- "vso-db-credentials + secretkv" --> POD
POD --> PGB --> PG
PVC -- "mounts /var/www/documents" --- POD
BK -- "dumps DB + writes to" --> PVC
- factory / erp CI runs
tofu applyoveriac/to declare erp's Vault objects — a Postgres dynamic-secret role and a Kubernetes auth role — through the sharedapp_rolesmodule, and seeds the statickvv2erp/configKV (admin login, instance UUID). - ArgoCD (factory's app-of-apps) syncs the
chart/into theerpnamespace. - The Dolibarr pod comes up from
dolibarr/dolibarr:22.0.4; its custom entrypoint rewrites the upstreamdocker-run.shso SQL runs throughpsqlinstead ofmysql. - VSO authenticates to Vault (the
authVaultAuthCRD), materialisingvso-db-credentials(dynamic, rotating DB user/password frompostgres/creds/erp) andsecretkv(static config fromkvv2erp/config); both are injected into the pod, and a credential rotation triggers a rollout restart. - The pod connects to the
erpPostgres database through the toolspgbouncer.tools:5432pooler. - A 50Gi Longhorn RWX PVC mounts
/var/www/documents(plus/var/www/html/customand/var/backups), holding every uploaded document and generated PDF. - The backup subsystem dumps the
erpdatabase with a version-matchedpg_dumpand lands the archive underdocuments/admin/backupon that same PVC — see Backup & recovery.
Caution
Recovery ordering: Vault MUST be unsealed before erp is scaled up. The Dolibarr pod has no usable DB credentials of its own — it depends entirely on VSO materialising
vso-db-credentialsfrompostgres/creds/erp. If erp is scaled up while Vault is still sealed, the pod crash-loops with no database access. During a cluster rebuild, unseal Vault first, confirm VSO has reconciled the erp secrets, and only then scale erp. The full sequence (cluster bring-up → Vault unseal → storage → apps) is covered by Backup & recovery, the storage concept, the factory recover playbooks, and the cluster-wide CLUSTER_RECOVERY.md runbook.
Index
| Page | What it covers | Status |
|---|---|---|
| Deployment | The chart, the upstream image + custom entrypoint, the Postgres-over-pgbouncer wiring, the Vault CRDs (dynamic creds + static config), and the ingress | ✅ Active |
| Backup & recovery | The document PVC, the pg_dump-based backup subsystem, restore procedure, and where erp sits in cluster-recovery ordering |
✅ Active |
| Operations | The read-only bin/arcodange ops CLI and day-to-day operational tasks (table-ownership fix-ups, liveness checks, audits) |
✅ Active |
Maintenance rule
Important
When the erp repo changes shape, these pages change in the same PR. If you alter the chart structure, the custom entrypoint, the Vault wiring, the document PVC, the backup subsystem, or the ops CLI, update this hub and the relevant child page in the same change. A reference map that drifts from the real
chart/,iac/, andbackup/sends agents confidently down dead paths — and for the lab's most data-critical app that risk is highest here.
Cross-references
- Applications hub — the common four-ingredient app pattern; erp is its complex sibling, beside the webapp and url-shortener archetypes.
- 01 · factory — the ArgoCD app-of-apps that emits erp's
ApplicationCRD. - tools secrets-and-vso — the
app_rolesmodule + VSO runtime that delivers erp's dynamic DB creds and static config, and the pgbouncer pooler the pod connects through. - factory postgres-iac — the per-app
erpPostgreSQL database + role erp runs on. - storage concept — how the 50Gi Longhorn RWX document PVC is provisioned and recovered.
- factory recover playbooks — the Ansible recovery steps that must precede scaling erp back up.
- safe-prod-like-environment ADR — why the lab keeps erp deployed prod-like and the data-criticality trade-offs behind it.