Skip to main content

Configuring and enforcing HTTPS

Configuring and enforcing HTTPS

Web traffic should not travel through the internet in plaintext. When exposing our Odoo web server to be used on a network, we should use the HTTPS protocol to have the traffic encrypted.
In some cases, it might be acceptable to use a self-signed certificate. Keep in mind that using a self-signed certificate can pose some security risks, however, such as man-in-the-middle attacks, and may not be allowed by some browsers.
For a more robust solution, you should use a certificate signed by a recognized certificate authority. This is particularly important if you're running a commercial or e-commerce website.


Note

The Let's Encrypt service at https://letsencrypt.org provides free certificates. An Odoo add-on module exists to handle the automatic requesting of SSL certificates for the Odoo server, but at the time of writing, it wasn't yet ported to Odoo 12. You can learn more at https://github.com/OCA/server-tools/tree/11.0/letsencrypt.

Creating a self-signed SSL certificate

Next, we should install a certificate that will enable us to use SSL.
To create a self-signed certificate, use the following commands:
$ sudo mkdir /etc/ssl/nginx && cd /etc/ssl/nginx
$ sudo openssl req -x509 -newkey rsa:2048 \
-keyout server.key -out server.crt -days 365 -nodes
$ sudo chmod a-wx *           # make files read only
$ sudo chown www-data:root *   # access only to www-data group
The preceding code creates an /etc/ssl/nginx directory and creates a passwordless self-signed SSL certificate. When running the openssl command, the user will be asked for some additional information, and then a certificate and key files will be generated. Finally, the ownership of these files is given to the www-datauser, which is used to run the web server.

Configuring HTTPS access on nginx

Now that we have an SSL certificate, we're ready to configure nginx to use it. To enforce HTTPS, we need to redirect all HTTP traffic. Replace the server directive we defined previously with the following code:
server { 
  listen 80; 
  rewrite ^(.*) https://$host$1 permanent;
}
Now, if we reload the nginx configuration and access the server with a web browser, we'll see that the http://address has been converted into an https:// address.
However, this address won't return any content until we configure the HTTPS service properly; this can be done by adding the following server configuration:
server {
  listen 443;

  # 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/ssl/nginx/server.crt;
  ssl_certificate_key /etc/ssl/nginx/server.key;
  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-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
 ssl_prefer_server_ciphers on;

  # log
 access_log /var/log/nginx/odoo.access.log;
  error_log /var/log/nginx/odoo.error.log;

  # Redirect longpoll requests to odoo longpolling port
 location /longpolling {
    proxy_pass http://odoochat;
  }

  # Redirect requests to odoo backend server
 location / {
    proxy_redirect off;
    proxy_pass http://odoo;
  }

  # common gzip
 gzip_types text/css text/scss text/plain text/xml application/xml application/json application/javascript;
  gzip on;
}
The preceding code will listen to the HTTPS port and use the /etc/ssl/nginx/ certificate files to encrypt the traffic. This is similar to the server configuration section we looked at in the Setting up an nginx reverse proxy section.
If we reload the configuration, we should now have our Odoo service working through HTTPS, as shown in the following commands:
$ 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  # or: sudo systemctl reload nginx
* 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.

Note

In older Odoo images, the PosBox would only work in HTTP mode; for it to work, an exception had to be added to nginx for the  /pos/ URL. Recent images of Odoo 10 and later include a self-signed certificate allowing HTTPS communication between PosBOx and IoT Box. The change was introduced by https://github.com/odoo/odoo/pull/27936.

Caching static content

We can configure nginx to cache the static files served, and have the repeated requests to be served directly from the nginx cache, without the need to pass on a request to the upstream odoo server.
Activating static content caching allows for a faster response time and reduces the workload for Odoo servers.


To enable this setting, add the following code before the location /longpolling section:
 # cache static data  
  location ~* /web/static/ { 
proxy_cache_valid 200 60m; 
    proxy_buffering on; 
    expires 864000; 
    proxy_pass http://odoo; 
  } 
With this command, static data is now cached for 60 minutes. Further, additional requests in that interval will be responded to directly by nginx from the cache.

Comments

Popular posts from this blog

The message and activity features

The message and activity features Odoo has available global  messaging  and activity planning features, provided by the  Discuss  application, with technical name mail. The mail module provides the  mail.thread  abstract class that makes it simple to add the messaging features to any model, and the  mail.activity.mixin  that adds planned activity features. This was done in  Chapter 4 ,  Extending Modules , to explain how to inherit features from mixin abstract classes. To add these features, we need to add the mail dependency to the add-on module,  library_checkout , and then have the library checkout model class inherit from the abstract classes providing the following features. Edit the  'depends'  key in the  library_checkout/__manifest__.py   file, to add the mail module, shown as follows: Copy 'depends': ['library_member' , 'mail' ], And edit the  library_checkout/m...

Setting up an nginx reverse proxy

Setting up an nginx reverse proxy While Odoo itself can serve web pages, it's strongly recommended that there is a  reverse  proxy positioned in front of it. A reverse proxy acts as an intermediary that manages the traffic between 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 as an application firewall, limiting the URLs accepted for processing Also, on the performance side, it can provide the following significant improvements: Cached static content, hence reducing the load on the Odoo servers Compressed content to speed up loading time Act as a load balancer, distributing load between several servers Apache is a popular choice when considering a reverse proxy, although  nginx  is a recent alternative with good technical argumen...

The QWeb template language

The QWeb template language The  QWeb  parser looks for special directives in the templates and replaces them with dynamically generated HTML. These directives are XML element attributes and can be used in any valid tag or element, such as  <div> ,  <span> , or  <field> . Sometimes, we may want to use a QWeb directive but we don't want to place it in any of the XML elements in our template. For those cases, we have a  <t>  special element that can have QWeb directives, such as  t-if  or  t-foreach , but is silent and won't have any output on the final XML/HTML produced. The QWeb directives will frequently make use of evaluated expressions to produce different results, depending on the current record values. There are two different QWeb implementations: client-side JavaScript and server-side Python. The reports and website pages use the server-side Python implementation of QWeb. Kanban views us...