Professional Odoo 11 Deployment Guide

Odoo 11 + Domain Support + Nginx as Reverse Proxy & Caching Server + CertBot SSL Encryption

Hello and greetings everyone.

The purpose of this tutorial is to help our fellow Odoo developers/implementers to deploy Odoo professionally & properly without problems.

Furthermore, I worked on many projects and I saw many deployments done by companies I worked for and other competitor partners and I didn't like it because it wasn't professional enough for that reason I decided to share my experience and help Odoo community.

Anyways, let's start our tutorial and show how deployment is done at least in the scenario I'll be demonstrating here.

Scenario:

We are going to deploy every service separately on different servers.

  1. Server1 is for Postgres Database (192,168.1.10).

  2. Server2 is for Odoo Application (192.168.1.11).

  3. Server3 is for Nginx as (Reverse Proxy - Caching - Loadbalancer) (192.168.1.12).


The approach we are going to use is Active-Active implementation.

Preassuming all servers have Ubuntu 16.04 server installed on them.

Important note: why can't we deploy Odoo on Windows Servers in production? simply because Python doesn't support multiprocessing on Windows which means Odoo will be running only on a single process which means you have a limited amount of users to use the system concurrently before it fails or becomes very laggy. According to Odoo documentation, about 6 users can work concurrently on a single process. so in conclusion, Linux is the best environment for production deployment. The most recommended OS by Odoo is Ubuntu because It's Debian based and all Linux programs and packages are available by default.

Ok... I prepared 3 scripts on my GitHub account for installing each service separately and this work is inspired by Yenthe Van Ginneken install script.

Here is the link to my scripts https://github.com/mmhy2003/Odoo-Deploy


Postgres Installation:

In case you prefer installing PostgreSQL cluster instead of a single DB implementation go to my next articleDeploy PostgreSQL Cluster for Odoo and ignore PostgreSQL installation step here and proceed to Odoo installation directly.

Login to Postgres server (192.168.1.10), download Postgres install script by this command:

sudo wget https://raw.githubusercontent.com/mmhy2003/Odoo-Deploy/11.0/01-postgres-install.sh
sudo chmod +x 01-postgres-install.sh

I recommend to review and modify script parameters depending on your needs. I preconfigured DB user & password to be odoo.

sudo ./01-postgres-install.sh

After installing Postgres, there are some configurations need to be customized depending on the network setup.

We are going to modify pg_hba.conf file as follows.

sudo nano /etc/postgresql/9.5/main/pg_hba.conf

Under this section in the configuration, we need to add & modify these parts as follows.

# IPv4 local connections:
host all all 127.0.0.1/32 trust
host all all 192.168.1.1/24 trust

Then, save modification by pressing Ctrl+O then Enter then Ctrl+X to exit the editor.

By modifying this part, we tell Postgres to trust any user trying to connect from the local server (Postgres Server) or from any computer or server on the same network only.

After that, we modify postgresql.conf file.

sudo nano /etc/postgresql/9.5/main/postgresql.conf

Go and look for this line and change it as follows

#listen_addresses = 'localhost'

Remove hash sign from the beginning of the line to enable this part.

listen_addresses = '*'

Then, we save modification by pressing Ctrl+O then Enter then Ctrl+X to exit the editor.

Now, Postgres will listen for all connection requests from the subnet we specified in the previous step.

Everything is done now, let us restart the service in order to reflect new changes.

sudo service postgres restart

Odoo Installation:

Log into Odoo server (192.168.1.11), download Odoo install script by this command:

sudo wget https://raw.githubusercontent.com/mmhy2003/Odoo-Deploy/11.0/02-odoo-install.sh
sudo chmod +x 02-odoo-install.sh

I also recommend to review & modify the script parameters to fit your needs.

sudo nano 02-odoo-install.sh

POSTGRES_SERVER="192.168.1.10"
POSTGRES_PORT="5432"
POSTGRES_USER="odoo"
POSTGRES_PASS="odoo"
IS_ENTERPRISE="True" #To install Odoo enterprise modules

Important note: If you purchased and have access to Odoo enterprise modules and want to install them, change IS_ENTERPRISE from False to True, at some point in the setup you will be prompt to enter Github user/pass in order to download the modules, if you are not interested, keep it False.

Then, save modification by pressing Ctrl+O then Enter then Ctrl+X to exit the editor.

And run the script:

sudo ./02-odoo-install.sh

The script will take some time to prepare everything for you. I advise you to go and grab a coffee while it finishes unless you have good internet connection no need for waiting or you are deploying on the cloud :-).

After installation, we start configuring Odoo service by:

sudo nano /etc/odoo-server.conf

[options]
; This is the password that allows database operations:
admin_passwd = C0mplexPa$$ # Remove semicolon to use master password specified here
db_host = 192.168.1.10 db_port = 5432
db_user = odoo db_password = odoo xmlrpc_port = 8069 ;dbfilter = ^%d$ limit_memory_hard = 1677721600 limit_memory_soft = 629145600 limit_request = 8192 limit_time_cpu = 600 limit_time_real = 1200 max_cron_threads = 1 workers = 4 proxy_mode = True # Remove semicolon to activate proxy mode logfile = /var/log/odoo/odoo-server.log
addons_path = /odoo/odoo-server/addons
,/odoo/odoo-server/odoo/addons
,/odoo/modules

Then, save modification by pressing Ctrl+O then Enter then Ctrl+X to exit the editor.

UPDATE:

How to calculate the number of workers and Physical RAM needed (Dedicated Servers VS Virtual Servers):

Dedicated Server:

  1. If you have 2 Xeon processors with 20 cores, 2*20 = 40 Cores, in addition to Hyperthreading technology enabled that means you have in total 80 Cores.

  2.  #workers = (2 * Cores) + 1 = (2 * 80) + 1 = 161. you can ignore plus one because it doesn't add nor take from performance much unless you already have heavy cron jobs like DB backup or DB sync jobs.

  3. RAM = #workers * ((light_worker_ratio * light_worker_ram) + (heavy_worker_ratio * heavy_worker_ram)) = 161 * ((0.8 * 150) + (0.2 * 1024)) = 52292.8 MB ~= 51 GB RAM.

  4. With this configuration # of concurrent users = 160 * 6 = 960 Users ~= 1K Users.

Virtual Server:

  1. It's pretty much the same but put in your consideration you are dealing with vCPUs which means they are shared resources.

  2. Either you use the same way I calculated # of workers (in dedicated server configuration) or let # of workers = # of virtual cores.

  3. You need to test both configurations performance wise, I advise you to use a tool called Apache JMeter to help you decide which is the best.

Finally, start the service by:

sudo service odoo-server start


Nginx Installation:

Log in to Nginx server (192.168.1.12), download Nginx install script:

sudo wget https://raw.githubusercontent.com/mmhy2003/Odoo-Deploy/11.0/03-nginx-install.sh
sudo chmod +x 03-nginx-install.sh

Let's modify Nginx installation script before execution.

sudo nano 03-nginx-install.sh

OE_DOMAIN="odoo.mohamedhammad.info *.odoo.mohamedhammad.info" # Modify it to your own domain name it's important for SSL registering
OE_HOST="192.168.1.11" # Change it to Odoo server Local IP address
OE_PORT="8069"
NGINX_CONFIG="odoo"
NGINX_CONFIG_PATH="/etc/nginx/sites-available/${NGINX_CONFIG}"

Then, save modification by pressing Ctrl+O then Enter then Ctrl+X to exit the editor.

Run the script:

sudo ./03-nginx-install.sh

Then, let's review our website configuration file.

sudo nano /etc/nginx/sites-enabled/odoo

We will find the following:

#odoo server
upstream odoo {
        server 192.168.1.11:8069 weight=1 fail_timeout=0;
# For more instances of Odoo add them below #server <SECOND-SERVER>:8069 weight=1 fail_timeout=0; } upstream odoochat { server 192.168.1.11:8072 weight=1 fail_timeout=0;
# For more instances of Odoo add them below
#server <SECOND-SERVER>:8072 weight=1 fail_timeout=0; } # http -> https #server { # listen 80; # listen [::]:80 ipv6only=on; # server_name odoo.mohamedhammad.info *.odoo.mohamedhammad.info; # add_header Strict-Transport-Security max-age=2592000; # rewrite ^/.*$ https://\$host\$request_uri? permanent; #} server { #listen 443; #listen [::]:443 ipv6only=on; listen 80; listen [::]:80 ipv6only=on; server_name odoo.mohamedhammad.info *.odoo.mohamedhammad.info; proxy_read_timeout 720s; proxy_connect_timeout 720s; proxy_send_timeout 720s; keepalive_timeout 60; # Add Headers for odoo proxy mode 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 on; #ssl_certificate /etc/letsencrypt/live/odoo.mohamedhammad.info/fullchain.pem; #ssl_certificate_key /etc/letsencrypt/live/odoo.mohamedhammad.info/privkey.pem; #ssl_session_timeout 30m; #ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES1$ #ssl_prefer_server_ciphers on; # log access_log /var/log/nginx/odoo.access.log; error_log /var/log/nginx/odoo.error.log; # Redirect requests to odoo backend server location / { proxy_redirect off; proxy_pass http://odoo; } location /longpolling { proxy_pass http://odoochat; } # cache some static data in memory for 60mins. # under heavy load this should relieve stress on the OpenERP web interface a bit. location ~* /[0-9a-zA-Z_]*/static/ { proxy_cache_valid 200 60m; proxy_buffering on; expires 864000; proxy_pass http://odoo; } # common gzip gzip_types text/css text/less text/plain text/xml application/xml application/json application/javascript; gzip on; }

Then, save modification by pressing Ctrl+O then Enter then Ctrl+X to exit the editor.

Important note: don't enable SSL section yet, we need first to start service without encryption to register SSL certificate then we reconfigure SSL section and link nginx with private & public key files.

Restart Nginx service by:

sudo service nginx restart

After that we start registering SSL certificates by Certbot:

sudo certbot --nginx certonly

You will be prompt to enter email & company's information to be included in the certificate, in addition, you will be notified on the specified email whenever certificate requires renewal.

After filling all information needed, choose website domain you want to create a certificate for it. In our case, it's odoo.mohamedhammad.info

Lastly, it will show you where on the system the keys are stored keep it in mind because we are going to include it in the configuration file.

After that we head back to our website configuration file again:

sudo nano /etc/nginx/sites-enabled/odoo

#odoo server
upstream odoo {
        server 192.168.1.11:8069 weight=1 fail_timeout=0;
        #server <SECOND-SERVER>:8069 weight=1 fail_timeout=0;
}
upstream odoochat {
        server 192.168.1.11:8072 weight=1 fail_timeout=0;
#server <SECOND-SERVER>:8072 weight=1 fail_timeout=0; } # http -> https server { listen 80; listen [::]:80 ipv6only=on; server_name odoo.mohamedhammad.info *.odoo.mohamedhammad.info; add_header Strict-Transport-Security max-age=2592000; rewrite ^/.*$ https://\$host\$request_uri? permanent; } server { listen 443; listen [::]:443 ipv6only=on; #listen 80; #listen [::]:80 ipv6only=on; server_name odoo.mohamedhammad.info *.odoo.mohamedhammad.info; proxy_read_timeout 720s; proxy_connect_timeout 720s; proxy_send_timeout 720s; keepalive_timeout 60; # Add Headers for odoo proxy mode 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 on; ssl_certificate /etc/letsencrypt/live/odoo.mohamedhammad.info/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/odoo.mohamedhammad.info/privkey.pem; ssl_session_timeout 30m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES1$ ssl_prefer_server_ciphers on; # log access_log /var/log/nginx/odoo.access.log; error_log /var/log/nginx/odoo.error.log; # Redirect requests to odoo backend server location / { proxy_redirect off; proxy_pass http://odoo; } location /longpolling { proxy_pass http://odoochat; } # cache some static data in memory for 60mins. # under heavy load this should relieve stress on the OpenERP web interface a bit. location ~* /[0-9a-zA-Z_]*/static/ { proxy_cache_valid 200 60m; proxy_buffering on; expires 864000; proxy_pass http://odoo; } # common gzip gzip_types text/css text/less text/plain text/xml application/xml application/json application/javascript; gzip on; }

To configure CertBot to auto-renew certificate periodically, add a scheduled action command in Ubuntu to do it for you:

sudo crontab -e

You will be prompt to choose your favorite text editor, choose nano for the sake of easiness.

# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command

0 3 * * 1 certbot renew --dry-run # Certificate will be renewed everyweek at 3 AM

Then, save modification by pressing Ctrl+O then Enter then Ctrl+X to exit the editor.

Finally, everything should be configured right and ready to test.

sudo service nginx restart


Important Notes:

  1. Domain/Subdomain must be pointing to Nginx server's public IP address for everything to work well.

  2. At the time being CertBot doesn't support wildcard SSL certificates.

  3. In order to use the live chat feature, you should at least specify 2 workers.