Introduction

Overview
This project aims to simplify following processes:
- development and maintenance of addons for Odoo
- deployment and maintenance of Odoo servers.
This project is successor of odoo-helper-scripts
Following features available:
- Super easy installation of Odoo for development
- Super easy installation of Odoo for production (see docs)
- Simple way to manage multiple development instances of Odoo on same developer’s machine
- Everything (including nodejs) installed in virtualenv - no conflicts with system packages
- Best test runner for Odoo modules:
- Easy run test for developed modules
- Show errors in the end of the log, that is really useful feature for large (few megabytes size test logs)
- Test module migrations with ease
- Super easy of third-party addons installation:
- Install modules directly from Odoo Apps
- Easily connect git repositories with Odoo modules to Odoo instance managed by Odood
- Automatic resolution of addons dependencies:
- Handle
requirements.txt - Handle
odoo_requirements.txt
- Handle
- Simple database management via commandline: create, backup, drop, rename, copy database
- Simple installation via prebuilt debian package (see releases)
- Support for assemblies: single repo with all addons for project, populated in semi-automatic way.
- Build with docker-support in mind
- Basic integration with odoo-module-migrator. See docs
The War in Ukraine
2022-02-24 Russia invaded Ukraine…
If you want to help or support Ukraine to stand against russian inavasion, please, visit the official site of Ukraine and find the best way to help.
Thanks.
Supported OS
Currently debian-based operating systems are supported. Tested on Ubuntu and Debian. Theoretically it should work on macOS also.
Supported Odoo versions
- Odoo 19.0 (experimental)
- Odoo 18.0 (tested)
- Odoo 17.0 (tested)
- Odoo 16.0 (tested)
- Odoo 15.0 (tested)
- Odoo 14.0 (tested)
- Odoo 13.0 (tested)
- Odoo 12.0 (tested)
- Odoo 11.0 (best efforts)
- Odoo 10.0 (best efforts)
- Odoo 9.0 (best efforts)
- Odoo 8.0 (best efforts)
- Odoo 7.0 (partial)
Installation (as Debian Package)
To install Odood, just find debian package in releases and install it. Thats all.
Note, that usually you will need to manually install additional system packages, that include:
- postgresql - if you plan to use local instance of postgresql.
- wkhtmltopdf - Required to generate pdf reports. See Odoo docs for more info.
Installation (on MacOS)
There is experimental support for MacOS implemented as homebrew’s tap. Just run:
brew tap katyukha/odood
brew install odood
It is recommented to use pyenv on MacOS to init Odood projects.
For example, use option --pyenv when creating new odood project via odood init:
odood init -v 18 --pyenv
Also, take into account that you have to install missing dependencies on MacOS. If you know how to make MacOS support better, just create issue or pull request with your ideas or patches.
Docker images
Odood has pre-build docker images with already installed Odoo and Odood. These images could be useful as base to distribute products based on Odoo as docker images. Take a look for base images at github package registry.
License
Odood is distributed under MPL-2.0 license.
Quick start
Overview
Odood is Command Line Interface (CLI) tool.
Odood and each subcommand of Odood has option --help, thus
if you are interested what it can do, just type odood --help :)
Installation
To install the latest stable version of Odood on Debian/Ubuntu, run:
wget -O /tmp/odood.deb \
"https://github.com/katyukha/Odood/releases/latest/download/odood_$(dpkg --print-architecture).deb"
sudo apt install -yq /tmp/odood.deb
For macOS, specific versions, and system dependency details, see Installing Odood.
Odoo installation
To install Odoo 18 for local development:
odood init -i odoo-18 -v 18 --db-user=odoo18 --http-port=18069
This installs Odoo 18 into the odoo-18 directory, using a dedicated database user and HTTP port.
For more options and multi-instance setups, see Local Development.
For Docker Compose or VPS/bare-metal deployments, see the Deployment Overview.
Server management
After installation the following commands are available from inside the project directory:
odood server start # start Odoo in the background
odood server stop # stop Odoo
odood server restart # restart Odoo
odood server browse # open Odoo in your browser
odood server log # view server logs
odood server status # check if Odoo is running
odood status # status of this Odoo instance
Database management
Create a test database (name generated automatically):
odood db create --demo --tdb --recreate
Or create a database with a specific name:
odood db create --demo --recreate my-demo-db
List databases:
odood db list
# shortcut:
odood lsd
Addons management
Install a third-party addon
Add the repository containing the addon, then install it:
# Add repository (full URL or GitHub shortcut)
odood repo add https://github.com/crnd-inc/generic-addons
# or:
odood repo add --github crnd-inc/generic-addons
Odood clones the repository into repositories/crnd-inc/generic-addons/ and symlinks all addons to custom_addons/, making them visible to Odoo.
Install a specific module into a database:
odood addons install -d my-demo-db generic_location
Update third-party modules
One of the most frequent tasks is updating third-party modules. The typical workflow:
# Change to the repository directory
cd repositories/crnd-inc/generic-addons
# Pull latest changes
git pull
# Relink addons (handles new addons and new Python dependencies)
odood addons link .
# Update all modules in this directory for all databases
# (stops Odoo automatically before update, starts again after)
odood addons update -a --ual --dir .
Running tests
Run tests for a single module on a temporary database:
odood test -t generic_location
Run tests for all installable addons in the current repository directory:
odood test -t --dir .
Odood creates a temporary database, runs the tests with coloured error/warning highlights, then drops the database.
Installation
Debian / Ubuntu
Download and install the latest stable release:
wget -O /tmp/odood.deb \
"https://github.com/katyukha/Odood/releases/latest/download/odood_$(dpkg --print-architecture).deb"
sudo apt install -yq /tmp/odood.deb
To install a specific version, visit the releases page, download the .deb for the desired version and architecture, and install it the same way.
macOS
macOS support is experimental. Install via the Homebrew tap:
brew tap katyukha/odood
brew install odood
On macOS, use pyenv to manage the Python version for Odood projects.
Pass --pyenv when creating a new project so Odood installs and configures the right Python version automatically:
odood init -v 18 --pyenv
Missing system dependencies (PostgreSQL client libraries, etc.) need to be installed manually. If you run into issues or have improvements for macOS support, please open an issue or pull request.
System dependencies
Odood itself is a self-contained binary, but the Odoo instances it manages need several system packages:
- PostgreSQL — required if you plan to run a local database server (
sudo apt install postgresql). - wkhtmltopdf — required to generate PDF reports. Download the right release for your OS from the wkhtmltopdf releases page. See also the Odoo docs on wkhtmltopdf.
Build from source
Building from source is primarily useful for Odood development. For regular use, install the prebuilt Debian package instead.
- Clone the repository and enter its root directory.
- Install build dependencies:
libpq-dev python3-dev. - Install LDC (the LLVM-based D compiler). Use LDC rather than DMD for release builds — DMD has a known CTFE regression that causes release builds to fail.
- Build:
The binary is written todub build -b release --compiler=ldc2build/odood. - Link it onto your
PATH, e.g.:mkdir -p ~/bin ln -s "$(pwd)/build/odood" ~/bin/
DMD note:
dub build -b releasewith DMD fails due to a CTFE regression instd.regex/std.uni. Debug builds (dub build) and unit tests (dub test -c unittest) still work fine with DMD.
Docker images
Prebuilt Docker images with Odoo and Odood already installed are published to the GitHub Container Registry:
ghcr.io/katyukha/odood/odoo/{serie}:latest
Available series: 16.0, 17.0, 18.0, 19.0.
These images are useful as a base for distributing Odoo-based products as containers, and for CI pipelines. See Docker Compose for deployment details.
Development Workflow
Overview
This page describes a recommended workflow for developing Odoo addons in a repository managed alongside Odood. It covers local testing (including coverage and warnings), translation management, forward-porting across Odoo series, and CI/CD configuration for both GitHub Actions and GitLab CI.
Assumption: This workflow is designed for multi-addon repositories — a single git repository containing several related Odoo addons, with one stable branch per supported Odoo series (
17.0,18.0,19.0, …). This is the standard layout in the Odoo ecosystem, used by OCA and most independent addon vendors.
Branching Strategy
The recommended branch naming convention mirrors the Odoo series:
- Stable branch —
{serie}(e.g.18.0): production-ready code. - Development branches —
{serie}-{feature}(e.g.18.0-my-feature): feature or fix branches. CI pipelines are typically triggered on these branches.
Local Development
Running Tests
Run tests for a single module on a temporary database:
odood test -t <module>
Run tests for all installable addons in the current directory:
odood test -t --dir .
Odood creates a temporary database, runs the tests, prints a summary with highlighted errors and warnings, then drops the database.
Coverage
Odood uses Python’s coverage tool (installed in the project virtualenv) to measure test coverage.
# Print a terminal coverage summary after tests
odood test -t --dir . --coverage-report
# Fail if total coverage falls below a threshold (useful in CI)
odood test -t --dir . --coverage-report --coverage-fail-under 90
# Generate an HTML report in htmlcov/ (open htmlcov/index.html in a browser)
odood test -t --dir . --coverage-html
--coverage-report and --coverage-html can be combined in the same command.
Warnings report
Odood collects all Odoo log warnings during the test run. To print a deduplicated block of all collected warnings at the end (after the pass/fail summary):
odood test -t --dir . --warning-report
This is useful for spotting deprecation notices or misconfigured modules without having to scan the full test log.
Migration Tests
Migration tests verify that your addons upgrade correctly from the stable branch to the current development branch. Odood automates the full cycle: checks out the stable branch, installs modules, optionally populates data, checks out the development branch, and runs the upgrade tests.
Run migration tests for all addons in the current directory:
odood test -t --migration --dir .
Note: Migration tests are expected to be a soft failure in CI. They may fail if third-party dependencies introduce changes that are incompatible with the older (stable) version of this repository — a situation outside the developer’s control.
Translation Management
See the dedicated Translation Management page for the full workflow, flag reference, and guidance on using AI assistants for translations.
Module Versioning
Odoo addon versions follow the A.B.X.Y.Z scheme, where:
A.B— Odoo series (e.g.18.0). Set once when the addon or branch is created; never changed manually.X— addon major version. Increment for significant data-structure changes that may break backward compatibility.Y— addon minor version. Increment for noticeable data-structure changes, or whenever a database migration script is required.Z— addon patch version. Increment for low-risk changes (bug fixes, UI tweaks, new fields that don’t require migration).
Rules of thumb:
- If you add a migration script → bump at least
Y. - If the migration may break backward compatibility → bump
X. - Everything else → bump
Z.
Rather than editing __manifest__.py files by hand, you can let Odood bump versions automatically:
odood repo bump-versions
This inspects the git diff, identifies which modules have changed, and increments their patch version (Z).
Run it inside the repository directory before committing. For minor or major bumps, adjust the version manually afterwards.
Odood also enforces that every changed module has its version bumped via odood repo check-versions.
Version Checks and Pre-commit
Before pushing, verify that all modified modules have their versions bumped:
odood repo check-versions --ignore-translations
The --ignore-translations flag prevents translation-only commits from triggering a version bump requirement.
To run pre-commit hooks (linters, formatters, etc.) locally:
# First-time setup — installs pre-commit and all hooks into the virtualenv:
odood pre-commit set-up
# Run hooks manually against all staged files:
odood pre-commit run
Per-addon Changelog
To track user-facing changes at the module level, each addon can contain a changelog/ directory.
Each file inside describes changes introduced in a specific version, using the naming pattern:
changelog/
└── changelog.X.Y.Z.md
For example, changelog/changelog.1.3.0.md contains a markdown description of what changed in version 1.3.0 of that addon.
The file content is free-form markdown — describe what changed from an end-user perspective, not implementation details.
Odood reads these files when generating the assembly-level changelog.
When you run odood assembly sync --changelog, it aggregates per-addon changelogs across all updated modules into a single CHANGELOG.md (and CHANGELOG.latest.md) at the assembly root — useful for release notes and communicating changes to end users.
Releasing a Repository
Once your changes are committed and versions are bumped, cut a release with
odood repo release. The full release strategy — version conventions, the
standard release flow, the hotfix flow, and CI setup — is documented on a
dedicated page: Release Management.
In short:
# Auto-detect the bump level from changed addons, verify versions,
# generate the changelog, tag, and push:
odood repo release --changelog --push
# First release of a never-tagged repository:
odood repo release --initial
To patch an already-released version while the stable branch has moved on, use
the hotfix flow (odood repo hotfix) — see
Release Management → Hotfix flow.
Forward-porting
When you maintain addons across multiple Odoo series (e.g. 17.0 and 18.0), development typically happens on the oldest supported series first, and the resulting changes are then forward-ported to newer series.
For example, you develop a fix on 17.0, then need to carry it into 18.0 and 19.0.
The naive approach — manually cherry-picking or re-applying changes — is tedious because:
- Module versions embed the series prefix and must be updated (e.g.
17.0.1.2.3→18.0.1.2.3). - Migration script directories also embed the series (e.g.
migrations/17.0.1.2.3/→migrations/18.0.1.2.3/). - Translation files in the target branch should be kept as-is — conflicts in
.po/.potfiles are meaningless and always resolved in favour of the target branch.
odood repo do-forward-port automates all of this, leaving only genuine business-logic conflicts for you to resolve manually.
Workflow
-
Switch to your Odoo environment for the target series (e.g. your
18.0project). -
Change into the repository directory.
-
Create (or check out) a forward-port branch:
git checkout -b 18.0-forward-port-<feature> -
Run the forward-port command, naming the source series:
odood repo do-forward-port -s 17.0The command will automatically:
- Fetch
origin/17.0and open a merge (--no-ff --no-commit) into the current branch, staging all changes for review. - Reset
.po/.potfiles to the target-branch version — translation conflicts are always discarded. - Fix version number conflicts in each addon’s
__manifest__.py, rewriting the series prefix. - Rename migration script directories from the source series to the target series (e.g.
migrations/17.0.1.2.3/→migrations/18.0.1.2.3/).
- Fetch
-
Resolve any remaining merge conflicts (business logic, structural changes, etc.).
-
Run tests to verify everything works in the target series:
odood test -t --dir . -
Commit and push:
git push origin 18.0-forward-port-<feature> -
Open a pull/merge request into the
18.0stable branch and wait for CI to pass. -
Repeat steps 1–8 for each remaining target series (
19.0, etc.).
Note:
do-forward-portis currently marked experimental. In straightforward cases (no structural conflicts) it produces a ready-to-commit merge with zero manual intervention.
CI/CD Configuration
Key concept: --config-from-env and ODOOD_OPT_*
The prebuilt Docker images (ghcr.io/katyukha/odood/odoo/{serie}:latest) already have Odoo installed and ready.
ODOOD_OPT_* environment variables allow you to override individual Odoo configuration options (i.e. values in odoo.conf) at runtime — without modifying any file on disk.
Combined with the --config-from-env flag, this is the standard way to point CI containers at the PostgreSQL sidecar.
Note: The
--config-from-envflag andODOOD_OPT_*support are only compiled in when Odood is built with the-d-version OdoodInDockerflag, and thus are available only in the official prebuilt Docker images. The Debian package and source builds do not include this flag.
For example, set these environment variables in your CI job:
ODOOD_OPT_DB_HOST=postgres
ODOOD_OPT_DB_USER=odoo
ODOOD_OPT_DB_PASSWORD=odoo
Then invoke Odood as:
odood --config-from-env addons link .
odood --config-from-env test -t --dir .
Common ODOOD_OPT_* variables
Each variable maps directly to the corresponding key in Odoo’s [options] section of odoo.conf.
The prefix ODOOD_OPT_ is stripped and the remainder is lowercased before being applied.
| Environment variable | odoo.conf key | Description |
|---|---|---|
ODOOD_OPT_DB_HOST | db_host | PostgreSQL host |
ODOOD_OPT_DB_PORT | db_port | PostgreSQL port (default: 5432) |
ODOOD_OPT_DB_USER | db_user | PostgreSQL user |
ODOOD_OPT_DB_PASSWORD | db_password | PostgreSQL password |
ODOOD_OPT_ADMIN_PASSWD | admin_passwd | Odoo master password (database manager) |
ODOOD_OPT_WORKERS | workers | Number of worker processes (0 = single-process mode) |
ODOOD_OPT_PROXY_MODE | proxy_mode | Set True when running behind a reverse proxy |
ODOOD_OPT_DBFILTER | dbfilter | Regex to restrict which databases are served |
ODOOD_OPT_LIMIT_MEMORY_HARD | limit_memory_hard | Hard memory limit per worker (bytes) |
ODOOD_OPT_LIMIT_MEMORY_SOFT | limit_memory_soft | Soft memory limit per worker (bytes) |
ODOOD_OPT_LIMIT_TIME_CPU | limit_time_cpu | CPU time limit per request (seconds) |
ODOOD_OPT_LIMIT_TIME_REAL | limit_time_real | Real time limit per request (seconds) |
ODOOD_OPT_LOG_LEVEL | log_level | Log level (info, debug, warning, error) |
Any other valid odoo.conf option can be set the same way — the list above covers the most commonly needed ones in containerised deployments.
For deployment context (not CI), see Docker Compose deployment.
GitHub Actions
The following workflow runs on development branches (18.0-*).
It has three jobs: lint (runs first), then tests and migration-tests in parallel.
name: Tests
on:
push:
branches:
- '18.0-*'
jobs:
lint:
name: Lint & version checks
runs-on: ubuntu-latest
container:
image: ghcr.io/katyukha/odood/odoo/18.0:latest
steps:
- uses: actions/checkout@v4
- name: Add repo as git safe directory
run: git config --global --add safe.directory "$(pwd)"
- name: Link addons
run: odood --config-from-env addons link .
- name: Add dependencies
run: odood --config-from-env addons add --single-branch --odoo-requirements ./odoo_requirements.txt
- name: Check versions
run: odood --config-from-env repo check-versions --ignore-translations
- name: Install pre-commit
run: odood --config-from-env pre-commit set-up
- name: Run pre-commit
run: odood --config-from-env pre-commit run
tests:
name: Tests
runs-on: ubuntu-latest
needs: lint
container:
image: ghcr.io/katyukha/odood/odoo/18.0:latest
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: odoo
POSTGRES_PASSWORD: odoo
POSTGRES_DB: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
ODOOD_OPT_DB_HOST: postgres
ODOOD_OPT_DB_USER: odoo
ODOOD_OPT_DB_PASSWORD: odoo
steps:
- uses: actions/checkout@v4
- name: Add repo as git safe directory
run: git config --global --add safe.directory "$(pwd)"
- name: Link addons
run: odood --config-from-env addons link .
- name: Add dependencies
run: odood --config-from-env addons add --single-branch --odoo-requirements ./odoo_requirements.txt
- name: Run tests
run: odood --config-from-env test -t --dir .
migration-tests:
name: Migration Tests
runs-on: ubuntu-latest
needs: lint
# Migration tests may fail if dependencies introduce incompatible changes
# with an older version of this repo — treated as a soft failure.
continue-on-error: true
container:
image: ghcr.io/katyukha/odood/odoo/18.0:latest
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: odoo
POSTGRES_PASSWORD: odoo
POSTGRES_DB: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
ODOOD_OPT_DB_HOST: postgres
ODOOD_OPT_DB_USER: odoo
ODOOD_OPT_DB_PASSWORD: odoo
steps:
- uses: actions/checkout@v4
- name: Add repo as git safe directory
run: git config --global --add safe.directory "$(pwd)"
- name: Link addons
run: odood --config-from-env addons link .
- name: Add dependencies
run: odood --config-from-env addons add --single-branch --odoo-requirements ./odoo_requirements.txt
- name: Run migration tests
run: odood --config-from-env test -t --migration --dir .
Tip: If your addons have no third-party dependencies, you can omit the “Add dependencies” step and the
odoo_requirements.txtfile.
GitLab CI
The following pipeline mirrors the GitHub Actions structure using GitLab CI’s extends keyword to share the common setup.
image: ghcr.io/katyukha/odood/odoo/18.0:latest
stages:
- lint
- test
# Shared setup: link addons and fetch dependencies.
# Requires odoo_requirements.txt at repo root; remove the second line if not needed.
.setup:
before_script:
- git config --global --add safe.directory "$(pwd)"
- odood --config-from-env addons link .
- odood --config-from-env addons add --single-branch --odoo-requirements ./odoo_requirements.txt
# Shared PostgreSQL sidecar and matching ODOOD_OPT_* variables.
.with-postgres:
services:
- name: postgres:15
alias: postgres
variables:
POSTGRES_USER: odoo
POSTGRES_PASSWORD: odoo
POSTGRES_DB: postgres
ODOOD_OPT_DB_HOST: postgres
ODOOD_OPT_DB_USER: odoo
ODOOD_OPT_DB_PASSWORD: odoo
lint:
extends: .setup
stage: lint
script:
- odood --config-from-env repo check-versions --ignore-translations
- odood --config-from-env pre-commit set-up
- odood --config-from-env pre-commit run
tests:
extends:
- .setup
- .with-postgres
stage: test
script:
- odood --config-from-env test -t --dir .
migration-tests:
extends:
- .setup
- .with-postgres
stage: test
only:
- /^18\.0-.*$/
script:
# Migration tests may fail if dependencies introduce incompatible changes
# with an older version of this repo — treated as a soft failure.
- odood --config-from-env test -t --migration --dir .
allow_failure: true
Note: Adjust the Odoo series (
18.0) in the image tag and theonlyregex to match your project’s series.
Release Management
This page describes the release strategy for addon repositories managed with Odood, covering version conventions, the standard release flow, and the hotfix flow.
Scope: This page applies to addon repositories — git repositories containing one or more Odoo addons, with one stable branch per supported Odoo series. It is not about upgrading Odoo itself (see Upgrading Odoo).
Why repository versions?
When multiple addon repositories depend on each other, there is a natural consistency risk: repo A merges a breaking change, and repo B — which depends on A — has not yet been updated. If assembly sources point to branches, any deploy during that window picks up an inconsistent combination.
Repository versions solve this by giving each repo a pinnable snapshot. An assembly spec can reference a specific release of repo A alongside a specific release of repo B — a combination that was tested together. The typical promotion path then becomes:
- Cut new releases of the relevant repos.
- Update the assembly spec to pin the new versions.
- Sync the assembly and deploy to a staging environment.
- Validate. Promote to production.
Enabling this pinning is the primary reason repository versions exist — a release is first and foremost an immutable, tested snapshot you can reference. On top of that, the version number itself carries meaning: it follows semver-like semantics derived from the aggregate addon changes (see Concepts), so the segment that changed signals whether an upgrade may carry breaking changes.
Code freeze, scoped to a tag
The traditional model — where the stable branch (e.g. 18.0) is always deployable
and every merged PR is production-ready — works well for mature, slow-moving
repositories. For repositories under active development it creates a subtle risk:
the version deployed to a test environment and the version promoted to production
a day or two later may differ, because new commits landed on the branch in between.
The usual remedy is a code freeze — a window during which no new merges are allowed while testing and promotion happen. That stabilises what you test, but at the cost of blocking everyone’s work for the duration.
Repository releases don’t eliminate the freeze — they make it light, and they end it with a tag. The purpose of a freeze is to have one immutable, tested thing to promote, and a tag is exactly that: an immutable snapshot of a single commit. In practice the cycle becomes:
- Active development — feature branches merge into stable as usual.
- Light freeze — in the run-up to a release, stop merging new features into stable. Bug fixes and translation updates are still welcome — that is the only restriction, so it is far less disruptive than a full merge freeze.
- Release — when stable is in good shape, cut a tag. You test and promote that exact tag, so it no longer matters what lands on the branch afterwards.
- Next iteration — held-back feature branches merge and active development resumes.
The freeze still exists, but it shrinks to “no new features for a short while,” scoped to the snapshot the tag captures rather than to the branch as a whole.
Translation batching
With branch-based pinning, translation updates must be kept in sync with ongoing development and merged as they are ready. With release pinning, translations can be batched and merged as a single MR in the days before a planned release, keeping them entirely out of the development cycle until they are needed.
Concepts
Repository version
A repository version is a git tag on the stable branch. The git tag is the sole
source of truth. Tags follow the format A.B.X.Y.Z:
| Segment | Meaning |
|---|---|
A.B | Odoo series (e.g. 18.0) |
X | Major — a breaking change: any addon had a major version bump, or an addon was removed, since the last release |
Y | Minor — any addon had a minor or patch bump, or an addon was added, since the last release |
Z | Patch — only ever set by a deliberate patch release (release --patch or hotfix release), never by auto-detection |
Repository versions follow semver-like semantics over the aggregate of addon changes, so that — when addon authors follow the same convention — a glance at the version segment that changed tells you whether a release carries potentially breaking changes.
Auto-detected releases always end in .0 (e.g. 18.0.1.0.0, 18.0.2.1.0).
A Z > 0 tag is a patch release, produced only by a deliberate patch: either
release --patch (a mainline patch on the latest serie release) or the
hotfix flow (hotfix release, on an older chain).
The bump level is computed automatically by odood repo release from the aggregate
of addon version changes since the last release tag. You can override it with
--major, --minor, or --patch.
Why does a patch-only addon change bump repository
Y, notZ? Because auto-detection never produces aZbump — a routine release, even one that only contains addon patch bumps, always ends in.0. AZ > 0release requires a deliberate patch —release --patch(mainline) or the hotfix flow (hotfix release, on an older chain).
Addon versions
Addon versions (the A.B.X.Y.Z string in each addon’s __manifest__.py) are a
separate concern, managed by each addon’s maintainer independently of the
repository release cycle. The rule is: every change to an addon must increase its
version before the branch is merged to stable. This is enforced by CI on every pull
request — by the time anything lands on the stable branch, addon versions are already
correct.
odood repo release re-verifies this internally as a safety gate, but in normal
practice the gate is always clear by release time.
Addon version bump semantics (when to bump X vs Y vs Z within an addon) are
a separate topic and are not covered here.
Standard Release Flow
Development follows a standard feature-branch model (see Development Workflow for branching strategy, local testing, and CI/CD setup):
- Work happens on branches named after the target series (e.g.
18.0-my-feature). - Each branch is reviewed and merged into the stable series branch (e.g.
18.0). - Releases are decoupled from individual merges — a release is a deliberate decision made when the maintainer considers the stable branch ready to snapshot. Multiple feature PRs, fixes, and translation updates may all land on stable before a single release is cut.
Making a release
When the stable branch is in a state worth pinning:
# Standard release — auto-detects bump level, generates changelog, tags, pushes:
odood repo release --changelog --push
odood repo release will:
- Fetch remote tags to find the latest release (union of local and remote, to handle tags pushed by others not yet fetched locally).
- Verify that every addon changed since the last release tag has a bumped version (safety gate — normally already satisfied by CI).
- Compute the next repository version from the aggregate addon changes
(the most significant change wins):
- Any addon had a major bump, or an addon was removed →
Xincremented,YandZreset to0. - Any addon had a minor or patch bump, or an addon was added →
Yincremented,Zreset to0.
- Any addon had a major bump, or an addon was removed →
- Optionally generate
CHANGELOG.md/CHANGELOG.latest.mdand commit them. - Create a git tag with the new version.
- Push the branch and tag if
--pushis given.
--pushbranch guard: When--pushis supplied for a standard release, the command requires the current branch to match the stable series branch (e.g.18.0). This prevents accidentally tagging from a feature branch. The guard does not apply to--patch, which is a conscious, explicit choice.
Override the auto-detected bump level when needed:
odood repo release --major # force X bump
odood repo release --minor # force Y bump
odood repo release --patch # force Z bump (mainline patch release)
--patchis the mainline patch: a deliberateZbump on top of the latest serie release (e.g. a small fix you want to ship as18.0.2.1.1without a minor bump). It must be requested explicitly — auto-detection never produces aZbump — and, being explicit, carries no branch restriction.To patch an older release while the stable branch has already moved on, use the hotfix flow (
odood repo hotfix) instead — it builds on the right patch chain rather than the latest serie tag.
When nothing changed since the last tag, release exits successfully without
creating a tag. In automation, add --fail-nothing-to-release to exit with
code 1 instead — handy for gating downstream steps that should only run when a
release was actually cut. (hotfix release accepts the same flag.)
First release
For a repository that has never been tagged:
odood repo release --initial
This creates tag <serie>.1.0.0 without inspecting addon changes. The first
non---initial release bootstraps from <serie>.1.0.0 and then applies the
bump, so it lands above <serie>.1.0.0 (e.g. <serie>.1.1.0 for a minor
bump) — never <serie>.1.0.0 itself.
Hotfix Flow
A hotfix is a targeted fix applied to an already-released version, independent of ongoing development on the stable branch.
Hotfix vs. mainline patch. Both bump
Z, but they differ in their base. A mainlinerelease --patchbuilds on the latest serie release — use it for a quick fix on top of the current line. The hotfix flow builds on a specific older patch chain via a dedicated branch — use it when stable has already moved past the release you need to fix.
When to use: A critical bug is found in the deployed version 18.0.2.1.0, but
the stable branch already has several changes that are not ready to ship. You need
to release a fix as 18.0.2.1.1 without including the unreleased work.
Conceptual workflow
stable branch (18.0):
... ── [2.1.0] ──── [ongoing work] ─── [ongoing work] ──→ (not ready)
│
└── hotfix/18.0.2.1.x
│
[fix commit]
│
[2.1.1 tag] ←── hotfix release here
│
cherry-pick back to stable branch
The entire hotfix lifecycle lives under the odood repo hotfix command group
(start → check → release), keeping it separate from mainline releases.
Step-by-step
-
Create a hotfix branch with
odood repo hotfix start:odood repo hotfix start --from=18.0.2.1.0This validates the primary tag, finds the latest existing tag in the
18.0.2.1.*chain (so subsequent patches like18.0.2.1.2are handled correctly), createshotfix/18.0.2.1.xfrom it, and prints next steps.The
--fromargument always takes the primary release (Z == 0), never an intermediate hotfix.startis non-destructive when the branch already exists: it switches to the existing local branch (preserving any work-in-progress), or — if the branch exists only onorigin— checks out a tracking branch from it rather than creating a divergent local one. A fresh branch is created only when none exists locally or remotely. -
Apply the fix. Commit normally; bump affected addon versions.
Optionally preview the check before releasing — run from the hotfix branch:
odood repo hotfix check --ignore-translationsThis compares against the latest tag in the branch’s patch chain — exactly what
hotfix releasewill verify. -
Release the patch — from the hotfix branch:
odood repo hotfix release --changelog --pushhotfix releasederives the chain from the currenthotfix/A.B.X.Y.xbranch, takes the chain’s latest tag as the base, and bumpsZ— producing e.g.18.0.2.1.1. Because the base is the chain (not the latest serie tag), the patch builds on the old release even when stable has moved on. It refuses to run when not on a hotfix branch.
In CI: both
hotfix checkandhotfix releasederive the chain from the branch name, so they must run with thehotfix/A.B.X.Y.xbranch checked out — they cannot work from a detachedHEAD(e.g. a tag-triggered pipeline). Use a branch-triggered job for the hotfix branch.
-
Cherry-pick the fix back to the stable branch:
git checkout 18.0 git cherry-pick <fix-commit-hash>Version conflicts during cherry-pick are expected and mechanical: always keep the stable branch’s (higher) addon version.
-
Do not merge the hotfix branch into stable. Cherry-pick individual fix commits only. The hotfix branch diverged from an old release tag; a merge would bring in stale version history.
Versioning Invariants
| Property | Rule |
|---|---|
| Auto-detected release | Always ends in .0 (e.g. 18.0.2.1.0) |
| Patch release | Only Z changes; X.Y stays equal to the release it builds on (e.g. 18.0.2.1.1) |
| Patch chain | All patches sharing the same A.B.X.Y prefix build on the same X.Y release |
These invariants make it trivial to:
- Tell a patch release from a primary release:
Z > 0means patch (a hotfix, or a deliberate patch on stable);Z == 0means primary. - Find the latest release for a series (including patches): take the max over all
A.B.*tags. - Find all patches for a given primary release: filter tags by
A.B.X.Y.*and sort.
Caveats
A few sharp edges worth knowing:
-
The patch chain is a tag namespace, not a single branch.
release --patchpatches the latest serie release;hotfix releasepatches the chain its branch is based on (getLatestPatchpicks the chain’s highest tag, so it always counts up). When both target the sameA.B.X.Ychain, theirZnumbers interleave across divergent commits — a mainline patch may take18.0.2.1.1, then a hotfix on the same primary becomes18.0.2.1.2on a different commit. Tags never collide, but read the chain as “all patches built on theX.Yrelease”, not as one linear history. -
A mainline release bases on the highest serie tag.
releaseandrelease --patchcompare against — and bump from — the numerically latest serie tag. If you hotfix the latest release (18.0.2.1.0→18.0.2.1.1) and then run a normal release on stable before cherry-picking the fix back, that hotfix tag becomes the base, and the version check may report “current version must be greater than origin” for addons the hotfix bumped. Cherry-picking the fix back to stable first (step 4 of the hotfix flow) resolves this — treat the error as a reminder to back-port.
Pre-release version check
Before releasing, you can preview exactly what odood repo release will verify:
odood repo check-versions --since-last-release --ignore-translations
check-versions chooses its comparison baseline from the flags:
| Command | Compares against | Use for |
|---|---|---|
check-versions | stable branch tip (origin/<serie>) | CI on a PR |
check-versions --since-last-release | the latest release tag for the serie (any chain, including patches) | previewing a standard release |
hotfix check | the latest tag in the current hotfix branch’s patch chain | previewing hotfix release |
To preview a hotfix instead, run odood repo hotfix check from the hotfix
branch — it mirrors what hotfix release will verify (see the
Hotfix flow).
CI setup for addon repositories
Add a version check job to your PR pipeline to catch unbumped addon versions before they reach the stable branch.
GitHub Actions
name: Check addon versions
on:
pull_request:
branches:
- '18.0'
jobs:
check-versions:
runs-on: ubuntu-latest
container:
image: ghcr.io/katyukha/odood/odoo/18.0:latest
steps:
- uses: actions/checkout@v6
- name: Add safe directory
run: git config --global --add safe.directory "$(pwd)"
- name: Check addon versions
run: odood repo check-versions --ignore-translations
GitLab CI
check_addon_versions:
image: ghcr.io/katyukha/odood/odoo/18.0:latest
before_script:
- git config --global --add safe.directory "$(pwd)"
script:
- odood repo check-versions --ignore-translations
only:
- merge_requests
Both examples use the Odood Docker image (which includes a pre-configured Odoo
installation and the odood binary). The check compares the PR branch against
origin/<serie> — the stable branch — and fails if any changed addon has not had
its version bumped.
Translation Management
Overview
Odood automates the full translation workflow for Odoo addons: generating .pot template files,
creating or updating .po translation files, and deduplicating entries.
All translation work is done through a temporary database that Odood creates, uses, and drops automatically.
Prerequisite: The
gettextpackage must be installed on your system (msgmerge,msguniq). On Debian/Ubuntu:sudo apt install gettext.
How Odoo translations work
Each addon stores translations under i18n/:
my_addon/
└── i18n/
├── my_addon.pot ← template: all translatable strings extracted from source
├── uk.po ← Ukrainian translations
├── de.po ← German translations
└── fr.po ← French translations
The .pot file is the source of truth for what needs translating — it is extracted directly
from the addon’s Python, XML, and CSV files by Odoo itself.
The .po files contain the actual translations (msgstr values) for a specific language.
The correct workflow
Initial setup (new addon or new language)
Generate the .pot file and create .po files for the first time:
odood translations regenerate \
--pot \
--pot-remove-dates \
-l uk_UA \
--addon-dir .
This creates i18n/<addon>.pot and i18n/uk.po for every installable addon found under ..
The .po files will have all msgstr values empty — ready to be filled in.
After adding new translatable strings
When source code adds new strings, update existing .po files without overwriting already-translated entries:
odood translations regenerate \
--pot \
--pot-remove-dates \
--pot-update \
--missing-only \
-l uk_UA \
--addon-dir .
--potregenerates the.potfrom the current source.--pot-updatemerges the updated.potinto each.pofile.--missing-onlypreserves existingmsgstrvalues — only new strings get empty entries appended.
Odood automatically runs msguniq before the merge to eliminate duplicate msgid entries that
may have accumulated in the .po file.
Targeting specific addons
Instead of --addon-dir, list addon names explicitly:
odood translations regenerate \
--pot --pot-remove-dates --pot-update --missing-only \
-l uk_UA \
my_addon other_addon
Multiple languages at once
Repeat -l for each language:
odood translations regenerate \
--pot --pot-remove-dates --pot-update --missing-only \
-l uk_UA \
-l de_DE \
-l fr_FR \
--addon-dir .
Custom language code / file name mapping
Some languages use a different file name than the language code prefix (e.g. zh_TW saved as zh_Traditional).
Use --lang-file for explicit control:
odood translations regenerate \
--pot --pot-update --missing-only \
--lang-file zh_TW:zh_Traditional \
--addon-dir .
Flag reference
| Flag | Description |
|---|---|
--pot | Regenerate the .pot template file from the installed addon. |
--pot-update | Merge the .pot into existing .po files with msgmerge. |
--missing-only | Skip .po files that already exist unless --pot-update is also set; preserves existing msgstr values on merge. |
--pot-remove-dates | Strip POT-Creation-Date and PO-Revision-Date headers. Recommended: reduces noise in git diffs. |
-l <lang> | Language code in ll_CC format (e.g. uk_UA). The file is named after the language prefix (uk.po). Repeatable. |
--lang-file <lang:file> | Explicit language:filename mapping (e.g. zh_TW:zh_Traditional). Repeatable. |
--addon-dir <path> | Scan <path> (non-recursively) for installable linked addons. Repeatable. |
--addon-dir-r <path> | Same as --addon-dir but recursive. Repeatable. |
--no-drop-db | Keep the temporary database after the run (useful for debugging). |
What to commit
Commit both .pot and .po files alongside your code changes.
The .pot file acts as a record of what the addon exposes for translation;
keeping it in version control makes it easy to see which strings changed in a given commit.
Using AI assistants for translations
Important for AI-assisted workflows
When using an AI assistant to help fill translations, always follow this order:
- Run
odood translations regeneratefirst to produce the correct.postructure with authoritativemsgidentries extracted from the actual source code. - Then ask the AI to fill only the
msgstrvalues in the generated file.
Never ask an AI to write msgid lines from scratch.
AI assistants frequently produce msgid strings that don’t match the actual source strings,
introduce duplicate entries, or get plural forms wrong — all of which silently corrupt the
translation file and cause Odoo to ignore the affected translations.
Odood partially mitigates this by running msguniq automatically when --missing-only --pot-update
are both set, which deduplicates any repeated msgid entries before merging.
But the safest approach is to never let them appear in the first place.
Correct workflow with an AI assistant:
# 1. Generate the structure
odood translations regenerate \
--pot --pot-remove-dates --pot-update --missing-only \
-l uk_UA \
--addon-dir .
# 2. Open the generated .po file and ask the AI to fill the empty msgstr values.
# The AI reads existing msgid entries from the file — it does not invent them.
Deployment Overview
Odood supports three main deployment patterns, each suited to a different operational context. Choose the pattern that matches your team size, infrastructure, and operational preferences. For all patterns, Assembly is the recommended way to manage third-party addons in production environments.
Patterns at a glance
| Pattern | Typical use | Key tool |
|---|---|---|
| Local development | Developer machine, multiple Odoo versions side by side | odood init |
| Docker Compose | Single-server, small team, easier ops than bare-metal | Prebuilt images + ODOOD_OPT_* |
| VPS / bare-metal | Traditional production, full control, systemd | odood deploy |
How to choose
flowchart TD
A([Where are you deploying?]) --> B{Developer machine?}
B -->|yes| Local[Local Development\nodood init]
B -->|no| C{Do you manage\nthe server directly?}
C -->|no — hosted / managed| DC[Docker Compose\nprebuilt images]
C -->|yes| D{Prefer containers\nover bare-metal?}
D -->|yes| DC
D -->|no| Prod[Production VPS\nodood deploy]
Local development is the fastest way to get Odoo running for day-to-day addon development. It installs everything into a single directory, supports multiple isolated instances on one machine (different ports and database users), and requires no special privileges.
Docker Compose is a good fit when you want a simple, reproducible deployment on a single server without dealing with systemd, nginx configuration, or Python virtualenv setup. The prebuilt Odood images have Odoo pre-installed and can be configured entirely through environment variables. It is not ideal for horizontal scaling — multiple replicas require shared RWX storage for Odoo’s data directory.
VPS / bare-metal gives you full control over the host system: dedicated service accounts, systemd unit files, nginx, logrotate, fail2ban, and Let’s Encrypt integration. This is the traditional approach for production installations where you manage the server directly.
Next steps
Local Development
This page covers everything you need to run one or more Odoo instances on a developer machine using odood init.
Prerequisites
The following system packages are required:
- PostgreSQL — local database server. Install via your package manager (e.g.
sudo apt install postgresql). - Python build dependencies — Odood creates a Python virtualenv for Odoo. Usually the standard
python3,python3-dev, andpython3-venvpackages suffice. - wkhtmltopdf (optional) — required only if you need to generate PDF reports. Download from the wkhtmltopdf releases page and install the
.debthat matches your OS.
Basic installation
Minimal installation of Odoo 18:
odood init -i odoo-18 -v 18
Typical installation with a dedicated database user and HTTP port (recommended when running multiple instances):
odood init -i odoo-18 -v 18 --db-user=odoo18 --http-port=18069
After the command completes, Odoo is installed in the odoo-18 directory. Any subsequent odood command run from inside that directory (or any subdirectory) automatically targets that instance.
Key odood init flags
Version and install type
| Flag | Description |
|---|---|
-v <series> | Odoo series to install (16, 17, 18, 19, …) |
--install-type=archive | Install from the official Odoo source archive (default) |
--install-type=git | Clone from the Odoo git repository (enables odood venv update-odoo) |
Database
| Flag | Description |
|---|---|
--db-user=<user> | PostgreSQL role for this instance (default: odoo). The role must already exist unless --create-db-user is also passed. |
--db-password=<pass> | Password for the PostgreSQL role (default: odoo) |
--db-host=<host> | PostgreSQL host (default: localhost) |
--db-port=<port> | PostgreSQL port (default: 5432) |
--create-db-user | Create the PostgreSQL role automatically. Requires sudo. Not recommended on macOS — PostgreSQL installation methods on macOS vary and the automatic user creation may not work reliably. |
HTTP
| Flag | Description |
|---|---|
--http-port=<port> | Port Odoo listens on (default: 8069) |
--longpolling-port=<port> | Gevent / long-polling port (default: 8072) |
Python and Node
| Flag | Description |
|---|---|
--python=<path> | Path to the Python executable to use for the virtualenv |
--node-version=<ver> | Node.js version to install (for frontend assets) |
--pyenv | Use pyenv to manage the Python version (see macOS section) |
Advanced
| Flag | Description |
|---|---|
--repo=<url> | Git URL of a third-party addon repository to add during init |
--branch=<ref> | Branch/ref for the --repo repository |
Run odood init --help to see the full list of options.
Multiple instances on one machine
Each instance needs a unique combination of:
- Installation directory (
-i) - HTTP port (
--http-port) - Database user (
--db-user)
Example: three active development instances:
odood init -i odoo-16 -v 16 --db-user=odoo16 --http-port=16069
odood init -i odoo-17 -v 17 --db-user=odoo17 --http-port=17069
odood init -i odoo-18 -v 18 --db-user=odoo18 --http-port=18069
Switch between them by changing your working directory:
cd ~/odoo-16 && odood server start
cd ~/odoo-18 && odood server start
Managing the server
From inside the project directory:
odood server start # start Odoo in the background
odood server stop # stop Odoo
odood server restart # restart Odoo
odood server status # check whether Odoo is running
odood server log # view server log (opens in less)
odood server browse # open Odoo in the default browser
odood status # overall status of this instance
Adding third-party repositories
# Add by full git URL
odood repo add https://github.com/crnd-inc/generic-addons
# GitHub shortcut
odood repo add --github crnd-inc/generic-addons
# OCA shortcut (fetches from github.com/OCA/<name>)
odood repo add --oca web
Odood clones the repository into repositories/<owner>/<name>/ and symlinks all installable addons into custom_addons/, making them visible to Odoo automatically.
Updating Odoo
To update Odoo to the latest available version, run:
odood venv update-odoo
This works for both archive and git-based installations.
macOS specifics
On macOS the system Python may be incompatible with some Odoo dependencies. Use the --pyenv flag to let Odood manage Python via pyenv:
odood init -i odoo-18 -v 18 --pyenv
Make sure pyenv is installed and initialised in your shell before running the command.
Migrating from odoo-helper-scripts
If you have existing Odoo instances that were created with odoo-helper-scripts, Odood can import them:
odood discover odoo-helper
Run this command from the root of an odoo-helper-scripts project. Odood will detect the existing configuration and create the odood.yml file that it needs to manage the instance.
Docker Compose Deployment
This page covers deploying Odoo with the prebuilt Odood Docker images using Docker Compose.
Use with care. The Docker Compose pattern is well suited for test environments, CI pipelines, and teams with solid Docker experience. Docker Compose based installations are not battle-tested in production yet. If you need a stable, low-maintenance production setup, prefer Production (VPS) instead.
When to use
Docker Compose is a reasonable choice when:
- You need a test or staging environment that mirrors production without the overhead of bare-metal setup.
- You are running CI pipelines and want a clean, reproducible Odoo stack per run.
- Your team has solid Docker and Docker Compose experience and is comfortable debugging container-level issues.
- You want configuration managed entirely through environment variables.
It is not recommended for production unless your team already operates Docker Compose deployments confidently and understands the operational trade-offs.
It is also not the right choice for horizontal scaling — multiple Odoo replicas need shared RWX storage for /opt/odoo/data.
For traditional bare-metal or VPS production deployments see Production (VPS).
Prerequisites
- Docker Engine (v20.10+)
- Docker Compose v2 (the
docker composeplugin, not the legacydocker-composebinary)
Prebuilt images
The official Odood Docker images are published to the GitHub Container Registry:
ghcr.io/katyukha/odood/odoo/{serie}:latest
Available series: 16.0, 17.0, 18.0, 19.0.
Note: The
--config-from-envflag andODOOD_OPT_*environment variable support are compiled into these images using the-d-version OdoodInDockerbuild flag. They are not available in the Debian package or source builds. See theODOOD_OPT_*reference table in Development Workflow for a full list of supported variables.
HTTP example
The following Compose file runs Odoo 18 with PostgreSQL behind a Traefik reverse proxy over plain HTTP.
It corresponds to the example in examples/docker-compose/odoo-and-db/.
# Odood Docker Compose Example — HTTP
#
# Runs Odoo 18 with PostgreSQL behind a Traefik reverse proxy over plain HTTP.
#
# Usage:
# docker compose up -d
#
# Odoo will be available at http://localhost
# Traefik dashboard at http://localhost:8080 (disable in production)
volumes:
odood-example-db-data:
odood-example-odoo-data:
services:
odood-example-db:
image: postgres:16
container_name: odood-example-db
environment:
# Credentials must match ODOOD_OPT_DB_USER / ODOOD_OPT_DB_PASSWORD below.
POSTGRES_USER: odoo
POSTGRES_PASSWORD: odoo-db-pass
# Prevents PostgreSQL from auto-creating a default database;
# all Odoo databases must be created by Odoo itself.
POSTGRES_DB: postgres
volumes:
- odood-example-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U odoo"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped
odood-example-odoo:
image: ghcr.io/katyukha/odood/odoo/18.0:latest
container_name: odood-example-odoo
labels:
# Route all HTTP traffic to Odoo on port 8069.
- "traefik.enable=true"
- "traefik.http.routers.odoo-route.rule=Host(`localhost`)"
- "traefik.http.routers.odoo-route.service=odoo-service"
- "traefik.http.routers.odoo-route.entrypoints=web"
- "traefik.http.services.odoo-service.loadbalancer.server.port=8069"
# Route /websocket traffic to the Gevent worker on port 8072.
- "traefik.http.routers.odoo-ge-route.rule=Host(`localhost`) && Path(`/websocket`)"
- "traefik.http.routers.odoo-ge-route.service=odoo-ge-service"
- "traefik.http.routers.odoo-ge-route.entrypoints=web"
- "traefik.http.services.odoo-ge-service.loadbalancer.server.port=8072"
depends_on:
odood-example-db:
# Wait until PostgreSQL is healthy before starting Odoo.
condition: service_healthy
environment:
# Database connection — must match POSTGRES_USER/PASSWORD above.
ODOOD_OPT_DB_HOST: odood-example-db
ODOOD_OPT_DB_USER: odoo
ODOOD_OPT_DB_PASSWORD: odoo-db-pass
# Odoo master password used to create/drop databases via the web UI.
ODOOD_OPT_ADMIN_PASSWD: admin
# Number of Odoo worker processes. Increase for higher load.
# Rule of thumb: (CPU cores * 2) + 1, minimum 2.
ODOOD_OPT_WORKERS: "2"
# Required when Odoo runs behind a reverse proxy.
ODOOD_OPT_PROXY_MODE: "True"
volumes:
- odood-example-odoo-data:/opt/odoo/data
restart: unless-stopped
odood-example-traefik:
image: "traefik:v3.2"
container_name: "odood-example-traefik"
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entryPoints.web.address=:80"
ports:
- "80:80"
# Traefik dashboard — remove in production.
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
restart: unless-stopped
HTTPS example
The HTTPS example adds TLS termination at the Traefik layer with automatic HTTP→HTTPS redirect.
It corresponds to examples/docker-compose/odoo-and-db-ssl/.
Before starting, place your certificate and key under ./traefik/certs/ and configure ./traefik/traefik-certs.yml to reference them.
# Odood Docker Compose Example — HTTPS
#
# Runs Odoo 18 with PostgreSQL behind Traefik with TLS termination.
# HTTP (port 80) is automatically redirected to HTTPS (port 443).
volumes:
odood-example-ssl-db-data:
odood-example-ssl-odoo-data:
services:
odood-example-ssl-db:
image: postgres:16
container_name: odood-example-ssl-db
environment:
POSTGRES_USER: odoo
POSTGRES_PASSWORD: odoo-db-pass
POSTGRES_DB: postgres
volumes:
- odood-example-ssl-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U odoo"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped
odood-example-ssl-odoo:
image: ghcr.io/katyukha/odood/odoo/18.0:latest
container_name: odood-example-ssl-odoo
labels:
- "traefik.enable=true"
- "traefik.http.routers.odoo-route.rule=Host(`localhost`)"
- "traefik.http.routers.odoo-route.service=odoo-service"
- "traefik.http.routers.odoo-route.entrypoints=webssl"
- "traefik.http.routers.odoo-route.tls=true"
- "traefik.http.services.odoo-service.loadbalancer.server.port=8069"
- "traefik.http.routers.odoo-ge-route.rule=Host(`localhost`) && Path(`/websocket`)"
- "traefik.http.routers.odoo-ge-route.service=odoo-ge-service"
- "traefik.http.routers.odoo-ge-route.entrypoints=webssl"
- "traefik.http.routers.odoo-ge-route.tls=true"
- "traefik.http.services.odoo-ge-service.loadbalancer.server.port=8072"
depends_on:
odood-example-ssl-db:
condition: service_healthy
environment:
ODOOD_OPT_DB_HOST: odood-example-ssl-db
ODOOD_OPT_DB_USER: odoo
ODOOD_OPT_DB_PASSWORD: odoo-db-pass
ODOOD_OPT_ADMIN_PASSWD: admin
ODOOD_OPT_WORKERS: "2"
ODOOD_OPT_PROXY_MODE: "True"
volumes:
- odood-example-ssl-odoo-data:/opt/odoo/data
restart: unless-stopped
odood-example-ssl-traefik:
image: "traefik:v3.2"
container_name: "odood-example-ssl-traefik"
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.file.filename=/traefik-certs.yml"
- "--entryPoints.web.address=:80"
- "--entryPoints.webssl.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=webssl"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
ports:
- "80:80"
- "443:443"
volumes:
- "./traefik/traefik-certs.yml:/traefik-certs.yml"
- "./traefik/certs/:/certs/"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
restart: unless-stopped
Database initialisation
On first start, Odoo’s web UI presents a database creation form accessible at http://localhost (or https://localhost for the SSL example).
Alternatively, initialise a database from the command line:
docker compose exec odood-example-odoo \
odood --config-from-env db create --demo my-db
To create a database and mark it as initialized (skipping the web setup wizard):
docker compose exec odood-example-odoo \
odood --config-from-env db ensure-initialized --demo my-db
Backup and restore
Back up all databases to /opt/odoo/data/backups/ inside the container:
docker compose exec odood-example-odoo \
odood --config-from-env db backup -a
The backup files are stored in the odood-example-odoo-data volume. Copy them out with docker cp or mount a host path to /opt/odoo/data/backups/.
Restore a specific database from a backup file:
docker compose exec odood-example-odoo \
odood --config-from-env db restore my-db /opt/odoo/data/backups/my-db-backup.zip
Upgrading
Pull the latest images and recreate the containers:
docker compose pull
docker compose up -d
Odoo will restart with the new image.
Note: For assembly-based deployments, use the dedicated workflow in Upgrading assembly-based deployments below — it stops Odoo first, runs the addon update step, and covers recovery.
Using assembly images
When third-party addons are managed with Assembly, the assembly’s addon directory
(dist/) is baked into a custom Docker image at build time — not cloned or mounted at runtime.
Every assembly release becomes a distinct, pinned image that can be rolled back if needed.
Building assembly images
Odood generates the Dockerfile automatically. Add --dockerfile to the assembly sync command
in your CI workflow and it will be created (or updated) on every sync:
odood --config-from-env assembly sync \
--changelog \
--dockerfile \
--commit --push
The generated Dockerfile:
- Copies
odood-assembly.ymlanddist/into/opt/odoo/assembly/ - Runs
odood assembly use /opt/odoo/assemblyto register the assembly inodood.yml - Runs
odood assembly linkto create symlinks incustom_addons/, install Python requirements, and make addons visible to Odoo
Registering the assembly is what makes --assembly work in upgrade commands inside the container.
The image inherits the base image’s CMD, which already includes --wait-pg, so no entrypoint customisation is needed.
See Assembly CI — Full release cycle for complete GitHub Actions workflows covering sync, PR creation, and image publishing.
Image tags and docker-compose.yml
The recommended CI workflow publishes two tags per release derived from the assembly VERSION file
(e.g. 18.0.1.2.3):
- Full version (
18.0.1.2.3) — pinned; use this indocker-compose.yml. - Minor version (
18.0.1.2) — floating; always points to the latest patch of that minor.
Always pin to the full version tag in docker-compose.yml — never :latest.
An explicit tag lets you roll back to the previous image if an upgrade fails.
Pass the image reference as an environment variable so it can be updated at upgrade time
without editing the Compose file directly:
services:
odoo:
image: ${ODOO_IMAGE} # e.g. ghcr.io/my-org/my-assembly:18.0.1.2.3
depends_on:
db:
condition: service_healthy
environment:
ODOOD_OPT_DB_HOST: db
ODOOD_OPT_DB_USER: odoo
ODOOD_OPT_DB_PASSWORD: odoo-db-pass
ODOOD_OPT_ADMIN_PASSWD: admin
ODOOD_OPT_WORKERS: "2"
ODOOD_OPT_PROXY_MODE: "True"
volumes:
- odoo-data:/opt/odoo/data
restart: unless-stopped
Upgrading assembly-based deployments
Running two different versions of addon code against the same database simultaneously risks corruption. Always stop Odoo before running addon updates, even in containerised environments.
Add the following odoo-upgrade service to your docker-compose.yml. It shares the image and
data volume with the main odoo service but only runs on demand via the upgrade profile:
odoo-upgrade:
image: ${ODOO_IMAGE}
profiles: [upgrade]
depends_on:
db:
condition: service_healthy
environment:
ODOOD_OPT_DB_HOST: db # match your DB service name
ODOOD_OPT_DB_USER: odoo
ODOOD_OPT_DB_PASSWORD: odoo-db-pass
command: >
bash -c "
odood --config-from-env db backup -a &&
odood --config-from-env addons update --installed-only --assembly &&
odood --config-from-env addons install --missing-only --assembly
"
volumes:
- odoo-data:/opt/odoo/data
restart: "no"
What each command in the upgrade sequence does:
db backup -a— backs up every database before any changes are made.addons update --installed-only --assembly— updates only addons that are already installed, skipping uninstalled ones (safe and idempotent). Applies to all databases by default. Runs first so that existing dependencies are at their new versions before new addons are installed.addons install --missing-only --assembly— installs assembly addons not yet present in any database (handles newly added modules across releases). Applies to all databases by default.
--assembly works because the generated Dockerfile registers the assembly in odood.yml
via odood assembly use, so the container knows where to find the assembly addons.
Upgrade workflow
# Set the new assembly image version (explicit tag — never :latest)
export ODOO_IMAGE=ghcr.io/my-org/my-assembly:18.0.1.2.3
# 1. Pull the new image
docker compose pull
# 2. Stop Odoo — the DB container keeps running so the upgrade container can connect
docker compose stop odoo
# 3. Backup all databases, update changed addons, install new assembly addons
docker compose --profile upgrade run --rm odoo-upgrade
# 4a. Exit 0 — start Odoo with the new image
docker compose up -d odoo
# 4b. Non-zero — see Recovery below; Odoo remains stopped until you intervene
Recovery
If the upgrade fails, restore every database from its pre-upgrade backup and restart Odoo with the previous image.
# 1. List the backups created before the failed upgrade
docker compose run --rm --no-deps odoo-upgrade \
ls /opt/odoo/data/backups/
# 2. Restore each database from its pre-upgrade backup
# Repeat for every database, replacing the name and timestamp
docker compose run --rm --no-deps odoo-upgrade \
odood --config-from-env db restore mydb \
/opt/odoo/data/backups/mydb-TIMESTAMP.zip
# 3. Roll back to the previous image and start Odoo
export ODOO_IMAGE=ghcr.io/my-org/my-assembly:18.0.1.2.2
docker compose up -d odoo
Important: If
addons updatepartially succeeded before the failure (some modules updated, then a crash), the database is in a mixed state — some modules at the new version, others at the old. Do not attempt to undo partial updates manually. Restore from the pre-upgrade backup; that is the only clean recovery path.
--no-depsstarts the upgrade container without attempting to start its declared dependencies — safe to use in recovery when the DB container is already running.
Health checks and startup ordering
Container health check
The Odood base image already defines a HEALTHCHECK using odood server healthcheck.
This command hits Odoo’s /web/health endpoint (Odoo 14+) or /web/ (older versions) and exits 0 only when Odoo is responding correctly.
No healthcheck: block is needed in your docker-compose.yml — the image provides it.
You can run it manually at any time:
docker compose exec odood-example-odoo \
odood --config-from-env server healthcheck
Waiting for PostgreSQL
The base Odood image’s entrypoint already calls odood server run --wait-pg before starting Odoo,
so the container waits for PostgreSQL to accept connections before launching Odoo.
The depends_on: condition: service_healthy in the examples provides an additional layer — Docker
won’t start the Odoo container at all until PostgreSQL passes its own health check.
If you build a custom entrypoint, use odood server wait-pg explicitly:
odood --config-from-env server wait-pg --timeout 120
odood --config-from-env server run
Scaling caveat
Running multiple Odoo replicas requires that /opt/odoo/data is stored on shared, RWX-capable storage (e.g. NFS or a cloud file share) so that all replicas can read and write session files and filestore. Without this, session state will be inconsistent across replicas.
Production deployment
Overview
Production installation focuses more on security and stability. Thus, it does the following additional tasks:
- Creates separate user to run Odoo
- Creates systemd service or init script to run Odoo at startup
- Optionally configures:
- logrotate
- nginx
- fail2ban
- certbot
Also, production installation expects that it is running on a clean system, and no other Odoo is installed on the same system.
Indirect dependencies
Note, that Odood will not automatically install indirect dependencies, thus you have to manually install following system packages (if needed):
- postgresql - it is required to install postgresql server manually, before running
odood deploycommand if you use--local-postgresoption. - wkhtmltopdf - Required to generate pdf reports. See Odoo docs for more info.
- nginx - if you want to exopose installed Odoo to external world via
nginx. In this case,Odoodwill automatically generate template config fornginx. - certbot - if you want to automatically generate Let’s Encrypt certificates.
- fail2ban [Optional] - if you want to automatically block incorrect logins by IP. In this case Odood will automatically generate configs for
fail2ban.
In case of Ubuntu:24.04 system required dependencies could be installed via command:
sudo apt install postgresql nginx certbot
wget -O /tmp/wkhtmltopdf-0.12.6.1-3.deb https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb
sudo apt install /tmp/wkhtmltopdf-0.12.6.1-3.deb
Note: choose right release for your operation sysmte, when installing wkhtmltopdf
Deployment
So, let’s assume that all needed indirect system dependencises (in example it is only postgresql server) already installed. Then, use following command to install Odoo 18 for production with local postgres:
sudo odood deploy -v 18 --local-postgres --supervisor=systemd
After this command completed, there will be installed Odoo and it will be configured to use local postgresql.
This Odoo instance will be managed by systemd service.
Note: on production installation each call to odood have to be run as sudo or from superuser.
Odood will automatically handle switching access rights when needed.
Also, it is recommended to use assembly functionality to manage third-party addons on production instances. This way, it is possible to deploy server in following way:
sudo odood deploy -v 18 \
--local-postgres \
--supervisor=systemd \
--assembly-repo=https://github.com/my/assembly
This way, server will be automatically configured to use assembly https://github.com/my/assembly
Backup and restore
Backing up databases
Odood stores backups in the backups/ directory of the installation.
# Backup a single database
sudo odood db backup -d mydb
# Backup all databases on this instance
sudo odood db backup -a
It is good practice to back up before any upgrade or configuration change.
Restoring from backup
sudo odood db restore mydb /path/to/odood/backups/mydb-2025-01-15.zip
If the target database already exists, drop it first:
sudo odood db drop mydb
sudo odood db restore mydb /path/to/odood/backups/mydb-2025-01-15.zip
Upgrading
Upgrading with assembly (recommended)
If the server is configured to use Assembly, a single command handles the full upgrade:
sudo odood assembly upgrade --backup
This will automatically:
- Back up all databases
- Pull the latest assembly changes
- Relink addons
- Update all addons in all databases
- Restart the server
Upgrading without assembly
If you manage third-party repositories directly:
# 1. Back up all databases
sudo odood db backup -a
# 2. Update Odoo itself to the latest revision of the current series
sudo odood venv update-odoo
# 3. Pull latest changes from all third-party repositories
sudo odood repo pull-all
# 4. Refresh the addon list and update addons in all databases
sudo odood addons update-list
sudo odood addons update --dir custom_addons
For more details on upgrade scenarios — including local development and cross-series migration — see Upgrading Odoo.
Complete sample: Public server
Following list of commands will install Odoo with configured nginx, postgresql, certbot and fail2ban on server available in public space.
This sample, assumes, that you have control over your domain, and already point your domain to server where Odoo have to be installed.
Note, you have to update command below with your correct architecture.
So, Let ’s run following commands to get complete production ready Odoo installation on Ubuntu 24.04:
sudo apt-get update -yq # update list of packages
sudo apt-get upgrade -yq # upgrade packages
# Install required system dependencies
sudo apt-get install -yq wget nginx postgresql certbot fail2ban
# Download and install latest version of Odood
wget -O /tmp/odood.deb \
"https://github.com/katyukha/Odood/releases/latest/download/odood_$(dpkg --print-architecture).deb"
sudo apt install -yq /tmp/odood.deb
# Download and install correct version of Wkhtmltopdf
wget -O /tmp/wkhtmltopdf-0.12.6.1-3.deb https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb
sudo apt install -yq /tmp/wkhtmltopdf-0.12.6.1-3.deb
# Deploy Odoo 18.0 on the server
sudo odood deploy \
-v 18 \
--local-postgres \
--supervisor=systemd \
--enable-logrotate \
--enable-fail2ban \
--local-nginx-server-name=my.test.server \
--letsencrypt-email=me@my.test.server
Complete sample: Private network server with self-signed SSL certificates
Following list of commands will install Odoo with configured nginx, postgresql, on server in a private network with self-signed SSL certificates under following paths:
- /etc/nginx/ssl/my.test.server.int.crt
- /etc/nginx/ssl/my.test.server.int.key
This sample assumes that you have already generated self-signed certificates.
So, Let ’s run following commands to get complete production ready Odoo installation on Ubuntu 24.04:
sudo apt-get update -yq # update list of packages
sudo apt-get upgrade -yq # upgrade packages
# Install required system dependencies
sudo apt-get install -yq wget nginx postgresql certbot fail2ban
# Download and install latest version of Odood
wget -O /tmp/odood.deb \
"https://github.com/katyukha/Odood/releases/latest/download/odood_$(dpkg --print-architecture).deb"
sudo apt install -yq /tmp/odood.deb
# Download and install correct version of Wkhtmltopdf
wget -O /tmp/wkhtmltopdf-0.12.6.1-3.deb https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb
sudo apt install -yq /tmp/wkhtmltopdf-0.12.6.1-3.deb
# Deploy Odoo 18.0 on the server
sudo odood deploy \
-v 18 \
--local-postgres \
--supervisor=systemd \
--enable-logrotate \
--local-nginx-server-name=my.test.server.int \
--local-nginx-ssl \
--local-nginx-ssl-cert=/etc/nginx/ssl/my.test.server.int.crt \
--local-nginx-ssl-key=/etc/nginx/ssl/my.test.server.int.key
Upgrading Odoo
This page covers how to update Odoo and third-party addons in an existing Odood-managed instance.
Before you upgrade
Always back up your databases before any upgrade or configuration change:
# Back up all databases
odood db backup -a
# Or back up a single database
odood db backup -d mydb
On a production server, prefix with sudo.
Updating Odoo itself (same series)
To update Odoo to the latest available revision of the current series (e.g., 18.0.x → latest 18.0):
odood venv update-odoo
This works for both archive-based and git-based installations. After updating Odoo, restart the server and update your installed addons (see below).
On a production server:
sudo odood venv update-odoo
Updating third-party addons
With assembly (recommended for production)
If the instance is configured to use Assembly, a single command handles everything:
odood assembly upgrade
With an automatic pre-upgrade backup of all databases:
odood assembly upgrade --backup
This pulls the latest assembly, relinks addons, and updates all addons in all databases.
On a production server, prefix with sudo.
Without assembly
If you manage third-party repositories directly, follow this sequence:
# 1. Stop the server
odood server stop
# 2. Pull latest changes from all cloned repositories
odood repo pull-all
# 3. Refresh the addon list
odood addons update-list
# 4. Update addons — list every affected repository with --dir
odood addons update --dir repositories/vendor1/repo1 --dir repositories/vendor2/repo2
# 5. Start the server
odood server start
Why stop the server first? Running old and new code simultaneously during an upgrade can corrupt data or leave modules in an inconsistent state. Stop the server, apply the updates, then restart.
Why use --dir and not the web UI? CLI updates run to completion before any HTTP
request can touch the upgraded models. Web-triggered upgrades can break mid-way if a
model change makes the active session invalid, leaving the database in a broken state.
Updating all repositories at once: if your addons span multiple repositories and
have cross-repo dependencies, pass a --dir flag for each affected repository so Odoo
resolves the dependency graph in a single pass.
Check all databases: if you have multiple databases on this instance, run the update
for every database that has the affected addons installed — not just the primary one.
odood addons update --dir ... updates all databases by default; use -d mydb to
restrict to a specific one if you intentionally want to skip others.
After the server restarts, verify that the web UI is accessible and that Odoo started without errors before calling the upgrade done.
Full local development upgrade flow
A typical update session on a developer machine:
# Pull all repo updates
odood repo pull-all
# Refresh addon list and update all addons in the active database
odood addons update-list
odood addons update --dir custom_addons
# Or update only addons you changed
odood addons update my_addon another_addon
Local development instances don’t need the stop/start ceremony — the server restarts
automatically when you run odood addons update.
Assembly
Assembly is a repository that contains all third-party odoo addons needed for certain server, that is populated with addons from various sources in semi-automatic way.
The main purpose of assembly is to simplify deployment process to production servers.
Assembly contains odood-assembly.yml file (that is also referenced as assembly-spec),
that describes list of addons and list of git sources to populate this assembly with.
All third-party addons will be placed into dist directory inside assembly during sync operation.
After spec is created/updated there is need to run sync operation as next step.
The sync operation updates assembly with latest versions of addons according to the spec definition.
So, after sync is completed, and changes pushed to assembly git repo,
the servers that use this assembly could be updated in single step, by calling command
odood assembly upgrade that will do all the job.
Assembly Spec
Assembly spec is described in odood-assembly.yml file in root directory of assembly.
Assembly spec is YAML file that looks like:
spec:
addons-list:
- name: generic_m2o
- name: generic_mixin
- name: generic_tag
sources-list:
- url: https://github.com/crnd-inc/generic-addons
ref: '18.0'
Following shortcuts available for sources, to make spec more readable:
spec:
addons-list:
- name: generic_mixin
- generic_tag # Addons could be specified by name only.
sources-list:
- github: crnd-inc/generic-addons # converted to https://github.com/crnd-inc/generic-addons
- oca: web # converted to https://github.com/OCA/web
- crnd: mygroup/my-repo # converted to ssh://git@gitlab.crnd.pro/mygroup/my-repo
SSH for local development
The url:, github:, and oca: shortcuts produce HTTPS URLs, which is the right default for
CI environments that use token-based authentication (see Private git sources).
If you prefer SSH on your developer machine — to use your SSH keys and avoid credential prompts —
configure git’s built-in URL rewriting once in your global git config:
git config --global url."git@github.com:".insteadOf "https://github.com/"
git config --global url."git@gitlab.com:".insteadOf "https://gitlab.com/"
This transparently rewrites HTTPS URLs to SSH at the git level whenever Odood runs
git clone or git fetch. The odood-assembly.yml spec stays unchanged, so CI keeps working
with HTTPS while you get SSH locally.
Source naming and addon binding
Sources can be given a name, which serves two purposes:
- it allows addons to be explicitly bound to a specific source via the
sourcefield - it is used as the credential lookup key when the source is private (see Private git sources)
spec:
addons-list:
- name: my_addon
source: my_repo # fetch only from the source named "my_repo"
- name: other_addon # no binding — Odood searches all sources
sources-list:
- url: https://github.com/my/repo
name: my_repo
ref: 18.0
- url: https://github.com/other/repo
ref: 18.0
When source is set on an addon, Odood will only look for that addon in the named source.
This is useful when multiple sources contain a module with the same name.
no-search flag
By default, Odood searches every source for each addon that has no explicit source binding.
Setting no-search: true on a source opts it out of that automatic search — the source is only
used when an addon explicitly references it by name.
spec:
addons-list:
- name: my_addon
source: private_repo # will be fetched; explicit binding bypasses no-search
- name: shared_addon # will NOT be found in private_repo (no-search is set)
sources-list:
- url: https://github.com/public/repo
ref: 18.0
- url: https://github.com/my/private-repo
name: private_repo
ref: 18.0
no-search: true
This is useful for large repositories where you want precise control over which addons are pulled, or for private repositories that should only contribute explicitly listed addons.
Commit pinning
Odood assemblies support commit pinning that could be used for supply-chain hardening.
A source can be pinned to a specific commit using the commit field in source definition.
ref is still required — it is used for an efficient single-branch clone, and commit is checked
out after the fetch.
spec:
addons-list:
- name: my_addon
sources-list:
- url: https://github.com/my/repo
ref: 18.0
commit: a3f9c12bd047 # minimum 12 hex chars
Full 40-character SHAs are accepted as well as abbreviated hashes of at least 12 characters.
commit without ref is not allowed and will be rejected during spec validation.
Odoo Apps addons
Additionally, it is allowed to download addons from Odoo Apps. For example, following spec, will download all addons from Odoo Apps. No git sources provided.
spec:
addons-list:
- name: generic_m2o
odoo_apps: true
- name: generic_mixin
odoo_apps: true
- name: generic_tag
odoo_apps: true
Known addons
The known-addons list tells Odood about addons that are expected to be present on the target
server but are not managed by this assembly (e.g. modules that ship with Odoo itself, or modules
installed through a separate mechanism). These addons are excluded from dependency validation
during sync, so Odood will not report them as missing dependencies.
spec:
addons-list:
- name: my_addon
sources-list:
- url: https://github.com/my/repo
ref: 18.0
known-addons:
- sale
- account
- stock
Assembly layout
The layout field controls where synced addons are placed inside the assembly repository.
Two values are supported:
standard(default) — addons are placed in thedist/subdirectory.flat— addons are placed directly in the root of the assembly repository.
spec:
addons-list:
- name: my_addon
sources-list:
- url: https://github.com/my/repo
ref: 18.0
layout: flat
The flat layout is useful when the assembly repository itself is used directly as an Odoo
addons path without a dist/ indirection.
Assembly workflow
Typical assembly workflow could be split into two parts:
- Assembly maintenance
- Server operations
The first one includes such operations like:
- Initialization of new assembly
- Management of assembly spec, that describes what addons and from what sources have to be included in assembly.
- Assembly synchronization - just pull latest versions of addons defined in spec, and update the assembly repo.
The second one, includes operations to be performed on server side. These operations includes:
- Configure server to use assembly
- Upgrade server
Assembly maintenance
To create assembly, we have to have some Odood instance (may be local development instance), that will be used to maintain assembly. So, let’s assume that we have some Odood instance for Odoo 18, and we need to configure it to use assembly. We can initialize assembly as follows:
odood assembly init
This way, odood will create empty assembly for that project.
The generated assembly config (odood-assembly.yml) could look like:
spec:
addons-list: []
sources-list: []
If we want to add new module my_addon from github.com/my/repo to assembly, then we have to do add following changes in spec (odood-assembly.yml):
- Add name of addon in
addons-listsection ofspec - Add information about source to fetch this addons from in
sources-listsection ofspec
So, in result, our spec could look like:
spec:
addons-list:
- name: my_addon
sources-list:
- url: https://github.com/my/repo
ref: 18.0
As next step, we have to sync the assembly, to make Odood pull latest versions of selected modules from specified sources. We can do it using following command:
odood assembly sync
Upgrading pinned sources
By default the examples above use a branch name as the source ref (e.g. ref: 18.0).
odood assembly sync will always clone or pull from the tip of that branch.
An alternative is to pin each source to a specific version tag:
spec:
addons-list:
- name: my_addon
sources-list:
- url: https://github.com/my/repo
ref: 18.0.1.2.3 # pinned to a release tag
Pinning to a tag makes the assembly fully reproducible — every sync produces the same result — and enables supply-chain hardening with commit pinning. The trade-off is that you must explicitly advance the pin when a new release is available.
odood assembly upgrade-sources automates that step. It queries each source’s remote for the newest version tag matching the project’s Odoo series, updates the spec, and (optionally) commits and pushes:
# Preview what would change (no commit):
odood assembly upgrade-sources
# Update spec, commit and push:
odood assembly upgrade-sources --commit --push
Sources whose ref is a branch name (e.g. 18.0) are silently skipped — they are already always-latest and need no upgrade step.
After running upgrade-sources, follow up with odood assembly sync to pull the new addon versions into the dist/ directory.
After this command, specified addons will be located (updated) in dist folder inside assembly, and ready to commit.
Also, we have to manually add odood-assembly.yml to git index before commit, to make sure spec is committed too.
So, next we have to push assembly to some git repo and then we could use it on servers.
Server operations
Initialize server with assembly
At first, on the server we have to configure it in the way to use already existing assembly (from git repo).
To do this, we have to call command odood assembly init specifying git repository to initialize assembly from.
For example:
odood assembly init --repo <url of git repo with assembly>
As next step, it is good to link assembly, to ensure all addons from assembly is available on the server. To do this, we can use following command
odood assembly link --ual
So, after this steps the server is configured to use assembly.
Update of server assembly
When server is configured to use assembly, then server management becomes pretty simple - all server updates could be done via single command:
odood assembly upgrade [--backup]
That will do all the job: 0. Optionally backup all databases
- pull assembly changes,
- relink modules,
- update addons on all databases.
Docker Compose deployments
When running Odoo in Docker Compose, the assembly is baked into the Docker image at build time rather than cloned on the server. Updates therefore follow a different workflow: build a new image, stop the running container, run addon updates, restart with the new image.
See Docker Compose — Upgrading assembly-based deployments for the full workflow including backup, recovery steps, and the recommended Compose service layout.
Assembly management
There is group of commands designed to deal with assemblies: odood assembly.
Run odood assembly --help to get more info about available commands.
This group contains following commands:
odood assembly init- allows to initalize assembly (new assembly or clone existing assembly from git)odood assembly use- allows to configure server to use assembly from specified path. Useful in CI flows.odood assembly status- show current status of assemblyodood assembly sync- this command synchronizes assembly to actual state. This operation includes following steps done automatically:- Clone or update (pull) all git sources listed in spec
- Remove all addons in
distfolder of assembly - Copy latest versions of addons to
distfolder - Add copied addons to git index of assembly repo
- Optionally commit changes to assembly git repo
- Optionally generate changelog for assembly
odood assembly link- completely relink this assembly (remove all links to assembly fromcustom_addons, and create new links). This is needed to ensure that only actual assembly addons linked.odood assembly pull- pull changes for assembly repo. Useful during server updateodood assembly upgrade- simple way to upgrade server that is configured to use assembly.odood assembly upgrade-sources- scan each source whoserefis a version tag and update the spec to the newest matching tag found on the remote. See Upgrading pinned sources.odood addons update --assembly- this option could be used forodood addons install/update/uninstallcommands to install/update/uninstall addons contained in assembly.
Also, command odood addons find-installed could be used to generate spec for assembly based on third-party addons installed in specified database(s).
This is useful to migrate already existing Odood project to use assembly instead of multiple repositories.
Private git sources
Assemblies can clone private git repositories via access tokens.
For each source in spec, it is possible to specify name or access-group,
that could be used to check environment variables for access credentials to clone specified sources.
For example, if following source defined:
spec:
addons-list:
- name: my_addon
sources-list:
- github: my/private-repo
ref: 18.0
commit: a3f9c12bd047 # optional: pin to a specific commit
access-group: my_repos
Odood will check environment variable ODOOD_ASSEMBLY_my_repos_CRED for access credentials for this repo.
The format for this variable is: user:token
Note, that in case of GitHub Actions, you have to provide access token for private repo in GitHub Actions Secrets. Thus, additionally in CI workflow definition, you have to assign secret to correct environment variable (see docs).
Changelogs and versions
Assemblies support automatic generation of changelogs and update of repository version.
The odood assembly sync command has option --changelog, that enables automatic generation of changelogs for assembly repo.
When this option passed, then Odood will generate and maintain automatically following files in root directory of repo:
VERSION- this file will contain assembly version in format<odoo major>.<odoo minor>.<major>.<minor>.<patch>.CHANGELOG.md- full changelog, that will be updated on each sync automatically.CHANGELOG.latest.md- changelog of latest update.
Note, that recommended flow for update process is to create separate branch for each update, and apply each update with merge request.
Version
Example of VERSION file content:
18.0.1.2.3
This file is updated automatically on each sync (if --changelog option used).
Following rules are applied to generate new repo version:
- Odoo serie (
<odoo major>.<odoo minor>) will be set to project’s Odoo version - If new addon added to assembly, major version part will be increased
- If some addons were deleted, then major version part will be increased
- If some of assembly addons changed major part, then major version part of assembly will be increased.
- If some of assembly addons changed minor part, then minor version part will be increased
- All othe cases will increase patch part of assembly version.
CHANGELOG.md
The changelog file contains information about each update of assembly, that includes:
- Update version
- Update date
- Addons added (name and version of each addon)
- Addons removed (name and version of each addon)
- Addons updated (name, old_version, new_version for each addon)
- Notable changes (if updated addon has list of notable changes for specific versions)
Sample changelog
Below is example of changelog generated by Odood during assembly sync operation:
# Changelog
## Release 18.0.2.0.0 (2025-Dec-23 19:18:33)
### Added addons
- `my_new_addon` (18.0.0.1.0)
### Removed addons
- `my_old_addon` (18.0.0.0.3)
### Updated addons
- `some_addon` (18.0.1.2.1 -> 18.0.1.3.0)
### Notable changes
#### Addon `some_addon`
##### Version 1.3.0
- Some new useful feature added. Now users should be happy.
## Release 18.0.1.0.1 (2025-Dec-20 12:11:38)
### Updated addons
- `some_addon` (18.0.1.2.0 -> 18.0.1.2.1)
Notable changes
The idea for this section is to provide list of changes that could be interesting for end users. For example, it could contain information about some feature implemented or some breaking changes.
This feature expectes that addon developers provide information about notable changes of addon in following way:
- addon must contain directory
changelogthat will store changelogs for this addon - for each version of addon that has notable changes, file
changelog/changelog.X.Y.Z.mdhave to be added (hereX- major version of module,Y- minor version of module,Z- patch version of module; Odoo serie is not taken into account). This file should contain description of notable changes in MarkDown format. - note, there is limitation for only
h6headers inchangelog/changelog.X.Y.Z.mdfiles, because all headers larger thanh6will be used in final assembly changelog.
For example (in context of example above (Sample changelog)), we have to add changelog/changelog.1.3.0.md file inside root directory of module some_addon with following content:
- Some new useful feature added. Now users should be happy.
CHANGELOG.latest.md
This file in same format as CHANGELOG.md, but contains only info from last update.
Sample CI configuration to build/update assemblies automatically
Usually assembiles require CI to update modules automatically or semi-automatically.
Build assembly on GitHub CI
Sample GitHub Actions workflow configuration, that will build assembly automatically:
name: Sync assembly
on:
push:
branches:
- '18.0-*'
workflow_dispatch:
jobs:
sync-assembly:
name: Sync assembly
if: "!contains(github.event.head_commit.message, '[SYNC] Assembly synced')"
runs-on: ubuntu-latest
strategy:
fail-fast: true
permissions:
contents: write
pull-requests: write
container:
image: ghcr.io/katyukha/odood/odoo/18.0:latest
steps:
- uses: actions/checkout@v4
- name: Add current directory as safe directory for git
run: git config --global --add safe.directory "$(pwd)"
- name: Sync assembly
run: |
odood --config-from-env -v -d assembly -p . sync \
--changelog \
--dockerfile \
--commit \
--commit-user='Github Action' \
--commit-email='github-action@odood.dev' \
--push
The --dockerfile flag instructs Odood to generate (or regenerate) a Dockerfile in the assembly
repository root on every sync. This Dockerfile copies the synced dist/ directory into the image
and runs odood addons link — it is what enables building a Docker image from the assembly.
This workflow runs on all branches matching 18.0-*. Usual flow:
- Create a new branch
18.0-update - Wait for the job to complete
- Create a pull request
- Review and merge the pull request
- Delete the
18.0-updatebranch (or configure automatic stale-branch deletion)
Semi-automatic update cycle (recommended)
The workflow above commits directly to the current branch. For a more controlled flow that requires human review before merging, use a separate workflow that creates a PR automatically:
name: Init assembly sync
on: workflow_dispatch
jobs:
init-assembly-sync:
name: Init assembly sync
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
container:
image: ghcr.io/katyukha/odood/odoo/18.0:latest
env:
# Credentials for private repos (if needed):
# ODOOD_ASSEMBLY_myrepo_CRED: "x-access-token:${{ secrets.MY_REPO_PAT }}"
steps:
- uses: actions/checkout@v4
- name: Add current directory as safe directory for git
run: git config --global --add safe.directory "$(pwd)"
- name: Use current repo as assembly
run: odood -v -d --config-from-env assembly use .
- name: Sync assembly
run: |
odood -v -d --config-from-env assembly sync \
--changelog \
--commit \
--commit-user='Github Action' \
--commit-email='github-action@odood.dev' \
--push-to=18.0-assembly-update \
--fail-nothing-to-commit
create-pull-request:
name: Create assembly sync PR
runs-on: ubuntu-latest
needs: init-assembly-sync
permissions:
contents: read
pull-requests: write
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- id: check-pr-exists
run: |
prs=$(gh pr list \
--repo "$GITHUB_REPOSITORY" \
--head '18.0-assembly-update' \
--base '18.0' \
--json title \
--jq 'length')
if ((prs > 0)); then
echo "pr_exists=true" >> "$GITHUB_OUTPUT"
fi
- if: '!steps.check-pr-exists.outputs.pr_exists'
run: |
gh label create auto-update \
--repo "$GITHUB_REPOSITORY" \
--description "Automatic update" \
--force
gh pr create \
--repo "$GITHUB_REPOSITORY" \
--draft \
--title="Automatic assembly update" \
--body="Automatic assembly update" \
-l auto-update \
-B 18.0 -H 18.0-assembly-update
Key flags used in the sync step:
--push-to=18.0-assembly-update— pushes to a dedicated update branch instead of the current one.--fail-nothing-to-commit— exits non-zero if no addons changed, preventing a no-op PR.assembly use .— registers the current directory as the assembly path, needed when the assembly repository and the Odood project share the same repo.
Triggering this workflow creates a draft PR from 18.0-assembly-update into 18.0 (if one does
not already exist). Pushing to 18.0-assembly-update also triggers the Sync assembly workflow
above (it matches 18.0-*), which re-runs with --dockerfile to regenerate the Dockerfile.
Releasing a Docker image
Once the update PR is merged to the stable branch, trigger this workflow manually to tag the release and build a multi-architecture Docker image published to GHCR:
name: Do Release
on: workflow_dispatch
jobs:
set-tag:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Read version
id: version
run: echo "version=v$(cat VERSION)" >> $GITHUB_OUTPUT
- name: Create version tag
uses: actions/github-script@v7
with:
script: |
github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: 'refs/tags/${{ steps.version.outputs.version }}',
sha: context.sha
}).catch(err => {
if (err.status !== 422) throw err;
github.rest.git.updateRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: 'tags/${{ steps.version.outputs.version }}',
sha: context.sha
});
})
build-and-push-docker-image:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
ODOO_SERIE: '18.0'
permissions:
contents: write
packages: write
attestations: write
runs-on: ubuntu-latest
needs: set-tag
steps:
- uses: actions/checkout@v4
- name: Read version
id: version
run: echo "version=v$(cat VERSION)" >> $GITHUB_OUTPUT
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=match,pattern=v(.*),group=1,value=${{ steps.version.outputs.version }}
type=match,pattern=v(\d+\.\d+)\.(.*),group=1,value=${{ steps.version.outputs.version }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
with:
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
The metadata-action step derives two image tags from the assembly VERSION file
(e.g. 18.0.1.2.3):
- Full version (
18.0.1.2.3) — pinned; use this indocker-compose.ymlfor reproducibility and rollback. - Minor version (
18.0.1.2) — floating; always points to the latest patch of that minor version.
Multi-arch builds (linux/amd64,linux/arm64) require QEMU and Docker Buildx.
Remove the platforms line if you only need amd64.
Full release cycle
1. Trigger "Init assembly sync" (workflow_dispatch)
→ syncs addons, commits, pushes to 18.0-assembly-update, opens draft PR
→ "Sync assembly" fires automatically on the new branch, regenerates Dockerfile
2. Review and merge the PR to 18.0
3. Trigger "Do Release" (workflow_dispatch)
→ reads VERSION file, creates git tag, builds and pushes Docker image with version tags
4. Deploy using the upgrade workflow:
→ see Upgrading assembly-based deployments in Docker Compose docs
Private repo notes
In case when private repo have to be added to assembly, following additional steps have to be applied:
- Specify credentials for private repo (usually system user + access token) in GitHub Actions Secrets
- On Sync assembly step, assign variable
ODOOD_ASSEMBLY_accessgroup_CREDvalue in formatuser:passwordthat is fetched from action’s secrets, whereaccessgroupis value specified inaccess-groupornameproperty of corresponding git source
All the rest will be handled by Odood.
For example, in case when private git source is hosted on github, the Sync assembly step may look like:
- name: Sync assembly
env:
ODOOD_ASSEMBLY_myrepo_CRED: "x-access-token:${{ secrets.GH_MY_REPO_PAT }}
run: |
odood --config-from-env -v -d assembly -p . sync \
--changelog \
--commit \
--commit-user='Github Action' \
--commit-email='github-action@odood.dev' \
--push
It is expected, that assembly contains git-source named myrepo or that has access-group equal to myrepo.
Also, it is expected that access-token for this git repo added to GitHub Actions Secrets under name GH_MY_REPO_PAT
Build assembly on GitLab CI
Sample GitLab CI configuration, that will build assembly automatically:
build_assembly_on_commit:
image: ghcr.io/katyukha/odood/odoo/18.0:latest
before_script:
# Add current directory as safe, thus allowing git operations in this dir.
- git config --global --add safe.directory "$(pwd)"
script:
# Create temporary branch to allow push work from Odood
- git checkout -b 18.0-tmp-assembly
# Do assembly sync
- odood --config-from-env assembly -p . sync --commit --commit-user="GitLab Bot" --commit-email="gitlab-bot@odood.dev" --push --push-to "$CI_COMMIT_BRANCH"
except:
variables:
# Do not run package on commits created by packager itself
- $CI_COMMIT_MESSAGE =~ /\[SYNC\] Assembly synced/
refs:
# Do not run job for stable branches
- "18.0"
only:
refs:
- branches
Note, that it is required to allow gitlab-ci-token to push changes back to project. This have to be configured in repository settings (CI/CD Settings -> Job token permissions)
Usually, it is required to create new branch to run build job.
Migrating from odoo-helper-scripts
This page guides existing odoo-helper-scripts users through migrating to Odood.
What stays the same
The project directory layout is identical — backups/, conf/, custom_addons/,
data/, downloads/, odoo/, repositories/, venv/ are all in the same places.
Your existing Odoo installation, databases, and cloned repositories do not need to move.
The only structural change is the project config file:
odoo-helper.conf (Bash variable exports) is replaced by odood.yml (YAML).
Migrating an existing project
Odood can read an existing odoo-helper.conf and generate odood.yml automatically:
# In the root of your existing odoo-helper project
odood discover odoo-helper
# For a system-wide (production) installation managed as root
sudo odood discover odoo-helper --system
This reads odoo-helper.conf, creates odood.yml in the same directory, and sets up the
virtualenv wrapper that Odood needs. Your existing Odoo installation and data are untouched.
Command reference
Most commands map directly. The main differences are:
- Repository management moved under
odood repo - Virtualenv utilities moved under
odood venv - CI / dev tooling moved under
odood repo
Repository management
| odoo-helper-scripts | odood |
|---|---|
odoo-helper fetch --repo URL | odood repo add URL |
odoo-helper fetch --github user/repo | odood repo add --github user/repo |
odoo-helper fetch --oca repo | odood repo add --oca repo |
odoo-helper link . | odood addons link . |
odoo-helper addons update-list | odood addons update-list |
Server management
| odoo-helper-scripts | odood |
|---|---|
odoo-helper server start | odood server start |
odoo-helper server stop | odood server stop |
odoo-helper server restart | odood server restart |
odoo-helper server log | odood server log |
odoo-helper server ps | odood server status |
Addon management
| odoo-helper-scripts | odood |
|---|---|
odoo-helper addons install | odood addons install |
odoo-helper addons update | odood addons update |
odoo-helper addons uninstall | odood addons uninstall |
Database management
| odoo-helper-scripts | odood |
|---|---|
odoo-helper db list / lsd | odood db list |
odoo-helper db create | odood db create |
odoo-helper db drop | odood db drop |
odoo-helper db backup | odood db backup |
odoo-helper db restore | odood db restore |
odoo-helper db copy | odood db copy |
odoo-helper db rename | odood db rename |
Testing
| odoo-helper-scripts | odood |
|---|---|
odoo-helper test -m addon | odood test -m addon |
Translations
| odoo-helper-scripts | odood |
|---|---|
odoo-helper tr regenerate | odood tr regenerate |
Virtualenv / Python utilities
| odoo-helper-scripts | odood |
|---|---|
odoo-helper update-odoo | odood venv update-odoo |
odoo-helper exec CMD | odood venv exec CMD |
odoo-helper pip | odood venv pip |
odoo-helper python | odood venv python |
odoo-helper ipython | odood venv ipython |
CI / dev tooling
| odoo-helper-scripts | odood |
|---|---|
odoo-helper ci check-versions-git | odood repo check-versions |
odoo-helper ci fix-versions | odood repo bump-versions |
odoo-helper ci do-forward-port | odood repo do-forward-port |
odoo-helper ci auto-migrate-modules | odood repo migrate-addons |
odoo-helper repo fix-version-conflict | odood repo fix-version-conflict |
odoo-helper lint pylint / flake8 / style | odood pre-commit run |
When setting up pre-commit on a repository migrated from odoo-helper-scripts, use the
--odoo-helper-compat flag to generate a check-only configuration that matches
odoo-helper’s linting behaviour (no auto-formatting):
odood pre-commit init --odoo-helper-compat
Project info
| odoo-helper-scripts | odood |
|---|---|
odoo-helper status | odood status |
odoo-helper print-config | odood info |
What is not available in Odood
The following odoo-helper-scripts features do not have equivalents in Odood yet:
odoo-helper scaffold— no addon/repo scaffolding command yet
What is new in Odood
- Assembly — the recommended way to manage third-party addons on production servers. Assembly replaces the pattern of cloning multiple repositories directly on each server.
odood deploy— one-command production deployment with systemd, nginx, logrotate, fail2ban, and Let’s Encrypt integration.
Odood Directory Structure
Odood directory structure is similar to that one for odoo-helper-scripts,
so most users of odoo-helper-scripts will not notice that changes.
Odood project root directory contains following folders:
backups- directory for backups generated byodood db backupcommandconf- directory for configurations used by this odood project. Usually contains two files: one for normal local config and one that is used to run testsodoo.conf- main configuration used by defaultodoo.test.conf- configuration used to run tests, usually has a different port thanodoo.conf, and does not specify a logfile, so all log messages are written to stderr and caught by theodoodtest runner
custom_addons- directory for all addons that are not part of Odoo. Contains only symlinks to actual addon directories — see below.data- Odoo data directory used to store files and sessionsdownloads- directory containing addons downloaded directly from Odoo Appsodoo- Odoo source coderepositories- stores git repositories containing additional (non-standard) Odoo addonsvenv- virtualenv directoryodood.yml- configuration for this Odood project
Optional directories:
assembly- if the project is configured to use assembly, this directory contains the assembly repositorycache- various caches; for example, git sources defined in an assembly spec are cloned here and reused for subsequent sync operations
How addon paths work
Odoo locates installable addons through the addons_path setting in odoo.conf.
Odood configures this path to point at custom_addons/, which acts as a flat
namespace of all third-party addons available to Odoo.
custom_addons/ itself contains only symlinks, never actual addon code.
The real addon code lives in repositories/<owner>/<repo>/ (for git repos) or
downloads/ (for addons from Odoo Apps).
When you run odood repo add <url>, Odood:
- Clones the repository into
repositories/<owner>/<repo>/ - Scans it for installable addons (directories with a valid
__manifest__.py) - Creates a symlink in
custom_addons/<addon_name>→ the addon directory
This design keeps the addon namespace flat (Odoo doesn’t need to traverse nested
directories) while keeping the source repos isolated and easy to update with git pull.
If the symlinks ever get out of sync — for example after manually editing a repo or changing which addons it exposes — run:
odood addons link .
This rebuilds all symlinks in custom_addons/ to match the current state of all
repositories.
Frequently used commands
Short list of frequently used Odood commands.
Each command in this list supports -h or --help option, that will
print actual documentation on the command.
Thus, if you want to get most complete and actual documentation on particular command,
just call if with -h option.
Server management
odood start- start odoo serverodood restart- restart odoo serverodood stop- stop odoo serverodood log- see odoo server logsodood browse- open running odoo installation in browserodood server healthcheck- check if the Odoo HTTP server is responding; exits 0 if healthy, 1 if not. Useful as a Docker/K8s health probe.odood server wait-pg- wait for PostgreSQL to become available before proceeding. Useful in container entrypoints when the DB container may not be ready yet.
Addons management
odood addons list <path>- list odoo addons in specified directoryodood addons update-list- update list of available addons in all databases available for this serverodood addons install <addon1> [addonN]- install specified odoo addons for all databases available for this server; use--missing-onlyto skip already-installed onesodood addons update <addon1> [addonN]- update specified odoo addons for all databases available for this server; use--installed-onlyto skip non-installed onesodood addons uninstall <addon1> [addonN]- uninstall specified odoo addons for all databases available for this serverodood addons update --dir <path>- find all installable addons in specified directory and update themodood addons install --dir <path>- find all installable addons in specified directory and install themodood addons link .- link all addons in current directory.odood addons add -h- add third-party addons from odoo-apps (free only) or from odoo-requirements.txt
Both install and update support --ignore-unfinished-updates to proceed even if the database has pending addon state transitions.
Tests
odood test -t <module>- test single module on temporary databaseodood test -t --dir .- test all installable addons in current directoryodood test -t --migration --dir .- run migration tests for all installable addons in current directoryodood test --coverage-html -t <module>- test single module and create html coverage reportodood test --coverage-html --dir .- test all installable addons and create html coverage report
Pre-commit
Odood use pre-commit to run various linters, etc. Thus following commands are used to deal with it:
odood pre-commit init- Initialize pre-commit for repository. Create default pre-commit configurations.odood pre-commit set-up- Install pre-commit and all necessary dependencies in virtualenv.odood pre-commit run- Run pre-commit hooks for this repo manually.
Repository management
odood repo add <url>- fetch repository with third-party addons from git repo specified byurlodood repo add --oca <name>- fetch OCA repository namednamefrom OCA git repo. For example,--oca webmeans repo web from OCA.odood repo add --github <username/repository>- shortcut to easily fetch repo from github, by specifying only github username and repo name. For example:--github oca/webmeans repo web from OCA.odood repo bump-versions- increase versions of changed modules in git repo.odood repo release --initial- create the first release tag (<serie>.1.0.0) for a repository with no prior tags.odood repo release- auto-detect changed addons since the last tag, verify versions are bumped, and create the next release tag.odood repo release --changelog --push- generateCHANGELOG.md, commit it, tag, and push branch + tag to origin.
Database management
odood db list- list all databases available for current odoo instanceodood db create my_db- create databaseodood db backup -d my_db- backup my_dbodood db backup -a- backup all databases on the serverodood db drop my_db- drop databaseodood db restore my_db path/to/backup- restore database from backup
Translation management
odood tr regenerate --lang uk_UA <addon1> [addon2]...- regenerate translations for specified language for specified addonsodood tr regenerate --lang uk_UA --addon-dir <path>- regenerate translations for specified language for all installable addon in specified path
Assembly management
odood assembly init- initialize new empty assembly for this instanceodood assembly init --repo=git@github.com:my/assembly.git- initialize this instance with assembly from specified repoodood assembly upgrade- pull latest changes from assembly and upgrade serverodood assembly sync- synchronize assembly according to spec: fetch latest versions of modules from specified sources and update assembly repoodood assembly upgrade-sources- advance version-tag-pinned sources in the spec to the newest matching tags on their remotes; follow up withassembly syncto applyodood assembly link- relink all addons that are in assembly
Virtualenv management
odood venv run -- <command and args>- Run some command inside virtualenv of this instance.odood venv install-py-packages- Install specified python packages in this virtualenv.odood venv install-dev-tools- Install development tools inside virtualenv of this instance.odood ipython- run ipython inside virtualenv of this instance.odood venv reinstall- resinstall virtual environment.odood venv update-odoo- update Odoo in this instance.
Odood Command Reference
odood
Easily manage odoo installations.
Usage:
odood [options] <command>
Options:
| Flag | Description |
|---|---|
-v, --verbose | Enable verbose output |
-q, --quiet | Hide unnecessary output |
-d, --debug | Show additional debug information. |
-h, --help | Show this help |
--version | Show version |
Shortcuts:
| Name | Expands to | Description |
|---|---|---|
start | server start | Run the server in background. |
stop | server stop | Stop the server. |
restart | server restart | Restart the server. |
browse | server browse | Open odoo in browser. |
log | server log | View server logs. |
lsd | db list | Show databases. |
lsa | addons list | List addons. |
ual | addons update-list | Update list of addons. |
tr | translations | Manage translations. |
Commands:
init— Initialize new odood project.deploy— Deploy production-ready Odoo.server— Server management commands.status— Show the project status.db— Database management commandsaddons— Manage third-party addons.test— Run tests for modules.repo— Manage git repositories.venv— Manage virtual environment for this project.odoo— Odoo-related utility commands.assembly— Manage assembly of this projectscript— Run scripts in Odood environment.psql— Run psql for specified databasepre-commit— Work with pre-commit dev tool.translations— Manage translations for this project.config— Manage config of the projectdiscover— Discover already installed odoo, and configure Odood to manage it.info— Print info about this Odood project.
odood init
Initialize new odood project.
Usage:
odood init [options]
Options:
| Flag | Description |
|---|---|
-i, --install-dir | Directory to install odoo to |
-v, --odoo-version | Version of Odoo to install |
--install-type | Installation type. Accept values: git, archive. Default: archive. |
--odoo-branch | Branch in Odoo repo to install Odoo from. |
--odoo-repo | Install Odoo from specific repository. |
--pyenv | Use python from pyenv to initialize virtualenv for project. Install desired py version if needed |
--py-version | Install specific python version. By default system python used |
--node-version | Install specific node version. |
--db-host | Database host |
--db-port | Database port |
--db-user | Database user |
--db-password | Database password |
--create-db-user | [sudo] Create database user automatically during installation. Requires sudo. |
--http-host | Http host |
--http-port | Http port |
--log-to-stderr | Configure project without a log file (logs to stdout/stderr). Recommended for container deployments. |
-h, --help | Show this help |
odood deploy
Deploy production-ready Odoo.
Usage:
odood deploy [options]
Options:
| Flag | Description |
|---|---|
-v, --odoo-version | Version of Odoo to install |
--py-version | Install specific python version. |
--node-version | Install specific node version. |
--db-host | Database host |
--db-port | Database port |
--db-user | Database user |
--db-password | Database password |
--local-postgres | Configure local postgresql server (requires PostgreSQL installed) |
-w, --workers | Number of workers to apply for this instance. If set to 0, then Odoo will be started in threaded mode. Default: 0 |
--proxy-mode | Enable proxy-mode in odoo config |
--local-nginx | Autoconfigure local nginx (requires nginx installed) |
--local-nginx-server-name | Servername for nginx config. |
--local-nginx-ssl | Enable SSL for local nginx |
--local-nginx-ssl-cert | Path to SSL certificate for local nginx. |
--local-nginx-ssl-key | Path to SSL key for local nginx. |
--tls12-compat | Allow TLS 1.2 in addition to TLS 1.3 for backward compatibility with older clients. By default, only TLS 1.3 is enabled. |
--letsencrypt | Enable Let’s Encrypt configuration. |
--letsencrypt-email | Email for Let’s Encrypt account. |
--enable-logrotate | Enable logrotate for Odoo. |
--enable-fail2ban | Enable fail2ban for Odoo (requires fail2ban installed). |
--supervisor | What supervisor to use for deployment. One of: odood, init-script, systemd. Default: systemd. |
--log-to-stderr | Log to stderr. Useful when running inside docker. |
--use-system-ca-bundle | Set REQUESTS_CA_BUNDLE to the system CA certificate store, so Odoo uses system certificates instead of the bundled certifi CA bundle. |
--assembly-repo | Configure Odood to use assembly from this repo. Ensure, you have access to specified repo from this machine. |
-h, --help | Show this help |
odood server
Server management commands.
Usage:
odood server <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
-
run— Run the server. -
start— Run the server in background. -
status— Check if server is running -
stop— Stop the server -
restart— Restart the server running in background. -
browse— Open odoo in browser -
log— View server logs. -
healthcheck— Check if the Odoo HTTP server is healthy. Exits 0 if healthy, 1 if not. -
wait-pg— Wait for PostgreSQL to become available.
odood server run
Run the server.
Usage:
odood server run [options]
Options:
| Flag | Description |
|---|---|
--ignore-running | Ignore running Odoo instance. (Do not check/create pidfile). |
--wait-pg | Wait for PostgreSQL to be ready before starting the server. |
--wait-pg-timeout | Maximum time to wait for PostgreSQL in seconds. |
-h, --help | Show this help |
odood server start
Run the server in background.
Usage:
odood server start [options]
Options:
| Flag | Description |
|---|---|
-t, --timeout | Timeout to wait while server starts (in seconds). |
-h, --help | Show this help |
odood server status
Check if server is running
Usage:
odood server status
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood server stop
Stop the server
Usage:
odood server stop
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood server restart
Restart the server running in background.
Usage:
odood server restart [options]
Options:
| Flag | Description |
|---|---|
-t, --timeout | Timeout to wait while server starts (in seconds). |
-h, --help | Show this help |
odood server browse
Open odoo in browser
Usage:
odood server browse
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood server log
View server logs.
Usage:
odood server log
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood server healthcheck
Check if the Odoo HTTP server is healthy. Exits 0 if healthy, 1 if not.
Usage:
odood server healthcheck [options]
Options:
| Flag | Description |
|---|---|
-t, --timeout | HTTP request timeout in seconds. |
-h, --help | Show this help |
odood server wait-pg
Wait for PostgreSQL to become available.
Usage:
odood server wait-pg [options]
Options:
| Flag | Description |
|---|---|
-t, --timeout | Maximum time to wait in seconds. |
--interval | Time between connection attempts in seconds. |
-h, --help | Show this help |
odood status
Show the project status.
Usage:
odood status
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood db
Database management commands
Usage:
odood db <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
list— Show the databases available for this odoo instance.create— Create new odoo database.ensure-initialized— Ensure a database exists and is initialized as an Odoo database. Idempotent: safe to use in K8s init containers.drop— Drop the odoo database.exists— Check if database exists.is-initialized— Check if database is initialized as an Odoo database.rename— Rename database.copy— Copy database.backup— Backup database.restore— Restore database.stun— Stun (neutralize) database (disable cron and mail servers).populate— Populate database with test data.
odood db list
Show the databases available for this odoo instance.
Usage:
odood db list
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood db create
Create new odoo database.
Usage:
odood db create [options] <name>
Options:
| Flag | Description |
|---|---|
-d, --demo | Load demo data for this db |
-r, --recreate | Recreate database if it already exists. |
--tdb | Automatically generate default name of test database |
-l, --lang | Language of database, specified as ISO code of language. |
--password | Admin password for this database. |
--country | Country for this db. |
-i, --install | Install module specified by name. |
--install-dir | Install all modules from directory. |
--install-file | Install all modules listed in specified file. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
name | Name of database |
odood db ensure-initialized
Ensure a database exists and is initialized as an Odoo database. Idempotent: safe to use in K8s init containers.
Usage:
odood db ensure-initialized [options] <name>
Options:
| Flag | Description |
|---|---|
--wait-pg | Wait for PostgreSQL to be ready before proceeding. |
--wait-pg-timeout | Maximum time to wait for PostgreSQL in seconds. |
-d, --demo | Load demo data (only on first initialization). |
-l, --lang | Language code, e.g. en_US (only on first initialization). |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
name | Name of database. |
odood db drop
Drop the odoo database.
Usage:
odood db drop <name>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
name | Name of database(s) to drop. |
odood db exists
Check if database exists.
Usage:
odood db exists [options] <name>
Options:
| Flag | Description |
|---|---|
-q, --quiet | Suppress output, just return exit code |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
name | Name of database |
odood db is-initialized
Check if database is initialized as an Odoo database.
Usage:
odood db is-initialized [options] <name>
Options:
| Flag | Description |
|---|---|
-q, --quiet | Suppress output, just return exit code. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
name | Name of database. |
odood db rename
Rename database.
Usage:
odood db rename <old-name> <new-name>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
old-name | Name of original database. |
new-name | New name of database. |
odood db copy
Copy database.
Usage:
odood db copy <old-name> <new-name>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
old-name | Name of original database. |
new-name | New name of database. |
odood db backup
Backup database.
Usage:
odood db backup [options] <name>
Options:
| Flag | Description |
|---|---|
--zip | Make ZIP backup with filestore. |
--sql | Make SQL-only backup without filestore |
-a, --all | Backup all databases |
-d, --dest | Destination path for backup. By default will store at project’s backup directory. |
--nice | Lower the CPU priority of the backup by the given nice increment (1-19, higher = lower priority). |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
name | Name of database(s) to backup. |
odood db restore
Restore database.
Usage:
odood db restore [options] <name> <backup>
Options:
| Flag | Description |
|---|---|
--stun | Stun database (disable cron and mail servers) |
--selfish | Stop the server while database being restored. |
-f, --force | Enforce restore, even if backup is not valid. |
-r, --recreate | Recreate database if it already exists. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
name | Name of database to restore. |
backup | Path to backup (or name of backup) to restore database from. |
odood db stun
Stun (neutralize) database (disable cron and mail servers).
Usage:
odood db stun <name>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
name | Name of database to stun. |
odood db populate
Populate database with test data.
Usage:
odood db populate [options]
Options:
| Flag | Description |
|---|---|
-d, --dbname | Name of database to populate. |
-m, --model | Name of model to populate. Could be specified multiple times. |
-s, --size | Population size |
--repeat | Repeat population N times. |
-h, --help | Show this help |
odood addons
Manage third-party addons.
Usage:
odood addons <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
link— Link addons in specified directory.update-list— Update list of addons.list— List addons in specified directory.update— Update specified addons.install— Install specified addons.uninstall— Uninstall specified addons.add— Add addons to the projectis-installed— Print list of databases where specified addon is installed.generate-py-requirements— Generate python’s requirements.txt from addon’s manifests. By default, it prints requirements to stdout.find-installed— List addons installed in specified databases
odood addons link
Link addons in specified directory.
Usage:
odood addons link [options] <path>
Options:
| Flag | Description |
|---|---|
-f, --force | Rewrite already linked/existing addon. |
-r, --recursive | Search for addons in this directory recursively. |
--manifest-requirements | Install python dependencies from manifest’s external dependencies |
--individual-requirements | Install Python requirements per-addon instead of batched |
--with-odoo-requirements | Include Odoo’s requirements.txt in the batch install |
--ual | Update addons list for all databases |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to search for addons in. |
odood addons update-list
Update list of addons.
Usage:
odood addons update-list [options] <database>
Options:
| Flag | Description |
|---|---|
-a, --all | Update all databases. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
database | Database(s) to update addons list for. |
odood addons list
List addons in specified directory.
Usage:
odood addons list [options] <path>
Options:
| Flag | Description |
|---|---|
--by-path | Display addons by paths. |
--by-name | Display addons by name (default). |
--by-name-version | Display addon name with addon version |
-s, --system | Search for all addons available for Odoo. |
-r, --recursive | Search for addons recursively. |
--installable | Filter only installable addons. |
--not-installable | Filter only not-installable addons. |
--linked | Filter only linked addons. |
--not-linked | Filter only addons that are not linked. |
--with-price | Filter only addons that has price defined. |
--without-price | Filter only addons that does not have price defined. |
--assembly | Show addons available in assembly |
-t, --table | Display list of addons as table |
-f, --field | Display provided field in table. This have to be valid field from manifest. |
-c, --color | Color output by selected scheme: link - color addons by link status, installable - color addons by installable state. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to search for addons in. |
odood addons update
Update specified addons.
Usage:
odood addons update [options] <addon>
Options:
| Flag | Description |
|---|---|
-d, --db | Database(s) to apply operation to. |
--dir | Directory to search for addons |
--dir-r | Directory to recursively search for addons |
-f, --file | Read addons names from file (addon names must be separated by new lines) |
--assembly | Search for addons available in assembly |
--skip | Skip addon specified by name. |
--skip-re | Skip addon specified by regex. |
--skip-file | Skip addons listed in specified file (addon names must be separated by new lines) |
--skip-errors | Do not fail on errors during installation. |
--ignore-unfinished-updates | Do not fail if there are unfinished addon install/update/uninstall operations. |
--start | Start server after update (if everything is ok) |
--ual | Update addons list before update. |
-a, --all | Update all modules |
--installed-only | Skip addons that are not installed in the database. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
addon | Names of addons to operate on. |
odood addons install
Install specified addons.
Usage:
odood addons install [options] <addon>
Options:
| Flag | Description |
|---|---|
-d, --db | Database(s) to apply operation to. |
--dir | Directory to search for addons |
--dir-r | Directory to recursively search for addons |
-f, --file | Read addons names from file (addon names must be separated by new lines) |
--assembly | Search for addons available in assembly |
--skip | Skip addon specified by name. |
--skip-re | Skip addon specified by regex. |
--skip-file | Skip addons listed in specified file (addon names must be separated by new lines) |
--skip-errors | Do not fail on errors during installation. |
--ignore-unfinished-updates | Do not fail if there are unfinished addon install/update/uninstall operations. |
--start | Start server after update (if everything is ok) |
--ual | Update addons list before install. |
--missing-only | Skip addons that are already installed in the database. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
addon | Names of addons to operate on. |
odood addons uninstall
Uninstall specified addons.
Usage:
odood addons uninstall [options] <addon>
Options:
| Flag | Description |
|---|---|
-d, --db | Database(s) to apply operation to. |
--dir | Directory to search for addons |
--dir-r | Directory to recursively search for addons |
-f, --file | Read addons names from file (addon names must be separated by new lines) |
--assembly | Search for addons available in assembly |
--skip | Skip addon specified by name. |
--skip-re | Skip addon specified by regex. |
--skip-file | Skip addons listed in specified file (addon names must be separated by new lines) |
--skip-errors | Do not fail on errors during installation. |
--ignore-unfinished-updates | Do not fail if there are unfinished addon install/update/uninstall operations. |
--start | Start server after update (if everything is ok) |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
addon | Names of addons to operate on. |
odood addons add
Add addons to the project
Usage:
odood addons add [options]
Options:
| Flag | Description |
|---|---|
--single-branch | Clone repository with –single-branch options. This could significantly reduce size of data to be downloaded and increase performance. |
-r, --recursive | Recursively process odoo_requirements.txt. If set, then Odood will automatically process odoo_requirements.txt file inside repositories mentioned in provided odoo_requirements.txt |
--manifest-requirements | Install python dependencies from manifest’s external dependencies |
--odoo-apps | Add addon from odoo apps. |
--odoo-requirements | Add modules (repos) from odoo_requirements.txt file (or directory containing odoo_requirements.txt), that is used by odoo-helper-scripts. |
-h, --help | Show this help |
odood addons is-installed
Print list of databases where specified addon is installed.
Usage:
odood addons is-installed <addon>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
addon | Name of addon or path to addon to check. |
odood addons generate-py-requirements
Generate python’s requirements.txt from addon’s manifests. By default, it prints requirements to stdout.
Usage:
odood addons generate-py-requirements [options] <addon>
Options:
| Flag | Description |
|---|---|
-o, --out-file | Path to file where to store generated requirements |
--dir | Directory to search for addons to generate requirements.txt for. |
--dir-r | Directory to recursively search for addons to generate requirements.txt for. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
addon | Name of addon to generate requirements for. |
odood addons find-installed
List addons installed in specified databases
Usage:
odood addons find-installed [options]
Options:
| Flag | Description |
|---|---|
-d, --db | Name of database to check for addons. |
-o, --out-file | Path to file where to store result |
-f, --format | Output format. One of: list, assembly-spec. Default: list. |
-a, --all | Check all databases |
--non-system | List only custom addons, that are not default Odoo addons. |
-h, --help | Show this help |
odood test
Run tests for modules.
Usage:
odood test [options] <addon>
Options:
| Flag | Description |
|---|---|
-t, --temp-db | Create temporary database for tests. |
--no-drop-db | Do not drop temporary database after test completed. |
--isw | Ignore warnings that are considered safe. |
--simplified-log | Display simplified log messages. |
--migration | Run migration against stable branch. |
--coverage | Calculate code coverage. |
--coverage-report | Print coverage report. |
--coverage-html | Prepare HTML report for coverage. |
--coverage-skip-covered | Skip covered files in coverage report. |
--coverage-ignore-errors | Ignore coverage errors. |
--coverage-fail-under | Fail if coverage is less than specified value. |
--no-error-report | Do not print error report in the end of the test. |
--error-report | Print error report in the end of the test. |
--warning-report | Print warning report in the end of the test. |
-d, --db | Database to run tests for. |
--additional-addon | Specify additional addon to install before test. |
--no-install-addons | Do not install addons before test. Could be useful to speed up local tests. |
--dir | Directory to search for addons to test |
--dir-r | Directory to recursively search for addons to test |
-f, --file | Read addons names from file (addon names must be separated by new lines) |
--skip | Skip (do not run tests) addon specified by name. |
--skip-re | Skip (do not run tests) addon specified by regex. |
--skip-file | Skip addons listed in specified file (addon names must be separated by new lines) |
--migration-start-ref | git reference (branch/commit/tag) to start migration from |
--migration-repo | run migration tests for repo specified by path |
--migration-last-release | Start migration test from the latest release tag. Fails if no release tags exist for the current Odoo serie. |
--populate-model | Name of model to populate. Could be specified multiple times. |
--populate-size | Population size. |
--test-tag | Filter tests by tag (Odoo 12.0+). Repeatable. Supports Odoo tag syntax: plain tags, /module, /module:Class.method, -tag to exclude. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
addon | Names of addons to run tests for. |
odood repo
Manage git repositories.
Usage:
odood repo <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
add— Add git repository to Odood project.pull-all— [Experimental] Pull changes from all repos and relink addons.fix-version-conflict— Fix version conflicts in manifests of addons in this repo.fix-series— Fix series in manifests of addons in this repo. Set series to project’s seriebump-versions— Bump versions for modules that have changes (comparably to stable branch).check-versions— Check changed addons has updated versions.migrate-addons— Migrate code of addons that has older odoo serie to serie of this project.do-forward-port— [Experimental] Do forwardport changes from older branch.release— Release addon repository: auto-version, tag, and optionally push.hotfix— Manage hotfix (patch) releases on dedicated hotfix branches.
odood repo add
Add git repository to Odood project.
Usage:
odood repo add [options] <repo>
Options:
| Flag | Description |
|---|---|
--oca | Add Odoo Community Association (OCA) repository. If set, then ‘repo’ argument could be specified as name of repo under ‘https://github.com/OCA’ organization. |
--github | Add github repository. If set, then ‘repo’ argument could be specified as ‘owner/name’ that will be converted to ‘https://github.com/owner/name’. |
--single-branch | Clone repository with –single-branch options. This could significantly reduce size of data to be downloaded and increase performance. |
-r, --recursive | If set, then system will automatically fetch recursively dependencies of this repository, specified in odoo_requirements.txt file inside cloned repo. |
-b, --branch | Branch to clone |
--ual | Update addons list. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
repo | Repository URL to clone from. |
odood repo pull-all
[Experimental] Pull changes from all repos and relink addons.
Usage:
odood repo pull-all
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood repo fix-version-conflict
Fix version conflicts in manifests of addons in this repo.
Usage:
odood repo fix-version-conflict <path>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to fix conflicts in. |
odood repo fix-series
Fix series in manifests of addons in this repo. Set series to project’s serie
Usage:
odood repo fix-series <path>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to fix conflicts in. |
odood repo bump-versions
Bump versions for modules that have changes (comparably to stable branch).
Usage:
odood repo bump-versions [options] <path>
Options:
| Flag | Description |
|---|---|
--major | Increase major version for addons. |
--minor | Increase minor version for addons. |
--patch | Increase patch version for addons. |
--ignore-translations | Ignore translations. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to search for addons to bump versions. |
odood repo check-versions
Check changed addons has updated versions.
Usage:
odood repo check-versions [options] <path>
Options:
| Flag | Description |
|---|---|
--ignore-translations | Ignore translations. |
--since-last-release | Compare against the latest release tag instead of the stable branch tip. Shows exactly what ‘odood repo release’ will verify. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to search for addons to bump versions. |
odood repo migrate-addons
Migrate code of addons that has older odoo serie to serie of this project.
Usage:
odood repo migrate-addons [options] <path>
Options:
| Flag | Description |
|---|---|
-m, --module | Name of module to migrate |
--commit | Commit changes. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to migrate addons in. |
odood repo do-forward-port
[Experimental] Do forwardport changes from older branch.
Usage:
odood repo do-forward-port [options] <path>
Options:
| Flag | Description |
|---|---|
-s, --source | Source branch to forwardport changes from |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to migrate addons in. |
odood repo release
Release addon repository: auto-version, tag, and optionally push.
Usage:
odood repo release [options] <path>
Options:
| Flag | Description |
|---|---|
--initial | Create the first release for a repository with no prior tags at version |
--major | Force a major version bump. |
--minor | Force a minor version bump. |
--patch | Force a patch version bump. |
--ignore-translations | Ignore translation files (.po/.pot) when detecting changes. |
--fail-nothing-to-release | Exit with code 1 when no changed addons are detected. |
--push | Push the release tag (and branch) to origin. |
--changelog | Generate CHANGELOG.md and CHANGELOG.latest.md and commit them before tagging. |
--commit-message | Commit message for the changelog commit (default: ‘Release |
--commit-user | Git author name for the changelog commit. |
--commit-email | Git author email for the changelog commit. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to release (default: current directory). |
odood repo hotfix
Manage hotfix (patch) releases on dedicated hotfix branches.
Usage:
odood repo hotfix <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
start— Set up a hotfix branch from a primary release tag. Run this before ‘odood repo hotfix release’.check— Check addon versions on the current hotfix branch against the latest tag in its patch chain. Previews what ‘odood repo hotfix release’ will verify.release— Release a hotfix (patch) on the current hotfix branch: bump Z on top of the chain’s latest tag, tag, and optionally push.
odood repo hotfix start
Set up a hotfix branch from a primary release tag. Run this before ‘odood repo hotfix release’.
Usage:
odood repo hotfix start [options] <path>
Options:
| Flag | Description |
|---|---|
--from | Primary release tag to patch (e.g. 18.0.2.1.0). Must have Z == 0. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository (default: current directory). |
odood repo hotfix check
Check addon versions on the current hotfix branch against the latest tag in its patch chain. Previews what ‘odood repo hotfix release’ will verify.
Usage:
odood repo hotfix check [options] <path>
Options:
| Flag | Description |
|---|---|
--ignore-translations | Ignore translation files (.po/.pot) when detecting changes. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository (default: current directory). |
odood repo hotfix release
Release a hotfix (patch) on the current hotfix branch: bump Z on top of the chain’s latest tag, tag, and optionally push.
Usage:
odood repo hotfix release [options] <path>
Options:
| Flag | Description |
|---|---|
--ignore-translations | Ignore translation files (.po/.pot) when detecting changes. |
--fail-nothing-to-release | Exit with code 1 when no changed addons are detected. |
--push | Push the release tag (and branch) to origin. |
--changelog | Generate CHANGELOG.md and CHANGELOG.latest.md and commit them before tagging. |
--commit-message | Commit message for the changelog commit (default: ‘Release |
--commit-user | Git author name for the changelog commit. |
--commit-email | Git author email for the changelog commit. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository (default: current directory). |
odood venv
Manage virtual environment for this project.
Usage:
odood venv <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
install-dev-tools— Install Dev Toolsinstall-py-packages— Install Python packagesreinstall— Reinstall virtualenv.update-odoo— Update Odoo itself.reinstall-odoo— Reinstall Odoo to different Odoo version.pip— Run pip for this environment. All arguments after ‘–’ will be forwarded directly to pip.npm— Run npm for this environment. All arguments after ‘–’ will be forwarded directly to npm.ipython— Run ipython in this environment. All arguments after ‘–’ will be forwarded directly to IPython.python— Run python for this environment. All arguments after ‘–’ will be forwarded directly to python.lodoo— Run lodoo in this environment. All arguments after ‘–’ will be forwarded directly to lodoo.run— Run command in this virtual environment. The command and all arguments must be specified after ‘–’. For example: ‘odood venv run – ipython’
odood venv install-dev-tools
Install Dev Tools
Usage:
odood venv install-dev-tools
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood venv install-py-packages
Install Python packages
Usage:
odood venv install-py-packages [options] <package>
Options:
| Flag | Description |
|---|---|
-r, --requirements | Path to requirements.txt to install python packages from |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
package | Python package specification to install. |
odood venv reinstall
Reinstall virtualenv.
Usage:
odood venv reinstall [options]
Options:
| Flag | Description |
|---|---|
--py-version | Install specific python version. |
--node-version | Install specific node version. |
-h, --help | Show this help |
odood venv update-odoo
Update Odoo itself.
Usage:
odood venv update-odoo [options]
Options:
| Flag | Description |
|---|---|
-b, --backup | Backup Odoo before update. |
-h, --help | Show this help |
odood venv reinstall-odoo
Reinstall Odoo to different Odoo version.
Usage:
odood venv reinstall-odoo [options]
Options:
| Flag | Description |
|---|---|
-b, --backup | Backup Odoo before update. |
--no-backup | Do not take backup of Odoo and venv. |
--venv-py-version | Install specific python version. |
--venv-node-version | Install specific node version. |
--install-type | Installation type. Accept values: git, archive. Default: archive. |
-v, --version | Odoo version to install. |
-h, --help | Show this help |
odood venv pip
Run pip for this environment. All arguments after ‘–’ will be forwarded directly to pip.
Usage:
odood venv pip
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood venv npm
Run npm for this environment. All arguments after ‘–’ will be forwarded directly to npm.
Usage:
odood venv npm
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood venv ipython
Run ipython in this environment. All arguments after ‘–’ will be forwarded directly to IPython.
Usage:
odood venv ipython
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood venv python
Run python for this environment. All arguments after ‘–’ will be forwarded directly to python.
Usage:
odood venv python
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood venv lodoo
Run lodoo in this environment. All arguments after ‘–’ will be forwarded directly to lodoo.
Usage:
odood venv lodoo
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood venv run
Run command in this virtual environment. The command and all arguments must be specified after ‘–’. For example: ‘odood venv run – ipython’
Usage:
odood venv run
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood odoo
Odoo-related utility commands.
Usage:
odood odoo <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
odood odoo shell
Run an interactive Odoo shell.
Usage:
odood odoo shell [options]
Options:
| Flag | Description |
|---|---|
-d, --db | Database to run shell for. |
-h, --help | Show this help |
odood odoo recompute
Recompute stored fields for a model.
Usage:
odood odoo recompute [options]
Options:
| Flag | Description |
|---|---|
-f, --field | Name of field to recompute. |
-d, --db | Name of database to recompute fields for. |
--all-db | Recompute for all databases. |
-m, --model | Name of model to recompute fields for |
-h, --help | Show this help |
odood assembly
Manage assembly of this project
Usage:
odood assembly [options] <command>
Options:
| Flag | Description |
|---|---|
-p, --assembly-path | Path to assembly directory. |
-h, --help | Show this help |
Commands:
init— Initialize assembly for this projectuse— Use (attach) assembly located at specified path. Mostly useful in CI flows.status— Project assembly statussync— Synchronize assembly with updates from sources.link— Link addons from this assembly to custom addonspull— Pull updates for this assembly.upgrade— Upgrade assembly (optionally do backup, pull changes, update addons).upgrade-sources— Upgrade assembly source refs to the latest version tags on their remotes.
odood assembly init
Initialize assembly for this project
Usage:
odood assembly init [options]
Options:
| Flag | Description |
|---|---|
--repo | Url to git repo with assembly to use for this project. |
-h, --help | Show this help |
odood assembly use
Use (attach) assembly located at specified path. Mostly useful in CI flows.
Usage:
odood assembly use <path>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to already existing assembly. |
odood assembly status
Project assembly status
Usage:
odood assembly status
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood assembly sync
Synchronize assembly with updates from sources.
Usage:
odood assembly sync [options]
Options:
| Flag | Description |
|---|---|
--commit | Commit changes. |
--commit-message | Commit message |
--commit-user | Name of user to use for commit |
--commit-email | Email of user to use for commit |
--fail-nothing-to-commit | Fail (set exit code = 1) if there is nothing to commit |
--push | Automatically push changes if needed. |
--push-to | Name of branch to push changes to. |
--changelog | Generate changelog for assembly. |
--dockerfile | Generate Dockerfile for assembly. |
--generate-lock | Generate requirements.lock.txt after syncing |
--with-odoo-requirements | Include Odoo’s requirements.txt when generating lock file |
-h, --help | Show this help |
odood assembly link
Link addons from this assembly to custom addons
Usage:
odood assembly link [options]
Options:
| Flag | Description |
|---|---|
--manifest-requirements | Install python dependencies from manifest’s external dependencies |
--individual-requirements | Install Python requirements per-addon instead of batched |
--with-odoo-requirements | Include Odoo’s requirements.txt in the batch install |
--ual | Update addons list for all databases |
-h, --help | Show this help |
odood assembly pull
Pull updates for this assembly.
Usage:
odood assembly pull [options]
Options:
| Flag | Description |
|---|---|
--link | Relink addons in this assembly after pull |
-h, --help | Show this help |
odood assembly upgrade
Upgrade assembly (optionally do backup, pull changes, update addons).
Usage:
odood assembly upgrade [options]
Options:
| Flag | Description |
|---|---|
--backup | Do backup of all databases |
--skip-errors | Continue upgrade next databases if upgrade of db had error. |
--start | Start the server if upgrade completed successfully and server was not running before upgrade. |
-h, --help | Show this help |
odood assembly upgrade-sources
Upgrade assembly source refs to the latest version tags on their remotes.
Usage:
odood assembly upgrade-sources [options]
Options:
| Flag | Description |
|---|---|
--commit | Commit the updated spec. |
--commit-message | Commit message. |
--commit-user | Name of user to use for commit. |
--commit-email | Email of user to use for commit. |
--push | Push changes after committing. |
--push-to | Name of branch to push changes to. |
-h, --help | Show this help |
odood script
Run scripts in Odood environment.
Usage:
odood script <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
odood script py
Run Python script in this environment.
Usage:
odood script py [options] <script>
Options:
| Flag | Description |
|---|---|
-d, --db | Database to run script for |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
script | Path to script to run |
odood script sql
Run SQL script in this environment.
Usage:
odood script sql [options] <script>
Options:
| Flag | Description |
|---|---|
-d, --db | Database to run script for |
-n, --no-commit | Do not commit changes. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
script | Path to script to run |
odood psql
Run psql for specified database
Usage:
odood psql [options]
Options:
| Flag | Description |
|---|---|
-d, --db | Name of database to connect to. |
-h, --help | Show this help |
odood pre-commit
Work with pre-commit dev tool.
Usage:
odood pre-commit <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
init— Initialize pre-commit for this repo.set-up— Set up pre-commit for specified repo.update— Update pre-commit for specified repo.run— Run pre-commit for specified repo.
odood pre-commit init
Initialize pre-commit for this repo.
Usage:
odood pre-commit init [options] <path>
Options:
| Flag | Description |
|---|---|
-f, --force | Enforce initialization. This will rewrite pre-commit configurations. |
--no-setup | Do not set up pre-commit. Could be used if pre-commit already set up. |
--odoo-helper-compat | Generate pre-commit config compatible with odoo-helper linting style (check-only, no auto-formatting). |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to initialize pre-commit. |
odood pre-commit set-up
Set up pre-commit for specified repo.
Usage:
odood pre-commit set-up <path>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to configure. |
odood pre-commit update
Update pre-commit for specified repo.
Usage:
odood pre-commit update <path>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to configure. |
odood pre-commit run
Run pre-commit for specified repo.
Usage:
odood pre-commit run <path>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Path to repository to run pre-commit for. |
odood translations
Manage translations for this project.
Usage:
odood translations <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
regenerate— Regenerate translations for specified addons.
odood translations regenerate
Regenerate translations for specified addons.
Usage:
odood translations regenerate [options] <addon>
Options:
| Flag | Description |
|---|---|
--pot-remove-dates | Remove dates from generated .pot file. |
--pot | Generate .pot file for translations. |
--pot-update | Update translations based on regenerated .pot file. |
--missing-only | Generate only missing translations. |
--no-drop-db | Do not drop database after regeneration of translations |
--addon-dir | Directory to search for addons |
--addon-dir-r | Directory to recursively search for addons |
--lang-file | Combination of lang and file (separated by ‘:’) to generate translations for. For example: uk_UA:uk. |
-l, --lang | Language to generate translations for. For example: uk_UA. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
addon | Names of addons to regenerate translations for. |
odood config
Manage config of the project
Usage:
odood config <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
update— Update the config.
odood config update
Update the config.
Usage:
odood config update
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
odood discover
Discover already installed odoo, and configure Odood to manage it.
Usage:
odood discover <command>
Options:
| Flag | Description |
|---|---|
-h, --help | Show this help |
Commands:
odoo-helper— Discover odoo-helper-scripts project.
odood discover odoo-helper
Discover odoo-helper-scripts project.
Usage:
odood discover odoo-helper [options] <path>
Options:
| Flag | Description |
|---|---|
-s, --system | Discover system (server-wide) odoo-helper project installation. |
-h, --help | Show this help |
Arguments:
| Name | Description |
|---|---|
path | Try to discover odoo-helper project in specified path. |
odood info
Print info about this Odood project.
Usage:
odood info [options]
Options:
| Flag | Description |
|---|---|
--json | Print output in json format |
-h, --help | Show this help |
Assembly Spec Reference
The assembly spec is stored in odood-assembly.yml in the root of the assembly repository.
It is a YAML file with a single required top-level key: spec.
spec:
addons-list: [...]
sources-list: [...]
known-addons: [...]
layout: standard
spec fields
| Field | Required | Default | Description |
|---|---|---|---|
addons-list | yes | — | List of addon entries to include in the assembly. |
sources-list | no | [] | List of git source entries to fetch addons from. Alias: git-sources. |
known-addons | no | [] | Addon names assumed to be present on the target server; excluded from dependency validation. |
layout | no | standard | Controls where synced addons are placed. See Layout. |
Addon entry
Each entry in addons-list is either a plain string (addon name only) or a mapping:
addons-list:
- my_addon # string shorthand — name only
- name: other_addon # mapping form
source: my_repo # optional: bind to a named source
- name: paid_addon
odoo_apps: true # optional: download from Odoo Apps
| Field | Required | Default | Description |
|---|---|---|---|
name | yes | — | Technical name of the Odoo addon. |
source | no | null | Name of the source entry to fetch this addon from. When set, Odood will only search the named source and will fetch the addon even if that source has no-search: true. |
odoo_apps | no | false | When true, download this addon from Odoo Apps instead of a git source. |
Source entry
Each entry in sources-list defines a git repository to clone addons from.
Exactly one of url, github, oca, or crnd must be provided.
sources-list:
- url: https://github.com/my/repo
name: my_repo
ref: 18.0
commit: a3f9c12bd047
access-group: my_repos
no-search: false
URL shortcuts
| Field | Expands to |
|---|---|
url: <full-url> | used as-is |
github: owner/repo | https://github.com/owner/repo |
oca: repo | https://github.com/OCA/repo |
crnd: group/repo | ssh://git@gitlab.crnd.pro/group/repo |
Local SSH preference: github: and oca: expand to HTTPS, which works for CI token auth.
Developers who prefer SSH can configure git’s url.insteadOf globally — see
SSH for local development.
Source fields
| Field | Required | Default | Description |
|---|---|---|---|
url / github / oca / crnd | yes | — | Git repository URL (see shortcuts above). |
name | no | null | Identifier for this source. Used to bind addons via source: and as the credential lookup key for private repos. |
ref | no | null | Branch or tag to clone/fetch. Alias: branch (deprecated). |
commit | no | null | Commit hash to check out after fetching ref. Minimum 12 hex characters. Requires ref to be set. |
access-group | no | null | Credential group name for private repos. Overrides name for credential lookup. See Private git sources. |
no-search | no | false | When true, Odood will not auto-search this source for addons. The source is still used when an addon explicitly binds to it via source:. |
Layout
| Value | Behaviour |
|---|---|
standard | Synced addons are placed in the dist/ subdirectory of the assembly repo. |
flat | Synced addons are placed directly in the root of the assembly repo. |
Complete example
spec:
addons-list:
- generic_mixin # shorthand
- name: generic_tag
- name: generic_m2o
source: generic_addons # explicit source binding
- name: paid_addon
odoo_apps: true # from Odoo Apps
sources-list:
- github: crnd-inc/generic-addons
name: generic_addons
ref: '18.0'
commit: a3f9c12bd047 # pinned commit
- oca: web
ref: '18.0'
- github: my/private-repo
name: private_repo
ref: '18.0'
access-group: my_creds
no-search: true # only used for explicitly bound addons
known-addons:
- sale
- account
layout: standard
odoo_requirements.txt
odoo_requirements.txt is a text file that lists the repositories and apps to install on an Odoo instance. The format originates from odoo-helper and is supported by Odood.
Usage
Install all repositories and apps listed in the file:
odood addons add --odoo-requirements path/to/odoo_requirements.txt
You can also pass a directory — Odood will look for odoo_requirements.txt inside it:
odood addons add --odoo-requirements path/to/my-project/
This is convenient when the file lives alongside your project’s other config files and you want to point at the project root rather than the file itself.
Format
The file is parsed line by line. Each non-empty, non-comment line is a set of options:
Fetch addons from any git repository
-r|--repo <git repository> [-b|--branch <git branch>]
Fetch addons from github repository
--github <github username/reponame> [-b|--branch <git branch>]
Fetch OCA addons from any OCA github repository
--oca <OCA reponame> [-b|--branch <git branch>]
Fetch addons directly from Odoo Apps
--odoo-app <app name>
Notes
- The file must end with a newline character.
- Lines beginning with
#are treated as comments and ignored.
Example
# Third-party repos
--github crnd-inc/generic-addons --module generic_mixin -b 16.0
--oca project -m project_description
# From Odoo Apps
--odoo-app bureaucrat_helpdesk_lite
Migrate addons code to next Odoo serie
Odood provides ability to migrate addon code to next odoo serie.
This is implemented via odood repo migrate-addons command, that
under the hood uses odoo-module-migrator project.
For example, you have to take following steps to migrate repo from Odoo 17 to Odoo 18:
- Add repo to Odood project for Odoo 18
- Create new branch in repo 18.0 based on stable 17.0
- Run
odood repo migrate-addonsinside repo with addons to be migrated. - Test that everything works fine, and fix (or disable) things that are broken.
- Commit changes and push changes.
Example
For example, let’s assume that we want to migrate repo https://github.com/myname/myrepo from 17.0 to 18.0.
As pre requisite for this task we have to have Odoo 18 development installation installed via Odood.
(if you do not have it, you can install it via command odood init -v 18 -i odoo-18 --db-user=odoo18 --http-port=18069 --create-db-user)
So, let’s fetch this repo in Odoo 18 project:
cd odoo-18
odood repo add -b 17.0 git@github.com:myname/myrepo
After this step, we will have repo cloned in repositories/myname/myrepo.
So, let’s change directory to that one:
cd repositories/myname/myrepo
Next, we have to create new 18.0 branch:
git checkout -b 18.0
(branch name represents the version of Odoo for which addons on this branch are expected to work)
So, next, we have to run migrator to actually migrate code of addons:
odood repo migrate-addons
Check output of this command, maybe there are some notes or some hints to something that was not migrated automatically. Try to fix it. Test if everything works fine. Fix broken things and commit.
That’s all.
Notes
Possibly, it could be better strategy to migrate addons one by one. In this case, you can specify name of addon that you want to migrate:
odood repo migrate-addons -m my_module
(In this case, my_module is name of module to migrate. This option could be specified multiple times).
Changelog
Release 0.6.3 (2026-06-08)
Added
- Support for
--test-tagoption forodood testcommand - Experimental
odood repo releasecommand, that could automatically tag repo and generate changelogs. - Experimental
odood repo hotfixcommand, that could be used to manage hotfixes of repositories. - Experimental
odood assembly upgrade-sourcescommand, that allows to bump pinned releases on repository. - Experimental
odood test --migration-last-releaseoption, that allows to test repo migration against latest release. - Added option
odood db backup --nicethat allows to lower cpu priority of backup task
Changed
- Switched to DarkCommand CLI lib:
- better autocomplete (file paths when needed)
- better automatic documentation (CLI Ref)
- Updated default pre-commit configs.
You can apply it to your repo with
odood pre-commit init -f, but review introduced changes before committing, because this command overwrites pre-commit configs.
Fixed
- Run
msguniqbeforemsgmergewhen regenerating translations, because AI too frequently generates duplicate translations andmsgmergefails - Use
data_dirfromodoo.conffor backup/restore to ensure backups are correct whendata_dirchanged to non-standard location. Before fix, it was required to modify data dir on both places:odood.ymlandodoo.conf
Release 0.6.2 (2026-05-09)
Added
- Added new documentation on assembly spec
- Updated assembly documentation with more examples
Fixed
- Correct handling of
no-searchparam on assembly spec.
Release 0.6.1 (2026-04-20)
Added
- Batch Python requirements installation: when linking addons (via
odood addons link,odood assembly link, orodood venv reinstall), all Python requirements are now gathered and installed in a singlepip installcall instead of one call per addon. This improves performance and lets pip resolve the full dependency tree at once.- New flag
--individual-requirementsforodood addons linkandodood assembly linkto fall back to per-addon installation (old behavior). - New flag
--with-odoo-requirementsforodood addons linkandodood assembly linkto include Odoo’s ownrequirements.txtin the batch install.
- New flag
- Assembly requirements lock file support: if
requirements.lock.txtexists in the assembly root,odood assembly linkinstalls only from that file and skips per-addon requirement scanning. This gives assembly maintainers full control over the Python dependency tree for reproducible deployments.- New flag
--generate-lockforodood assembly syncto generate the lock file after syncing (runspip freezeto produce pinned versions). - New flag
--with-odoo-requirementsforodood assembly syncto include Odoo’s requirements when generating the lock file.
- New flag
- New flag
--odoo-helper-compatforodood pre-commit initthat generates a pre-commit config compatible with odoo-helper-scripts’ default linting style (check-only — no auto-formatting). Useful for migrating projects from odoo-helper.- Added bandit security scanner hook to the default pre-commit config.
- Added
odoolintcatchall check to the default pylintrc
- Added support for commit pinning on the assembly spec
- Added
--log-to-stderrflag toodood init(mirrorsodood deploy): initialises the project without a log file so all Odoo output goes to stderr/stdout. Recommended for container deployments. - Odoo stderr is now forwarded to the caller during addon install/update and database initialisation when no logfile is configured.
- Added ability to restore backup into empty but existing database. Useful in container environments.
Changed
- Tests now use os-provided available tcp ports to run Odoo, thus it is possible to run few different tests with different databaes in parallel
odood venv reinstallnow installs all addon Python requirements in a single batched pip call instead of one per addon.- Switched to
darkarchivelib to handle archives. Thus, backups do not require temporary files anymore, and could be done in more space-eficient way.
Release 0.6.0 (2026-03-11)
Added
- Added
odood server healthcheckcommand. One step to make Odood container-friendly. - Added
odood server wait-pgcommand - Added
odood server run --wait-pgoption - Added
odood db is-initializedcommand to check if database is already initialized. - Added
odood db ensure-initializedcommand to initialize database if it is not initialized yet. - Added new options to
odood addons install--missing-only- install only addons that are not installed in specified db from the list.--ignore-unfinished-updates- do not fail on unfinished updates
- Added new options to
odood addons update--installed-only- install only addons that are not installed in specified db from the list.--ignore-unfinished-updates- do not fail on unfinished updates
- Added
--tls12-compatflag toodood deployto allow TLS 1.2 in addition to TLS 1.3 for backward compatibility with older clients. - Added
--use-system-ca-bundleflag toodood deployto setREQUESTS_CA_BUNDLEto the system CA certificate store. Auto-detects the CA bundle path across Debian/Ubuntu, RHEL/CentOS/Fedora, and openSUSE.
Changed
- Changed template for
nginxconfiguration fordeploycommand:- Added security headers
- Database manager (
/web/database) is blocked by default - Bugfixes related to nginx config generation
- Nginx SSL configuration now defaults to TLS 1.3 only with hardened cipher
suites (FIPS 140-2/3 compliant, no CBC/RC4/3DES). Use
--tls12-compatto enable TLS 1.2 with ECDHE forward secrecy ciphers. - Command
odood db listrewritten in D (no more python / lodoo call) - Commands
odood addons installandodood addons updatenow will fail if there are unfinished addon updates before running command or after. This way these commands ensures clean state of db before and after operation. - Default dockerimage’s command now waits when pg is ready before running Odoo (
odood server run --wait-pginsteand ofodood server run) - “No access rules” warnings are no longer treated as test errors. Models
that intentionally have no ACLs (e.g. sudo()-only technical models) will
no longer cause
odood testto fail.
Fixed
- Odood now will handle
db_sslmodeparameter correctly inside it’s internal database interactions
Release 0.5.5 (2026-02-25)
Added
- New command
odood venv lodoothat exposes LOdoo bundled to current project.
Fixed
- Fixed bad dependency on
cbor==5.4.2. Patch the requirements.txt during Odoo installation.
Release 0.5.4 (2026-02-06)
Added
- Assemblies:
- added support for
known-addonskey in spec - added support for assembly layout config (standard and flat)
- added support for downloading addons from Odoo Apps
- Clone/update git sources in parallel
- Added assemply spec validation before sync operation
- Added new option
--dockerfilethat allows to automatically generate Dockerfile for assembly on sync. Thus we have the way to build standard images for assemblies.
- added support for
- Added ability to pull all repositories via command
odood repo pull-all. This could be helpfull during development to pull all repos on instance. - Added command
odood pre-commit updatethat could be used to update pre-commit dependencies (in pre-commit config). Just an alias for standardpre-commit autoupdatethat is run inside correct repo dir and within correct venv. - Added option
--workerstodeploycommand
Changed
- Clean up pip cache after deploy, when docker image is built.
- Assembly, if
VERSION,Dockerfileor.dockerignorechanged, that commit of changes allowed.
Release 0.5.3 (2026-01-08)
Added
- Build docker images for ARM64 architecture
- New option to
assembly upgradecommand:--start- automatically start server if upgrade is successful and server was not running before upgrade.
- Added new option
odood assembly --assembly-paththat could be used to specify different assembly path for assembly commands. Mostly, this option could be useful for CI
Changed
- Now, when assembly contains
requirements.txtfile, it will be processed automatically before assembly link operation.
Release 0.5.2 (2025-12-23)
Added
- Added option
--starttoaddons install/update/uninstallcommand to automatically start server if it was stopped. - Added automatic generation of changelogs on
assembly syncif option--changelogspecified. If enabled, then Odood will automatically generate VERSION file for assembly repo. It could be used later to track versions of assemblies.
Changed
- Database populatation now works only for Odoo version 14-17, because starting from Odoo 18 population means duplication instead of generation.
- After backup of database completed, log message about backup completed and duration of operation.
Fixed
- Fixed bug with false-positives in when running migration tests on new addons.
Release 0.5.1 (2025-11-02)
Added
- Experimental support for Odoo 19
- Experimental support for deployment with let’s encrypt certs.
Release 0.5.0 (2025-09-12)
Added
- New options to
odood deploycommand:local-nginx-sslto enable SSL configuration for local nginxlocal-nginx-ssl-keychoose path to ssl key for the serverlocal-nginx-ssl-certchoose paht to ssl certificate for the server
- Git sources in assembly spec now supports shortucts
githubandocathat allows to simplify configuration of git sources - During assembly sync, Odood can automatically apply acccess credentials from env variables:
- For named sources
ODOOD_ASSEMBLY_repo_name_CRED - Added support for access groups (
access-groupfor sources inodood-assembly.yml), this way it is possible to use same token for multiple repos. The name isODOOD_ASSEMBLY_access_group_CRED - The format of
ODOOD_ASSEMBLY_<group/repo>_CREDvariable isusername:password
- For named sources
- During assembly upgrade, check for unfinished install/upgrade and print waring if there are any unfinished install/upgrade/uninstall
- Added new option
assembly-repoforodood deploycommand, that allows to automatically configure deployed instance to use specified assembly.
Release 0.4.4 (2025-08-03)
Added
- Automatic check for missing dependencies of assembly addons on assembly sync.
- Ability to use existing assembly for project via
odood assembly usecommand. This could be useful in CI to automate assembly sync process. - Added new options to specify commit params for
odood assembly synccommand. - Added experimental
odood repo do-forward-portcommand
Changed
odood lognow will automatically show the end of logfile
Release 0.4.3 (2025-07-05)
Added
- Addd new command
odood repo migrate-addonsthat uses under the hood OCA’s utility odoo-module-migrator to migrate source code of modules to project’s serie from older odoo series.
Fixes
- Fix installation of odoo on Ubuntu 22.04 because of non-recent setuptools and recent update of zope.event.
Release 0.4.2 (2025-06-21)
Fixes
- Fix handling of check if nginx is installed on Ubuntu 22.04
Release 0.4.1 (2025-06-20)
Added
- New command
odood repo check-versionsthat could be used to check if module versions updated. - New option
--langtoodood translate regeneratecommand. With this option, translation file will be detected automatically. - New option
--repeattoodood db populatecommand, that allow to repeat database population N times. - Added new command
odood assembly upgrade, that could be used to upgrade assembly in single command, that includes:- optionally, take backup before any other step
- pull latest changes
- relink assembly addons
- update all assembly addons for all databases available on managed instance
Release 0.4.0 (2025-05-29)
Added
- New command
odood db populatethat allows to populate database with test data - New options to
odood testcommand (--populate-modeland--populate-size) that could be used to populate database with test data before running tests. Especially, this could be useful for migration tests - New command
odood assemblythat could be used to manage Odoo instance in assembly style, when all addons used on instance are placed in single repo. - Added new flag
--assemblytoodood addons list/update/install/uninstallcommands
Changed
- Command
odood odoo recompute- changed parameters:- use options instead of arguments
- allow to run for multiple databases (or for all databases)
- Command
odood db list-installed-addonsrenamed toodood addons find-installed. - Command
odood addons find-installedgot new options:--non-system- output only non-system addons (that are not included in official Odoo community)--format- what format to use for output: list, assembly-spec
Release 0.3.1 (2025-04-23)
Added
- Support and release for arm64 architecture
- Added new command
repo bump-versionsto automatically bump versions of modules - Added new options for
odood deploycommand:--local-nginxthat allows to automatically configure local nginx (requires nginx installed)--enable-fail2banthat allows to automatically configure fail2ban for Odoo (required fail2ban installed)
Removed
- Dropped support for Ubuntu: 20.04 (compile release for Ubuntu 22.04+)
- Dropped support for Debian: Bullseye (compile release for Debian bookworm+)
Release 0.3.0 (2025-03-14)
Added
- New command
odood translations regeneratethat allows to regenerate translations for modules. Could be useful to automatically or semiautomatically generate.poand.potfiles for modules. Also, this command available as shortcutodood tr regenerate. - New flag
--no-install-addonsadded toodood test. It could be used to speed up running tests on localc machine on same db.
Changed
- Breaking Changed approach to docker images. No more custom entry point. Just single option (on application level), that allows to update Odoo configuration from environment variables. Default command uses this option. but custom commands will need to use this option. Currently, this requires explicit specification of this command on Odood runs. This may be changed in future.
- Breaking Do not use separate config file for tests on deployments (Odoo installations installed via
odood deploycommand)
Release 0.2.2 (2025-03-10)
Added
- Experimental support for PyEnv integration.
Changed
- Replace dpq with Peque
odood script pycommand: now output of script will be redirected on stdout. Thus no more need to wait while script completed to get intermediate output of script.
Release 0.2.1 (2025-01-23)
Changed
- Added new command
entrypointthat is available only in version for docker images, that is used as entrypoint for docker container and that is responsible for applying configuration from environment variables to Odoo configuration file before any further action. - Added new command
odood odoo recomputethat allows to recompute computed fields for specified model in specified database.
Release 0.2.0 (2024-12-12)
Added
- New experimental command
odood deploythat could be used to deploy production-ready Odoo instance. - Added experimental support for Odoo 18
- Added new command
odood repo fix-seriesthat allows to set series for all modules in repo to project’s serie. - Added automatic builds of docker images with pre-installed Odoo.
Changed
- Pre-commit related commands moved to
pre-commitsubcommand. Thus, following commands now available to work with pre-commit:odood pre-commit initodood pre-commit set-upodood pre-commit run
- Change command
odood server run. Command usesexecvto run Odoo, thus, Odoo process will replace Odood process. Thus, option--detachis not available here. If you want to start Odoo in background, thenodood server startcommand exists. Instead, this command (odood server run) is designed to run Odoo with provided args in same way as you run Odoo binary directly. For example, following commandodood server run -- -d my_database --install=crm --stop-after-init, that will installcrmmodule, will be translated toodoo -d my_database --install=crm --stop-after-init, that will be ran inside virtualenv of current Odood project.- Added new option
--ignore-runningthat allows to ignore server running. - Removed option
--detachas it does not have sense. Useodood server startinstead.
- Added new option
- Changed generation of default test db name.
Before it was:
odood<serie>-odood-testNow it will be:<db_user>-odood-test
Release 0.1.0 (2024-08-15)
Added
- New command
odood venv pipthat allows to run pip from current venv. - New command
odood venv npmthat allows to run npm from current venv. - New command
odood venv pythonthat allows to run python from current venv. - New command
odood venv ipythonthat allows to run ipython from current venv. - Added new option
--ualto commandodood repo addthat allows to automatically update list of addons when repository was added. - New command
odood venv runthat allows to run any command from current venv. - New command
odood repo run-pre-committo run pre-commit for the repo.
Changed
- Database restoration reimplemented in D, thus now it restores db dump and filestore in parallel.
Release 0.0.15 (2023-10-30)
Added
- Added ability skip addons specified in file during install/update/upgrade.
- Added new options to
odood testcommand:--filethat could be used to pass the path to file to read addons to test from--skip-fileread names of addons to skip from file
Changed
- Installation of dependencies from manifest is now optional. It is frequent case, when authors of module place incorrect dependencies in manifest, thus installation of addon may fail.
Fixes
- Fix error when running
addons install/update/uninstallwith non-existing logfile. This was caused by attempt to determine starting point of logfile to search for errors happened during operation. Now this case is handled correctly.
Release 0.0.14 (2023-10-04)
Added
- Added new options
--skipand--skip-retoodood testcommand, that allow to not run tests for specified addons. Useful in cases, when there is need to skip some addons found via options--dirand--dir-r - Added new options
--skipand--skip-retoodood addons install/update/uninstallcommands. Useful in cases, when there is need to skip some addons found via options--dirand--dir-r - Added new option
--skip-errorstoodood addons install/update/uninstallcommands, that allows to not fail when installing addons in database, thus allowing to install addons to other databases, and fail in the end. - Added new option
--install-typetoodood initandodood venv reinstall-odoocommands, thus, now it is possible to install Odoo as git repo or as unpacked archive depending on this option
Changed
- Load Python dynamically, thus make Odood more portable.
- Finally, make Odood portable. Now we have universal deb package, that could be installed on most debian-based repos newer then ubuntu:20.04
- Commands
odood addons install/update/uninstallnow will report Odoo errors raised during addons installation.
Release 0.0.13 (2023-09-08)
Added
- Command
odood addons generate-py-requirementsthat allows to generate requirements txt files for specified modules. - Added new option
--tdbtoodood db createcommand, that allows to use automatically generated default name for tests database. - Added new command
odood db list-installed-addons. This command could be used to print to stdout or file list of addons installed on specific databases.
Release 0.0.12 (2023-08-14)
Added
- Command
odood odoo shellthat allows to open odoo shell for specified db. - Added release for
debian:bullseye
Changed
- Implement backup of database on D level. This way it provides better error handling.
- Added ability to cache downloads if
ODOOD_CACHE_DIRenvironment variable is set.
Release 0.0.11 (2023-07-27)
Added
- New option
--simplified-logadded toodood testcommand. Thus it is possible to display meaningful log info (log level, logger, message).
Changed
- Command
odood venv reinstall-odoonow backups old odoo by default. But it is possible to disable backup with option--no-backup - Now it is allowed to specify only name of backup to restore database from. In this case, Odood will try to find corresponding backup in standard backups directory of project.
Fixed
- Correctly handle
--additional-addonspassed for tests in case when migration test enabled: update that addons before running tests.
Release 0.0.10 (2023-07-08)
Added
- New option
--alltoodood db backupcommand, that allows to backup all databases within single command. - New command
infothat will display info about project, optionally in JSON fromat. - New option
--filetoodood addons installandodood addons updatecommands. This option allows to get list of addons to install / update from provided file. This way, it is possible to avoid specifying list of addons manually. - New option
--install-filetoodood db createcommand, that will automatically install modules from specified files. - New option
--coverage-ignore-errorstoodood testcommand, that allows to ignore coverage errors, that a frequent case during migration tests (because files available on start may disapear during migration). - New option
--recreatetodb restorecommand, thus it is possible to automatically drop database before restoration if needed. - Added flag
--backuptovenv update-odoocommand. - Added new command
odood venv reinstall-odoo, that could be used to reinstall odoo to different version in same venv. This could be used for migrations to avoid the need to setup new machine for migrated instance.
Changed
- Command
odood db backup: when--destoption supplied and it is existing directory, then database will be backed up in this directory with automatically generated name of backup. - Automatically supply
--ignore-errorstocoveragewhen running migration tests
Release 0.0.9 (2023-06-01)
Added
- New option
--ualtoodood addons installandodood addons updatecomands - New option
--additional-addontoodood testcommand - New options for
odood addons listcommand:--with-priceand--without-priceforodood addons listcommand--color=priceto highlight addons that have or have no prices--tableto output list of addons as table
- New command
odood venv install-py-packagesthat could be used to easily install python packages in Odood virtualenv environment - New option
--warning-reporttoodood testcommand: if this option provided, then Odood will print uniq list of warnings in the end of test run
Release 0.0.8 (2023-05-05)
Added
- Add new option –color=installable to addons list command
- Added command
odood ci fix-version-conflictto resolve version conflicts in module manifests
Changed
odood testcommand: show error report by default, but add option to disable it.- Clone repos recursively optionally. Before this change,
command
odood repo addwas clonning repositories recursively (parseodoo_requirements.txtfile in clonned repo and clone dependencies mentioned there). After this change, recursive add repo is optional, end could be enable by optionodood repo add --recursive ... odoo testwith option--iswwill additionally ignore following warning:unknown parameter 'tracking'