Installing Odoo Modules via Command Line and Git: Complete Guide

08.01.2026
19:40

Odoo's modular architecture makes it one of the most flexible ERP systems available. While the standard installation includes core modules, Odoo's real power comes from thousands of community and commercial modules. This guide covers professional module management: using command-line tools and git version control for installation, updates, and maintenance.

Why Choose CLI and Git Over Web Interface

Installing modules through Odoo's web interface is straightforward — upload a ZIP file, click install, done. However, this approach has significant limitations for professional deployments:

No Version Control. You lose track of which module versions are installed, when updates occurred, and what changed between versions.

Manual Update Process. Each module requires individual manual updates through the interface. With dozens of modules, this becomes hours of repetitive work.

Dependency Hell. Modules often depend on other modules. Manual dependency tracking and installation through the GUI quickly becomes unmanageable.

Zero Automation. You cannot automate module installation in CI/CD pipelines, Docker containers, or when provisioning new instances.

No Change History. When a module breaks your system, rolling back to a previous working version is nearly impossible.

Professional deployment requires git for module management and CLI for installation. This approach provides complete control, reproducibility, and automation capabilities that scale with your organization.

Understanding Odoo Module Architecture

Before installing modules, understanding Odoo's module structure is essential.

Directory Structure

Odoo searches for modules in directories specified in the addons_path configuration parameter. Standard structure:

/opt/odoo/
├── odoo/                    # Core Odoo codebase
│   └── addons/             # Built-in modules
├── addons/                  # Official Enterprise modules
└── custom-addons/          # Your custom modules
    ├── module1/
    ├── module2/
    └── module3/

Each module is a directory with specific structure:

module_name/
├── __init__.py             # Python package initialization
├── __manifest__.py         # Module metadata
├── models/                 # Data models
│   ├── __init__.py
│   └── model_name.py
├── views/                  # XML views
│   └── view_name.xml
├── security/               # Access rights
│   ├── ir.model.access.csv
│   └── security.xml
├── data/                   # Data to load
│   └── data.xml
├── static/                 # Static files (CSS, JS, images)
│   ├── description/
│   │   └── icon.png
│   └── src/
└── i18n/                   # Translations
    ├── es.po
    └── fr.po

Manifest File

Every module requires a __manifest__.py file containing metadаta:

{
    'name': 'Module Name',
    'version': '16.0.1.0.0',
    'category': 'Sales',
    'summary': 'Short description',
    'description': 'Detailed description',
    'author': 'Author Name',
    'website': 'https://example.com',
    'license': 'LGPL-3',
    'depends': ['base', 'sale'],
    'data': [
        'security/ir.model.access.csv',
        'views/view_name.xml',
    ],
    'demo': [
        'demo/demo_data.xml',
    ],
    'installable': True,
    'application': False,
    'auto_install': False,
}

The depends parameter is critical — it specifies module dependencies. Odoo automatically installs dependent modules.

Environment Preparation

Before installing modules, prepare your system properly.

Verify Odoo Installation

Check Odoo service status:

sudo systemctl status odoo

Verify Odoo version:

odoo --version

Alternative Python check:

python3 -c "import odoo; print(odoo.release.version)"

Identify Addons Paths

Locate Odoo configuration file:

sudo find / -name odoo.conf 2>/dev/null

Common locations:

  • /etc/odoo/odoo.conf
  • /etc/odoo.conf
  • ~/.odoorc

Check current addons paths:

grep addons_path /etc/odoo/odoo.conf

Create Custom Addons Directory

Create dedicated directory for third-party modules:

sudo mkdir -p /opt/odoo/custom-addons

Set proper ownership:

sudo chown -R odoo:odoo /opt/odoo/custom-addons

Add directory to configuration:

sudo nano /etc/odoo/odoo.conf

Find or add the addons_path line:

addons_path = /opt/odoo/odoo/addons,/opt/odoo/addons,/opt/odoo/custom-addons

Order matters — Odoo checks directories left to right. If modules with identical names exist in multiple directories, the first found is used.

Installing Modules via Git Clone

Git is the primary method for installing community modules. Most modules are hosted on GitHub or GitLab.

Finding Modules

Primary Odoo module sources:

Odoo Community Association (OCA):

  • Repository: https://github.com/OCA
  • High code quality
  • Regular updates
  • Strict code review process

GitHub:

  • Search: https://github.com/search?q=odoo+module
  • Vast module selection
  • Varying quality levels

Odoo Apps Store:

  • https://apps.odoo.com
  • Official marketplace
  • Paid and free modules

Cloning Single Module

Navigate to custom addons directory:

cd /opt/odoo/custom-addons

Clone module repository:

git clone https://github.com/OCA/sale-workflow.git

This creates a sale-workflow directory containing all repository modules.

Cloning Specific Version

Odoo modules are version-specific. For Odoo 16.0, use the 16.0 branch:

git clone -b 16.0 https://github.com/OCA/sale-workflow.git

Check available branches before cloning:

git ls-remote --heads https://github.com/OCA/sale-workflow.git

Cloning Multiple Repositories

Create script for batch module installation:

nano /opt/odoo/install-modules.sh

Script content:

#!/bin/bash

ADDONS_DIR="/opt/odoo/custom-addons"
BRANCH="16.0"

cd $ADDONS_DIR

repos=(
    "https://github.com/OCA/sale-workflow.git"
    "https://github.com/OCA/account-financial-tools.git"
    "https://github.com/OCA/project.git"
    "https://github.com/OCA/stock-logistics-warehouse.git"
)

for repo in "${repos[@]}"; do
    repo_name=$(basename $repo .git)
    if [ -d "$repo_name" ]; then
        echo "Updating $repo_name..."
        cd $repo_name
        git pull origin $BRANCH
        cd ..
    else
        echo "Cloning $repo_name..."
        git clone -b $BRANCH $repo
    fi
done

sudo chown -R odoo:odoo $ADDONS_DIR
echo "Installation completed"

Make script executable:

chmod +x /opt/odoo/install-modules.sh

Run installation:

sudo /opt/odoo/install-modules.sh

Cloning Specific Commit

Sometimes a specific module version is needed rather than latest:

git clone -b 16.0 https://github.com/OCA/sale-workflow.git
cd sale-workflow
git checkout abc123def456

Clone with limited history depth:

git clone --depth 1 -b 16.0 https://github.com/OCA/sale-workflow.git

The --depth 1 flag downloads only the latest commit without history, saving time and space.

Working with Submodule Repositories

Many Odoo projects use git submodules for dependency management.

Adding Modules as Submodules

Initialize git repository for your project:

cd /opt/odoo
git init

Add modules as submodules:

git submodule add -b 16.0 https://github.com/OCA/sale-workflow.git custom-addons/sale-workflow

Commit changes:

git add .gitmodules custom-addons/sale-workflow
git commit -m "Add sale-workflow module"

Cloning Projects with Submodules

When cloning projects with submodules:

git clone https://github.com/yourcompany/odoo-project.git
cd odoo-project

Initialize and update submodules:

git submodule init
git submodule update

Clone with submodules directly:

git clone --recurse-submodules https://github.com/yourcompany/odoo-project.git

Updating Submodules

Update all submodules to latest versions in their branches:

git submodule update --remote --merge

Update specific submodule:

git submodule update --remote custom-addons/sale-workflow

Installing Python Dependencies

Many modules require additional Python libraries.

Finding requirements.txt

Check for requirements.txt files in modules:

find /opt/odoo/custom-addons -name requirements.txt

Installing Dependencies

Install dependencies for specific module:

pip3 install -r /opt/odoo/custom-addons/sale-workflow/requirements.txt

With system packages flag:

sudo pip3 install --break-system-packages -r /opt/odoo/custom-addons/sale-workflow/requirements.txt

Creating Unified requirements.txt

Combine all requirements.txt from installed modules:

find /opt/odoo/custom-addons -name requirements.txt -exec cat {} \; | sort | uniq > /opt/odoo/all-requirements.txt

Install all dependencies at once:

pip3 install -r /opt/odoo/all-requirements.txt

Using Virtual Environment

Create virtual environment for dependency isolation:

python3 -m venv /opt/odoo/venv

Activate environment:

source /opt/odoo/venv/bin/activate

Install dependencies in environment:

pip install -r /opt/odoo/all-requirements.txt

Activating Modules via Command Line

After installing module files, activate them in Odoo.

Update Module List

Odoo scans addons directories at startup but doesn't automatically detect new modules. Update list:

odoo -d your_database -u base --stop-after-init

Command parameters:

  • -d your_database — database name
  • -u base — update base module (triggers rescan)
  • --stop-after-init — stop after initialization

Install Module via CLI

Install module in database:

odoo -d your_database -i module_name --stop-after-init

Install multiple modules simultaneously:

odoo -d your_database -i module1,module2,module3 --stop-after-init

Update Installed Module

After modifying module code, update it:

odoo -d your_database -u module_name --stop-after-init

Update all installed modules:

odoo -d your_database -u all --stop-after-init

Using odoo-bin

If Odoo installed from source:

cd /opt/odoo/odoo
./odoo-bin -d your_database -i module_name --stop-after-init

With configuration file:

./odoo-bin -c /etc/odoo/odoo.conf -d your_database -i module_name --stop-after-init

Installation Without Stopping Service

For production servers, use --no-http flag:

odoo -d your_database -i module_name --no-http

Odoo performs installation in background without starting web server.

Working with Odoo Shell

Odoo Shell is an interactive Python console for data operations.

Starting Odoo Shell

Launch shell for specific database:

odoo shell -d your_database

With configuration file:

odoo shell -c /etc/odoo/odoo.conf -d your_database

Installing Module via Shell

Install module programmatically:

env['ir.module.module'].search([('name', '=', 'sale_management')]).button_immediate_install()

Install multiple modules:

modules = env['ir.module.module'].search([('name', 'in', ['sale_management', 'purchase'])])
modules.button_immediate_install()

Checking Module Status

Check installed modules:

installed = env['ir.module.module'].search([('state', '=', 'installed')])
for module in installed:
    print(f"{module.name}: {module.latest_version}")

Find modules requiring updates:

to_upgrade = env['ir.module.module'].search([('state', '=', 'to upgrade')])
for module in to_upgrade:
    print(module.name)

Updating Module via Shell

Update module programmatically:

module = env['ir.module.module'].search([('name', '=', 'sale_management')])
module.button_immediate_upgrade()

API Automation

For complete automation, use Odoo's XML-RPC API.

Connecting to API

Create Python script for connection:

import xmlrpc.client

url = 'http://localhost:8069'
db = 'your_database'
username = 'admin'
password = 'admin'

common = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/common')
uid = common.authenticate(db, username, password, {})

models = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/object')

Installing Module via API

Find module by name:

module_id = models.execute_kw(db, uid, password,
    'ir.module.module', 'search',
    [[('name', '=', 'sale_management')]])

Install module:

models.execute_kw(db, uid, password,
    'ir.module.module', 'button_immediate_install',
    [module_id])

Batch Installation via API

Install module list:

module_names = ['sale_management', 'purchase', 'stock']

for name in module_names:
    module_id = models.execute_kw(db, uid, password,
        'ir.module.module', 'search',
        [[('name', '=', name)]])

    if module_id:
        models.execute_kw(db, uid, password,
            'ir.module.module', 'button_immediate_install',
            [module_id])
        print(f"Installed: {name}")

Managing Module Versions

Version control is critical for system stability.

Creating versions.txt File

Record versions of all installed modules:

cd /opt/odoo/custom-addons
find . -maxdepth 2 -name __manifest__.py -exec grep -H "version" {} \; > versions.txt

Use git for tracking:

cd /opt/odoo/custom-addons/sale-workflow
git log -1 --format="%H" > VERSION

Creating Version Tags

Create git tag after successful update:

cd /opt/odoo/custom-addons/sale-workflow
git tag -a v1.0.0 -m "Stable version for production"
git push origin v1.0.0

Rolling Back to Previous Version

If module update causes issues:

cd /opt/odoo/custom-addons/sale-workflow
git log --oneline
git checkout <commit-hash>

Then update module in Odoo:

odoo -d your_database -u sale_workflow --stop-after-init

Pinning Versions via Requirements

For Python modules, use exact versions:

pip freeze > /opt/odoo/requirements-frozen.txt

Use this file during deployment:

pip install -r /opt/odoo/requirements-frozen.txt

Working with Private Repositories

Company modules often reside in private repositories.

Configuring SSH Keys

Generate SSH key for odoo user:

sudo -u odoo ssh-keygen -t rsa -b 4096 -C "odoo@yourserver"

Copy public key:

sudo cat /home/odoo/.ssh/id_rsa.pub

Add key to Git server settings (GitHub, GitLab, Bitbucket).

Cloning Private Repository

Use SSH URL instead of HTTPS:

cd /opt/odoo/custom-addons
sudo -u odoo git clone git@github.com:yourcompany/private-modules.git

Using Access Tokens

For HTTPS, use personal access token:

git clone https://YOUR_TOKEN@github.com/yourcompany/private-modules.git

Configure credential helper:

git config --global credential.helper store

Token saves after first clone.

HTTPS Clone with Authentication

Use URL with credentials:

git clone https://username:token@gitlab.com/yourcompany/private-modules.git

For security, use environment variables:

GIT_USER="username"
GIT_TOKEN="your_token"
git clone https://${GIT_USER}:${GIT_TOKEN}@gitlab.com/yourcompany/private-modules.git

Structuring Custom Modules

Organize modules for easy management.

Categorization

Create category-based directory structure:

mkdir -p /opt/odoo/custom-addons/{oca,proprietary,custom,community}

Place modules by category:

  • oca/ — OCA modules
  • proprietary/ — proprietary modules
  • custom/ — internally developed modules
  • community/ — community modules

Update configuration:

addons_path = /opt/odoo/odoo/addons,/opt/odoo/custom-addons/oca,/opt/odoo/custom-addons/proprietary,/opt/odoo/custom-addons/custom,/opt/odoo/custom-addons/community

Using Symbolic Links

Create symbolic links to individual modules:

cd /opt/odoo/custom-addons
ln -s /opt/odoo/sources/sale-workflow/sale_order_priority ./

Useful when repository contains many modules but only some are needed.

Organization via requirements-repos.txt

Create file with repository list:

# OCA modules
https://github.com/OCA/sale-workflow.git@16.0
https://github.com/OCA/account-financial-tools.git@16.0

# Custom modules
git@github.com:yourcompany/custom-modules.git@main

Write script for automatic installation:

#!/bin/bash

while IFS= read -r line; do
    [[ "$line" =~ ^#.*$ ]] && continue
    [[ -z "$line" ]] && continue

    repo=$(echo $line | cut -d@ -f1)
    branch=$(echo $line | cut -d@ -f2)
    name=$(basename $repo .git)

    cd /opt/odoo/custom-addons
    if [ -d "$name" ]; then
        cd $name
        git pull origin $branch
    else
        git clone -b $branch $repo
    fi
done < requirements-repos.txt

Updating Modules

Regular module updates are critical for security and bug fixes.

Updating via Git Pull

Update module to latest version in branch:

cd /opt/odoo/custom-addons/sale-workflow
git pull origin 16.0

Batch Update All Modules

Update all git repositories in directory:

find /opt/odoo/custom-addons -type d -name .git -exec sh -c 'cd "{}" && cd .. && git pull' \;

More readable script:

#!/bin/bash

for dir in /opt/odoo/custom-addons/*/; do
    if [ -d "$dir/.git" ]; then
        echo "Updating $(basename $dir)..."
        cd "$dir"
        git pull
    fi
done

Checking Updates Before Applying

Check available updates without applying:

cd /opt/odoo/custom-addons/sale-workflow
git fetch origin
git log HEAD..origin/16.0 --oneline

Updating Modules in Odoo After Git Pull

After updating module files, update in database:

odoo -d your_database -u sale_workflow --stop-after-init

Update all changed modules:

odoo -d your_database -u all --stop-after-init

Testing Modules

Test modules before production installation.

Creating Test Database

Create copy of production database for testing:

createdb -T production_db test_db

Via psql:

psql -c "CREATE DATABASE test_db WITH TEMPLATE production_db OWNER odoo;"

Installing Module in Test Database

Install module only in test database:

odoo -d test_db -i new_module --stop-after-init

Running Automated Tests

Run module tests:

odoo -d test_db -i new_module --test-enable --stop-after-init

Run tests without installation:

odoo -d test_db --test-enable --test-tags new_module --stop-after-init

Checking Dependencies

Verify all dependencies installed:

odoo -d test_db -i new_module --test-enable --stop-after-init 2>&1 | grep -i "error\|warning"

Removing Modules

Sometimes complete module removal is necessary.

Uninstallation via CLI

Uninstall module from database:

odoo shell -d your_database

Execute in shell:

module = env['ir.module.module'].search([('name', '=', 'module_name')])
module.button_immediate_uninstall()

Removing Module Files

After uninstallation, remove files:

rm -rf /opt/odoo/custom-addons/module_name

If module installed via git:

cd /opt/odoo/custom-addons
git rm -r module_name
git commit -m "Remove module_name"

Database Cleanup

Some modules leave data after removal. Clean manually:

env.cr.execute("DELETE FROM ir_model_data WHERE module='module_name'")
env.cr.execute("DELETE FROM ir_model WHERE model LIKE 'module_name.%'")
env.cr.commit()

Migrating Modules Between Odoo Versions

When upgrading Odoo, modules require migration.

Checking Compatibility

Check if module version exists for new Odoo version:

cd /opt/odoo/custom-addons/sale-workflow
git branch -r | grep 17.0

Switching to New Version

Switch to new version branch:

git checkout 17.0

Updating After Migration

After Odoo upgrade, update all modules:

odoo -d your_database -u all --stop-after-init

Creating Migration Script

Automate migration:

#!/bin/bash

OLD_VERSION="16.0"
NEW_VERSION="17.0"
ADDONS_DIR="/opt/odoo/custom-addons"

cd $ADDONS_DIR

for dir in */; do
    if [ -d "$dir/.git" ]; then
        cd "$dir"
        if git branch -r | grep -q "$NEW_VERSION"; then
            echo "Migrating $dir to $NEW_VERSION..."
            git fetch origin
            git checkout $NEW_VERSION
            git pull origin $NEW_VERSION
        else
            echo "Version $NEW_VERSION unavailable for $dir"
        fi
        cd ..
    fi
done

Troubleshooting Common Issues

Problem: Module Not Appearing in List

Cause: Odoo hasn't scanned directory or path not in addons_path.

Solution:

Check configuration:

grep addons_path /etc/odoo/odoo.conf

Check permissions:

ls -la /opt/odoo/custom-addons/module_name

Update module list:

odoo -d your_database -u base --stop-after-init

Problem: Error "No module named 'module_dependency'"

Cause: Module Python dependencies not installed.

Solution:

Find requirements.txt:

find /opt/odoo/custom-addons/module_name -name requirements.txt

Install dependencies:

pip3 install -r /opt/odoo/custom-addons/module_name/requirements.txt

Problem: Module Installed But Not Working

Cause: Dependencies not updated or version conflict.

Solution:

Check Odoo logs:

tail -f /var/log/odoo/odoo-server.log

Force module update:

odoo -d your_database -u module_name --stop-after-init

Check dependencies in manifest.py:

cat /opt/odoo/custom-addons/module_name/__manifest__.py | grep depends

Problem: Git Authentication Failed

Cause: SSH keys or access tokens incorrectly configured.

Solution:

Test SSH connection:

ssh -T git@github.com

Check git settings:

git config --global --list

Use SSH instead of HTTPS:

git remote set-url origin git@github.com:username/repo.git

Problem: Module Version Conflicts

Cause: Incompatible dependency versions installed.

Solution:

Check all module versions:

odoo shell -d your_database

Execute in shell:

modules = env['ir.module.module'].search([('state', '=', 'installed')])
for m in modules:
    print(f"{m.name}: {m.latest_version}")

Roll back problematic module:

cd /opt/odoo/custom-addons/module_name
git log --oneline
git checkout <previous-commit>

CI/CD Automation

Integrate module installation into deployment pipeline.

GitLab CI Example

Create .gitlab-ci.yml:

stages:
  - test
  - deploy

test_modules:
  stage: test
  script:
    - cd /opt/odoo/custom-addons
    - git pull
    - pip3 install -r requirements.txt
    - odoo -d test_db -i module_name --test-enable --stop-after-init

deploy_production:
  stage: deploy
  script:
    - cd /opt/odoo/custom-addons
    - git pull origin main
    - pip3 install -r requirements.txt
    - odoo -d production_db -u module_name --stop-after-init
    - systemctl restart odoo
  only:
    - main

GitHub Actions Example

Create .github/workflows/deploy.yml:

name: Deploy Odoo Modules

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.5.3
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Deploy to server
        run: |
          ssh user@server "cd /opt/odoo/custom-addons && git pull"
          ssh user@server "pip3 install -r /opt/odoo/custom-addons/requirements.txt"
          ssh user@server "odoo -d production_db -u all --stop-after-init"
          ssh user@server "systemctl restart odoo"

Docker Integration

Create Dockerfile for Odoo with custom modules:

FROM odoo:16.0

USER root

COPY custom-addons /opt/odoo/custom-addons
RUN pip3 install -r /opt/odoo/custom-addons/requirements.txt

RUN chown -R odoo:odoo /opt/odoo/custom-addons

USER odoo

Build image:

docker build -t mycompany/odoo:16.0 .

Module Monitoring

Track module state in production.

Checking Installed Modules

Get list of installed modules:

odoo shell -d your_database

Execute:

installed = env['ir.module.module'].search([('state', '=', 'installed')])
for m in installed:
    print(f"{m.name} - {m.latest_version}")

Creating Module Report

Create script for report generation:

#!/usr/bin/env python3
import xmlrpc.client

url = 'http://localhost:8069'
db = 'your_database'
username = 'admin'
password = 'admin'

common = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/common')
uid = common.authenticate(db, username, password, {})
models = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/object')

modules = models.execute_kw(db, uid, password,
    'ir.module.module', 'search_read',
    [[('state', '=', 'installed')]],
    {'fields': ['name', 'latest_version', 'author']})

print("Installed modules:")
for m in modules:
    print(f"- {m['name']}: {m['latest_version']} (by {m['author']})")

Setting Up Alerts

Configure critical module monitoring:

#!/bin/bash

CRITICAL_MODULES=("sale_management" "account" "stock")
DB="your_database"

for module in "${CRITICAL_MODULES[@]}"; do
    status=$(odoo shell -d $DB -c "env['ir.module.module'].search([('name','=','$module')]).state")
    if [ "$status" != "installed" ]; then
        echo "ALERT: Module $module is not installed!"
    fi
done

Conclusion

Professional Odoo module management via command line and git provides complete system control. Key advantages of this approach:

Reproducibility. You know exactly which module versions are installed and can recreate environment on any server.

Automation. Module installation and updates fully automate through scripts and CI/CD.

Version Control. Git enables change tracking, rollback to previous versions, and branch management.

Team Collaboration. Multiple developers work with modules using standard git tools.

Security. Easy module change auditing and code source tracking.

Essential commands for daily work:

Clone modules:

git clone -b 16.0 https://github.com/OCA/sale-workflow.git

Update modules:

cd /opt/odoo/custom-addons/sale-workflow && git pull

Install in Odoo:

odoo -d your_database -i module_name --stop-after-init

Update module:

odoo -d your_database -u module_name --stop-after-init

Follow these practices, and Odoo module management becomes a straightforward, predictable process.

Content:
15% discount on new VPS
Hurry up to order a server in any location
Choose a VPS

Other articles

08.01.2026
67
Knowledge base / Review
WordPress Overview: What It Is and Who It’s For
08.01.2026
83
Knowledge base / Automatic installation of scripts
How to Quickly Install CyberPanel on a Virtual Server from THE.Hosting