How to Install Odoo 20 on Ubuntu 24.04

Odoo is a popular open-source suite of business apps that help companies manage and run their business. It includes a wide range of applications such as CRM, e-commerce, website builder, billing, accounting, manufacturing, warehouse, project management, inventory, and more, all integrated with each other.
Odoo can be installed in different ways, depending on the use case and available technologies. The easiest and quickest way to install Odoo is by using the official Odoo APT repositories.
Installing Odoo in a virtual environment, or deploying as a Docker container, gives you more control over the application and allows you to run multiple Odoo instances on the same system.
This guide walks you through how to install Odoo 20 on Ubuntu 24.04 inside a Python virtual environment. We will download Odoo from the official GitHub repository and use Nginx as a reverse proxy. You can also install Odoo 19 with the version changes below.
Prerequisites
Before you begin, make sure you have:
- A server running Ubuntu 24.04 with at least 2GB of RAM
- Python 3.12 or later
- PostgreSQL 16 or later
- wkhtmltopdf 0.12.6 (for PDF headers/footers)
- A user with sudo privileges
- A domain name pointing to your server (for TLS/SSL setup)
These minimum versions match Odoo 20 requirements and help avoid issues with database compatibility and PDF report rendering. Ubuntu 24.04 ships Python 3.12 and PostgreSQL 16, so the packages from the standard repositories are enough.
Installing Odoo 19 on Ubuntu 24.04
For a new Odoo 19 installation, follow the same steps below, replacing odoo20 with odoo19 in the system user, PostgreSQL role, directory paths, configuration filename, and service name. When you reach the Git clone step, use the 19.0 branch:
git clone https://www.github.com/odoo/odoo --depth 1 --branch 19.0 /opt/odoo19/odooUbuntu 24.04’s Python 3.12 and PostgreSQL 16 also meet Odoo 19 requirements. The configuration below explicitly binds Odoo to 127.0.0.1, so the SSH tunnel and Nginx setup work with either version. These instructions cover a new installation; upgrading an existing database requires a separate migration.
Installing Dependencies
The first step is to install Git, Pip, Node.js, and the development tools required to build Odoo dependencies:
sudo apt update
sudo apt install git curl python3-venv python3-pip build-essential wget python3-dev \
python3-wheel libfreetype6-dev libxml2-dev libzip-dev libldap2-dev libsasl2-dev \
python3-setuptools libjpeg-dev zlib1g-dev libpq-dev \
libxslt1-dev libtiff5-dev libjpeg8-dev libopenjp2-7-dev \
liblcms2-dev libwebp-dev libharfbuzz-dev libfribidi-dev libxcb1-devInstalling Node.js
Ubuntu 24.04 ships with an older version of Node.js. To get a supported LTS release, install Node.js from the NodeSource repository:
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt install nodejsInstall the rtlcss utility (used for right-to-left language support):
sudo npm install -g rtlcssOptionally, verify the installed versions:
python3 --version
node --version
npm --versionCreating a System User
Running Odoo under the root user poses a great security risk. We will create a new system user and group with home directory /opt/odoo20 that will run the Odoo service:
sudo useradd -m -d /opt/odoo20 -U -r -s /bin/bash odoo20You can name the user anything you want, as long as you create a PostgreSQL user with the same name.
Installing and Configuring PostgreSQL
Odoo uses PostgreSQL as the database backend. Ubuntu 24.04 includes PostgreSQL 16 in the standard repositories, which is the minimum version Odoo 20 supports. Install it with:
sudo apt install postgresqlOnce the service is installed, create a PostgreSQL user with the same name as the previously created system user. The -d option allows database creation, while -R and -S deny role creation and superuser privileges:
sudo su - postgres -c "createuser -R -S -d odoo20"You do not need to create a database manually. Odoo will automatically create and initialize the database when you access the web interface for the first time.
Installing wkhtmltopdf
wkhtmltopdf is an open-source CLI tool for rendering HTML pages into PDF and images. Odoo uses it to generate PDF reports.
The wkhtmltopdf package in Ubuntu repositories is built without the patched Qt, which breaks headers and footers. Use the official 0.12.6 build from GitHub:
wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.debInstall the downloaded package:
sudo apt install ./wkhtmltox_0.12.6.1-3.jammy_amd64.debsudo apt --fix-broken install to resolve them.Installing and Configuring Odoo 20
We will install Odoo from the source inside an isolated Python virtual environment.
First, switch to the “odoo20” user:
sudo su - odoo20Clone the Odoo 20 source code from GitHub:
git clone https://www.github.com/odoo/odoo --depth 1 --branch 20.0 /opt/odoo20/odooCreate a new Python virtual environment for Odoo:
cd /opt/odoo20
python3 -m venv odoo-venvActivate the virtual environment:
source odoo-venv/bin/activateOdoo dependencies are specified in the requirements.txt file. Install all required Python modules with pip3:
pip3 install wheel
pip3 install -r odoo/requirements.txtOnce done, deactivate the environment:
deactivateCreate a separate directory for third-party addons:
mkdir /opt/odoo20/odoo-custom-addonsLater we will add this directory to the addons_path parameter. This parameter defines a list of directories where Odoo searches for modules.
Switch back to your sudo user:
exitCreate a configuration file:
sudo nano /etc/odoo20.confAdd the following content:
[options]
; This is the password that allows database operations:
admin_passwd = my_admin_passwd
db_host = False
db_port = False
db_user = odoo20
db_password = False
http_interface = 127.0.0.1
addons_path = /opt/odoo20/odoo/addons,/opt/odoo20/odoo-custom-addonsmy_admin_passwd to a strong, secure password. This password is used to create, duplicate, and delete databases. Do not commit the configuration file containing this password to version control; add it to .gitignore if you keep a copy in a repository.Creating the Systemd Service
A unit file is a configuration file that holds information about a service.
Create a file named odoo20.service:
sudo nano /etc/systemd/system/odoo20.serviceAdd the following content:
[Unit]
Description=Odoo 20
Requires=postgresql.service
After=network.target postgresql.service
[Service]
Type=simple
SyslogIdentifier=odoo20
User=odoo20
Group=odoo20
ExecStart=/opt/odoo20/odoo-venv/bin/python3 /opt/odoo20/odoo/odoo-bin -c /etc/odoo20.conf
StandardOutput=journal+console
[Install]
WantedBy=multi-user.targetReload systemd to recognize the new unit file:
sudo systemctl daemon-reloadStart the Odoo service and enable it to start on boot:
sudo systemctl enable --now odoo20Verify that the service is running:
sudo systemctl status odoo20The output should show that the Odoo service is active and running:
● odoo20.service - Odoo 20
Loaded: loaded (/etc/systemd/system/odoo20.service; enabled; preset: enabled)
Active: active (running) since Sun 2026-10-25 10:00:00 UTC; 10s ago
...To view the Odoo service logs using journalctl
:
sudo journalctl -u odoo20Other useful commands to manage the Odoo service:
sudo systemctl restart odoo20
sudo systemctl stop odoo20
sudo systemctl start odoo20Testing the Installation
Odoo listens on 127.0.0.1:8069 on the server. To test it from your computer before configuring Nginx, open a separate terminal on your computer and create an SSH tunnel. Replace your_user with your SSH login and your_server_ip with the server address:
ssh -N -L 18069:127.0.0.1:8069 your_user@your_server_ipKeep this terminal open and visit http://127.0.0.1:18069 in your local browser. If the installation is successful, you will see the Odoo database creation screen where you can create your first database and start using Odoo. The SSH tunnel encrypts traffic between your computer and the server. Press Ctrl+C in the tunnel terminal when you finish testing.
Enabling Multiprocessing
By default, Odoo runs in multithreading mode. Before configuring Nginx, enable multiprocessing so Odoo starts the dedicated WebSocket worker on port 8072, which the reverse proxy configuration below uses.
To enable multiprocessing, edit the Odoo configuration and set a non-zero number of worker processes. The number of workers is calculated based on the number of CPU cores and available RAM.
According to the official Odoo documentation , use these formulas:
Worker number calculation:
- Theoretical maximum workers = (system_cpus * 2) + 1
- 1 worker can serve ~= 6 concurrent users
- Cron workers also require CPU
RAM memory calculation:
- Assume 20% of requests are heavy (1 GB RAM) and 80% are light (150 MB RAM)
- Needed RAM =
workers * ((0.8 * 150) + (0.2 * 1024))
To check the number of CPUs on your system:
grep -c ^processor /proc/cpuinfoFor a system with 4 CPU cores, 8 GB of RAM, and 30 concurrent users:
30 users / 6 = 5workers needed(4 * 2) + 1 = 9maximum workers- Use 5 workers + 1 cron worker = 6 total workers
- RAM needed:
6 * ((0.8 * 150) + (0.2 * 1024)) ~= 2 GB
Open the Odoo configuration file:
sudo nano /etc/odoo20.confUnder [options], add the following settings. This example is for the 4-core, 8 GB server above; reduce the worker count for a smaller server and leave RAM for PostgreSQL and the operating system. The memory limits apply to each worker, not the whole service.
limit_memory_hard = 2684354560
limit_memory_soft = 2147483648
limit_request = 8192
limit_time_cpu = 600
limit_time_real = 1200
max_cron_threads = 1
workers = 5Restart the Odoo service:
sudo systemctl restart odoo20Configuring Nginx as a Reverse Proxy with TLS Termination
The default Odoo web server serves traffic over HTTP. To make the Odoo deployment more secure, we will configure Nginx as a reverse proxy with TLS termination to serve traffic over HTTPS.
TLS termination means Nginx processes and decrypts incoming TLS (HTTPS) connections, then forwards unencrypted HTTP requests to Odoo. The traffic between Nginx and Odoo will not be encrypted.
Using a reverse proxy provides benefits such as load balancing, TLS termination, caching, compression, and serving static content.
Before continuing, ensure you have:
- A domain name pointing to your server. We will use
example.com. - Nginx installed.
- A TLS certificate for your domain (for example, a free Let’s Encrypt certificate).
Create the Nginx server block configuration:
sudo nano /etc/nginx/sites-available/odoo.confAdd the following configuration:
# Odoo servers
upstream odoo {
server 127.0.0.1:8069;
}
upstream odoochat {
server 127.0.0.1:8072;
}
# HTTP -> HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name www.example.com example.com;
return 301 https://example.com$request_uri;
}
# WWW -> NON-WWW redirect
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
return 301 https://example.com$request_uri;
}
# Main server block
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
proxy_read_timeout 720s;
proxy_connect_timeout 720s;
proxy_send_timeout 720s;
# Proxy headers
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
# SSL parameters
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# Log files
access_log /var/log/nginx/odoo.access.log;
error_log /var/log/nginx/odoo.error.log;
# Websocket (live chat)
location /websocket {
proxy_pass http://odoochat;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
# Handle / requests
location / {
proxy_redirect off;
proxy_pass http://odoo;
}
# Cache static files
location ~* /web/static/ {
proxy_cache_valid 200 90m;
proxy_buffering on;
expires 864000;
proxy_pass http://odoo;
}
# Gzip compression
gzip_types text/css text/less text/plain text/xml application/xml application/json application/javascript;
gzip on;
}example.com with your actual domain name and update the SSL certificate paths accordingly.The /websocket location uses proxy_http_version 1.1 because WebSocket upgrades require HTTP/1.1, while Nginx 1.24 defaults to HTTP/1.0 for upstream connections. It also repeats the proxy headers from the server block. Nginx does not pass server-level proxy_set_header directives into a location that defines its own. Without the repeated headers, Odoo would not see the original host, client address, or protocol on WebSocket connections.
Ubuntu 24.04 ships Nginx 1.24, where HTTP/2 is enabled with the http2 parameter on the listen lines. The standalone http2 on; directive requires Nginx 1.25.1 or later and fails the configuration test on this version.
Enable the site by creating a symbolic link:
sudo ln -s /etc/nginx/sites-available/odoo.conf /etc/nginx/sites-enabled/Test the Nginx configuration:
sudo nginx -tIf there are no errors, restart Nginx:
sudo systemctl restart nginxNext, tell Odoo to use the proxy. Open the configuration file and add the following line:
sudo nano /etc/odoo20.confproxy_mode = TrueRestart the Odoo service:
sudo systemctl restart odoo20You can now access your Odoo instance at https://example.com.
Firewall Configuration (Optional)
If UFW is enabled, allow SSH and web traffic, and block direct access to Odoo’s port now that Nginx is configured:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 8069/tcpTroubleshooting
Missing PDF headers or footers
Make sure you are using the official wkhtmltopdf 0.12.6 build, not the distro package.
Database connection errors
Verify that the PostgreSQL role exists and that /etc/odoo20.conf uses the correct db_user.
Odoo is not reachable on port 8069 from another machine
Odoo 20 listens only on 127.0.0.1 by default. Earlier releases listened on all interfaces. Reach Odoo through Nginx or an SSH tunnel. If you need direct access on a trusted network, set http_interface = 0.0.0.0 in /etc/odoo20.conf and restart the service.
WebSocket errors or live chat does not update
The /websocket location sends traffic to port 8072, which Odoo opens only in multiprocessing mode. Confirm that workers is set to a non-zero value in /etc/odoo20.conf and that sudo ss -ltnp | grep 8072 shows Odoo listening. Check that the Nginx location includes proxy_http_version 1.1 and the Upgrade and Connection headers.
Updating Odoo 20
To update your Odoo source installation, pull the latest changes and refresh dependencies:
sudo su - odoo20
cd /opt/odoo20/odoo
git checkout 20.0
git pull
source /opt/odoo20/odoo-venv/bin/activate
pip3 install -r requirements.txt
deactivate
exit
sudo systemctl restart odoo20Odoo does not publish release tags in its GitHub repository. The 20.0 branch is the update channel for a source installation, so back up the database before you pull updates on a production server.
FAQ
Does Odoo 20 work on Ubuntu 24.04?
Yes. Odoo 20 requires Python 3.12 or later and PostgreSQL 16 or later, and Ubuntu 24.04 ships both in its standard repositories. For PDF reports with headers and footers, you also need the official wkhtmltopdf 0.12.6 build.
What PostgreSQL version does Odoo 20 require?
PostgreSQL 16 or later. Odoo 19 accepted PostgreSQL 13 and newer.
Which wkhtmltopdf version should I use?
Use the official wkhtmltopdf 0.12.6 build for correct PDF headers and footers.
Can I install Odoo 19 with this guide?
Yes. Follow the Odoo 19 version changes
before you begin. The explicit http_interface = 127.0.0.1 setting in the configuration keeps Odoo 19 bound to localhost, matching the SSH tunnel and reverse proxy instructions.
How do I upgrade an existing Odoo 19 installation to Odoo 20?
Switching the Git branch is not enough. The database must be migrated to the new version, and custom modules must be ported. Follow the official Odoo upgrade documentation
and test the upgrade on a copy of the database first.
Conclusion
We have shown you how to install Odoo 20 on Ubuntu 24.04 in a Python virtual environment and serve it over HTTPS through Nginx. Your next step should be to set up automatic daily backups of Odoo databases .
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page