Chapter 2: Managing Odoo Server Instances
In Chapter 1, Installing the Odoo Development Environment, we looked at how to set up an Odoo instance using only the standard core add-ons that are shipped with source. This chapter focuses on adding non-core or custom add-ons to an Odoo instance. In Odoo, you can load add-ons from multiple directories. In addition, it is recommended that you load your third-party add-ons or your own custom add-ons from separate folders to avoid conflicts with Odoo core modules. Even Odoo Enterprise Edition is a type of add-on directory, and you need to load this just like a normal add-ons directory.
In this chapter, we will cover the following recipes:
- Configuring the add-ons path
- Standardizing your instance directory layout
- Installing and upgrading local add-on modules
- Installing add-on modules from GitHub
- Applying changes to add-ons
- Applying and trying proposed pull requests
In this book, we will use the terms
add-on
ormodule
orapp
oradd-on module
interchangeably. All of them refer to the Odoo app or Extension app that can be installed in Odoo from the user interface.
Configuring the add-ons path
With the help of the addons_path
parameter, you can load your own add-on modules into Odoo. When Odoo initializes a new database, it will search for add-on modules within directories that have been provided in the addons_path
configuration parameter. Odoo will search in these directories for the potential add-on module.
Directories listed in addons_path
are expected to contain subdirectories, each of which is an add-on module. Following initialization of the database, you will be able to install modules that are given in these directories.
Getting ready
This recipe assumes that you have an instance ready with a configuration file generated, as described in the Storing the instance configuration in a file recipe in Chapter 1, Installing the Odoo Development Environment. Note that the source code of Odoo is available in ~/odoo-dev/odoo
, and the configuration file in ~/odoo-dev/myodoo.cfg
.
How to do it…
To add the ~/odoo-dev/local-addons
directory to addons_path
of the instance, perform the following steps:
- Edit the configuration file for your instance, that is,
~/odoo-dev/myodoo.cfg
. - Locate the line starting with
addons_path=
. By default, this should look like the following:addons_path = ~/odoo-dev/odoo/addons
- Modify the line by appending a comma, followed by the name of the directory you want to add to
addons_path
, as shown in the following code:addons_path = ~/odoo-dev/odoo/addons,~/odoo-dev/local-addons
- Restart your instance from the terminal:
$ ~/odoo-dev/odoo/odoo-bin -c my-instance.cfg
How it works…
When Odoo is restarted, the configuration file is read. The value of the addons_path
variable is expected to be a comma-separated list of directories. Relative paths are accepted, but they are relative to the current working directory and therefore should be avoided in the configuration file.
At this point, we have only listed the add-on directory in Odoo, but no add-on modules are present in ~/odoo-dev/local-addons
. And even if you add a new add-on module to this directory, Odoo does not show this module in the user interface. For this, you need to perform an extra operation, as explained in the next recipe, Updating the add-on modules list.
Note
The reason behind this is that when you initialize a new database, Odoo automatically lists your custom modules in available modules, but if you add new modules following database initialization, then you need to manually update the list of available modules, as shown in the Updating the add-on modules list recipe.
There's more…
When you call the odoo-bin
script for the first time to initialize a new database, you can pass the --addons-path
command-line argument with a comma-separated list of directories. This will initialize the list of available add-on modules with all of the add-ons found in the supplied add-ons path. When you do this, you have to explicitly include the base add-ons directory (odoo/odoo/addons
), as well as the core add-ons directory (odoo/addons
). A small difference with the preceding recipe is that the local add-ons must not be empty; they must contain at least one sub-directory, which has the minimal structure of an add-on module.
In Chapter 3, Creating Odoo Add-On Modules, we will look at how to write your own modules. In the meantime, here's a quick hack to produce something that will make Odoo happy:
$ mkdir -p ~/odoo-dev/local-addons/dummy $ touch ~/odoo-dev/local-addons/dummy/ init .py $ echo '{"name": "dummy", "installable": False}' > \ ~/odoo-dev/local-addons/dummy/ manifest .py
You can use the --save
option to save the path to the configuration file:
$ odoo/odoo-bin -d mydatabase \ --add-ons-path="odoo/odoo/addons,odoo/addons,~/odoo-dev/local-addons" \ --save -c ~/odoo-dev/my-instance.cfg --stop-after-init
In this case, using relative paths is OK, since they will be converted into absolute paths in the configuration file.
Note
Since Odoo only checks directories in the add-ons path for the presence of add-ons when the path is set from the command line, not when the path is loaded from a configuration file, the dummy module is no longer necessary. You may, therefore, remove it (or keep it until you're sure that you won't need to create a new configuration file).
Standardizing your instance directory layout
We recommend that your development and production environments all use a similar directory layout. This standardization will prove helpful when you have to perform maintenance operations, and it will also ease your day-to-day work.
This recipe creates a directory structure that groups files with similar life cycles or similar purposes in standardized subdirectories.
Note
This recipe is only useful if you want to manage similar folder structure development and production environments. If you do not want this, you can skip this recipe.
Also, it is not compulsory to observe the same folder structure as in this recipe. Feel free to alter this structure to suit your needs.
How to do it…
To create the proposed instance layout, you need to perform the following steps:
- Create one directory per instance:
$ mkdir ~/odoo-dev/projectname $ cd ~/odoo-dev/projectname
- Create a Python
virtualenv
object in a subdirectory calledenv/
:$ python3 -m venv env
- Create some subdirectories, as follows:
$ mkdir src local bin filestore logs
The functions of the subdirectories are as follows:
src/
: This contains the clone of Odoo itself, as well as the various third-party add-on projects (we have added Odoo source code to the next step in this recipe).local/
: This is used to save your instance-specific add-ons.bin/
: This includes various helper executable shell scripts.filestore/
: This is used as a file store.logs/
(optional): This is used to store the server log files.
- Clone Odoo and install the requirements (refer to Chapter 1, Installing the Odoo Development Environment, for details on this):
$ git clone -b 14.0 --single-branch --depth 1 https://github.com/odoo/odoo.git src/odoo $ env/bin/pip3 install -r src/odoo/requirements.txt
- Save the following shell script as
bin/odoo
:#!/bin/sh ROOT=$(dirname $0)/.. PYTHON=$ROOT/env/bin/python3 ODOO=$ROOT/src/odoo/odoo-bin $PYTHON $ODOO -c $ROOT/projectname.cfg "$@" exit $?
- Make the script executable:
$ chmod +x bin/odoo
- Create an empty dummy local module:
$ mkdir -p local/dummy $ touch local/dummy/ init .py $ echo '{"name": "dummy", "installable": False}' >\ local/dummy/ manifest .py
- Generate a configuration file for your instance:
$ bin/odoo --stop-after-init --save \ --addons-path src/odoo/odoo/addons,src/odoo/addons,local \ --data-dir filestore
- Add a
.gitignore
file, which is used to tell GitHub to exclude given directories so that Git will ignore these directories when you commit the code, for example,filestore/
,env/
,logs/
, andsrc/
:# dotfiles, with exceptions: .* !.gitignore # python compiled files *.py[co] # emacs backup files *~ # not tracked subdirectories /env/ /src/ /filestore/ /logs/
- Create a Git repository for this instance and add the files you've added to Git:
$ git init $ git add . $ git commit -m "initial version of projectname"
How it works…
We generate a clean directory structure with clearly labeled directories and dedicated roles. We are using different directories to store the following:
- The code maintained by other people (in
src/
) - The local-specific code
filestore
of the instance
By having one virtualenv
environment per project, we are sure that the project's dependencies will not interfere with the dependencies of other projects that may be running a different version of Odoo or will use different third-party add-on modules, which require different versions of Python dependencies. This comes at the cost of a little disk space.
In a similar way, by using separate clones of Odoo and third-party add-on modules for our different projects, we are able to let each of these evolve independently and only install updates on the instances that need them, hence reducing the risk of introducing regressions.
The bin/odoo
script allows us to run the server without having to remember the various paths or activate the virtualenv
environment. This also sets the configuration file for us. You can add additional scripts in there to help you in your day-to-day work. For instance, you can add a script to check out the different third-party projects that you need to run your instance.
Regarding the configuration file, we have only demonstrated the bare minimum options to set up here, but you can obviously set up more, such as the database name, the database filter, or the port on which the project listens. Refer to Chapter 1, Installing the Odoo Development Environment, for more information on this topic.
Finally, by managing all of this in a Git repository, it becomes quite easy to replicate the setup on a different computer and share the development among a team.
Speedup tip
To facilitate project creation, you can create a template repository containing the empty structure, and fork that repository for each new project. This will save you from retyping the bin/odoo
script, the .gitignore
file, and any other template file you need (continuous integration configuration, README.md
, ChangeLog
, and so on).
There's more...
The development of complex modules requires various configuration options, which leads to updating the configuration file whenever you want to try any configuration option. Updating the configuration file frequently can be a headache, and to avoid this, an alternative way is to pass all configuration options from the command line, as follows:
- Activate
virtualenv
manually:$ source env/bin/activate
- Go to the Odoo source directory:
$ cd src/odoo
- Run the server:
./odoo-bin --addons-path=addons,../../local -d test-14 -i account,sale,purchase --log-level=debug
In step 3, we passed a few configuration options directly from the command line. The first is --add-ons-path
, which loads Odoo's core add-ons directory, addons
, and your add-ons directory, local
, in which you will put your own add-on modules. Option -d
will use the test-14
database or create a new database if it isn't present. The -i
option will install the account
, sale
, and purchase
modules. Next, we passed the log-level
option and increased the log level to debug
so that it will display more information in the log.
Note
By using the command line, you can quickly change the configuration options. You can also see live logs in the terminal. For all available options, refer to Chapter 1, Installing the Odoo Development Environment, or use the --help
command to view a list of all options and the description of each option.
Installing and upgrading local add-on modules
The core functionality of Odoo comes from its add-on modules. You have a wealth of add-ons available as part of Odoo itself, as well as add-on modules that you can download from the app store or that have been written by yourself.
In this recipe, we will demonstrate how to install and upgrade add-on modules through the web interface and from the command line.
The main benefits of using the command line for these operations include being able to act on more than one add-on at a time and having a clear view of the server logs as the installation or update progresses, which is very useful when in development mode or when scripting the installation of an instance.
Getting ready
Make sure that you have a running Odoo instance with its database initialized and the add-ons path properly set. In this recipe, we will install/upgrade a few add-on modules.
How to do it…
There are two possible methods to install or update add-ons—you can use the web interface or the command line.
From the web interface
To install a new add-on module in your database using the web interface, perform the following steps:
- Connect to the instance using the Administrator account and open the Apps menu:
Figure 2.1 – List of Odoo apps
- Use the search box to locate the add-on you want to install. Here are a few instructions to help you with this task:
- Activate the Not Installed filter.
- If you're looking for a specific functionality add-on rather than a broad functionality add-on, remove the Apps filter.
- Type a part of the module name in the search box and use this as a Module filter.
- You may find that using the list view gives something more readable.
- Click on the Install button under the module name in the card.
Note that some Odoo add-on modules have external Python dependencies. If Python dependencies are not installed in your system, then Odoo will abort the installation and it will show the following dialog:

Figure 2.2 – Warning for external library dependency
To fix this, just install the relevant Python dependencies on your system.
To update a pre-installed module in your database, perform the following steps:
- Connect to the instance using the Administrator account.
- Open the Apps menu.
- Click on Apps:
Figure 2.3 – Odoo apps list
- Use the search box to locate the add-on you want to install. Here are a few tips:
- Activate the Installed filter.
- If you're looking for a specific functionality add-on rather than a broad functionality add-on, remove the Apps filter.
- Type a part of the add-on module name into the search box and then press Enter to use this as a Module filter. For example, type
CRM
and press Enter to search CRM apps. - You may find that using the list view gives you something more readable.
- Click on the three dots in the top right-corner of the card and click on the Upgrade option:

Figure 2.4 – Drop-down link for upgrading the module
Activate developer mode to see the technical name of the module. See Chapter 1, Installing the Odoo Development Environment, if you don't know how to activate developer mode:

Figure 2.5 – Application's technical names
After activating developer mode, it will show the module's technical name in red. If you are using Odoo Community Edition, you will see some extra apps with the Upgrade button. Those apps are Odoo Enterprise Edition apps, and in order to install/use them, you need to purchase a license.
From the command line
To install new add-ons in your database, perform the following steps:
- Find the names of the add-ons. This is the name of the directory containing the _
manifest_.py
file, without the leading path. - Stop the instance. If you are working on a production database, make a backup.
- Run the following command:
$ odoo/odoo-bin -c instance.cfg -d dbname -i addon1,addon2 \ --stop-after-init
You may omit
-d dbname
if this is set in your configuration file. - Restart the instance.
To update an already installed add-on module in your database, perform the following steps:
- Find the name of the add-on module to update; this is the name of the directory containing the _
manifest_.py
file, without the leading path. - Stop the instance. If you are working on a production database, make a backup.
- Run the following command:
$ odoo/odoo-bin -c instance.cfg -d dbname -u addon1 \ --stop-after-init
You may omit
-d dbname
if this is set in your configuration file. - Restart the instance.
How it works…
The add-on module installation and update are two closely related processes, but there are some important differences, as highlighted in the following two sections.
Add-on installation
When you install an add-on, Odoo checks its list of available add-ons for an uninstalled add-on with the supplied name. It also checks for the dependencies of that add-on and, if there are any, it will recursively install them before installing the add-on.
The installation process of a single module consists of the following steps:
- If there are any, run the add-on
preinit
hook. - Load the model definitions from the Python source code and update the database structure, if necessary (refer to Chapter 4, Application Models, for details).
- Load the data files of the add-on and update the database contents, if necessary (refer to Chapter 6, Managing Module Data, for details).
- Install the add-on demo data if demo data has been enabled in the instance.
- If there are any, run the add-on
postinit
hook. - Run a validation of the view definitions of the add-on.
- If demo data is enabled and a test is enabled, run the tests of the add-on (refer to Chapter 18, Automated Test Cases, for details).
- Update the module state in the database.
- Update the translations in the database from the add-on's translations (refer to Chapter 11, Internationalization, for details).
Note
The
preinit
andpostinit
hooks are defined in the _manifest_.py
file using thepre_init_hook
andpost_init_hook
keys, respectively. These hooks are used to invoke Python functions before and after the installation of an add-on module. To learn more aboutinit
hooks, refer to Chapter 3, Creating Odoo Add-On Modules.
Add-on update
When you update an add-on, Odoo checks in its list of available add-on modules for an installed add-on with the given name. It also checks for the reverse dependencies of that add-on (these are the add-ons that depend on the updated add-on). If any, it will recursively update them, too.
The update process of a single add-on module consists of the following steps:
- Run the add-on module's pre-migration steps, if any (refer to Chapter 6, Managing Module Data, for details).
- Load the model definitions from the Python source code and update the database structure if necessary (refer to Chapter 4, Application Models, for details).
- Load the data files of the add-on and update the database's contents if necessary (refer to Chapter 6, Managing Module Data, for details).
- Update the add-on's demo data if demo data is enabled in the instance.
- If your module has any migration methods, run the add-on post-migration steps (refer to Chapter 6, Managing Module Data, for details).
- Run a validation of the view definitions of the add-on.
- If demo data is enabled and a test is enabled, run the tests of the add-on (refer to Chapter 18, Automated Test Cases, for details).
- Update the module state in the database.
- Update the translations in the database from the add-on's translations (refer to Chapter 11, Internationalization, for details).
Note
Note that updating an add-on module that is not installed does nothing at all. However, installing an add-on module that is already installed reinstalls the add-on, which can have some unintended effects with some data files that contain data that is supposed to be updated by the user and not updated during the normal module update process (refer to the Using the noupdate and forcecreate flags recipe in Chapter 6, Managing Module Data). There is no risk of error from the user interface, but this can happen from the command line.
There's more…
Be careful with dependency handling. Consider an instance where you want to have the sale
, sale_stock
, and sale_specific
add-ons installed, with sale_specific
depending on sale_stock
, and sale_stock
depending on sale
. To install all three, you only need to install sale_specific
, as it will recursively install the sale_stock
and sale
dependencies. To update all three, you need to update sale
, as this will recursively update the reverse dependencies, sale_stock
and sale_specific
.
Another tricky part with managing dependencies is when you add a dependency to an add-on that already has a version installed. Let's understand this by continuing with the previous example. Imagine that you add a dependency on stock_dropshipping
in sale_specific
. Updating the sale_specific
add-on will not automatically install the new dependency, and neither will requesting the installation of sale_specific
. In this situation, you can get very nasty error messages because the Python code of the add-on is not successfully loaded, but the data of the add-on and the models' tables in the database are present. To resolve this, you need to stop the instance and manually install the new dependency.
Installing add-on modules from GitHub
GitHub is a great source of third-party add-ons. A lot of Odoo partners use GitHub to share the add-ons they maintain internally, and the Odoo Community Association (OCA) collectively maintains several hundred add-ons on GitHub. Before you start writing your own add-on, ensure that you check that nothing already exists that you can use as is or as a starting point.
This recipe will show you how to clone the partner-contact
project of the OCA from GitHub and make the add-on modules it contains available in your instance.
Getting ready
Suppose you want to add new fields to the customers (partner) form. By default, the Odoo customers model doesn't have a gender
field. If you want to add a gender
field, you need to create a new module. Fortunately, someone on a mailing list tells you about the partner_contact_gender
add-on module, which is maintained by the OCA as part of the partner-contact
project.
The paths that are used in this recipe reflect the layout that was proposed in the Standardizing your instance directory layout recipe.
How to do it…
To install partner_contact_gender
, perform the following steps:
- Go to your project's directory:
$ cd ~/odoo-dev/my-odoo/src
- Clone the
14.0
branch of thepartner-contact
project in thesrc/
directory:$ git clone --branch 14.0 \ https://github.com/OCA/partner-contact.git src/partner-contact
- Change the add-ons path to include that directory and update the add-ons list of your instance (refer to the Configuring the add-ons path recipe and Updating the add-on modules list recipes in this chapter). The
add-ons_path
line ofinstance.cfg
should look like this:addons_path = ~/odoo-dev/my-odoo/src/odoo/odoo/addons, \ ~/odoo-dev/my-odoo/src/odoo/addons, \ ~/odoo-dev/my-odoo/src/, \ ~/odoo-dev/local-addons
- Install the
partner_contact_gender
add-on (if you don't know how to install the module, take a look at the previous recipe, Installing and upgrading local add-on modules).
How it works…
All of the Odoo Community Association code repositories have their add-ons contained in separate subdirectories, which is coherent in accordance with what is expected by Odoo regarding the directories in the add-ons path. Consequently, just cloning the repository somewhere and adding that location in the add-ons path is enough.
There's more…
Some maintainers follow a different approach and have one add-on module per repository, living at the root of the repository. In that case, you need to create a new directory, which you will add to the add-ons path and clone all of the add-ons from the maintainer you need in this directory. Remember to update the add-on modules list each time you add a new repository clone.
Applying changes to add-ons
Most add-ons that are available on GitHub are subject to change and do not follow the rules that Odoo enforces for its stable release. They may receive bug fixes or enhancements, including issues or feature requests that you have submitted, and these changes may introduce database schema changes or updates in the data files and views. This recipe explains how to install the updated versions.
Getting ready
Suppose you reported an issue with partner_contact_gender
and received a notification that the issue was solved in the last revision of the 14.0
branch of the partner-contact
project. In this case, you will want to update your instance with this latest version.
How to do it…
To apply a source modification to your add-on from GitHub, you need to perform the following steps:
- Stop the instance using that add-on.
- Make a backup if it is a production instance (refer to the Manage Odoo server databases recipe in Chapter 1, Installing the Odoo Development Environment).
- Go to the directory where
partner-contact
was cloned:$ cd ~/odoo-dev/my-odoo/src/partner-contact
- Create a local tag for the project so that you can revert to that version in case things break:
$ git checkout 14.0 $ git tag 14.0-before-update-$(date --iso)
- Get the latest version of the source code:
$ git pull --ff-only
- Update the
partner_address_street3
add-on in your databases (refer to the Installing and upgrading local add-on modules recipe). - Restart the instance.
How it works…
Usually, the developer of the add-on module occasionally releases the newest version of the add-on. This update typically contains bug fixes and new features. Here, we will get a new version of the add-on and update it in our instances.
If git pull --ff-only
fails, you can revert to the previous version using the following command:
$ git reset --hard 14.0-before-update-$(date --iso)
Then, you can try git pull
(without --ff-only
), which will cause a merge, but this means that you have local changes on the add-on.
See also
If the update step breaks, refer to the Updating Odoo from Source recipe in Chapter 1, Installing the Odoo Development Environment, for recovery instructions. Remember to always test an update on a copy of a database production first.
Applying and trying proposed pull requests
In the GitHub world, a Pull Request (PR) is a request that's made by a developer so that the maintainers of a project can include some new developments. Such a PR may contain a bug fix or a new feature. These requests are reviewed and tested before being pulled into the main branch.
This recipe explains how to apply a PR to your Odoo project in order to test an improvement or a bug fix.
Getting ready
As in the previous recipe, suppose you reported an issue with partner_address_street3
and received a notification that the issue was solved in a PR, which hasn't been merged in the 14.0
branch of the project. The developer asks you to validate the fix in PR #123. You need to update a test instance with this branch.
You should not try out such branches directly on a production database, so first create a test environment with a copy of the production database (refer to Chapter 1, Installing the Odoo Development Environment).
How to do it…
To apply and try out a GitHub PR for an add-on, you need to perform the following steps:
- Stop the instance.
- Go to the directory where
partner-contact
was cloned:$ cd ~/odoo-dev/my-odoo/src/partner-contact
- Create a local tag for the project so that you can revert to that version in case things break:
$ git checkout 14.0 $ git tag 14.0-before-update-$(date --iso)
- Pull the branch of the
pull
request. The easiest way to do this is by using the number of the PR, which should have been communicated to you by the developer. In our example, this is PR number123
:$ git pull origin pull/123/head
- Update the
partner_contact_gender1
add-on module in your database and restart the instance (refer to the Installing and upgrading local add-on modules recipe if you don't know how to update the module). - Test the update—try to reproduce your issue, or try out the feature you wanted.
If this doesn't work, comment on the PR page of GitHub, explaining what you did and what didn't work so that the developer can update the PR.
If it works, say so on the PR page too; this is an essential part of the PR validation process, and it will speed up merging in the main branch.
How it works…
We are using a GitHub feature that enables pull requests to be pulled by number using the pull/nnnn/head
branch name, where nnnn
is the number of the PR. The Git pull command will merge the remote branch in ours, applying the changes in our code base. After this, we update the add-on module, test it, and report back to the author of the change with regard to any failures or success.
There's more…
You can repeat step 4 of this recipe for different pull requests in the same repository if you want to test them simultaneously. If you are really happy with the result, you can create a branch to keep a reference to the result of the applied changes:
$ git checkout -b 14.0-custom
Using a different branch will help you remember that you are not using the version from GitHub, but a custom one.
Note
The git branch
command can be used to list all of the local branches you have in your repository.
From then on, if you need to apply the latest revision of the 14.0
branch from GitHub, you will need to pull it without using --ff-only
:
$ git pull origin 14.0