Skip to content

Maxed-OSS/cpa-stack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cpa-stack

The open-source back office for a CPA or bookkeeping firm: five proven, unmodified open-source applications, one docker compose up.

Published by maxed-oss. We run this exact stack for our own back office and publish the recipe. There is no account, no telemetry to us, and nothing here depends on us: every application below is the official upstream image, pinned to a supported version, wired together with configuration only.

What's inside

Application What it does for a firm Port Image (pinned) Upstream license
ERPNext Firm ledger, invoicing, accounts payable, practice management 8081 frappe/erpnext:v15 GPL-3.0
Kimai Time tracking and timesheets 8082 kimai/kimai2:2.61.0 AGPL-3.0
Nextcloud Client document storage and sharing 8080 nextcloud:33-apache AGPL-3.0
Documenso E-signature (engagement letters, internal docs) 8083 documenso/documenso:v2.14.0 AGPL-3.0
Metabase Dashboards and analytics over your data 8084 metabase/metabase:v0.62.3.5 AGPL-3.0

Supporting services: PostgreSQL 16, MariaDB 10.11 LTS, Redis 7.4. Data lives in named Docker volumes; nothing is stored inside containers.

Design principles

  • Unmodified upstream. Every image is the official one, untouched. You get upstream security updates, upstream docs, and upstream community support.
  • Pinned versions. No :latest roulette. Update deliberately (see "Updating" below).
  • API-first. Each application ships a full REST API, so any practice tooling you use (or build) can integrate without vendor lock-in.
  • Config only. This repository is a compose file, an env template, and documentation. There is no code to trust.

Requirements

  • A Linux host (Ubuntu 24.04 tested) with 16 GB+ RAM and 160 GB+ disk.
  • Docker 24+ with the Compose v2 plugin.
  • For production: a domain, a reverse proxy for TLS, and an SMTP account for Documenso's signing invitations.

Quickstart

git clone https://github.com/maxed-oss/cpa-stack.git
cd cpa-stack

# 1. Configure secrets (fill in every REPLACE_ME).
cp .env.example .env
nano .env

# 2. Documenso needs a PKCS#12 signing certificate at ./cert.p12.
#    Self-signed is fine to evaluate:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem \
  -days 365 -nodes -subj "/CN=yourfirm.example"
openssl pkcs12 -export -out cert.p12 -inkey key.pem -in cert.pem -passout pass:
rm key.pem cert.pem

# 3. Start everything.
docker compose up -d

# 4. Watch ERPNext finish its one-time site creation (a few minutes).
docker compose logs -f erpnext-create-site

First logins:

Health checks

Most services carry container-level healthchecks (docker compose ps shows them). From the host:

curl -sf http://localhost:8080/status.php        # Nextcloud
curl -sf http://localhost:8081/api/method/ping   # ERPNext
curl -sf -o /dev/null http://localhost:8082/     # Kimai
curl -sf -o /dev/null http://localhost:8083/     # Documenso
curl -sf http://localhost:8084/api/health        # Metabase

Backups

The stack's state is nine named volumes plus your .env and cert.p12:

nextcloud_data  nextcloud_db_data  erpnext_sites  erpnext_logs  erpnext_db_data
erpnext_redis_queue_data  kimai_db_data  documenso_db_data  metabase_db_data

Minimum viable backup, run on a schedule and shipped off the host:

# Logical database dumps (consistent, restorable independently).
docker compose exec -T nextcloud-db pg_dump -U nextcloud nextcloud | gzip > nextcloud.sql.gz
docker compose exec -T documenso-db pg_dump -U documenso documenso | gzip > documenso.sql.gz
docker compose exec -T metabase-db  pg_dump -U metabase  metabase  | gzip > metabase.sql.gz
docker compose exec -T erpnext-db mariadb-dump -uroot -p"$ERPNEXT_DB_ROOT_PASSWORD" --all-databases | gzip > erpnext.sql.gz
docker compose exec -T kimai-db   mariadb-dump -uroot -p"$KIMAI_DB_ROOT_PASSWORD" kimai | gzip > kimai.sql.gz

# File volumes (documents, ERPNext site files).
docker run --rm -v cpa-stack_nextcloud_data:/data -v "$PWD":/backup alpine \
  tar czf /backup/nextcloud_data.tar.gz -C /data .
docker run --rm -v cpa-stack_erpnext_sites:/data -v "$PWD":/backup alpine \
  tar czf /backup/erpnext_sites.tar.gz -C /data .

Three rules that matter more than the tooling: encrypt backups before they leave the host, keep at least one copy a compromised host cannot delete (object storage with retention/immutability), and rehearse a restore on a clean machine before you trust any of it.

Updating

  1. Snapshot first (backups above).
  2. Bump one image pin at a time in docker-compose.yml, reading that application's upstream release notes (major upgrades of ERPNext and Nextcloud have their own documented migration paths).
  3. docker compose pull && docker compose up -d, then re-run the health checks.

Production notes

  • Put a reverse proxy (Caddy, Traefik, nginx) with TLS in front of the five web ports; do not expose the raw ports to the internet.
  • The databases and redis instances bind no host ports by design; keep it that way.
  • Set real hostnames in NEXTCLOUD_TRUSTED_DOMAINS, KIMAI_TRUSTED_HOSTS, and DOCUMENSO_WEBAPP_URL once the proxy is up.
  • Use a unique generated secret for every REPLACE_ME; never reuse one across services.
  • For legally sensitive e-signatures, replace the self-signed cert.p12 following Documenso's certificate documentation.

License

This repository (the compose file, env template, and docs) is Apache-2.0. Each application it deploys is upstream software under its own license, listed in the table above; the images are pulled unmodified from their official registries.

About

The open-source back office for a CPA or bookkeeping firm: five unmodified, version-pinned open-source apps (ERPNext, Kimai, Nextcloud, Documenso, Metabase) wired together with one docker compose up. Config only, no code to trust.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors