This Ansible playbook automates the traditional (non-Docker) installation of Modoboa mail server platform.
For Docker-based deployment, see Modoboa Docker Ansible.
Create modoboa-deploy.yml:
---
- name: Deploy Modoboa mail server
hosts: modoboa
become: true
vars:
# Domain configuration
modoboa_domain: example.com
modoboa_hostname: mail.example.com
# Admin credentials
modoboa_admin_email: admin@example.com
modoboa_admin_password: "secure_admin_password"
# Database configuration
modoboa_db_engine: postgresql
postgresql_version: 15
modoboa_db_name: modoboa
modoboa_db_user: modoboa
modoboa_db_password: "secure_db_password"
# Web server
modoboa_webserver: nginx
tasks:
# Install system packages
- name: Install prerequisites (Debian/Ubuntu)
apt:
name:
- python3
- python3-pip
- python3-venv
- python3-dev
- build-essential
- git
- curl
- wget
- postfix
- dovecot-core
- dovecot-imapd
- dovecot-lmtpd
- dovecot-sieve
- nginx
- "{{ 'postgresql-' + postgresql_version if modoboa_db_engine == 'postgresql' else [] }}"
- libpq-dev
- libffi-dev
- libssl-dev
- libxml2-dev
- libxslt1-dev
- libjpeg-dev
- librrd-dev
- rrdtool
- libpcre3-dev
state: present
update_cache: true
when: ansible_os_family == "Debian"
# Configure hostname
- name: Set hostname
hostname:
name: "{{ modoboa_hostname }}"
- name: Update /etc/hosts
lineinfile:
path: /etc/hosts
line: "127.0.1.1 {{ modoboa_hostname }} {{ modoboa_hostname.split('.')[0] }}"
state: present
# Install and configure PostgreSQL
- name: Start PostgreSQL
systemd:
name: postgresql
state: started
enabled: true
when: modoboa_db_engine == 'postgresql'
- name: Create Modoboa database
become_user: postgres
postgresql_db:
name: "{{ modoboa_db_name }}"
encoding: UTF8
lc_collate: en_US.UTF-8
lc_ctype: en_US.UTF-8
template: template0
state: present
when: modoboa_db_engine == 'postgresql'
- name: Create Modoboa database user
become_user: postgres
postgresql_user:
name: "{{ modoboa_db_user }}"
password: "{{ modoboa_db_password }}"
db: "{{ modoboa_db_name }}"
priv: ALL
role_attr_flags: CREATEDB,LOGIN
when: modoboa_db_engine == 'postgresql'
# Create Modoboa user
- name: Create modoboa system user
user:
name: modoboa
shell: /bin/bash
home: /srv/modoboa
create_home: yes
system: yes
# Install Modoboa
- name: Create Modoboa directory
file:
path: /srv/modoboa
state: directory
owner: modoboa
group: modoboa
mode: '0755'
- name: Clone Modoboa installer
git:
repo: https://github.com/modoboa/modoboa-installer
dest: /srv/modoboa/modoboa-installer
version: master
become_user: modoboa
# Create installer configuration
- name: Create installer.cfg
copy:
dest: /srv/modoboa/modoboa-installer/installer.cfg
owner: modoboa
group: modoboa
mode: '0600'
content: |
[general]
hostname = {{ modoboa_hostname }}
debug = false
[database]
engine = {{ modoboa_db_engine }}
host = localhost
port = {% if modoboa_db_engine == 'postgresql' %}5432{% else %}3306{% endif %}
user = {{ modoboa_db_user }}
password = {{ modoboa_db_password }}
name = {{ modoboa_db_name }}
[webserver]
name = {{ modoboa_webserver }}
[ssl]
enabled = true
generate = true
type = letsencrypt
[modoboa]
user = modoboa
password = {{ modoboa_admin_password }}
[extensions]
modoboa-amavis = enabled
modoboa-antivirus = enabled
modoboa-autoreply = enabled
modoboa-contacts = enabled
modoboa-dmarc = enabled
modoboa-imap-migration = enabled
modoboa-radicale = enabled
modoboa-rspamd = enabled
modoboa-sievefilters = enabled
modoboa-webmail = enabled
# Run Modoboa installer
- name: Run Modoboa installer
command: ./run.py {{ modoboa_domain }}
args:
chdir: /srv/modoboa/modoboa-installer
become_user: modoboa
register: installer_output
changed_when: "'Successfully' in installer_output.stdout"
# Configure firewall
- name: Configure UFW firewall
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- "25"
- "587"
- "465"
- "143"
- "993"
- "110"
- "995"
- "80"
- "443"
handlers:
- name: restart nginx
systemd:
name: nginx
state: restarted
- name: restart postfix
systemd:
name: postfix
state: restarted
- name: restart dovecot
systemd:
name: dovecot
state: restarted
Create inventory.ini:
[modoboa]
mail.example.com ansible_user=root
[modoboa:vars]
ansible_python_interpreter=/usr/bin/python3
# Run the playbook
ansible-playbook -i inventory.ini modoboa-deploy.yml
# With custom variables
ansible-playbook -i inventory.ini modoboa-deploy.yml \
-e modoboa_domain=example.com \
-e modoboa_hostname=mail.example.com \
-e modoboa_admin_password="super_secure_password"
| Variable | Default | Description |
|---|---|---|
modoboa_domain |
Required | Email domain |
modoboa_hostname |
Required | Mail server FQDN |
modoboa_admin_email |
Required | Admin email |
modoboa_admin_password |
Required | Admin password |
modoboa_db_engine |
postgresql |
Database engine |
modoboa_db_name |
modoboa |
Database name |
modoboa_db_user |
modoboa |
Database user |
modoboa_db_password |
Required | Database password |
modoboa_webserver |
nginx |
Web server (nginx/apache2) |
https://mail.example.comadmin@example.com# A Record
mail.example.com. IN A <server-ip>
# MX Record
example.com. IN MX 10 mail.example.com.
# SPF Record
example.com. IN TXT "v=spf1 mx a -all"
# DKIM Record (get from Modoboa UI)
dkim._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=..."
# DMARC Record
_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine"
Any questions?
Feel free to contact us. Find all contact information on our contact page.