Note: mailcow is designed as a Docker-native solution. This playbook installs the underlying components (Postfix, Dovecot, Rspamd, etc.) without Docker for environments where Docker is not available.
For the recommended Docker-based deployment, see mailcow Docker Ansible.
Create mailcow-components-deploy.yml:
---
- name: Deploy mailcow components (non-Docker)
hosts: mailserver
become: true
vars:
# Server configuration
mail_hostname: mail.example.com
mail_domain: example.com
# Database configuration
mariadb_root_password: "secure_db_root_password"
mariadb_mail_password: "secure_mail_password"
# SSL configuration
ssl_email: admin@example.com
tasks:
# Install prerequisites
- name: Install prerequisites
apt:
name:
- postfix
- dovecot-core
- dovecot-imapd
- dovecot-lmtpd
- dovecot-sieve
- rspamd
- clamav
- clamav-daemon
- mariadb-server
- python3-pymysql
- openssl
- certbot
- python3-certbot-nginx
state: present
update_cache: true
when: ansible_os_family == "Debian"
# Configure Postfix
- name: Configure Postfix main.cf
lineinfile:
path: /etc/postfix/main.cf
regexp: "^myhostname ="
line: "myhostname = {{ mail_hostname }}"
notify: restart postfix
- name: Configure Postfix mydomain
lineinfile:
path: /etc/postfix/main.cf
regexp: "^mydomain ="
line: "mydomain = {{ mail_domain }}"
notify: restart postfix
# Configure Dovecot
- name: Configure Dovecot protocols
lineinfile:
path: /etc/dovecot/dovecot.conf
regexp: "^#protocols ="
line: "protocols = imap pop3 lmtp"
notify: restart dovecot
# Configure MariaDB
- name: Start MariaDB
systemd:
name: mariadb
state: started
enabled: true
- name: Set MariaDB root password
mysql_user:
name: root
password: "{{ mariadb_root_password }}"
host_all: true
login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Create mail database
mysql_db:
name: mailcow
state: present
login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Create mail database user
mysql_user:
name: mailcow
password: "{{ mariadb_mail_password }}"
priv: 'mailcow.*:ALL'
host: localhost
state: present
login_unix_socket: /var/run/mysqld/mysqld.sock
# Configure Rspamd
- name: Enable Rspamd integration with Postfix
lineinfile:
path: /etc/postfix/main.cf
line: "smtpd_milters = inet:localhost:11332"
notify: restart postfix
# SSL Certificate
- name: Obtain Let's Encrypt certificate
command: >
certbot certonly --nginx --non-interactive --agree-tos
--email {{ ssl_email }}
-d {{ mail_hostname }}
args:
creates: /etc/letsencrypt/live/{{ mail_hostname }}/fullchain.pem
# Enable and start services
- name: Enable and start services
systemd:
name: "{{ item }}"
state: started
enabled: true
loop:
- postfix
- dovecot
- rspamd
- clamav-daemon
- mariadb
handlers:
- name: restart postfix
systemd:
name: postfix
state: restarted
- name: restart dovecot
systemd:
name: dovecot
state: restarted
- name: restart rspamd
systemd:
name: rspamd
state: restarted
Create inventory.ini:
[mailserver]
mail.example.com ansible_user=root
[mailserver:vars]
ansible_python_interpreter=/usr/bin/python3
# Run the playbook
ansible-playbook -i inventory.ini mailcow-components-deploy.yml
# With custom variables
ansible-playbook -i inventory.ini mailcow-components-deploy.yml \
-e mail_hostname=mail.example.com \
-e mail_domain=example.com
| Variable | Default | Description |
|---|---|---|
mail_hostname |
Required | Mail server FQDN |
mail_domain |
Required | Email domain |
mariadb_root_password |
Required | MariaDB root password |
mariadb_mail_password |
Required | Database user password |
ssl_email |
Required | Email for Let’s Encrypt |
# 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"
# Using doveadm
doveadm user add user@example.com password
# Or configure via database
mysql -u root -p mailcow
⚠️ This is NOT the official mailcow: This playbook installs the component stack that mailcow uses, but without the Docker orchestration, web UI, and integrated management.
For the full mailcow experience with web administration, SOGo groupware, and automated management, use the Docker-based deployment.
Any questions?
Feel free to contact us. Find all contact information on our contact page.