First have a look at the official deployment documentation, which has a good introduction paragraph about db filtering.
Odoo is a multi-tenant system: a single Odoo system may run and serve a number of database instances.
Examples
Let's take some examples to illustrate how does the code works:
dbfilter is a regex that is built dynamically: you can use variables %d and %h to adapt its content depending on the HOST header of the http request.
Concretely:
-
%dis replaced by the first subdomain after www:-
https://demo.example.com:
%d = demo -
https://www.demo.example.com:
%d = demo
-
https://demo.example.com:
-
%his replaced by the full domain, port excluded if any:-
https://demo.example.com:
%h = demo.domain.com -
https://demo.example.com:8080:
%h = demo.domain.com
-
https://demo.example.com:
So, if you define dbfilter = ^%d.*\Z, a user accessing https://demo.example.com will have access to databases matching ^demo.*\Z, e.g.:
demodemo_backup_20180404
Beware
re.match is used:
dbs = [i for i in dbs if re.match(r, i)]
So it's easy to write a regex more permissive than expected. If you define dbfilter = demo_* for example, it will also match demoinefromage_prod.
dbfilter_from_header module
You can't always match databases names with domain names.
For example, you might have a single Odoo instance to serve 2 databases:
customer1_prodcustomer2_prod
But each of these customers wants its own custom domain, respectively:
https://back.customer1.comhttps://app.customer2.com
To support this case, you can use OCA's dbfilter_from_header module.
Installation
$ git clone https://github.com/OCA/server-tools -b 9.0 --no-checkout --single-branch --depth 1
$ cd server-tools
$ git config core.sparsecheckout true
$ echo "dbfilter_from_header" > .git/info/sparse-checkout
$ git read-tree -mu HEADConfiguration
On Nginx side, you need to define a dedicated dbfilter for each virtual host.
In our case, for https://back.customer1.com:
server_name back.customer1.com;
(...)
location / {
(...)
proxy_set_header X-Odoo-dbfilter ^customer1_.*\Z;
2 things to note:
- before passing the request to Odoo, Nginx takes all HTTP headers, lowercase them and converts dashes to underscores;
- we use
\Zinstead of$to match end of string, because nginx cannot escape$
2 levels of filtering
dbfilter_from_header respects the dbfilter defined at Odoo level, so we can setup 2 levels of filtering:
dbfilter = ^.+prod.*$proxy_set_header X-Odoo-dbfilter ^.*customer1.*\Z;