Skip to content

Automate Odoo Server Management with Ansible (2026)

DeployMonkey Team · March 23, 2026 12 min read

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 --version

Step 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: restarted

Step 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 = True

Step 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: restarted

Step 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.pem

Step 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: 5

Running 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.yml

Ansible vs Shell Scripts

FeatureAnsibleShell Scripts
IdempotentYes (safe to re-run)Must code manually
Multi-serverBuilt-inSSH loops
TemplatesJinja2sed/awk
Secret managementAnsible VaultManual
Error handlingBuilt-inset -e, trap
Learning curveYAML + modulesBash

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.