Why Ansible for Odoo?
Ansible automates server configuration and management. Instead of SSH-ing into servers and running commands manually, you write playbooks that describe the desired state. Ansible connects to your servers via SSH and makes them match that state. No agent installation needed — just SSH access.
For Odoo, Ansible is invaluable when you manage multiple servers, need repeatable deployments, or want to ensure consistent configuration across environments. Set up one Odoo server manually in 2 hours, or write an Ansible playbook once and deploy to any number of servers in minutes.
What Ansible Automates for Odoo
- Server hardening (firewall, SSH config, fail2ban)
- PostgreSQL installation and tuning
- Odoo installation from source
- nginx reverse proxy configuration
- SSL certificate provisioning
- Odoo configuration file management
- Systemd service setup
- Backup scheduling
- Module updates and upgrades
- Monitoring agent installation
Step 1: Install Ansible
# macOS
brew install ansible
# Ubuntu/Debian
sudo apt install ansible
# pip (any OS)
pip install ansible
ansible --versionStep 2: Define Inventory
# inventory/production.yml
all:
children:
odoo_servers:
hosts:
odoo-prod-1:
ansible_host: 10.0.1.10
odoo_workers: 6
odoo_cron_threads: 2
odoo-prod-2:
ansible_host: 10.0.1.11
odoo_workers: 6
odoo_cron_threads: 0 # No cron on secondary
db_servers:
hosts:
db-prod-1:
ansible_host: 10.0.1.20
pg_max_connections: 200
vars:
ansible_user: root
odoo_version: "19.0"
odoo_domain: erp.yourdomain.com
db_password: "{{ vault_db_password }}"Step 3: Create Odoo Installation Playbook
# playbooks/install-odoo.yml
---
- name: Install Odoo
hosts: odoo_servers
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Install system packages
apt:
name:
- git
- python3-pip
- python3-dev
- python3-venv
- libxml2-dev
- libxslt1-dev
- zlib1g-dev
- libsasl2-dev
- libldap2-dev
- build-essential
- libssl-dev
- libffi-dev
- libjpeg-dev
- libpq-dev
- npm
- wkhtmltopdf
state: present
- name: Create odoo system user
user:
name: odoo
system: yes
home: /opt/odoo
shell: /bin/false
- name: Clone Odoo repository
git:
repo: https://github.com/odoo/odoo.git
dest: /opt/odoo/odoo
version: "{{ odoo_version }}"
depth: 1
become_user: odoo
- name: Create Python virtualenv
pip:
requirements: /opt/odoo/odoo/requirements.txt
virtualenv: /opt/odoo/venv
virtualenv_command: python3 -m venv
become_user: odoo
- name: Deploy Odoo configuration
template:
src: templates/odoo.conf.j2
dest: /etc/odoo.conf
owner: odoo
mode: '0640'
notify: Restart Odoo
- name: Deploy systemd service
template:
src: templates/odoo.service.j2
dest: /etc/systemd/system/odoo.service
notify:
- Reload systemd
- Restart Odoo
- name: Enable and start Odoo
systemd:
name: odoo
enabled: yes
state: started
handlers:
- name: Reload systemd
systemd:
daemon_reload: yes
- name: Restart Odoo
systemd:
name: odoo
state: restartedStep 4: Configuration Templates
# templates/odoo.conf.j2
[options]
admin_passwd = {{ vault_admin_password }}
db_host = {{ hostvars[groups['db_servers'][0]]['ansible_host'] }}
db_port = 5432
db_user = odoo
db_password = {{ db_password }}
addons_path = /opt/odoo/odoo/addons,/opt/odoo/custom-addons
data_dir = /opt/odoo/data
workers = {{ odoo_workers | default(4) }}
max_cron_threads = {{ odoo_cron_threads | default(1) }}
limit_memory_hard = 2684354560
limit_memory_soft = 2147483648
limit_time_cpu = 600
limit_time_real = 1200
proxy_mode = TrueStep 5: PostgreSQL Playbook
# playbooks/install-postgresql.yml
---
- name: Install and Configure PostgreSQL
hosts: db_servers
become: yes
tasks:
- name: Install PostgreSQL
apt:
name: postgresql
state: present
- name: Create Odoo database user
become_user: postgres
postgresql_user:
name: odoo
password: "{{ db_password }}"
role_attr_flags: CREATEDB
- name: Deploy PostgreSQL tuning
template:
src: templates/postgresql-tuning.conf.j2
dest: /etc/postgresql/16/main/conf.d/tuning.conf
notify: Restart PostgreSQL
- name: Allow Odoo server connections
postgresql_pg_hba:
dest: /etc/postgresql/16/main/pg_hba.conf
contype: host
databases: all
users: odoo
source: "10.0.1.0/24"
method: scram-sha-256
notify: Restart PostgreSQL
handlers:
- name: Restart PostgreSQL
systemd:
name: postgresql
state: restartedStep 6: Nginx + SSL Playbook
# playbooks/setup-nginx.yml
---
- name: Configure Nginx and SSL
hosts: odoo_servers
become: yes
tasks:
- name: Install nginx and certbot
apt:
name:
- nginx
- certbot
- python3-certbot-nginx
state: present
- name: Deploy nginx config
template:
src: templates/nginx-odoo.conf.j2
dest: /etc/nginx/sites-available/odoo
notify: Reload nginx
- name: Enable site
file:
src: /etc/nginx/sites-available/odoo
dest: /etc/nginx/sites-enabled/odoo
state: link
notify: Reload nginx
- name: Obtain SSL certificate
command: certbot --nginx -d {{ odoo_domain }} --non-interactive --agree-tos -m admin@{{ odoo_domain }}
args:
creates: /etc/letsencrypt/live/{{ odoo_domain }}/fullchain.pemStep 7: Update and Maintenance Playbook
# playbooks/update-odoo.yml
---
- name: Update Odoo
hosts: odoo_servers
become: yes
serial: 1 # One server at a time for rolling updates
tasks:
- name: Pull latest code
git:
repo: https://github.com/odoo/odoo.git
dest: /opt/odoo/odoo
version: "{{ odoo_version }}"
become_user: odoo
- name: Update Python dependencies
pip:
requirements: /opt/odoo/odoo/requirements.txt
virtualenv: /opt/odoo/venv
become_user: odoo
- name: Restart Odoo
systemd:
name: odoo
state: restarted
- name: Wait for Odoo to be healthy
uri:
url: http://localhost:8069/web/health
status_code: 200
register: result
until: result.status == 200
retries: 30
delay: 5Running Playbooks
# Full installation
ansible-playbook -i inventory/production.yml playbooks/install-postgresql.yml
ansible-playbook -i inventory/production.yml playbooks/install-odoo.yml
ansible-playbook -i inventory/production.yml playbooks/setup-nginx.yml
# Update Odoo (rolling)
ansible-playbook -i inventory/production.yml playbooks/update-odoo.yml
# Encrypt sensitive variables
ansible-vault encrypt inventory/group_vars/all/vault.ymlAnsible vs Shell Scripts
| Feature | Ansible | Shell Scripts |
|---|---|---|
| Idempotent | Yes (safe to re-run) | Must code manually |
| Multi-server | Built-in | SSH loops |
| Templates | Jinja2 | sed/awk |
| Secret management | Ansible Vault | Manual |
| Error handling | Built-in | set -e, trap |
| Learning curve | YAML + modules | Bash |
DeployMonkey + Ansible
DeployMonkey handles server provisioning and Odoo configuration internally. If you prefer to manage your own infrastructure with Ansible, DeployMonkey can complement your setup by providing application-level management and monitoring.