A small set of DevOps utilities for Odoo deployments and local development.
Project description
odoo-devops-tools
A small set of DevOps utilities for Odoo deployments and local development.
The main entrypoint is odt-env — a CLI that provisions and syncs a reproducible Odoo workspace from an INI file.
What odt-env does
- Clones and updates Odoo and addon repositories
- Generates a ready-to-run
odoo-server.conf - Generates helper scripts (run, test, backup/restore, update, …)
- Optionally provisions a Python virtual environment and a wheelhouse (useful for offline installs / CI builds)
odt-env is designed to be repeatable: re-running it should converge your workspace to what the INI file describes.
Table of contents
- Installation
odt-env
Installation
Using pip:
pip install odoo-devops-tools
Or using uv:
uv tool install --reinstall odoo-devops-tools
Verify:
odt-env --help
odt-env
Provision and sync a reproducible Odoo workspace from an INI configuration file.
Requirements
- git
- uv (Python package & project manager): https://docs.astral.sh/uv/
Optional (only for some helper scripts):
- PostgreSQL client tools (e.g.
pg_dump,psql) for backup/restore.
Quick start
1) Typical local dev (sync + venv + configs/scripts)
odt-env /path/to/ROOT/odoo-project.ini --sync-all --create-venv
2) Sync repositories only (no Python provisioning)
odt-env /path/to/ROOT/odoo-project.ini --sync-all
3) CI / build machine: create wheelhouse (no install into venv)
odt-env /path/to/ROOT/odoo-project.ini --sync-all --create-wheelhouse
4) Offline install from an existing wheelhouse
odt-env /path/to/ROOT/odoo-project.ini --create-venv --reuse-wheelhouse
5) Hard rebuild of the venv
odt-env /path/to/ROOT/odoo-project.ini --sync-all --rebuild-venv
If you run no options, odt-env only regenerates configs and helper scripts:
odt-env /path/to/ROOT/odoo-project.ini
Concepts: ROOT vs. DEST_ROOT
-
ROOT is where the workspace is physically created (repos, venv, wheelhouse, generated files).
- Default: the directory containing the INI file.
- Override with
--root(must point to an existing directory).
-
DEST_ROOT controls what paths get embedded into generated files (configs/scripts).
- Default: same as ROOT.
- Override with
--dest-root(does not need to exist on the build machine).
A typical deployment workflow is: build under a temporary directory, but generate configs/scripts that reference the final location on the target host:
odt-env /path/to/odoo-project.ini --sync-all --create-wheelhouse \
--root /tmp/build-root \
--dest-root /srv/odoo/myproject
Workspace layout
ROOT is the directory containing odoo-project.ini (or the path passed via --root).
If you pass --dest-root, odt-env still writes files under ROOT, but paths embedded in generated files are based on DEST_ROOT.
Default layout:
ROOT/odoo/— Odoo repositoryROOT/odoo-addons/<name>/— addon repositoriesROOT/odoo-backups/— backups directoryROOT/odoo-data/— data directory (customizable via[config] data_dir)ROOT/odoo-configs/— generated config (e.g.odoo-server.conf)ROOT/odoo-scripts/— generated helper scriptsROOT/odoo-logs/— runtime logs (created byinstance.sh)ROOT/venv/— virtualenv / Python toolchain (when enabled)ROOT/wheelhouse/— wheel cache for offline installs (when enabled)
Configuration (INI)
Sections overview
odt-env reads an INI file with these sections:
[virtualenv]— Python version, managed Python, requirements, constraints…[odoo]— Odoo repo + branch[addons.<name>]— addon repos (repeatable per addon)[config]— values rendered intoodoo-server.conf(db, ports, log settings, …)[include]— optional includes (config inheritance)
Example configuration
This example provisions an Odoo 18.0 workspace with two addon repositories:
[virtualenv]
python_version = 3.11
# Optional (default: true): when false, odt-env will NOT install a managed CPython via `uv python install`.
# Instead it will rely on an existing system Python that matches `python_version`.
# managed_python = false
build_constraints =
requirements =
requirements_ignore =
[odoo]
repo = https://github.com/odoo/odoo.git
branch = 18.0
# Optional: If true, keep repo as a shallow, single-branch clone (depth=1). If false (default), do a full clone/fetch.
shallow_clone = true
[addons.oca-web]
repo = https://github.com/OCA/web.git
branch = 18.0
[addons.oca-helpdesk]
repo = https://github.com/OCA/helpdesk.git
branch = 18.0
[config]
http_port = 8069
gevent_port = 8072
db_host = 127.0.0.1
db_port = 5432
db_name = sample_odoo18
db_user = sample_odoo18
db_password = sample_odoo18
log_level = debug
max_cron_threads = 0
Includes (config inheritance)
You can split configuration across multiple INI files (for example a shared base + environment-specific overrides).
Rules:
- paths are resolved relative to the INI file that declares the include,
- included files load first; the including file loads last (later values override earlier ones),
- prefix a file path with
?to make it optional (missing file is skipped).
Example:
odoo-base.ini:
[virtualenv]
python_version = 3.11
build_constraints =
requirements =
requirements_ignore =
[odoo]
repo = https://github.com/odoo/odoo.git
branch = 18.0
[config]
http_port = 8069
gevent_port = 8072
db_host = 127.0.0.1
db_port = 5432
db_name = sample_odoo18
db_user = sample_odoo18
db_password = sample_odoo18
odoo-dev.ini:
[include]
files = odoo-base.ini
[odoo]
branch = develop
[config]
db_name = sample_odoo18_dev
odoo-test.ini:
[include]
files =
odoo-base.ini
?odoo-dev.ini
[config]
db_name = sample_odoo18_test
Variables & interpolation
odt-env uses Python ExtendedInterpolation, so you can reference values with ${section:option}.
It also injects workspace path variables into the INI DEFAULT scope (available from any section):
${ini_dir}— directory containing the INI file${root_dir}— workspace root directory${odoo_dir}—ROOT/odoo${addons_dir}—ROOT/odoo-addons${backups_dir}—ROOT/odoo-backups${configs_dir}—ROOT/odoo-configs${config_path}— full path to the generatedodoo-server.conf${scripts_dir}—ROOT/odoo-scripts${venv_python}— full path to the venv Python executable
Note on --dest-root:
odt-envalways builds under filesystem ROOT.- When
--dest-rootis provided, variables like${root_dir},${odoo_dir},${addons_dir}, … are evaluated against DEST_ROOT for the[config]section (so generatedodoo-server.confuses deployment paths). - Other sections (
[odoo],[addons.*],[virtualenv]) continue to use filesystem ROOT (so git/venv/wheelhouse operations work locally). ${ini_dir}always points to the directory of the entry INI file on the build machine (useful for includes).
Tip: create your own helper section (e.g. [vars]) and reuse it elsewhere:
[vars]
project = sample_odoo18
branch = 18.0
[virtualenv]
python_version = 3.11
requirements =
-r ${ini_dir}/requirements-dev.txt
[odoo]
repo = https://github.com/odoo/odoo.git
branch = ${vars:branch}
[addons.oca-web]
repo = https://github.com/OCA/web.git
branch = ${odoo:branch}
[config]
db_name = ${vars:project}
data_dir = ${root_dir}/odoo-data/${vars:project}
logfile = ${root_dir}/odoo-logs/${vars:project}.log
addons_path behavior
odt-env always computes a base addons_path for odoo-server.conf that includes:
- the Odoo core addons directory (
ROOT/odoo/addonsand/orROOT/odoo/odoo/addons), - every synced addon repository (
ROOT/odoo-addons/<name>).
If you set addons_path in [config], it extends (appends to) the computed base list (it does not replace it). Duplicates are removed.
Format:
- comma-separated list and/or multi-line value,
- relative paths are resolved relative to
ROOT(same as${root_dir}).
Example:
[config]
addons_path =
odoo-addons/3rd_party_addons,
${addons_dir}/extra_addons,
Shallow clones (shallow_clone)
By default, repositories are kept as full clones (full history, branches, tags). For very large repositories (especially odoo/odoo), you can enable a shallow, single-branch workflow.
Where to set it:
[odoo] shallow_clone = true[addons.<name>] shallow_clone = true
Behavior:
- initial clone:
git clone --depth 1 --single-branch --branch <branch> … - sync/update: fetch only
origin <branch>with--depth 1, then hard-reset toorigin/<branch>
Pros:
- faster clone/fetch
- less disk usage
Limitations:
- depth is fixed to 1 (only the branch tip is available),
- operations requiring history (e.g. long
git log,git bisect,git describeon older tags) won’t work as expected, - switching from full → shallow does not automatically drop history; delete the repo directory and re-sync to realize the benefits.
Switching back to full:
- set
shallow_clone = false(or remove it) and re-run a sync;odt-envwill unshallow and widen the fetch refspec so laterfetch --all --tagscan pull all branches/tags.
Command-line options
Tip: The quick-start section covers the most common workflows. Use this section as a reference when you need to fine-tune behavior.
Paths & outputs
--root— workspace ROOT directory (default: directory containing the INI)--dest-root— deployment root for paths embedded in generated configs/scripts (default: same as ROOT)--no-configs— do not generate config files (e.g.odoo-server.conf)--no-scripts— do not generate helper scripts underROOT/odoo-scripts/--no-data-dir— do not create the Odoo data folder underROOT/odoo-data/(or custom[config] data_dir)
Repository sync
--sync-odoo— sync onlyROOT/odoo--sync-addons— sync onlyROOT/odoo-addons/*(no-op if no[addons.*]sections exist)--sync-all— sync both Odoo + addons
Python / venv / wheelhouse
--create-venv— create/updateROOT/venvand install Python dependencies (from wheelhouse)--rebuild-venv— delete + recreateROOT/venv(implies--create-venv)--create-wheelhouse— build/update the lock +ROOT/wheelhouse/without installing requirements into venv
(may still create/updateROOT/venv/as a Python toolchain)--reuse-wheelhouse— reuse an existingROOT/wheelhouse/and install strictly offline (requires--create-venv)--clear-pip-wheel-cache— remove all items from pip’s wheel cache
Python environment & wheelhouse
Python dependencies are installed into the venv only when you pass --create-venv (or --rebuild-venv).
- venv location:
ROOT/venv - Python version:
[virtualenv] python_version - tooling:
uv venvanduv pip - wheelhouse location:
ROOT/wheelhouse/ - installs use offline mode from wheelhouse (
--offline --no-index)
Reuse an existing wheelhouse (offline)
If ROOT/wheelhouse/ is already prepared:
odt-env /path/to/odoo-project.ini --create-venv --reuse-wheelhouse
This skips lock compilation and wheel building and performs a strict offline install from the existing wheelhouse. You can combine it with --sync-all/--sync-odoo/--sync-addons (repo sync still happens; deps install is offline).
Managed Python install
By default, odt-env manages the requested CPython version via uv:
- Option:
[virtualenv] managed_python - Default:
true
Behavior:
managed_python = true: when creatingROOT/venv/,odt-envensures the requested Python exists by runninguv python install.managed_python = false:odt-envskipsuv python installand relies on an already-installed system Python that matchespython_version.
Example:
[virtualenv]
python_version = 3.11
managed_python = false
Generated helper scripts
Scripts are generated into ROOT/odoo-scripts/. All scripts:
- use the generated config file (
ROOT/odoo-configs/odoo-server.conf), - forward extra CLI arguments to the underlying command.
Script list
Linux/macOS:
run.sh— start Odoo in the foregroundinstance.sh— manage Odoo as a background service (start/stop/restart/status) and log toROOT/odoo-logs/odoo-server.logtest.sh— run testsshell.sh— open an interactive Odoo shellinitdb.sh— initialize databasebackup.sh— create a timestamped ZIP backup (DB + filestore) intoROOT/odoo-backups/restore.sh— restore a backup ZIPrestore_force.sh— restore and overwrite an existing DBupdate.sh— update modules, auto-detecting addons to update using file-content hashes stored in the DBupdate_all.sh— force a full upgrade (-u base)
Windows:
run.bat,test.bat,shell.bat,initdb.bat,backup.bat,restore.bat,restore_force.bat,update.bat,update_all.bat
Common usage
Start the server:
./odoo-scripts/run.sh
odoo-scripts\run.bat
Manage the background instance (Linux only):
./odoo-scripts/instance.sh start
./odoo-scripts/instance.sh status
./odoo-scripts/instance.sh restart
./odoo-scripts/instance.sh stop
Update modules:
./odoo-scripts/update.sh
odoo-scripts\update.bat
Run tests:
./odoo-scripts/test.sh -u base
./odoo-scripts/test.sh -u mail,web
./odoo-scripts/test.sh -u my_custom_addon
odoo-scripts\test.bat -u base
odoo-scripts\test.bat -u mail,web
odoo-scripts\test.bat -u my_custom_addon
Backup / restore:
./odoo-scripts/backup.sh
./odoo-scripts/restore.sh PATH/TO/BACKUP.zip
./odoo-scripts/restore_force.sh PATH/TO/BACKUP.zip
odoo-scripts\backup.bat
odoo-scripts\restore.bat PATH\TO\BACKUP.zip
odoo-scripts\restore_force.bat PATH\TO\BACKUP.zip
Safety: local changes policy
If any target repository (Odoo or an addon) contains local uncommitted changes (including untracked files), odt-env aborts. Commit/stash/clean your working tree before running odt-env.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file odoo_devops_tools-1.0.2.tar.gz.
File metadata
- Download URL: odoo_devops_tools-1.0.2.tar.gz
- Upload date:
- Size: 31.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
66b8da964873d6e0dce5fb2b265b9c9f2c8f7a20cfc6fe307f93830145ee8180
|
|
| MD5 |
92890d3fee1225a89331c7764cadc458
|
|
| BLAKE2b-256 |
cbaad8883cea784992c0329ba1326e7d1935331b6cc5d5bcccd11712af9b7fb3
|
File details
Details for the file odoo_devops_tools-1.0.2-py3-none-any.whl.
File metadata
- Download URL: odoo_devops_tools-1.0.2-py3-none-any.whl
- Upload date:
- Size: 26.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fece8ada0f04d65b12eec22ec143d25d0479a1b56c1d7d982b8cc57b9ae9b23b
|
|
| MD5 |
0eb39287c8275f3f5d2a47185efc62cd
|
|
| BLAKE2b-256 |
980a5844594698ee4e3aaface3950d8f364a3c6b31abba8d6c35899f5d1858ec
|