An opinionated Odoo deployment for small organisations in the Netherlands.
Immutable Docker Compose deployment for Odoo 19 Community with a small set of packaged custom and OCA addons.
The repository is intended for local testing and deployment through platforms such as Coolify.
Dockerfilebuilds a custom image fromodoo:19.0.- OCA addons are installed as pinned Python packages from the OCA wheelhouse.
- Vendored project addons are installed through
hatch-odoointo theodoo.addonsnamespace during the Docker build. - Odoo and PostgreSQL runtime data live in Docker volumes.
- Production does not mount
/mnt/extra-addons; addon code is image content. - Installing addon code in the image and updating installed modules in the database are separate operations.
The source of truth is:
Runtime/services: docker-compose.yml
Image/addons: Dockerfile, pyproject.toml, addons/, odoo-modules.txt
Python packages: requirements.txt
Local env sample: .env.example
VAT workflow: docs/nl-eenmanszaak-vat-workflow.md
Create a local environment file:
cp .env.example .envEdit .env, then run:
docker compose up --buildOpen:
http://localhost:8069
For a clean local reset:
docker compose down -vThis deletes the local Odoo and PostgreSQL volumes.
Install developer checks, or run them through uvx without a persistent install:
uv tool install pre-commit
pre-commit install
uvx pre-commit run --all-filesIn Coolify, create a Docker Compose application from this repository.
Set real values for required secrets in the Coolify environment variables UI:
SERVICE_USER_POSTGRES=odoo
SERVICE_PASSWORD_POSTGRES=use-a-real-passwordOptional local setting:
ODOO_PORT=8069Do not commit production environment files.
After the first login:
- Install Invoicing.
- Go to Apps -> Update Apps List.
- Install or update the modules listed in odoo-modules.txt.
- Confirm the company fiscal localisation is set to Netherlands.
- Enable the accounting user rights described in
docs/nl-eenmanszaak-vat-workflow.md: especially Analytic Accounting and Show Full Accounting Features. - Validate that the official Odoo 19 Dutch reports are present before relying on the database for VAT filing:
scripts/check-nl-tax-readiness.sh <database>docker compose build --pull
docker compose up -d
docker compose logs -f odoo
scripts/update-odoo-modules.sh <database>
scripts/check-nl-tax-readiness.sh <database>With just:
just build
just up
just logs
just lint
just checkInstall just with your system package manager, for example:
brew install justRun all repository checks:
just lintjust lint uses uvx pre-commit run --all-files, so pre-commit does not need to be installed persistently.
Installing addon code in the image does not install or upgrade modules in an Odoo database.
Use the helper script against a staging copy first:
scripts/update-odoo-modules.sh <database>By default, the script updates the modules listed in:
odoo-modules.txt
To update a specific comma-separated module list:
scripts/update-odoo-modules.sh <database> module_a,module_bBack up PostgreSQL and the Odoo filestore before production module updates.
requirements.in is the human-edited dependency input.
requirements.txt is the pinned install file used by the Docker image.
Because OCA addon wheels depend on the Odoo runtime provided by the base image, regenerate and verify the pinned file inside an Odoo image. Do not hand-edit it casually.
Edit:
requirements.in
Then resolve from inside the Odoo base image:
docker run --rm -v "$PWD:/work" -w /work odoo:19.0 \
python3 -m pip install --break-system-packages -r requirements.inIf the resolver can satisfy the Odoo runtime constraint, compile the lock file with one chosen tool:
uv pip compile requirements.in -o requirements.txtor:
pip-compile -o requirements.txt requirements.inCommit both files and rebuild the image:
docker compose build --pullTest against a staging database before production deployment when addon packages or Odoo-related dependencies change.
Backups must preserve both:
- PostgreSQL database data.
- Odoo filestore data in /var/lib/odoo.
Before production module updates, back up both the database and the filestore. Test restores in staging when the accounting database becomes important.
docker compose exec odoo python3 -c 'import odoo.addons.account_invoice_digitize_ai'
docker compose exec odoo python3 -c 'import odoo.addons.account_financial_report, odoo.addons.date_range, odoo.addons.report_xlsx'
docker compose logs -f odooThis deployment targets an NL eenmanszaak doing services, installations, workshops, funded projects, and international collaborations.
For Odoo 19, the primary Dutch tax filing path is Odoo's built-in Dutch localisation:
l10n_nl
See docs/nl-eenmanszaak-vat-workflow.md
for the full workflow and transaction-based acceptance test.
Do not store API keys, database dumps, filestores, or production passwords in this repository.