Introduction
Dans le monde dynamique des ERP, Odoo s’est imposé comme une solution incontournable pour de nombreuses entreprises cherchant à optimiser leurs processus métiers. Pourtant, malgré ses nombreuses fonctionnalités, la question de la sécurité lors du déploiement d’Odoo reste prépondérante. Avec l’évolution des technologies et des méthodes, des outils tels que Docker Compose, Traefik et Vagrant sont devenus des alliés précieux pour garantir un déploiement à la fois flexible et sécurisé. Dans ce billet, nous explorerons comment combiner ces outils pour assurer un déploiement sécurisé d’Odoo, tout en se connectant en HTTPS. Que vous soyez novice ou expert en matière d’ERP, cette approche vous fournira les clés pour une mise en place optimale et rassurante.
Pourquoi utiliser Docker Compose, Traefik et Vagrant pour Odoo?
Installer vagrant sur Windows
1. Prérequis:
- Système d’exploitation Windows 7 ou supérieur.
- Droits d’administrateur sur la machine.
2. Installation:
- Étape 1: Téléchargez VirtualBox depuis le site officiel et installez-le.
- Étape 2: Rendez-vous sur le site officiel de Vagrant et téléchargez la version Windows (format
.msi
). - Étape 3: Exécutez le fichier
.msi
téléchargé et suivez les instructions d’installation.
3. Vérification de l’installation:
Après l’installation, ouvrez l’invite de commandes (CMD) ou PowerShell et vérifiez la version de Vagrant:
vagrant --version
PS C:\> vagrant.exe --version Vagrant 2.3.2
Création des Vagrantfiles
Le Vagrantfile
sert de fichier de configuration principal pour Vagrant. Il spécifie le type de machine, les ressources allouées, telles que la RAM et le nombre de CPU, ainsi que la manière dont la machine virtuelle sera accessible. De plus, ce fichier détaille les procédures de provisionnement et de configuration des machines. Dans notre contexte, nous utiliserons deux Vagrantfiles
pour déployer deux machines virtuelles distinctes : l’une sera dédiée au déploiement de Docker pour, par la suite, mettre en place Traefik et Odoo. L’autre machine sera exclusivement consacrée au déploiement de la base de données pour Odoo.
Déploiement de docker et docker-compose :
- Créez un nouveau dossier pour votre projet Vagrant.
- Dans ce dossier, créez un fichier nommé
Vagrantfile
et collez-y le contenu ci-dessus.
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.network "private_network", ip: "192.168.33.4"
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
end
config.vm.provision "shell", inline: <<-SHELL
# Install Docker
sudo apt update
sudo apt install -y docker.io
# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Install Bash completion for Docker and Docker Compose
sudo curl -L https://raw.githubusercontent.com/docker/compose/1.27.4/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
sudo curl -L https://raw.githubusercontent.com/docker/cli/master/contrib/completion/bash/docker -o /etc/bash_completion.d/docker
# Start Docker service
sudo systemctl start docker
# Set Docker service to start on boot
sudo systemctl enable docker
SHELL
end
vagrant up
`.Après l’achèvement de cette opération, une machine virtuelle Ubuntu sera mise en place avec Docker préinstallé et configuré pour l’usage. Pour accéder à cette machine virtuelle, utilisez la commande `vagrant ssh
`.
PS C:\Users\teachmemore\Documents\Vagrant\docker> vagrant ssh
Welcome to Ubuntu 16.04.7 LTS (GNU/Linux 4.4.0-210-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
...
Déploiement de PostgreSQL :
Opter pour l’installation d’une base de données sur une machine dédiée pour l’interface Odoo, plutôt que sa conteneurisation, offre des avantages substantiels, notamment en matière de sécurité. Une base de données installée sur une machine autonome diminue considérablement la surface d’attaque potentielle. De plus, une telle configuration permet de bénéficier de règles de pare-feu renforcées, en autorisant exclusivement le trafic indispensable et en bloquant toute autre communication non sollicitée.Mise en place d’une machine virtuelle dédiée à l’exécution de PostgreSQL :
Suivez les étapes ci-dessous pour déployer une machine virtuelle pour PostgreSQL :- Commencez par créer un dossier dédié à votre projet Vagrant.
- À l’intérieur de ce dossier, générez un fichier intitulé
Vagrantfile
et insérez-y le contenu approprié.
Vagrant.configure("2") do |config|
config.vm.box = "rockylinux/9"
config.vm.network "private_network", ip: "192.168.33.5"
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
end
end
Initialisation de la machine virtuelle :
Depuis votre terminal ou votre invite de commandes, accédez au dossier concerné puis lancez la commandevagrant up
.Après l’exécution complète de cette commande, une machine virtuelle Ubuntu sera opérationnelle. Pour y accéder, utilisez la commande vagrant ssh
.Installation de PostgreSQL :
# Mise à jour des référentiels de package
$ sudo dnf update
# Télécharger le référentiel de package
$ sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# Installation et initialisation du moteur PostgreSQL
$ sudo dnf install postgresql postgresql15-contrib -y
$ sudo dnf install -y postgresql15-server
$ sudo /usr/pgsql-15/bin/postgresql-15-setup initdb
# Séparation des données et de la configuration qui sont par défaut dans le même répertoire.
$ sudo -s
$ cd /var/lib/pgsql/15
$ mkdir conf
$ chown postgres: conf
$ mv data/*.conf conf/.
$ cd data
$ ln -sf ../conf/* .
# Lancement et mise en démarrage automatique du moteur de base de données
$ systemctl start postgresql-15.service
$ systemctl enable postgresql-15.service
$ systemctl status postgresql-15.service
Sécuriser la base de données
$ su - postgres -c psql
psql (13.11, server 15.4)
WARNING: psql major version 13, server major version 15.
Some psql features might not work.
Type "help" for help.
Type "help" for help..
postgres=#
postgres=# \password postgres
Enter new password: ********
Enter it again: ********
Configuration du certificat pour sécuriser les communications :
Afin d’assurer une communication sécurisée, nous allons générer un certificat SSL et l’intégrer à la configuration de PostgreSQL.Pour commencer, connectez-vous à votre machine virtuelle Docker. Dans le but d’optimiser cette étape, nous avons mis en place une automatisation de la génération des certificats via un conteneur Docker. À cet effet, j’ai élaboré un script bash qui s’appuie sur openssl pour faciliter la création de ces certificats. Bien que cette étape ne soit pas strictement nécessaire, elle illustre la puissance et l’efficacité de l’automatisation. Par conséquent, nous mettrons en place un conteneur dédié, agissant comme serveur PKI.Mise en place du conteneur PKI :
Sur la machine virtuelle Docker, créez un fichier intituléDockerfile
.Incorporez-y le code fourni ci-après, puis enregistrez le fichier.
# Utilisation d'une image de base avec OpenSSL préinstallé
FROM alpine:latest
# Installation d'OpenSSL
RUN apk add --no-cache openssl
# Copie du script dans le conteneur
COPY script.sh /script.sh
# Mettre le script en exécutable
RUN chmod +x /script.sh
# Création du répertoire où les certificats seront stockés
# (c'est aussi le répertoire qui sera monté en volume depuis l'hôte)
RUN mkdir -p /openssl-certs
# Exécution du script lors du démarrage du conteneur
CMD ["/script.sh"]
Créer un image docker à partir du Dockerfile en utilisant la commande suivante :
vagrant@ubuntu-xenial:~$ sudo docker build -t pki:1 .
Sending build context to Docker daemon 17.92kB
Step 1/6 : FROM alpine:latest
latest: Pulling from library/alpine
7264a8db6415: Pull complete
Digest: sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a
Status: Downloaded newer image for alpine:latest
---> 7e01a0d0a1dc
Step 2/6 : RUN apk add --no-cache openssl
---> Running in f3572003b7a2
fetch https://dl-cdn.alpinelinux.org/alpine/v3.18/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.18/community/x86_64/APKINDEX.tar.gz
(1/1) Installing openssl (3.1.2-r0)
Executing busybox-1.36.1-r2.trigger
OK: 8 MiB in 16 packages
Removing intermediate container f3572003b7a2
---> 4728e74c7121
Step 3/6 : COPY script.sh /script.sh
---> 35b23f862458
Step 4/6 : RUN chmod +x /script.sh
---> Running in d00b4dcb291b
Removing intermediate container d00b4dcb291b
---> 364bb35eada1
Step 5/6 : RUN mkdir -p /openssl-certs
---> Running in dbd653b027e5
Removing intermediate container dbd653b027e5
---> 7ca81a22fa2e
Step 6/6 : CMD ["/script.sh"]
---> Running in 1a48ba4e8811
Removing intermediate container 1a48ba4e8811
---> 5f7ca8775985
Successfully built 5f7ca8775985
Successfully tagged pki:1
vagrant@ubuntu-xenial:~$
Génération des certificats via le conteneur PKI :
Commençons par préparer notre environnement pour la création des certificats.Dans le répertoire/var
, établissez un espace de travail que nous désignerons ici par shared
.
À l’intérieur de cet espace, créez un sous-répertoire nommé certificats
.
Avec votre environnement prêt, exécutez la commande indiquée ci-après :
$ sudo docker run --rm \
-e SRVNAME="pgsql" \
-e CAPASS="motdepassdelacaroot" \
-e DN="teachmemore.fr" \
-v $PWD/certs:/openssl-certs \
pki:1
# output
---
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
42:52:19:28:c5:5d:72:17:3e:84:eb:13:96:9a:22:65:4a:69:83:13
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = ca.teachmemore.fr
Validity
Not Before: Aug 15 13:33:59 2023 GMT
Not After : Aug 12 13:33:59 2033 GMT
Subject: CN = ca.teachmemore.fr
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
---
Observations sur les certificats générés :
Il est à noter que les certificats émis par l’autorité de certification, en l’occurrence ca.teachmemore.fr
, ont une durée de validité de 10 ans. Tandis que les clés publiques et privées sont valides pour une année. Ces durées de validité sont modifiables directement au sein du script.”
vagrant@ubuntu-xenial:~/var/shared/certificats$ ls
ca.crt ca-key.pem ca.srl pgsql.crt pgsql.csr pgsql-key.pem pgsql.pem wildcard.crt wildcard.csr wildcard-key.pem wildcard.pem
psql-key.pem
(clé privée)
psql.crt
(clé publique)
ca.crt
(certificat de l’autorité de certification).
Transférez ces certificats vers la machine virtuelle exécutant le moteur PostgreSQL. Pour ce faire, des outils tels que WinSCP ou la commande SCP sont recommandés. Notez que le nom d’utilisateur et le mot de passe par défaut pour une VM configurée avec Vagrant sont respectivement vagrant
pour les deux.”
vagrant@ubuntu-xenial:~/var/shared/certificats$ sudo scp pgsql.crt pgsql-key.pem ca.crt vagrant@192.168.33.5:/home/vagrant/
The authenticity of host '192.168.33.5 (192.168.33.5)' can't be established.
ECDSA key fingerprint is SHA256:BZJxhOhX9OS5owUBMYfLmGWqvQbuB1YHAoe2w+K4pmU.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.33.5' (ECDSA) to the list of known hosts.
vagrant@192.168.33.5's password:
pgsql.crt 100% 1363 1.3KB/s 00:00
pgsql-key.pem 100% 1704 1.7KB/s 00:00
ca.crt 100% 1830 1.8KB/s 00:00
Manipulation des certificats sur la VM PostgreSQL :
Connectez-vous à la machine virtuelle hébergeant PostgreSQL et naviguez vers le répertoire de l’utilisateur vagrant
. Lorsque vous listez le contenu, vous devriez voir les certificats précédemment transférés. Modifiez le nom du fichier psql-key.pem
pour le renommer en psql.key
. Ensuite, transférez les trois certificats vers le chemin suivant : /var/lib/pgsql/15/conf
.
[vagrant@localhost ~]$ ls
ca.crt pgsql.crt pgsql-key.pem
[vagrant@localhost ~]$ mv pgsql-key.pem pgsql.key
#Changer de privilège
[vagrant@localhost ~]$ sudo -s
# Déplacer les fichier dans /var/lib/pgsql/15/conf
[root@localhost vagrant]# mv * /var/lib/pgsql/15/conf/
# Désigner l'utilisateur postgres comme propriétaire des certificats
[root@localhost vagrant]# chown postgres /var/lib/pgsql/15/conf/pgsql.key pgsql.crt ca.crt
/var/lib/pgsql/15/conf/postgresql.conf
. Par la suite, ajustez les autres paramètres de votre base de données conformément aux recommandations ci-après pour optimiser les performances de PostgreSQL.
# vi /var/lib/pgsql/15/conf/postgresql.conf
# Network Related Configuration
listen_addresses = '*'
…
shared_buffers = 1GB
work_mem = 205MB
maintenance_work_mem = 256MB
effective_cache_size = 3GB
effective_io_concurrency = 2
max_connections = 100
…
ssl = on
ssl_cert_file = '../conf/pgsql.crt'
ssl_key_file = '../conf/pgsql.key'
ssl_ca_file = '../conf/ca.crt'
192.168.33.4
, de communiquer avec la base de données située à l’adresse IP 192.168.33.5
.# vi /var/lib/pgsql/15/conf/pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32
hostssl all all 192.168.33.4/32 md5
Redémarrer les services postgresql une fois la configuration terminée
[root@localhost vagrant]# sudo systemctl restart postgresql-15.service
# vérifier le status du service
[root@localhost conf]# sudo systemctl status postgresql-15.service
● postgresql-15.service - PostgreSQL 15 database server
Loaded: loaded (/usr/lib/systemd/system/postgresql-15.service; enabled; preset: disabled)
Active: active (running) since Tue 2023-08-15 16:33:55 UTC; 2min 48s ago
Docs: https://www.postgresql.org/docs/15/static/
Process: 28341 ExecStartPre=/usr/pgsql-15/bin/postgresql-15-check-db-dir ${PGDATA} (code=exited, status=0/SUCCESS)
Main PID: 28346 (postmaster)
Tasks: 8 (limit: 12356)
Memory: 17.4M
CPU: 291ms
CGroup: /system.slice/postgresql-15.service
├─28346 /usr/pgsql-15/bin/postmaster -D /var/lib/pgsql/15/data/
├─28347 "postgres: logger "
├─28349 "postgres: checkpointer "
├─28350 "postgres: background writer "
├─28351 "postgres: walwriter "
├─28352 "postgres: autovacuum launcher "
├─28353 "postgres: stats collector "
└─28354 "postgres: logical replication launcher "
Aug 15 16:33:54 localhost.localdomain systemd[1]: Starting PostgreSQL 15 database server...
Aug 15 16:33:54 localhost.localdomain postmaster[28346]: 2023-08-15 16:33:54.998 UTC [28346] LOG: redirecting log output to logging collector process
Aug 15 16:33:54 localhost.localdomain postmaster[28346]: 2023-08-15 16:33:54.998 UTC [28346] HINT: Future log output will appear in directory "log".
Aug 15 16:33:55 localhost.localdomain systemd[1]: Started PostgreSQL 15 database server.
[root@localhost conf]# sudo -i -u postgres
[postgres@localhost conf]# psql –U postgres
postgres=# CREATE USER odoo WITH PASSWORD 'odoo';
CREATE ROLE
postgres=# ALTER USER odoo CREATEDB;
ALTER ROLE
postgres=# \q
docker-compose.yml
.Intégrez le code suivant à l’intérieur de ce fichier, puis sauvegardez vos changementsversion: '3.1'
services:
web:
image: odoo
environment:
- HOST=192.168.33.5
- USER=odoo
- PASSWORD=odoo
networks:
- traefik_default
volumes:
- $PWD/odoo.conf:/etc/odoo/odoo.conf
- "odoo-web-data:/var/lib/odoo:rw"
networks:
traefik_default:
external: true
volumes:
odoo-web-data:
Créer le réseau traefik_default avec docker et déployer le frontend Odoo
# création du réseau traefik_network
$ sudo docker network create traefik_default
# Lancer le déploiement du frontend Odoo
root@ubuntu-xenial:~/var/shared# docker-compose up -d
Creating certs_web_1 ... done
# Vérifier que le frontend a été déployé
root@ubuntu-xenial:~/certs# sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f758bd1d2751 odoo:16.0 "/entrypoint.sh odoo" 6 hours ago Up 6 hours 0.0.0.0:8069->8069/tcp, 8071-8072/tcp certs_web_1
# Créer des répertoires comme ci-dessous:
root@ubuntu-xenial:~# mkdir -p /var/shared/traefik/data/{certs,conf.d,auth}
# Installation de htpasswd pour générer un mot de passe
root@ubuntu-xenial:~# sudo apt install apache2-utils
# Créer ensuite le mot de passe console de traerfik
root@ubuntu-xenial:~# sudo htpasswd -Bbn admin Bonjour > data/auth/htpasswd
# Copie des certificats pour le reverse proxy
root@ubuntu-xenial:~# cd certificats/
root@ubuntu-xenial:~/var/shared/certificats# ls
ca.crt ca-key.pem ca.srl docker-compose.yml odoo.conf pgsql.crt pgsql.csr pgsql-key.pem pgsql.pem wildcard.crt wildcard.csr wildcard-key.pem wildcard.pem
root@ubuntu-xenial:~/var/shared/certificats cp wildcard-key.pem wildcard.crt ../data/certs/
traefik.toml
. Ensuite, insérez-y la configuration proposée ci-après et sauvegardez vos changements# sudo nano /var/shared/traefik/data/traefik.toml
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http]
[entryPoints.web.http.redirections]
[entryPoints.web.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
permanent = true
[entryPoints.websecure]
address = ":443"
[providers.docker]
exposedByDefault = false
[providers]
[providers.file]
directory = "/etc/traefik/conf.d"
watch = true
[api]
dashboard = true
api.yml
. Intégrez-y la configuration suggérée ci-après, puis validez en sauvegardant les ajustements réalisés.# sudo nano /var/shared/traefik/data/conf.d/api.yml
http:
routers:
api:
middlewares:
- auth
service: "api@internal"
rule: "Host(`rp.teachmemore.fr`)"
tls: {}
middlewares:
auth:
basicAuth:
usersFile: /etc/traefik/auth/htpasswd
/conf.d
, initiez un fichier dénommé tls.yml
. Intégrez la configuration proposée ci-après, et finalisez en sauvegardant les modifications effectuées.# sudo nano /var/shared/traefik/data/conf.d/tls.yml
tls:
certificates:
- certFile: /etc/traefik/certs/wildcard.crt
keyFile: /etc/traefik/certs/wildcard-key.pem
docker-compose.yml
au sein du répertoire /traefik
. Incorporez-y le code présenté ci-après.# sudo nano /var/shared/traefik/docker-compose.yml
version: "3.7"
services:
traefik:
image: traefik:v2.4
command:
- "--log.level=DEBUG"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "/var/shared/traefik/data/traefik.toml:/traefik.toml"
- "/var/shared/traefik/data/conf.d:/etc/traefik/conf.d:rw"
- "/var/shared/traefik/data/certs:/etc/traefik/certs:rw"
- "/var/shared/traefik/data/auth:/etc/traefik/auth"
restart: always
ports:
- "443:443"
- "80:80"
networks:
- traefik_default
networks:
traefik_default:
external: true
Lancer le déploiement de traefik.
root@ubuntu-xenial:~/var/shared/traefik# docker-compose up -d
Pulling traefik (traefik:latest)...
latest: Pulling from library/traefik
7264a8db6415: Already exists
af32133391e6: Pull complete
1022d3e6eb6d: Pull complete
ef9401db6143: Pull complete
Digest: sha256:429f3398a3cd1aa7436aa4f59d809040d3903506a9d83bee61688bb1429c7693
Status: Downloaded newer image for traefik:latest
Creating traefik_traefik_1 ... done
api.yml
Reprenez le fichier docker-compose.yml associé à Odoo. Interrompez le déploiement, puis apportez les modifications suggérées ci-après avant de relancer la mise en œuvre.
Le libellé a pour objectif de rediriger le trafic entrant en HTTPS via le port 443 vers HTTP sur le port 8069 du frontend Odoo. Plus précisément, il signale au service Odoo qu’il est derrière un proxy. Ainsi, pour s’y connecter, les utilisateurs doivent renseigner le FQDN odoo.teachmemore.fr dans leur navigateur.
N’oubliez pas d’ajouter une entrée DNS dans le fichier hosts pour une expérimentation en local
version: '3.1'
services:
web:
image: odoo
#ports:
#- "8069:8069"
environment:
- HOST=192.168.33.5
- USER=odoo
- PASSWORD=odoo
labels:
- "traefik.enable=true"
- "traefik.http.routers.odoo.rule=Host(`odoo.teachmemore.fr`)"
- "traefik.http.routers.odoo.tls=true"
- "traefik.http.services.odoo-service.loadbalancer.server.port=8069"
- "traefik.http.middlewares.odoo.headers.sslProxyHeaders.X-Forwarded-Proto=https"
networks:
- traefik_default
networks:
traefik_default:
external: true