DEV Community

Cover image for How to configure multiple databases on individual domain names using a single Odoo instance? [A Multi-Tenant Odoo App]
Akinshola Samuel AKINDE
Akinshola Samuel AKINDE

Posted on

How to configure multiple databases on individual domain names using a single Odoo instance? [A Multi-Tenant Odoo App]

Hey Guys... Haykins here 😊. Are you tired of managing multiple Odoo servers for different clients? scratch that. Let’s dockerize your hustle, make it scalable, and give each client their own domain β€” all on one Odoo engine. this also works out for B2B Startup adopting Odoo for their customers operational activities.


Quick Gist of what we are doing

We will be developing an Odoo setup where:

  • And Odoo instance that serves multiple clients
  • Each client has their own database
  • Each database is accessible via a custom domain or subdomain like:
    • client-1.haykinsodoo.docker
    • client-2.haykinsodoo.docker
    • client-3.haykinsodoo.docker
  • Lastly, using Docker, PostgreSQL, Traefik for SSL & routing, sprinkles of Naija developer ginger 😎, and my PC with internet. NEPA or not πŸ˜….

Now, let's get into it...

#1 Project Structure

let's get the project structure setup in this format:

β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ .env
β”œβ”€β”€ odoo.conf
└── traefik/
    β”œβ”€β”€ traefik.yml
    └── acme.json
Enter fullscreen mode Exit fullscreen mode

#2 Setting up Environment Variables

we will be creating an .env file on the root folder.

ODOO_VERSION=18.0
ODOO_DB_USER=odoo
ODOO_DB_PASSWORD=password
POSTGRES_PASSWORD=password
DOMAINS=client-1.haykinsodoo.docker,client-2.haykinsodoo.docker,client-3.haykinsodoo.docker
Enter fullscreen mode Exit fullscreen mode

#3 Setting up Docker Compose YAML

Next, we will be setting up the docker-compose.yml file

# version: "3.9"
# Odoo with Traefik and PostgreSQL
# This docker-compose file sets up Odoo with Traefik as a reverse proxy and PostgreSQL as the database.

services:
  db:
    image: postgres:15
    environment:
      - POSTGRES_USER=${ODOO_DB_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - PGDATA=/var/lib/postgresql/data/pgdata
    ports:
      - 8432:5432
    volumes:
      - db-data:/var/lib/postgresql/data
    secrets:
      - postgresql_password

  odoo:
    image: odoo:${ODOO_VERSION}
    depends_on:
      - db
    environment:
      - HOST=db
      - USER=${ODOO_DB_USER}
      - PASSWORD=${ODOO_DB_PASSWORD}
    secrets:
      - postgresql_password
    ports:
      - "8069:8069"
      - "8072:8072"
    volumes:
      - odoo-data:/var/lib/odoo
      - ./odoo.conf:/etc/odoo/odoo.conf
      - ./addons:/mnt/extra-addons
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.odoo.rule=HostRegexp(`{subdomain:.+}.haykinsodoo.docker`)"
      - "traefik.http.routers.odoo.entrypoints=web"
      # - "traefik.http.routers.odoo.entrypoints=websecure"
      # - "traefik.http.routers.odoo.tls=true"
      # - "traefik.http.routers.odoo.tls.certresolver=letsencrypt"
      - "traefik.http.services.odoo.loadbalancer.server.port=8069"

  traefik:
    image: traefik:v2.10
    command:
      - --api.insecure=true
      - --providers.docker=true
      # - --entrypoints.websecure.address=:443
      - --entrypoints.web.address=:80
      - --certificatesresolvers.letsencrypt.acme.httpchallenge=true
      - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
      - --certificatesresolvers.letsencrypt.acme.email=admin@haykinsodoo.docker
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # Traefik dashboard port
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./traefik/traefik.yml:/traefik.yml
      - ./traefik/acme.json:/letsencrypt/acme.json

volumes:
  db-data:
  odoo-data:

secrets:
  postgresql_password:
    file: odoo_pg_pass
Enter fullscreen mode Exit fullscreen mode

#4 Setting up the Odoo Configuration

We continue with creatinf an odoo.conf file and adding our configurations

[options]
addons_path = /mnt/extra-addons
admin_passwd = admin
db_host = db
db_port = 5432
db_user = odoo
db_password = password
dbfilter = ^%d$
xmlrpc_interface = 0.0.0.0
log_level = info
Enter fullscreen mode Exit fullscreen mode

This dbfilter = ^%d$ simply means when the site: client-1.haykinsodoo.docker is visited, Odoo will open client_1 as the database.

#5 Setting and Configuring Traefik

Let's create a traefik/traefik.yml

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"
  traefik:
    address: ":8080"

api:
  dashboard: true
  insecure: true

providers:
  docker:
    exposedByDefault: false
Enter fullscreen mode Exit fullscreen mode

Also, create acme.json and set file permissions (access rights) to 600, so that only the file owner has read and write access, while no one else, including the group and others, has any access.

$ touch traefik/acme.json # create the file

$ chmod 600 traefik/acme.json # change file permission
Enter fullscreen mode Exit fullscreen mode

#5 Let's get everything up and running

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

Oshee! Our Odoo live... For us to access the different instances

  1. client-1.haykinsodoo.docker will serve the client-1 database. (note: ensure to copy the master password which will be re-used for all other clients installations)
  2. client-2.haykinsodoo.docker will serve the client-2 database.
  3. client-3.haykinsodoo.docker will serve the client-3 database.

Note In Prod: Make sure those subdomains point to your VPS/public IP address (you can use your domain provider’s DNS settings to handle this).

Bonus Bonus Bonus: Create a DB Manually (Optional)

$ docker exec -it <odoo_container_id> /bin/bash

# run the below code inside container
$ odoo -d client-1 --init=base --stop-after-init
Enter fullscreen mode Exit fullscreen mode

Final 2kobo (thoughts 😊)

This entire process and setup gives you the power to serve, scale, and secure multiple Odoo clients like a true Odoo Developer and/or DevOps engineer. It’s modular, clean, and cheap to maintain.

So whether you’re a developer, startup founder, or building the next ERP-as-a-Service, this is your kick-off point. With this setup, you're running your own multi-tenant Odoo app.

visit my GitHub for the full code setup: https://github.com/thisishaykins/multi-tenant-odoo-app

πŸ™Œ Shoutout

Written by a Dev for Devs, proudly from the land of jollof, generators, and pure tech vibes. πŸ‡³πŸ‡¬
Built this with:

  • My PC
  • VS Code
  • Docker
  • Odoo
  • Postgres
  • Traefik
  • Naija jollof rice 🌢️

Drop your questions below or tag me on Twitter/X: @thisishaykins

Top comments (6)

Collapse
 
anbarino profile image
instagorio

Hello, thanks for the infos and the efffort you put here,
I have a question
for custom addons what is the best startegy to manage them per client, and the deployment pipline how it should be for each client how to manage it??

Thank you

Collapse
 
thisishaykins profile image
Akinshola Samuel AKINDE

Hi @anbarino, thanks for read... With regards to your question: custom addons can be shared across all clients. But not necessarily used as installation are client dependent (since there are different database for each client), same also for deployment pipeline.

Do let me know if you need further details and assistance. Cheers.

Collapse
 
emmanuel_momoh_fa94729909 profile image
Emmanuel Momoh

This article came just in time!!. Thanks for this as it solves my immediate need.

Collapse
 
asabuodu_innocentonochie profile image
Asabuodu Innocent Onochie

Thanks for this, it's very helpful and so impactful.

Collapse
 
steveajose profile image
SA

Very informative and practical. Thank you!

Collapse
 
adeniran_opeyemi_814a67dc profile image
Adeniran Opeyemi

Thanks for sharing πŸ™ŒπŸΎ