Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

The Odood Logo

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:
  • 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:

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.

  1. Clone the repository and enter its root directory.
  2. Install build dependencies: libpq-dev python3-dev.
  3. 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.
  4. Build:
    dub build -b release --compiler=ldc2
    
    The binary is written to build/odood.
  5. Link it onto your PATH, e.g.:
    mkdir -p ~/bin
    ln -s "$(pwd)/build/odood" ~/bin/
    

DMD note: dub build -b release with DMD fails due to a CTFE regression in std.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.318.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/.pot files 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

  1. Switch to your Odoo environment for the target series (e.g. your 18.0 project).

  2. Change into the repository directory.

  3. Create (or check out) a forward-port branch:

    git checkout -b 18.0-forward-port-<feature>
    
  4. Run the forward-port command, naming the source series:

    odood repo do-forward-port -s 17.0
    

    The command will automatically:

    • Fetch origin/17.0 and open a merge (--no-ff --no-commit) into the current branch, staging all changes for review.
    • Reset .po/.pot files 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/).
  5. Resolve any remaining merge conflicts (business logic, structural changes, etc.).

  6. Run tests to verify everything works in the target series:

    odood test -t --dir .
    
  7. Commit and push:

    git push origin 18.0-forward-port-<feature>
    
  8. Open a pull/merge request into the 18.0 stable branch and wait for CI to pass.

  9. Repeat steps 1–8 for each remaining target series (19.0, etc.).

Note: do-forward-port is 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-env flag and ODOOD_OPT_* support are only compiled in when Odood is built with the -d-version OdoodInDocker flag, 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 variableodoo.conf keyDescription
ODOOD_OPT_DB_HOSTdb_hostPostgreSQL host
ODOOD_OPT_DB_PORTdb_portPostgreSQL port (default: 5432)
ODOOD_OPT_DB_USERdb_userPostgreSQL user
ODOOD_OPT_DB_PASSWORDdb_passwordPostgreSQL password
ODOOD_OPT_ADMIN_PASSWDadmin_passwdOdoo master password (database manager)
ODOOD_OPT_WORKERSworkersNumber of worker processes (0 = single-process mode)
ODOOD_OPT_PROXY_MODEproxy_modeSet True when running behind a reverse proxy
ODOOD_OPT_DBFILTERdbfilterRegex to restrict which databases are served
ODOOD_OPT_LIMIT_MEMORY_HARDlimit_memory_hardHard memory limit per worker (bytes)
ODOOD_OPT_LIMIT_MEMORY_SOFTlimit_memory_softSoft memory limit per worker (bytes)
ODOOD_OPT_LIMIT_TIME_CPUlimit_time_cpuCPU time limit per request (seconds)
ODOOD_OPT_LIMIT_TIME_REALlimit_time_realReal time limit per request (seconds)
ODOOD_OPT_LOG_LEVELlog_levelLog 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.txt file.


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 the only regex 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:

  1. Cut new releases of the relevant repos.
  2. Update the assembly spec to pin the new versions.
  3. Sync the assembly and deploy to a staging environment.
  4. 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:

  1. Active development — feature branches merge into stable as usual.
  2. 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.
  3. 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.
  4. 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:

SegmentMeaning
A.BOdoo series (e.g. 18.0)
XMajor — a breaking change: any addon had a major version bump, or an addon was removed, since the last release
YMinor — any addon had a minor or patch bump, or an addon was added, since the last release
ZPatch — 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, not Z? Because auto-detection never produces a Z bump — a routine release, even one that only contains addon patch bumps, always ends in .0. A Z > 0 release 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:

  1. Fetch remote tags to find the latest release (union of local and remote, to handle tags pushed by others not yet fetched locally).
  2. Verify that every addon changed since the last release tag has a bumped version (safety gate — normally already satisfied by CI).
  3. 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 removedX incremented, Y and Z reset to 0.
    • Any addon had a minor or patch bump, or an addon was addedY incremented, Z reset to 0.
  4. Optionally generate CHANGELOG.md / CHANGELOG.latest.md and commit them.
  5. Create a git tag with the new version.
  6. Push the branch and tag if --push is given.

--push branch guard: When --push is 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)

--patch is the mainline patch: a deliberate Z bump on top of the latest serie release (e.g. a small fix you want to ship as 18.0.2.1.1 without a minor bump). It must be requested explicitly — auto-detection never produces a Z bump — 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 mainline release --patch builds 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 (startcheckrelease), keeping it separate from mainline releases.

Step-by-step

  1. Create a hotfix branch with odood repo hotfix start:

    odood repo hotfix start --from=18.0.2.1.0
    

    This validates the primary tag, finds the latest existing tag in the 18.0.2.1.* chain (so subsequent patches like 18.0.2.1.2 are handled correctly), creates hotfix/18.0.2.1.x from it, and prints next steps.

    The --from argument always takes the primary release (Z == 0), never an intermediate hotfix.

    start is 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 on originchecks 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.

  2. 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-translations
    

    This compares against the latest tag in the branch’s patch chain — exactly what hotfix release will verify.

  3. Release the patch — from the hotfix branch:

    odood repo hotfix release --changelog --push
    

    hotfix release derives the chain from the current hotfix/A.B.X.Y.x branch, takes the chain’s latest tag as the base, and bumps Z — 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 check and hotfix release derive the chain from the branch name, so they must run with the hotfix/A.B.X.Y.x branch checked out — they cannot work from a detached HEAD (e.g. a tag-triggered pipeline). Use a branch-triggered job for the hotfix branch.

  1. 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.

  2. 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

PropertyRule
Auto-detected releaseAlways ends in .0 (e.g. 18.0.2.1.0)
Patch releaseOnly Z changes; X.Y stays equal to the release it builds on (e.g. 18.0.2.1.1)
Patch chainAll 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 > 0 means patch (a hotfix, or a deliberate patch on stable); Z == 0 means 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 --patch patches the latest serie release; hotfix release patches the chain its branch is based on (getLatestPatch picks the chain’s highest tag, so it always counts up). When both target the same A.B.X.Y chain, their Z numbers interleave across divergent commits — a mainline patch may take 18.0.2.1.1, then a hotfix on the same primary becomes 18.0.2.1.2 on a different commit. Tags never collide, but read the chain as “all patches built on the X.Y release”, not as one linear history.

  • A mainline release bases on the highest serie tag. release and release --patch compare against — and bump from — the numerically latest serie tag. If you hotfix the latest release (18.0.2.1.018.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:

CommandCompares againstUse for
check-versionsstable branch tip (origin/<serie>)CI on a PR
check-versions --since-last-releasethe latest release tag for the serie (any chain, including patches)previewing a standard release
hotfix checkthe latest tag in the current hotfix branch’s patch chainpreviewing 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 gettext package 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 .
  • --pot regenerates the .pot from the current source.
  • --pot-update merges the updated .pot into each .po file.
  • --missing-only preserves existing msgstr values — 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

FlagDescription
--potRegenerate the .pot template file from the installed addon.
--pot-updateMerge the .pot into existing .po files with msgmerge.
--missing-onlySkip .po files that already exist unless --pot-update is also set; preserves existing msgstr values on merge.
--pot-remove-datesStrip 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-dbKeep 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:

  1. Run odood translations regenerate first to produce the correct .po structure with authoritative msgid entries extracted from the actual source code.
  2. Then ask the AI to fill only the msgstr values 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

PatternTypical useKey tool
Local developmentDeveloper machine, multiple Odoo versions side by sideodood init
Docker ComposeSingle-server, small team, easier ops than bare-metalPrebuilt images + ODOOD_OPT_*
VPS / bare-metalTraditional production, full control, systemdodood 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, and python3-venv packages suffice.
  • wkhtmltopdf (optional) — required only if you need to generate PDF reports. Download from the wkhtmltopdf releases page and install the .deb that 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

FlagDescription
-v <series>Odoo series to install (16, 17, 18, 19, …)
--install-type=archiveInstall from the official Odoo source archive (default)
--install-type=gitClone from the Odoo git repository (enables odood venv update-odoo)

Database

FlagDescription
--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-userCreate 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

FlagDescription
--http-port=<port>Port Odoo listens on (default: 8069)
--longpolling-port=<port>Gevent / long-polling port (default: 8072)

Python and Node

FlagDescription
--python=<path>Path to the Python executable to use for the virtualenv
--node-version=<ver>Node.js version to install (for frontend assets)
--pyenvUse pyenv to manage the Python version (see macOS section)

Advanced

FlagDescription
--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

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-env flag and ODOOD_OPT_* environment variable support are compiled into these images using the -d-version OdoodInDocker build flag. They are not available in the Debian package or source builds. See the ODOOD_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.yml and dist/ into /opt/odoo/assembly/
  • Runs odood assembly use /opt/odoo/assembly to register the assembly in odood.yml
  • Runs odood assembly link to create symlinks in custom_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 in docker-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 update partially 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-deps starts 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 deploy command if you use --local-postgres option.
  • 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, Odood will automatically generate template config for nginx.
  • 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

If the server is configured to use Assembly, a single command handles the full upgrade:

sudo odood assembly upgrade --backup

This will automatically:

  1. Back up all databases
  2. Pull the latest assembly changes
  3. Relink addons
  4. Update all addons in all databases
  5. 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

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 source field
  • 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 the dist/ 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-list section of spec
  • Add information about source to fetch this addons from in sources-list section of spec

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

  1. pull assembly changes,
  2. relink modules,
  3. 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 assembly
  • odood 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 dist folder of assembly
    • Copy latest versions of addons to dist folder
    • 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 from custom_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 update
  • odood assembly upgrade - simple way to upgrade server that is configured to use assembly.
  • odood assembly upgrade-sources - scan each source whose ref is 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 for odood addons install/update/uninstall commands 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 changelog that will store changelogs for this addon
  • for each version of addon that has notable changes, file changelog/changelog.X.Y.Z.md have to be added (here X - 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 h6 headers in changelog/changelog.X.Y.Z.md files, because all headers larger than h6 will 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:

  1. Create a new branch 18.0-update
  2. Wait for the job to complete
  3. Create a pull request
  4. Review and merge the pull request
  5. Delete the 18.0-update branch (or configure automatic stale-branch deletion)

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 in docker-compose.yml for 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:

  1. Specify credentials for private repo (usually system user + access token) in GitHub Actions Secrets
  2. On Sync assembly step, assign variable ODOOD_ASSEMBLY_accessgroup_CRED value in format user:password that is fetched from action’s secrets, where accessgroup is value specified in access-group or name property 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 identicalbackups/, 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-scriptsodood
odoo-helper fetch --repo URLodood repo add URL
odoo-helper fetch --github user/repoodood repo add --github user/repo
odoo-helper fetch --oca repoodood repo add --oca repo
odoo-helper link .odood addons link .
odoo-helper addons update-listodood addons update-list

Server management

odoo-helper-scriptsodood
odoo-helper server startodood server start
odoo-helper server stopodood server stop
odoo-helper server restartodood server restart
odoo-helper server logodood server log
odoo-helper server psodood server status

Addon management

odoo-helper-scriptsodood
odoo-helper addons installodood addons install
odoo-helper addons updateodood addons update
odoo-helper addons uninstallodood addons uninstall

Database management

odoo-helper-scriptsodood
odoo-helper db list / lsdodood db list
odoo-helper db createodood db create
odoo-helper db dropodood db drop
odoo-helper db backupodood db backup
odoo-helper db restoreodood db restore
odoo-helper db copyodood db copy
odoo-helper db renameodood db rename

Testing

odoo-helper-scriptsodood
odoo-helper test -m addonodood test -m addon

Translations

odoo-helper-scriptsodood
odoo-helper tr regenerateodood tr regenerate

Virtualenv / Python utilities

odoo-helper-scriptsodood
odoo-helper update-odooodood venv update-odoo
odoo-helper exec CMDodood venv exec CMD
odoo-helper pipodood venv pip
odoo-helper pythonodood venv python
odoo-helper ipythonodood venv ipython

CI / dev tooling

odoo-helper-scriptsodood
odoo-helper ci check-versions-gitodood repo check-versions
odoo-helper ci fix-versionsodood repo bump-versions
odoo-helper ci do-forward-portodood repo do-forward-port
odoo-helper ci auto-migrate-modulesodood repo migrate-addons
odoo-helper repo fix-version-conflictodood repo fix-version-conflict
odoo-helper lint pylint / flake8 / styleodood 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-scriptsodood
odoo-helper statusodood status
odoo-helper print-configodood 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 by odood db backup command
  • conf - directory for configurations used by this odood project. Usually contains two files: one for normal local config and one that is used to run tests
    • odoo.conf - main configuration used by default
    • odoo.test.conf - configuration used to run tests, usually has a different port than odoo.conf, and does not specify a logfile, so all log messages are written to stderr and caught by the odood test 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 sessions
  • downloads - directory containing addons downloaded directly from Odoo Apps
  • odoo - Odoo source code
  • repositories - stores git repositories containing additional (non-standard) Odoo addons
  • venv - virtualenv directory
  • odood.yml - configuration for this Odood project

Optional directories:

  • assembly - if the project is configured to use assembly, this directory contains the assembly repository
  • cache - 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:

  1. Clones the repository into repositories/<owner>/<repo>/
  2. Scans it for installable addons (directories with a valid __manifest__.py)
  3. 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 server
  • odood restart - restart odoo server
  • odood stop - stop odoo server
  • odood log - see odoo server logs
  • odood browse - open running odoo installation in browser
  • odood 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 directory
  • odood addons update-list - update list of available addons in all databases available for this server
  • odood addons install <addon1> [addonN] - install specified odoo addons for all databases available for this server; use --missing-only to skip already-installed ones
  • odood addons update <addon1> [addonN] - update specified odoo addons for all databases available for this server; use --installed-only to skip non-installed ones
  • odood addons uninstall <addon1> [addonN] - uninstall specified odoo addons for all databases available for this server
  • odood addons update --dir <path> - find all installable addons in specified directory and update them
  • odood addons install --dir <path> - find all installable addons in specified directory and install them
  • odood 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 database
  • odood test -t --dir . - test all installable addons in current directory
  • odood test -t --migration --dir . - run migration tests for all installable addons in current directory
  • odood test --coverage-html -t <module> - test single module and create html coverage report
  • odood 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 by url
  • odood repo add --oca <name> - fetch OCA repository named name from OCA git repo. For example, --oca web means 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/web means 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 - generate CHANGELOG.md, commit it, tag, and push branch + tag to origin.

Database management

  • odood db list - list all databases available for current odoo instance
  • odood db create my_db - create database
  • odood db backup -d my_db - backup my_db
  • odood db backup -a - backup all databases on the server
  • odood db drop my_db - drop database
  • odood 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 addons
  • odood 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 instance
  • odood assembly init --repo=git@github.com:my/assembly.git - initialize this instance with assembly from specified repo
  • odood assembly upgrade - pull latest changes from assembly and upgrade server
  • odood assembly sync - synchronize assembly according to spec: fetch latest versions of modules from specified sources and update assembly repo
  • odood assembly upgrade-sources - advance version-tag-pinned sources in the spec to the newest matching tags on their remotes; follow up with assembly sync to apply
  • odood 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:

FlagDescription
-v, --verboseEnable verbose output
-q, --quietHide unnecessary output
-d, --debugShow additional debug information.
-h, --helpShow this help
--versionShow version

Shortcuts:

NameExpands toDescription
startserver startRun the server in background.
stopserver stopStop the server.
restartserver restartRestart the server.
browseserver browseOpen odoo in browser.
logserver logView server logs.
lsddb listShow databases.
lsaaddons listList addons.
ualaddons update-listUpdate list of addons.
trtranslationsManage translations.

Commands:

  • init — Initialize new odood project.
  • deploy — Deploy production-ready Odoo.
  • server — Server management commands.
  • status — Show the project status.
  • db — Database management commands
  • addons — 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 project
  • script — Run scripts in Odood environment.
  • psql — Run psql for specified database
  • pre-commit — Work with pre-commit dev tool.
  • translations — Manage translations for this project.
  • config — Manage config of the project
  • discover — 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:

FlagDescription
-i, --install-dirDirectory to install odoo to
-v, --odoo-versionVersion of Odoo to install
--install-typeInstallation type. Accept values: git, archive. Default: archive.
--odoo-branchBranch in Odoo repo to install Odoo from.
--odoo-repoInstall Odoo from specific repository.
--pyenvUse python from pyenv to initialize virtualenv for project. Install desired py version if needed
--py-versionInstall specific python version. By default system python used
--node-versionInstall specific node version.
--db-hostDatabase host
--db-portDatabase port
--db-userDatabase user
--db-passwordDatabase password
--create-db-user[sudo] Create database user automatically during installation. Requires sudo.
--http-hostHttp host
--http-portHttp port
--log-to-stderrConfigure project without a log file (logs to stdout/stderr). Recommended for container deployments.
-h, --helpShow this help

odood deploy

Deploy production-ready Odoo.

Usage:

odood deploy [options]

Options:

FlagDescription
-v, --odoo-versionVersion of Odoo to install
--py-versionInstall specific python version.
--node-versionInstall specific node version.
--db-hostDatabase host
--db-portDatabase port
--db-userDatabase user
--db-passwordDatabase password
--local-postgresConfigure local postgresql server (requires PostgreSQL installed)
-w, --workersNumber of workers to apply for this instance. If set to 0, then Odoo will be started in threaded mode. Default: 0
--proxy-modeEnable proxy-mode in odoo config
--local-nginxAutoconfigure local nginx (requires nginx installed)
--local-nginx-server-nameServername for nginx config.
--local-nginx-sslEnable SSL for local nginx
--local-nginx-ssl-certPath to SSL certificate for local nginx.
--local-nginx-ssl-keyPath to SSL key for local nginx.
--tls12-compatAllow TLS 1.2 in addition to TLS 1.3 for backward compatibility with older clients. By default, only TLS 1.3 is enabled.
--letsencryptEnable Let’s Encrypt configuration.
--letsencrypt-emailEmail for Let’s Encrypt account.
--enable-logrotateEnable logrotate for Odoo.
--enable-fail2banEnable fail2ban for Odoo (requires fail2ban installed).
--supervisorWhat supervisor to use for deployment. One of: odood, init-script, systemd. Default: systemd.
--log-to-stderrLog to stderr. Useful when running inside docker.
--use-system-ca-bundleSet REQUESTS_CA_BUNDLE to the system CA certificate store, so Odoo uses system certificates instead of the bundled certifi CA bundle.
--assembly-repoConfigure Odood to use assembly from this repo. Ensure, you have access to specified repo from this machine.
-h, --helpShow this help

odood server

Server management commands.

Usage:

odood server <command>

Options:

FlagDescription
-h, --helpShow 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:

FlagDescription
--ignore-runningIgnore running Odoo instance. (Do not check/create pidfile).
--wait-pgWait for PostgreSQL to be ready before starting the server.
--wait-pg-timeoutMaximum time to wait for PostgreSQL in seconds.
-h, --helpShow this help

odood server start

Run the server in background.

Usage:

odood server start [options]

Options:

FlagDescription
-t, --timeoutTimeout to wait while server starts (in seconds).
-h, --helpShow this help

odood server status

Check if server is running

Usage:

odood server status

Options:

FlagDescription
-h, --helpShow this help

odood server stop

Stop the server

Usage:

odood server stop

Options:

FlagDescription
-h, --helpShow this help

odood server restart

Restart the server running in background.

Usage:

odood server restart [options]

Options:

FlagDescription
-t, --timeoutTimeout to wait while server starts (in seconds).
-h, --helpShow this help

odood server browse

Open odoo in browser

Usage:

odood server browse

Options:

FlagDescription
-h, --helpShow this help

odood server log

View server logs.

Usage:

odood server log

Options:

FlagDescription
-h, --helpShow 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:

FlagDescription
-t, --timeoutHTTP request timeout in seconds.
-h, --helpShow this help

odood server wait-pg

Wait for PostgreSQL to become available.

Usage:

odood server wait-pg [options]

Options:

FlagDescription
-t, --timeoutMaximum time to wait in seconds.
--intervalTime between connection attempts in seconds.
-h, --helpShow this help

odood status

Show the project status.

Usage:

odood status

Options:

FlagDescription
-h, --helpShow this help

odood db

Database management commands

Usage:

odood db <command>

Options:

FlagDescription
-h, --helpShow 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:

FlagDescription
-h, --helpShow this help

odood db create

Create new odoo database.

Usage:

odood db create [options] <name>

Options:

FlagDescription
-d, --demoLoad demo data for this db
-r, --recreateRecreate database if it already exists.
--tdbAutomatically generate default name of test database
-l, --langLanguage of database, specified as ISO code of language.
--passwordAdmin password for this database.
--countryCountry for this db.
-i, --installInstall module specified by name.
--install-dirInstall all modules from directory.
--install-fileInstall all modules listed in specified file.
-h, --helpShow this help

Arguments:

NameDescription
nameName 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:

FlagDescription
--wait-pgWait for PostgreSQL to be ready before proceeding.
--wait-pg-timeoutMaximum time to wait for PostgreSQL in seconds.
-d, --demoLoad demo data (only on first initialization).
-l, --langLanguage code, e.g. en_US (only on first initialization).
-h, --helpShow this help

Arguments:

NameDescription
nameName of database.

odood db drop

Drop the odoo database.

Usage:

odood db drop <name>

Options:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
nameName of database(s) to drop.

odood db exists

Check if database exists.

Usage:

odood db exists [options] <name>

Options:

FlagDescription
-q, --quietSuppress output, just return exit code
-h, --helpShow this help

Arguments:

NameDescription
nameName of database

odood db is-initialized

Check if database is initialized as an Odoo database.

Usage:

odood db is-initialized [options] <name>

Options:

FlagDescription
-q, --quietSuppress output, just return exit code.
-h, --helpShow this help

Arguments:

NameDescription
nameName of database.

odood db rename

Rename database.

Usage:

odood db rename <old-name> <new-name>

Options:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
old-nameName of original database.
new-nameNew name of database.

odood db copy

Copy database.

Usage:

odood db copy <old-name> <new-name>

Options:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
old-nameName of original database.
new-nameNew name of database.

odood db backup

Backup database.

Usage:

odood db backup [options] <name>

Options:

FlagDescription
--zipMake ZIP backup with filestore.
--sqlMake SQL-only backup without filestore
-a, --allBackup all databases
-d, --destDestination path for backup. By default will store at project’s backup directory.
--niceLower the CPU priority of the backup by the given nice increment (1-19, higher = lower priority).
-h, --helpShow this help

Arguments:

NameDescription
nameName of database(s) to backup.

odood db restore

Restore database.

Usage:

odood db restore [options] <name> <backup>

Options:

FlagDescription
--stunStun database (disable cron and mail servers)
--selfishStop the server while database being restored.
-f, --forceEnforce restore, even if backup is not valid.
-r, --recreateRecreate database if it already exists.
-h, --helpShow this help

Arguments:

NameDescription
nameName of database to restore.
backupPath 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:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
nameName of database to stun.

odood db populate

Populate database with test data.

Usage:

odood db populate [options]

Options:

FlagDescription
-d, --dbnameName of database to populate.
-m, --modelName of model to populate. Could be specified multiple times.
-s, --sizePopulation size
--repeatRepeat population N times.
-h, --helpShow this help

odood addons

Manage third-party addons.

Usage:

odood addons <command>

Options:

FlagDescription
-h, --helpShow 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 project
  • is-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

Link addons in specified directory.

Usage:

odood addons link [options] <path>

Options:

FlagDescription
-f, --forceRewrite already linked/existing addon.
-r, --recursiveSearch for addons in this directory recursively.
--manifest-requirementsInstall python dependencies from manifest’s external dependencies
--individual-requirementsInstall Python requirements per-addon instead of batched
--with-odoo-requirementsInclude Odoo’s requirements.txt in the batch install
--ualUpdate addons list for all databases
-h, --helpShow this help

Arguments:

NameDescription
pathPath to search for addons in.

odood addons update-list

Update list of addons.

Usage:

odood addons update-list [options] <database>

Options:

FlagDescription
-a, --allUpdate all databases.
-h, --helpShow this help

Arguments:

NameDescription
databaseDatabase(s) to update addons list for.

odood addons list

List addons in specified directory.

Usage:

odood addons list [options] <path>

Options:

FlagDescription
--by-pathDisplay addons by paths.
--by-nameDisplay addons by name (default).
--by-name-versionDisplay addon name with addon version
-s, --systemSearch for all addons available for Odoo.
-r, --recursiveSearch for addons recursively.
--installableFilter only installable addons.
--not-installableFilter only not-installable addons.
--linkedFilter only linked addons.
--not-linkedFilter only addons that are not linked.
--with-priceFilter only addons that has price defined.
--without-priceFilter only addons that does not have price defined.
--assemblyShow addons available in assembly
-t, --tableDisplay list of addons as table
-f, --fieldDisplay provided field in table. This have to be valid field from manifest.
-c, --colorColor output by selected scheme: link - color addons by link status, installable - color addons by installable state.
-h, --helpShow this help

Arguments:

NameDescription
pathPath to search for addons in.

odood addons update

Update specified addons.

Usage:

odood addons update [options] <addon>

Options:

FlagDescription
-d, --dbDatabase(s) to apply operation to.
--dirDirectory to search for addons
--dir-rDirectory to recursively search for addons
-f, --fileRead addons names from file (addon names must be separated by new lines)
--assemblySearch for addons available in assembly
--skipSkip addon specified by name.
--skip-reSkip addon specified by regex.
--skip-fileSkip addons listed in specified file (addon names must be separated by new lines)
--skip-errorsDo not fail on errors during installation.
--ignore-unfinished-updatesDo not fail if there are unfinished addon install/update/uninstall operations.
--startStart server after update (if everything is ok)
--ualUpdate addons list before update.
-a, --allUpdate all modules
--installed-onlySkip addons that are not installed in the database.
-h, --helpShow this help

Arguments:

NameDescription
addonNames of addons to operate on.

odood addons install

Install specified addons.

Usage:

odood addons install [options] <addon>

Options:

FlagDescription
-d, --dbDatabase(s) to apply operation to.
--dirDirectory to search for addons
--dir-rDirectory to recursively search for addons
-f, --fileRead addons names from file (addon names must be separated by new lines)
--assemblySearch for addons available in assembly
--skipSkip addon specified by name.
--skip-reSkip addon specified by regex.
--skip-fileSkip addons listed in specified file (addon names must be separated by new lines)
--skip-errorsDo not fail on errors during installation.
--ignore-unfinished-updatesDo not fail if there are unfinished addon install/update/uninstall operations.
--startStart server after update (if everything is ok)
--ualUpdate addons list before install.
--missing-onlySkip addons that are already installed in the database.
-h, --helpShow this help

Arguments:

NameDescription
addonNames of addons to operate on.

odood addons uninstall

Uninstall specified addons.

Usage:

odood addons uninstall [options] <addon>

Options:

FlagDescription
-d, --dbDatabase(s) to apply operation to.
--dirDirectory to search for addons
--dir-rDirectory to recursively search for addons
-f, --fileRead addons names from file (addon names must be separated by new lines)
--assemblySearch for addons available in assembly
--skipSkip addon specified by name.
--skip-reSkip addon specified by regex.
--skip-fileSkip addons listed in specified file (addon names must be separated by new lines)
--skip-errorsDo not fail on errors during installation.
--ignore-unfinished-updatesDo not fail if there are unfinished addon install/update/uninstall operations.
--startStart server after update (if everything is ok)
-h, --helpShow this help

Arguments:

NameDescription
addonNames of addons to operate on.

odood addons add

Add addons to the project

Usage:

odood addons add [options]

Options:

FlagDescription
--single-branchClone repository with –single-branch options. This could significantly reduce size of data to be downloaded and increase performance.
-r, --recursiveRecursively process odoo_requirements.txt. If set, then Odood will automatically process odoo_requirements.txt file inside repositories mentioned in provided odoo_requirements.txt
--manifest-requirementsInstall python dependencies from manifest’s external dependencies
--odoo-appsAdd addon from odoo apps.
--odoo-requirementsAdd modules (repos) from odoo_requirements.txt file (or directory containing odoo_requirements.txt), that is used by odoo-helper-scripts.
-h, --helpShow this help

odood addons is-installed

Print list of databases where specified addon is installed.

Usage:

odood addons is-installed <addon>

Options:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
addonName 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:

FlagDescription
-o, --out-filePath to file where to store generated requirements
--dirDirectory to search for addons to generate requirements.txt for.
--dir-rDirectory to recursively search for addons to generate requirements.txt for.
-h, --helpShow this help

Arguments:

NameDescription
addonName of addon to generate requirements for.

odood addons find-installed

List addons installed in specified databases

Usage:

odood addons find-installed [options]

Options:

FlagDescription
-d, --dbName of database to check for addons.
-o, --out-filePath to file where to store result
-f, --formatOutput format. One of: list, assembly-spec. Default: list.
-a, --allCheck all databases
--non-systemList only custom addons, that are not default Odoo addons.
-h, --helpShow this help

odood test

Run tests for modules.

Usage:

odood test [options] <addon>

Options:

FlagDescription
-t, --temp-dbCreate temporary database for tests.
--no-drop-dbDo not drop temporary database after test completed.
--iswIgnore warnings that are considered safe.
--simplified-logDisplay simplified log messages.
--migrationRun migration against stable branch.
--coverageCalculate code coverage.
--coverage-reportPrint coverage report.
--coverage-htmlPrepare HTML report for coverage.
--coverage-skip-coveredSkip covered files in coverage report.
--coverage-ignore-errorsIgnore coverage errors.
--coverage-fail-underFail if coverage is less than specified value.
--no-error-reportDo not print error report in the end of the test.
--error-reportPrint error report in the end of the test.
--warning-reportPrint warning report in the end of the test.
-d, --dbDatabase to run tests for.
--additional-addonSpecify additional addon to install before test.
--no-install-addonsDo not install addons before test. Could be useful to speed up local tests.
--dirDirectory to search for addons to test
--dir-rDirectory to recursively search for addons to test
-f, --fileRead addons names from file (addon names must be separated by new lines)
--skipSkip (do not run tests) addon specified by name.
--skip-reSkip (do not run tests) addon specified by regex.
--skip-fileSkip addons listed in specified file (addon names must be separated by new lines)
--migration-start-refgit reference (branch/commit/tag) to start migration from
--migration-reporun migration tests for repo specified by path
--migration-last-releaseStart migration test from the latest release tag. Fails if no release tags exist for the current Odoo serie.
--populate-modelName of model to populate. Could be specified multiple times.
--populate-sizePopulation size.
--test-tagFilter tests by tag (Odoo 12.0+). Repeatable. Supports Odoo tag syntax: plain tags, /module, /module:Class.method, -tag to exclude.
-h, --helpShow this help

Arguments:

NameDescription
addonNames of addons to run tests for.

odood repo

Manage git repositories.

Usage:

odood repo <command>

Options:

FlagDescription
-h, --helpShow 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 serie
  • bump-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:

FlagDescription
--ocaAdd Odoo Community Association (OCA) repository. If set, then ‘repo’ argument could be specified as name of repo under ‘https://github.com/OCA’ organization.
--githubAdd github repository. If set, then ‘repo’ argument could be specified as ‘owner/name’ that will be converted to ‘https://github.com/owner/name’.
--single-branchClone repository with –single-branch options. This could significantly reduce size of data to be downloaded and increase performance.
-r, --recursiveIf set, then system will automatically fetch recursively dependencies of this repository, specified in odoo_requirements.txt file inside cloned repo.
-b, --branchBranch to clone
--ualUpdate addons list.
-h, --helpShow this help

Arguments:

NameDescription
repoRepository URL to clone from.

odood repo pull-all

[Experimental] Pull changes from all repos and relink addons.

Usage:

odood repo pull-all

Options:

FlagDescription
-h, --helpShow 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:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
pathPath 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:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
pathPath 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:

FlagDescription
--majorIncrease major version for addons.
--minorIncrease minor version for addons.
--patchIncrease patch version for addons.
--ignore-translationsIgnore translations.
-h, --helpShow this help

Arguments:

NameDescription
pathPath 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:

FlagDescription
--ignore-translationsIgnore translations.
--since-last-releaseCompare against the latest release tag instead of the stable branch tip. Shows exactly what ‘odood repo release’ will verify.
-h, --helpShow this help

Arguments:

NameDescription
pathPath 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:

FlagDescription
-m, --moduleName of module to migrate
--commitCommit changes.
-h, --helpShow this help

Arguments:

NameDescription
pathPath 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:

FlagDescription
-s, --sourceSource branch to forwardport changes from
-h, --helpShow this help

Arguments:

NameDescription
pathPath 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:

FlagDescription
--initialCreate the first release for a repository with no prior tags at version .1.0.0. Skips change detection and version checking.
--majorForce a major version bump.
--minorForce a minor version bump.
--patchForce a patch version bump.
--ignore-translationsIgnore translation files (.po/.pot) when detecting changes.
--fail-nothing-to-releaseExit with code 1 when no changed addons are detected.
--pushPush the release tag (and branch) to origin.
--changelogGenerate CHANGELOG.md and CHANGELOG.latest.md and commit them before tagging.
--commit-messageCommit message for the changelog commit (default: ‘Release ’).
--commit-userGit author name for the changelog commit.
--commit-emailGit author email for the changelog commit.
-h, --helpShow this help

Arguments:

NameDescription
pathPath to repository to release (default: current directory).

odood repo hotfix

Manage hotfix (patch) releases on dedicated hotfix branches.

Usage:

odood repo hotfix <command>

Options:

FlagDescription
-h, --helpShow 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:

FlagDescription
--fromPrimary release tag to patch (e.g. 18.0.2.1.0). Must have Z == 0.
-h, --helpShow this help

Arguments:

NameDescription
pathPath 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:

FlagDescription
--ignore-translationsIgnore translation files (.po/.pot) when detecting changes.
-h, --helpShow this help

Arguments:

NameDescription
pathPath 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:

FlagDescription
--ignore-translationsIgnore translation files (.po/.pot) when detecting changes.
--fail-nothing-to-releaseExit with code 1 when no changed addons are detected.
--pushPush the release tag (and branch) to origin.
--changelogGenerate CHANGELOG.md and CHANGELOG.latest.md and commit them before tagging.
--commit-messageCommit message for the changelog commit (default: ‘Release ’).
--commit-userGit author name for the changelog commit.
--commit-emailGit author email for the changelog commit.
-h, --helpShow this help

Arguments:

NameDescription
pathPath to repository (default: current directory).

odood venv

Manage virtual environment for this project.

Usage:

odood venv <command>

Options:

FlagDescription
-h, --helpShow this help

Commands:

  • install-dev-tools — Install Dev Tools
  • install-py-packages — Install Python packages
  • reinstall — 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:

FlagDescription
-h, --helpShow this help

odood venv install-py-packages

Install Python packages

Usage:

odood venv install-py-packages [options] <package>

Options:

FlagDescription
-r, --requirementsPath to requirements.txt to install python packages from
-h, --helpShow this help

Arguments:

NameDescription
packagePython package specification to install.

odood venv reinstall

Reinstall virtualenv.

Usage:

odood venv reinstall [options]

Options:

FlagDescription
--py-versionInstall specific python version.
--node-versionInstall specific node version.
-h, --helpShow this help

odood venv update-odoo

Update Odoo itself.

Usage:

odood venv update-odoo [options]

Options:

FlagDescription
-b, --backupBackup Odoo before update.
-h, --helpShow this help

odood venv reinstall-odoo

Reinstall Odoo to different Odoo version.

Usage:

odood venv reinstall-odoo [options]

Options:

FlagDescription
-b, --backupBackup Odoo before update.
--no-backupDo not take backup of Odoo and venv.
--venv-py-versionInstall specific python version.
--venv-node-versionInstall specific node version.
--install-typeInstallation type. Accept values: git, archive. Default: archive.
-v, --versionOdoo version to install.
-h, --helpShow this help

odood venv pip

Run pip for this environment. All arguments after ‘–’ will be forwarded directly to pip.

Usage:

odood venv pip

Options:

FlagDescription
-h, --helpShow this help

odood venv npm

Run npm for this environment. All arguments after ‘–’ will be forwarded directly to npm.

Usage:

odood venv npm

Options:

FlagDescription
-h, --helpShow this help

odood venv ipython

Run ipython in this environment. All arguments after ‘–’ will be forwarded directly to IPython.

Usage:

odood venv ipython

Options:

FlagDescription
-h, --helpShow this help

odood venv python

Run python for this environment. All arguments after ‘–’ will be forwarded directly to python.

Usage:

odood venv python

Options:

FlagDescription
-h, --helpShow this help

odood venv lodoo

Run lodoo in this environment. All arguments after ‘–’ will be forwarded directly to lodoo.

Usage:

odood venv lodoo

Options:

FlagDescription
-h, --helpShow 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:

FlagDescription
-h, --helpShow this help

odood odoo

Odoo-related utility commands.

Usage:

odood odoo <command>

Options:

FlagDescription
-h, --helpShow this help

Commands:

  • shell — Run an interactive Odoo shell.
  • recompute — Recompute stored fields for a model.

odood odoo shell

Run an interactive Odoo shell.

Usage:

odood odoo shell [options]

Options:

FlagDescription
-d, --dbDatabase to run shell for.
-h, --helpShow this help

odood odoo recompute

Recompute stored fields for a model.

Usage:

odood odoo recompute [options]

Options:

FlagDescription
-f, --fieldName of field to recompute.
-d, --dbName of database to recompute fields for.
--all-dbRecompute for all databases.
-m, --modelName of model to recompute fields for
-h, --helpShow this help

odood assembly

Manage assembly of this project

Usage:

odood assembly [options] <command>

Options:

FlagDescription
-p, --assembly-pathPath to assembly directory.
-h, --helpShow this help

Commands:

  • init — Initialize assembly for this project
  • use — Use (attach) assembly located at specified path. Mostly useful in CI flows.
  • status — Project assembly status
  • sync — Synchronize assembly with updates from sources.
  • link — Link addons from this assembly to custom addons
  • pull — 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:

FlagDescription
--repoUrl to git repo with assembly to use for this project.
-h, --helpShow this help

odood assembly use

Use (attach) assembly located at specified path. Mostly useful in CI flows.

Usage:

odood assembly use <path>

Options:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
pathPath to already existing assembly.

odood assembly status

Project assembly status

Usage:

odood assembly status

Options:

FlagDescription
-h, --helpShow this help

odood assembly sync

Synchronize assembly with updates from sources.

Usage:

odood assembly sync [options]

Options:

FlagDescription
--commitCommit changes.
--commit-messageCommit message
--commit-userName of user to use for commit
--commit-emailEmail of user to use for commit
--fail-nothing-to-commitFail (set exit code = 1) if there is nothing to commit
--pushAutomatically push changes if needed.
--push-toName of branch to push changes to.
--changelogGenerate changelog for assembly.
--dockerfileGenerate Dockerfile for assembly.
--generate-lockGenerate requirements.lock.txt after syncing
--with-odoo-requirementsInclude Odoo’s requirements.txt when generating lock file
-h, --helpShow this help

Link addons from this assembly to custom addons

Usage:

odood assembly link [options]

Options:

FlagDescription
--manifest-requirementsInstall python dependencies from manifest’s external dependencies
--individual-requirementsInstall Python requirements per-addon instead of batched
--with-odoo-requirementsInclude Odoo’s requirements.txt in the batch install
--ualUpdate addons list for all databases
-h, --helpShow this help

odood assembly pull

Pull updates for this assembly.

Usage:

odood assembly pull [options]

Options:

FlagDescription
--linkRelink addons in this assembly after pull
-h, --helpShow this help

odood assembly upgrade

Upgrade assembly (optionally do backup, pull changes, update addons).

Usage:

odood assembly upgrade [options]

Options:

FlagDescription
--backupDo backup of all databases
--skip-errorsContinue upgrade next databases if upgrade of db had error.
--startStart the server if upgrade completed successfully and server was not running before upgrade.
-h, --helpShow 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:

FlagDescription
--commitCommit the updated spec.
--commit-messageCommit message.
--commit-userName of user to use for commit.
--commit-emailEmail of user to use for commit.
--pushPush changes after committing.
--push-toName of branch to push changes to.
-h, --helpShow this help

odood script

Run scripts in Odood environment.

Usage:

odood script <command>

Options:

FlagDescription
-h, --helpShow this help

Commands:

  • py — Run Python script in this environment.
  • sql — Run SQL script in this environment.

odood script py

Run Python script in this environment.

Usage:

odood script py [options] <script>

Options:

FlagDescription
-d, --dbDatabase to run script for
-h, --helpShow this help

Arguments:

NameDescription
scriptPath to script to run

odood script sql

Run SQL script in this environment.

Usage:

odood script sql [options] <script>

Options:

FlagDescription
-d, --dbDatabase to run script for
-n, --no-commitDo not commit changes.
-h, --helpShow this help

Arguments:

NameDescription
scriptPath to script to run

odood psql

Run psql for specified database

Usage:

odood psql [options]

Options:

FlagDescription
-d, --dbName of database to connect to.
-h, --helpShow this help

odood pre-commit

Work with pre-commit dev tool.

Usage:

odood pre-commit <command>

Options:

FlagDescription
-h, --helpShow 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:

FlagDescription
-f, --forceEnforce initialization. This will rewrite pre-commit configurations.
--no-setupDo not set up pre-commit. Could be used if pre-commit already set up.
--odoo-helper-compatGenerate pre-commit config compatible with odoo-helper linting style (check-only, no auto-formatting).
-h, --helpShow this help

Arguments:

NameDescription
pathPath 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:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
pathPath to repository to configure.

odood pre-commit update

Update pre-commit for specified repo.

Usage:

odood pre-commit update <path>

Options:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
pathPath to repository to configure.

odood pre-commit run

Run pre-commit for specified repo.

Usage:

odood pre-commit run <path>

Options:

FlagDescription
-h, --helpShow this help

Arguments:

NameDescription
pathPath to repository to run pre-commit for.

odood translations

Manage translations for this project.

Usage:

odood translations <command>

Options:

FlagDescription
-h, --helpShow this help

Commands:

  • regenerate — Regenerate translations for specified addons.

odood translations regenerate

Regenerate translations for specified addons.

Usage:

odood translations regenerate [options] <addon>

Options:

FlagDescription
--pot-remove-datesRemove dates from generated .pot file.
--potGenerate .pot file for translations.
--pot-updateUpdate translations based on regenerated .pot file.
--missing-onlyGenerate only missing translations.
--no-drop-dbDo not drop database after regeneration of translations
--addon-dirDirectory to search for addons
--addon-dir-rDirectory to recursively search for addons
--lang-fileCombination of lang and file (separated by ‘:’) to generate translations for. For example: uk_UA:uk.
-l, --langLanguage to generate translations for. For example: uk_UA.
-h, --helpShow this help

Arguments:

NameDescription
addonNames of addons to regenerate translations for.

odood config

Manage config of the project

Usage:

odood config <command>

Options:

FlagDescription
-h, --helpShow this help

Commands:

  • update — Update the config.

odood config update

Update the config.

Usage:

odood config update

Options:

FlagDescription
-h, --helpShow this help

odood discover

Discover already installed odoo, and configure Odood to manage it.

Usage:

odood discover <command>

Options:

FlagDescription
-h, --helpShow 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:

FlagDescription
-s, --systemDiscover system (server-wide) odoo-helper project installation.
-h, --helpShow this help

Arguments:

NameDescription
pathTry to discover odoo-helper project in specified path.

odood info

Print info about this Odood project.

Usage:

odood info [options]

Options:

FlagDescription
--jsonPrint output in json format
-h, --helpShow 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

FieldRequiredDefaultDescription
addons-listyesList of addon entries to include in the assembly.
sources-listno[]List of git source entries to fetch addons from. Alias: git-sources.
known-addonsno[]Addon names assumed to be present on the target server; excluded from dependency validation.
layoutnostandardControls 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
FieldRequiredDefaultDescription
nameyesTechnical name of the Odoo addon.
sourcenonullName 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_appsnofalseWhen 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

FieldExpands to
url: <full-url>used as-is
github: owner/repohttps://github.com/owner/repo
oca: repohttps://github.com/OCA/repo
crnd: group/repossh://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

FieldRequiredDefaultDescription
url / github / oca / crndyesGit repository URL (see shortcuts above).
namenonullIdentifier for this source. Used to bind addons via source: and as the credential lookup key for private repos.
refnonullBranch or tag to clone/fetch. Alias: branch (deprecated).
commitnonullCommit hash to check out after fetching ref. Minimum 12 hex characters. Requires ref to be set.
access-groupnonullCredential group name for private repos. Overrides name for credential lookup. See Private git sources.
no-searchnofalseWhen 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

ValueBehaviour
standardSynced addons are placed in the dist/ subdirectory of the assembly repo.
flatSynced 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-addons inside 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-tag option for odood test command
  • Experimental odood repo release command, that could automatically tag repo and generate changelogs.
  • Experimental odood repo hotfix command, that could be used to manage hotfixes of repositories.
  • Experimental odood assembly upgrade-sources command, that allows to bump pinned releases on repository.
  • Experimental odood test --migration-last-release option, that allows to test repo migration against latest release.
  • Added option odood db backup --nice that 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 msguniq before msgmerge when regenerating translations, because AI too frequently generates duplicate translations and msgmerge fails
  • Use data_dir from odoo.conf for backup/restore to ensure backups are correct when data_dir changed to non-standard location. Before fix, it was required to modify data dir on both places: odood.yml and odoo.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-search param 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, or odood venv reinstall), all Python requirements are now gathered and installed in a single pip install call instead of one call per addon. This improves performance and lets pip resolve the full dependency tree at once.
    • New flag --individual-requirements for odood addons link and odood assembly link to fall back to per-addon installation (old behavior).
    • New flag --with-odoo-requirements for odood addons link and odood assembly link to include Odoo’s own requirements.txt in the batch install.
  • Assembly requirements lock file support: if requirements.lock.txt exists in the assembly root, odood assembly link installs 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-lock for odood assembly sync to generate the lock file after syncing (runs pip freeze to produce pinned versions).
    • New flag --with-odoo-requirements for odood assembly sync to include Odoo’s requirements when generating the lock file.
  • New flag --odoo-helper-compat for odood pre-commit init that 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 odoolint catchall check to the default pylintrc
  • Added support for commit pinning on the assembly spec
  • Added --log-to-stderr flag to odood init (mirrors odood 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 reinstall now installs all addon Python requirements in a single batched pip call instead of one per addon.
  • Switched to darkarchive lib 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 healthcheck command. One step to make Odood container-friendly.
  • Added odood server wait-pg command
  • Added odood server run --wait-pg option
  • Added odood db is-initialized command to check if database is already initialized.
  • Added odood db ensure-initialized command 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-compat flag to odood deploy to allow TLS 1.2 in addition to TLS 1.3 for backward compatibility with older clients.
  • Added --use-system-ca-bundle flag to odood deploy to set REQUESTS_CA_BUNDLE to the system CA certificate store. Auto-detects the CA bundle path across Debian/Ubuntu, RHEL/CentOS/Fedora, and openSUSE.

Changed

  • Changed template for nginx configuration for deploy command:
    • 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-compat to enable TLS 1.2 with ECDHE forward secrecy ciphers.
  • Command odood db list rewritten in D (no more python / lodoo call)
  • Commands odood addons install and odood addons update now 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-pg insteand of odood 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 test to fail.

Fixed

  • Odood now will handle db_sslmode parameter correctly inside it’s internal database interactions

Release 0.5.5 (2026-02-25)

Added

  • New command odood venv lodoo that 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-addons key 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 --dockerfile that allows to automatically generate Dockerfile for assembly on sync. Thus we have the way to build standard images for assemblies.
  • 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 update that could be used to update pre-commit dependencies (in pre-commit config). Just an alias for standard pre-commit autoupdate that is run inside correct repo dir and within correct venv.
  • Added option --workers to deploy command

Changed

  • Clean up pip cache after deploy, when docker image is built.
  • Assembly, if VERSION, Dockerfile or .dockerignore changed, that commit of changes allowed.

Release 0.5.3 (2026-01-08)

Added

  • Build docker images for ARM64 architecture
  • New option to assembly upgrade command:
    • --start - automatically start server if upgrade is successful and server was not running before upgrade.
  • Added new option odood assembly --assembly-path that 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.txt file, it will be processed automatically before assembly link operation.

Release 0.5.2 (2025-12-23)

Added

  • Added option --start to addons install/update/uninstall command to automatically start server if it was stopped.
  • Added automatic generation of changelogs on assembly sync if option --changelog specified. 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 deploy command:
    • local-nginx-ssl to enable SSL configuration for local nginx
    • local-nginx-ssl-key choose path to ssl key for the server
    • local-nginx-ssl-cert choose paht to ssl certificate for the server
  • Git sources in assembly spec now supports shortucts github and oca that 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-group for sources in odood-assembly.yml), this way it is possible to use same token for multiple repos. The name is ODOOD_ASSEMBLY_access_group_CRED
    • The format of ODOOD_ASSEMBLY_<group/repo>_CRED variable is username:password
  • During assembly upgrade, check for unfinished install/upgrade and print waring if there are any unfinished install/upgrade/uninstall
  • Added new option assembly-repo for odood deploy command, 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 use command. This could be useful in CI to automate assembly sync process.
  • Added new options to specify commit params for odood assembly sync command.
  • Added experimental odood repo do-forward-port command

Changed

  • odood log now will automatically show the end of logfile

Release 0.4.3 (2025-07-05)

Added

  • Addd new command odood repo migrate-addons that 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-versions that could be used to check if module versions updated.
  • New option --lang to odood translate regenerate command. With this option, translation file will be detected automatically.
  • New option --repeat to odood db populate command, 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 populate that allows to populate database with test data
  • New options to odood test command (--populate-model and --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 assembly that could be used to manage Odoo instance in assembly style, when all addons used on instance are placed in single repo.
  • Added new flag --assembly to odood addons list/update/install/uninstall commands

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-addons renamed to odood addons find-installed.
  • Command odood addons find-installed got 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-versions to automatically bump versions of modules
  • Added new options for odood deploy command:
    • --local-nginx that allows to automatically configure local nginx (requires nginx installed)
    • --enable-fail2ban that 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 regenerate that allows to regenerate translations for modules. Could be useful to automatically or semiautomatically generate .po and .pot files for modules. Also, this command available as shortcut odood tr regenerate.
  • New flag --no-install-addons added to odood 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 deploy command)

Release 0.2.2 (2025-03-10)

Added

  • Experimental support for PyEnv integration.

Changed

  • Replace dpq with Peque
  • odood script py command: 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 entrypoint that 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 recompute that allows to recompute computed fields for specified model in specified database.

Release 0.2.0 (2024-12-12)

Added

  • New experimental command odood deploy that could be used to deploy production-ready Odoo instance.
  • Added experimental support for Odoo 18
  • Added new command odood repo fix-series that 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-commit subcommand. Thus, following commands now available to work with pre-commit:
    • odood pre-commit init
    • odood pre-commit set-up
    • odood pre-commit run
  • Change command odood server run. Command uses execv to run Odoo, thus, Odoo process will replace Odood process. Thus, option --detach is not available here. If you want to start Odoo in background, then odood server start command 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 command odood server run -- -d my_database --install=crm --stop-after-init, that will install crm module, will be translated to odoo -d my_database --install=crm --stop-after-init, that will be ran inside virtualenv of current Odood project.
    • Added new option --ignore-running that allows to ignore server running.
    • Removed option --detach as it does not have sense. Use odood server start instead.
  • Changed generation of default test db name. Before it was: odood<serie>-odood-test Now it will be: <db_user>-odood-test

Release 0.1.0 (2024-08-15)

Added

  • New command odood venv pip that allows to run pip from current venv.
  • New command odood venv npm that allows to run npm from current venv.
  • New command odood venv python that allows to run python from current venv.
  • New command odood venv ipython that allows to run ipython from current venv.
  • Added new option --ual to command odood repo add that allows to automatically update list of addons when repository was added.
  • New command odood venv run that allows to run any command from current venv.
  • New command odood repo run-pre-commit to 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 test command:
    • --file that could be used to pass the path to file to read addons to test from
    • --skip-file read 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/uninstall with 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 --skip and --skip-re to odood test command, that allow to not run tests for specified addons. Useful in cases, when there is need to skip some addons found via options --dir and --dir-r
  • Added new options --skip and --skip-re to odood addons install/update/uninstall commands. Useful in cases, when there is need to skip some addons found via options --dir and --dir-r
  • Added new option --skip-errors to odood addons install/update/uninstall commands, 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-type to odood init and odood venv reinstall-odoo commands, 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/uninstall now will report Odoo errors raised during addons installation.

Release 0.0.13 (2023-09-08)

Added

  • Command odood addons generate-py-requirements that allows to generate requirements txt files for specified modules.
  • Added new option --tdb to odood db create command, 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 shell that 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_DIR environment variable is set.

Release 0.0.11 (2023-07-27)

Added

  • New option --simplified-log added to odood test command. Thus it is possible to display meaningful log info (log level, logger, message).

Changed

  • Command odood venv reinstall-odoo now 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-addons passed for tests in case when migration test enabled: update that addons before running tests.

Release 0.0.10 (2023-07-08)

Added

  • New option --all to odood db backup command, that allows to backup all databases within single command.
  • New command info that will display info about project, optionally in JSON fromat.
  • New option --file to odood addons install and odood addons update commands. 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-file to odood db create command, that will automatically install modules from specified files.
  • New option --coverage-ignore-errors to odood test command, that allows to ignore coverage errors, that a frequent case during migration tests (because files available on start may disapear during migration).
  • New option --recreate to db restore command, thus it is possible to automatically drop database before restoration if needed.
  • Added flag --backup to venv update-odoo command.
  • 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 --dest option supplied and it is existing directory, then database will be backed up in this directory with automatically generated name of backup.
  • Automatically supply --ignore-errors to coverage when running migration tests

Release 0.0.9 (2023-06-01)

Added

  • New option --ual to odood addons install and odood addons update comands
  • New option --additional-addon to odood test command
  • New options for odood addons list command:
    • --with-price and --without-price for odood addons list command
    • --color=price to highlight addons that have or have no prices
    • --table to output list of addons as table
  • New command odood venv install-py-packages that could be used to easily install python packages in Odood virtualenv environment
  • New option --warning-report to odood test command: 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-conflict to resolve version conflicts in module manifests

Changed

  • odood test command: show error report by default, but add option to disable it.
  • Clone repos recursively optionally. Before this change, command odood repo add was clonning repositories recursively (parse odoo_requirements.txt file in clonned repo and clone dependencies mentioned there). After this change, recursive add repo is optional, end could be enable by option odood repo add --recursive ...
  • odoo test with option --isw will additionally ignore following warning: unknown parameter 'tracking'