In this post, I will guide you through the details to install Odoo 15 instances running with Python 3.8 + PostgreSQL 12 and Python 3.10 + PostgreSQL 14 on a single Ubuntu 22.04 Server.
Please note that if you are seeking for installing other Odoo versions, you could read other posts of mine for that:
- How to Install Odoo 8 on Ubuntu 22.04
- How to install Odoo 9 on Ubuntu 22.04
- How to install Odoo 10 on Ubuntu 22.04
- How to install Odoo 11 on Ubuntu 22.04
- How to install Odoo 12 on Ubuntu 22.04
- How to install Odoo 13 on Ubuntu 22.04
- How to install Odoo 14 on Ubuntu 22.04
- How to Install Odoo 16 on Ubuntu 22.04
Or, if you are an Odoo developer, you may interest in How to setup Odoo development environment on Ubuntu 22.04.
Executive Summary
After completion of the installation, we expect to achieve the following:
- There will be two Odoo 15 instances running on your Ubuntu 22.04 LTS Server:
- The first Odoo 15 instance, from now and on called
Odoo 15 Python 3.8
- Python Version: 3.8
- Running Unix User: odoo15_38
- PostgreSQL version: 12
- HTTP port: 8089, so that users can access it with a web browser with an address like http://your_ip:8089
- The second Odoo 15 instance, from now and on called
Odoo 15 Python 3.10
- Python Version: 3.10
- Running Unix User: odoo15_310
- PostgreSQL version: 14
- HTTP port: 8099, so that users can access it with a web browser with an address like http://your_ip:8099
- The first Odoo 15 instance, from now and on called
- Each of the 2 instances metioned above will run as a service with autostart.
- Each instance will be isolated in a dedicated Python virtual environment to avoid breaking existing things
- They will also be set with a secured master password to protect their databases. Users having master password will be able to create/delete/backup/restore databases.
Step1 – Create Odoo Running Users and Group
For security reason, we will run Odoo 15 instances under separate Unix user accounts that have the following specifications:
- For the Odoo 15 running Python 3.8:
- Account Name:
odoo15_38
- Home Directory:
/home/odoo15_38
- Account Name:
- For Odoo 15 running Python 3.10:
- Account Name:
odoo15_310
- Home Directory:
/home/odoo15_310
- Account Name:
- The user accounts will not be able to login for security purpose and should also be type of system so that Odoo can use to run as service;
- The user accounts will belong to a group that has access to Odoo 15 source code (i.e.
odoo
);
Create Unix group
Run the following command to create the group odoo:
sudo addgroup odoo
Create User odoo15_38
Run the following command to create the user account odoo15_38
and add it to the group odoo
:
sudo adduser odoo15_38 --system \ --home=/home/odoo15_38 --disabled-login \ --disabled-password --ingroup odoo
Create User odoo15_310
Run the following command to create the user account odoo15_310
and add it to the group odoo
:
sudo adduser odoo15_310 --system \ --home=/home/odoo15_310 --disabled-login \ --disabled-password --ingroup odoo
Step 2 – Install PostgreSQL 12 and 14
Odoo 15 was official released on October 1st, 2021 and fully supports the current PostgreSQL versions to that date, including PostgreSQL versions from 9.6 to 14. In the scope of this post, we’re going to install PostgreSQL 12 and PostgreSQL 14 for the two Odoo 15 instances. If you want other versions of PostgreSQL, you can follow another post of mine to install multiple PostgreSQL versions on Ubuntu 22.04.
Please note that Ubuntu 22.04 has no idea about PostgreSQL versions other than 14. In order to install PostgreSQL 12, we need to add the author’s PPA.
Adding official PostgreSQL PPA
# Create the file repository configuration: sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' # Import the repository signing key: wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
As usual, we should update the system before installing anything:
sudo apt-get update; sudo apt dist-upgrade
Install PostgreSQL 10 and 12
sudo apt install postgresql-12; sudo apt install postgresql-14;
After the installation is completed, and I assume that you did not have any postgreSQL version to be installed on the same server before, the listening port of the newly installed PostgreSQL clusters will be:
- PostgreSQL 12: 5432
- PostgreSQL 14: 5433
In case you have other versions of PostgreSQL running and you want to re-arrange the ports assignment, please follow the tutorial on changing PostgreSQL ports.
Create Database Roles
In this section, we’re going to create roles in your PostgreSQL clusters that have the same name as the unix accounts’ so that Odoo 15 instances will be able to authenticate the PostgreSQL clusters using the method ident
(without a password):
- Odoo 15 running Python 3.8 will connect PostgreSQL 12 on port 5432 using the role
odoo15_38
, - Odoo 15 running Python 3.10 will connect PostgreSQL 14 on port 5433 using the role
odoo15_310
Create Role odoo15_38
The command below will create a role named odoo15_38 in PostgreSQL 12 listening on port 5432
:
sudo -u postgres createuser odoo15_38 --interactive -p 5432
When being asked during the interactive session, please input as below:

Create Role odoo15_310
The command below will create a role named odoo15_310
in PostgreSQL 14 listening on port 5433
:
sudo -u postgres createuser odoo15_310 --interactive -p 5433
When being asked during the interactive session, please input as follow:

Step 3 – Download Odoo 15 source code from GitHub
In this section, we’re going to download the Odoo 15 source code from GitHub and implement security policy for read access for the users in the group odoo.
To download the source code of Odoo 15 from GitHub, just run the command below to clone it using git
over HTTP:
git clone -b 15.0 https://github.com/odoo/odoo.git /opt/odoo/odoo15
Or, you may clone the repository from GitHub over SSH for better performance and security using the following command:
git clone -b 15.0 git@github.com:odoo/odoo.git /opt/odoo/odoo15
Depending on your server’s internet connection speed, the process may take a few minutes or more. Please be patient or open another session to work for the next steps of installing Python in the mean time.
After the process is completed, you will find the Odoo 15 source code in the directory /opt/odoo/odoo15/
.
Now, secure the source code to allow only the user accounts of the group odoo
to read it by changing the source code owner to root
and acess group to odoo
.
sudo chown -hR root:odoo /opt/odoo/odoo15
Step 4 – Install Python 3.8 and 3.10
As discussed, Odoo 15 supports Python 3.7 and 3.8 officially. Recently, the Odoo team has also added support for Python 3.10. However, the Python version comes with Ubuntu 22.04 is 3.10 by default so we need to install Python 3.7 and 3.8 manually ourselves. As for the scope of this post, we are going to setup for Python 3.8 and Python 3.10 only. If you also want Python 3.7, you can follow the instructions on how to install multiple versions of Python. Let’s go for Python 3.8 and 3.10 for now:
Add Deadsnakes PPA
sudo add-apt-repository ppa:deadsnakes/ppa
Install Python 3.8 and its Virtual Environment tool
As we need to create an isolated Python environment for Odoo 15 to run to avoid to break existing things, we need to install Python Virtual Environment Tool also. Here is the command to install both Python 3.8 and its virtual environment tool:
sudo apt install python3.8 python3.8-venv
Now, run the command below to verify if Python 3.8 is properly installed:
python3.8 -V
You should see output as below:

Install Python 3.10 and its Virtual Environment tool
As Python 3.10 comes fresh with Ubuntu 22.04 by default installation, installing it is not needed. We just need to install its virtual environment tool by running the command below:
sudo apt install python3.10-venv
Step 5 – Install Odoo 15
Prerequisites
Install Ubuntu software and packages that are required to run Odoo 15:
sudo apt install python3.8-dev python3.10-dev \ build-essential libsass-dev libjpeg-dev \ libjpeg8-dev libldap-dev libldap2-dev \ libpq-dev libsasl2-dev libxslt1-dev zlib1g-dev
Install wkhtmltopdf
Odoo 15 generates PDF from HTML, that’s why we need the wkhtmltopdf.
Firstly, we need to download wkhtmltopdf package using wget
:
wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.jammy_amd64.deb
Then, install wkhtmltopdf using dpkg
:
sudo dpkg -i wkhtmltox_0.12.6.1-2.jammy_amd64.deb # force install dependencies sudo apt -f install -y
Install Odoo 15 with Python 3.8 and PostgreSQL 12
Create Odoo 15 Python 3.8 Virtual Environment
Firstly, we will need to create the parent folder for Odoo 15 Python 3.8 virtual environment:
sudo mkdir -p /python-venv/3.8/odoo15
Then, secure the virtual environment by changing the owner to odoo15_38
so that others will not be able to modify the environment:
sudo chown -hR odoo15_38:odoo /python-venv/3.8/odoo15
Switch the current user account to odoo15_38 with bash support:
sudo su - odoo15_38 -s /bin/bash
Create virtual environment:
python3.8 -m venv /python-venv/3.8/odoo15
Install required Python libraries for Odoo 15
Activate the virtual environment we’ve created:
source /python-venv/3.8/odoo15/bin/activate
As usual, we need to upgrade pip to its latest version for the activated environment first:
pip install --upgrade pip
Now, start installing libraries that are required by Odoo 15 for the virtual environment.
Please make sure you have finished cloning Odoo 15 source code before running the command below.
pip install -r /opt/odoo/odoo15/requirements.txt
Start Odoo 15
Now, we can start Odoo 15 in the virtual environment by running the following command that will connect PostgreSQL on port 5432 and offers HTTP port 8089 for you to access Odoo via web browser:
/opt/odoo/odoo15/odoo-bin --http-port=8089
In case your PostgreSQL 12 is running on a port other than 5432, you will have to let Odoo 15 know that by using the run option --db_port
. Hence, the command should be:
/opt/odoo/odoo15/odoo-bin --db_port=<your_postgres_port> --http-port=8089
You should see the output as below in the terminal:

Now, you can open your browser and input the address like http://your_id:8089 to see the Odoo 15 Database Creator / Selector User Interface as below:

Now, you can input database name, email, etc then hit the button Create database to initilize the first database for your Odoo instance.
Stop Odoo 15 and Exit
To stop the Odoo 15, just get back to the terminal and hit Ctrl+C twice.
Then, deactivate the current virtual environment
deactivate
Now, exit the current user odoo15_38
to get back to the previous account:
exit
Install Odoo 15 with Python 3.10 and PostgreSQL 14
Installing Odoo 15 with Python 3.10 is similar to Install Odoo 15 with Python 3.8. Here is are the commands.
Create parent folder for Odoo 15 Python 3.10 virtual environment:
sudo mkdir -p /python-venv/3.10/odoo15 sudo chown -hR odoo15_310:odoo /python-venv/3.10/odoo15
Then switch to the user odoo15_310 with bash support:
sudo su - odoo15_310 -s /bin/bash
After switching to the odoo15_310, let’s create Python 3.10 virtual environment for Odoo 15:
python3.10 -m venv /python-venv/3.10/odoo15
Now, activate the virtual environment:
source /python-venv/3.10/odoo15/bin/activate
As usual, let’s upgrade pip for its latest version
pip install --upgrade pip
Then, install Python libraries that are required by Odoo 15 dor the virtual environment:
pip install -r /opt/odoo/odoo15/requirements.txt
Start Odoo 15 that connects PostgreSQL 14 on port 5433 and offer HTTP port 8099 for clients to access via browsers:
/opt/odoo/odoo15/odoo-bin --db_port=5433 --http-port=8099
If your PostgreSQL 14 is running on a port other than 5433, you should change the run option --db_port
to that one.
After verifying that the Odoo 15 worked properly, just exit the virtual environment and get back to the previous unix account:
deactivate
exit
Step 6 – Run Odoo 15 as service / daemon
In this section, I will guide you on how to create startup services for your newly installed Odoo 15 instances so that they will be running as service and started every time the server reboots.
Odoo 15 Python 3.8 Daemon
Create Odoo 15 Configuration File
Configuration file is the file that stores configuration directives that let Odoo know how to run (e.g. addons path, database port, etc).
In this section, I will create a configuration file named odoo15_38.conf and store it in /home/odoo15_38. I will use the text editor nano
to create the file as below:
sudo nano /home/odoo15_38/odoo15_38.conf
Now, copy and pasted the following in your nano text editor UI:
[options] addons_path = /opt/odoo/odoo15/odoo/addons,/opt/odoo/odoo15/addons admin_passwd = admin csv_internal_sep = , data_dir = /home/odoo15_38/.local/share/Odoo db_host = False db_maxconn = 64 db_name = False db_password = False db_port = 5432 db_sslmode = prefer db_template = template0 db_user = False dbfilter = demo = {} email_from = False from_filter = False geoip_database = /usr/share/GeoIP/GeoLite2-City.mmdb http_enable = True http_interface = http_port = 8089 import_partial = limit_memory_hard = 2684354560 limit_memory_soft = 2147483648 limit_request = 8192 limit_time_cpu = 60 limit_time_real = 120 limit_time_real_cron = -1 list_db = True log_db = False log_db_level = warning log_handler = :INFO log_level = info logfile = longpolling_port = 8090 max_cron_threads = 2 osv_memory_age_limit = False osv_memory_count_limit = False pg_path = pidfile = proxy_mode = False reportgz = False screencasts = screenshots = /tmp/odoo_tests server_wide_modules = base,web smtp_password = False smtp_port = 25 smtp_server = localhost smtp_ssl = False smtp_ssl_certificate_filename = False smtp_ssl_private_key_filename = False smtp_user = False syslog = False test_enable = False test_file = test_tags = None transient_age_limit = 1.0 translate_modules = ['all'] unaccent = False upgrade_path = without_demo = False workers = 0
Please note that the master password to secure your instance is controlled by the directive admin_passwd
in the configuration file. You should change it to a strong one. You can also start tuning the instance by modifying other directives. After everything is fine for you, you save the file and exit by hitting Ctrl+X then input y
and press Enter.
To allow the account odoo15_38
to access the configration file while preventing others from to do that, we need to change the file owner by running the command below:
sudo chown odoo15_38:root /home/odoo15_38/odoo15_38.conf
Create Odoo 15 Unit File
I am using nano
to create the service file by running the command below:
sudo nano /lib/systemd/system/odoo15_38.service
Then copy and pasted the following in your nano editor UI
[Unit] Description=Odoo15_38 After=network.target postgresql.service [Service] Type=simple PermissionsStartOnly=true User=odoo15_38 Group=odoo SyslogIdentifier=odoo15_38 PIDFile=/run/odoo15_38/odoo15_38.pid ExecStartPre=/usr/bin/install -d -m755 -o odoo15_38 -g odoo /run/odoo15_38 ExecStart=/python-venv/3.8/odoo15/bin/python /opt/odoo/odoo15/odoo-bin -c /home/odoo15_38/odoo15_38.conf --pid=/run/odoo15_38/odoo15_38.pid ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s QUIT $MAINPID [Install] Alias=odoo15_38.service WantedBy=multi-user.target
Now save the file and exit (by pressing Ctrl+X
then input y
and press Enter before running the following command to notify systemd
that a new unit file exists:
sudo systemctl daemon-reload
To enable the service and set it to run on boot:
sudo systemctl enable --now odoo15_38
To start your Odoo 15 instance using systemd:
sudo systemctl start odoo15_38
Let’s open your web browser and input the address https://your_ip:8089 to see the Odoo 15 Database Creation User Interface.
To stop it, just run:
sudo systemctl stop odoo15_38
Odoo 15 Python 3.10 Daemon
We’re doing on a way similar to Odoo 15 Python 3.8 Daemon to create daemon for Odoo 15 Python 3.10.
Create Odoo 15 Configuration File
sudo nano /home/odoo15_310/odoo15_310.conf
Now, copy and pasted the following in your nano editor UI:
[options] addons_path = /opt/odoo/odoo15/odoo/addons,/opt/odoo/odoo15/addons admin_passwd = admin csv_internal_sep = , data_dir = /home/odoo15_310/.local/share/Odoo db_host = False db_maxconn = 64 db_name = False db_password = False db_port = 5433 db_sslmode = prefer db_template = template0 db_user = False dbfilter = demo = {} email_from = False from_filter = False geoip_database = /usr/share/GeoIP/GeoLite2-City.mmdb http_enable = True http_interface = http_port = 8099 import_partial = limit_memory_hard = 2684354560 limit_memory_soft = 2147483648 limit_request = 8192 limit_time_cpu = 60 limit_time_real = 120 limit_time_real_cron = -1 list_db = True log_db = False log_db_level = warning log_handler = :INFO log_level = info logfile = longpolling_port = 8100 max_cron_threads = 2 osv_memory_age_limit = False osv_memory_count_limit = False pg_path = pidfile = proxy_mode = False reportgz = False screencasts = screenshots = /tmp/odoo_tests server_wide_modules = base,web smtp_password = False smtp_port = 25 smtp_server = localhost smtp_ssl = False smtp_ssl_certificate_filename = False smtp_ssl_private_key_filename = False smtp_user = False syslog = False test_enable = False test_file = test_tags = None transient_age_limit = 1.0 translate_modules = ['all'] unaccent = False upgrade_path = without_demo = False workers = 0
Please note that the master password to secure your instance is controlled by the directive admin_passwd
in the configuration file. You should change it to a strong password. You can also tune the instance by modifying other directives. When everything is fine for you, just save the file and exit.
To allow the account odoo15_310
to access the configration file while preventing others from doing that, we need to change the file owner by running below command:
sudo chown odoo15_310:root /home/odoo15_310/odoo15_310.conf
Create Odoo 15 Unit File
sudo nano /lib/systemd/system/odoo15_310.service
Now, copy and pasted the following in your nano text editor UI
[Unit] Description=Odoo15_310 After=network.target postgresql.service [Service] Type=simple PermissionsStartOnly=true User=odoo15_310 Group=odoo SyslogIdentifier=odoo15_310 PIDFile=/run/odoo15_310/odoo15_310.pid ExecStartPre=/usr/bin/install -d -m755 -o odoo15_310 -g odoo /run/odoo15_310 ExecStart=/python-venv/3.10/odoo15/bin/python /opt/odoo/odoo15/odoo-bin -c /home/odoo15_310/odoo15_310.conf --pid=/run/odoo15_310/odoo15_310.pid ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s QUIT $MAINPID [Install] Alias=odoo15_310.service WantedBy=multi-user.target
Then save the file and exit before running the following command to notify systemd that a new unit file exists:
sudo systemctl daemon-reload
Then, enable the service and ask it to run on boot:
sudo systemctl enable --now odoo15_310
And then, start your Odoo 15 using systemd:
sudo systemctl start odoo15_310
Now, let’s open your web browser and input the address https://your_ip:8099 to see the Odoo 15 Database Creation User Interface.
To stop it, just run:
sudo systemctl stop odoo15_310
Conclusions
Now you have finished 6 detailed steps to install Odoo 15 instances on different ports on a single Ubuntu 22.04 server as below:
- Odoo 15 with Python 3.8 and PostgreSQL 12:
- HTTP Port: 8089
- Longpolling Port: 8090
- Odoo 15 with Python 3.8 and PostgreSQL 14:
- HTTP Port: 8099
- Longpolling Port: 8100
You can start manage your databases (i.e. create database, drop database, backup and existing database, restore database) by going to the addresses http://your_ip:8089/web/database/manager
(for Odoo 15 with Python 3.8 and PostgreSQL 12) or http://your_ip:8099/web/database/manager
(for Odoo 15 with Python 3.8 and PostgreSQL 14)