Using a reverse proxy

While Odoo itself can serve web pages, it is strongly recommended to have a reverse proxy in front of it. A reverse proxy acts as an intermediary managing the traffic between the clients sending requests and the Odoo servers responding to them. Using a reverse proxy has several benefits.

On the security side, it can do the following:

  • Handle (and enforce) HTTPS protocols to encrypt traffic
  • Hide the internal network characteristics
  • Act an "application firewall" limiting the URLs accepted for processing

And on the performance side, it can provide significant improvements:

  • Cache static content, thus reducing the load on the Odoo servers
  • Compress content to speed up loading times
  • Act as a load balancer distributing load between several servers

Apache is a popular option to use as reverse proxy. Nginx is a recent alternative with good technical arguments. Here we will choose to use nginx as a reverse proxy and show how it can be used perform the functions mentioned above.

Setting up nginx for reverse proxy

First, we should install nginx. We want it to listen on the default HTTP ports, so we should make sure they are not already taken by some other service. Performing this command should result in an error, as shown in the following:

$ curl http://localhost
curl: (7) Failed to connect to localhost port 80

If not, you should disable or remove that service to allow nginx to use those ports. For example, to stop an existing Apache server you should:

$ sudo /etc/init.d/apache2 stop

Now we can install nginx, which is done in the expected way:

$ sudo apt-get install nginx

To confirm that it is working correctly, we should see a "Welcome to nginx" page when visiting the server address with a browser or using curl http://localhost in the server.

Nginx configuration files follow the same approach as Apache: they are stored in /etc/nginx/available-sites/ and activated by adding a symbolic link in /etc/nginx/enabled-sites/. We should also disable the default configuration provided by the nginx installation, as shown in the following:

$ sudo rm /etc/nginx/sites-enabled/default
$ sudo touch /etc/nginx/sites-available/odoo
$ sudo ln -s /etc/nginx/sites-available/odoo /etc/nginx/sites-enabled/odoo

Using an editor, such as nano or vi, we should edit our nginx configuration file as follows:

$ sudo nano /etc/nginx/sites-available/odoo

First we add the upstreams, the backend servers nginx will redirect traffic to, the Odoo server in our case, which is listening on port 8069, shown in the following:

upstream backend-odoo {
  server 127.0.0.1:8069;
}
server {
  location / {
    proxy_pass http://backend-odoo;
  }
}

To test if the edited configuration is correct, use the following:

$ sudo nginx -t

In case you find errors, confirm the configuration file is correctly typed. Also, a common problem is for the default HTTP to be taken by another service, such as Apache or the default nginx website. Double-check the instructions given before to make sure that this is not the case, then restart nginx. After this, we can have nginx to reload the new configuration as follows:

$ sudo /etc/init.d/nginx reload

We can now confirm that nginx is redirecting traffic to the backend Odoo server, as shown in the following:

$ curl http://localhost
<html><head><script>window.location = '/web' + location.hash;</script></head></html>

Enforcing HTTPS

Next we should install a certificate to be able to use SSL. To create a self-signed certificate, follow the following steps:

$ sudo mkdir /etc/nginx/ssl && cd /etc/nginx/ssl
$ sudo openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
$ sudo chmod a-wx *            # make files read only
$ sudo chown www-data:root *   # access only to www-data group

This creates an ssl/ directory inside the /etc/nginx/ directory and creates a password less self-signed SSL certificate. When running the openssl command, some additional information will be asked, and a certificate and key files are generated. Finally, the ownership of these files is given to the user www-data used to run the web server.

Note

Using self-signed certificated can pose some security risks, such as man-in-the-middle attacks, and may even not be allowed by some browsers. For a robust solution, you should use a certificate signed by a recognized certificate authority. This is particularly important if you are running a commercial or e-commerce website.

Now that we have an SSL certificate, we are ready to configure nginx to use it.

To enforce HTTPS, we will redirect all HTTP traffic to it. Replace the server directive we defined previously with the following:

server {
  listen 80;
  add_header Strict-Transport-Security max-age=2592000;
  rewrite ^/.*$ https://$host$request_uri? permanent;
}

If we reload the nginx configuration now and access the server with a web browser, we will see that the http:// address will be converted into an https:// address.

But it won't return any content before we configure the HTTPS service properly, by adding the following server configuration:

server {
  listen 443 default;
  # ssl settings
  ssl on;
  ssl_certificate     /etc/nginx/ssl/cert.pem;
  ssl_certificate_key /etc/nginx/ssl/key.pem;
  keepalive_timeout 60;
  # proxy header and settings
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_redirect off;
 
  location / {
    proxy_pass http://backend-odoo;
  }
}

This will listen to the HTTPS port and use the /etc/nginx/ssl/ certificate files to encrypt the traffic. We also add some information to the request header to let the Odoo backend service know it's being proxied. For security reasons, it's important for Odoo to make sure the proxy_mode parameter is set to True. At the end, the location directive defines that all request are passed to the backend-odoo upstream.

Reload the configuration, and we should have our Odoo service working through HTTPS, as shown in the following:

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo service nginx reload 
 * Reloading nginx configuration nginx
   ...done.
$ curl -k https://localhost 
<html><head><script>window.location = '/web' + location.hash;</script></head></html>

The last output confirms that the Odoo web client is being served over HTTPS.

Nginx optimizations

Now, it is time for some fine-tuning of the nginx settings. They are recommended to enable response buffering and data compression that should improve the speed of the website. We also set a specific location for the logs.

The following configurations should be added inside the server listening on port 443, for example, just after the proxy definitions:

# odoo log files
access_log /var/log/nginx/odoo-access.log;
error_log  /var/log/nginx/odoo-error.log;
# increase proxy buffer size
proxy_buffers 16 64k;
proxy_buffer_size 128k;
# force timeouts if the backend dies
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
# enable data compression
gzip on;
gzip_min_length 1100;
gzip_buffers 4 32k;
gzip_types text/plain application/x-javascript text/xml text/css;
gzip_vary on;

We can also activate static content caching for faster responses to the types of requests mentioned in the preceding code example and to avoid their load on the Odoo server. After the location / section, add the following second location section:

location ~* /web/static/ {
  # cache static data
  proxy_cache_valid 200 60m;
  proxy_buffering on;
  expires 864000;
  proxy_pass http://backend-odoo;
}

With this, the static data is cached for 60 minutes. Further requests on those requests in that interval will be responded to directly by nginx from the cache.

Long polling

Long polling is used to support the instant messaging app, and when using multiprocessing workers, it is handled on a separate port, which is 8072 by default.

For our reverse proxy, this means that the longpolling requests should be passed to this port. To support this, we need to add a new upstream to our nginx configuration, as shown in the following code:

upstream backend-odoo-im { server 127.0.0.1:8072; }

Next, we should add another location to the server handling the HTTPS requests, as shown in the following code:

  location /longpolling { proxy_pass http://backend-odoo-im;}

With these settings, nginx should pass these requests to the proper Odoo server port.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset