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:
-
%d
is replaced by the first subdomain after www:-
https://demo.example.com:
%d = demo
-
https://www.demo.example.com:
%d = demo
-
https://demo.example.com:
-
%h
is 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.:
demo
demo_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_prod
customer2_prod
But each of these customers wants its own custom domain, respectively:
https://back.customer1.com
https://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 HEAD
Configuration
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
\Z
instead 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;