Skip to content


Repository files navigation

Ansible role for an all-in-one mail server based on opensSUSE Leap 15.4

GitHub Workflow Status Ansible Role

The purpose of this Ansible role is to fulfill my demands on my own mail server:

  • Supports openSUSE Leap 15.4
  • Orchestration of Postfix (MTA), Dovecot (MDA) and Rspamd
  • Postfix uses Dovecot for authentication (SMTP AUTH through Dovecot SASL)
  • No databases for configuration, just plain files
  • Mails to specific addresses can be relayed to another MTA
  • Mails to specific addresses can be rejected
  • Outgoing mails are DKIM signed
  • Relayed mails are ARC signed
  • Catch-all accounts can be configured
  • Multiple domains are supported
  • Sieve rules can be used
  • Spam
    • Spam with a high score is rejected
    • Spam detection can be disabled for specific senders (addresses or domains)
    • Potential spam is not automatically delivered into a Spam folder (of course a customa Sieve rule can be used)
    • Potential spam is greylisted
    • Spam can be learnt by moving the mail into a special IMAP folder
    • Spam can be learnt by applying the Junk flag, which is used by Thunderbird
    • Ham can be learnt by moving the mail into a special IMAP folder
    • Ham can be learnt by applying the NonJunk flag, which is used by Thunderbird
    • Ham can be learnt by marking the mail with a green flag in the iOS Mail App
  • Antivirus
    • Integration of ClamAV
    • Integration of
    • Infected mails are rejected
  • Nice reports (rspamd WebUI is sufficient for me)
  • Nearly all requirements are covered by tests
  • Tests are executed by a CI system

Usage and configuration

This role is available via Ansible Galaxy under the name chkpnt.mailserver. It can be installed with

$ ansible-galaxy install chkpnt.mailserver

and used within a playbook like

- hosts: server1
  remote_user: root
  - role: chkpnt.mailserver
        certificate: '/etc/ssl/servercerts/'
        private_key: '/etc/ssl/private/'
        generate_certificate_for_test: yes
        generate_safe_primes_for_dh: yes #
        - { domain:, selector: 'key1', private_key: '/var/lib/rspamd/dkim/' }
        - { domain:, selector: 'key1', private_key: '/var/lib/rspamd/dkim/' }
        - { domain:, selector: 'key1', private_key: '/var/lib/rspamd/dkim/' }
      # Hash can be computated with doveadm.
      # I recommend using Blowfish as the hashing schema, the ideal number of rounds depends on your system.
      # > doveadm pw -s BLF-CRYPT -r 10
        - { user: '', password: '{BLF-CRYPT}$2y$10$6W9VYuRklwLg8y2UoP6YHuK5Q8g7g.LOJdSa7K4CgoVMmARNYMVMK' } # Password: changeme
        - { user: '', password: '{BLF-CRYPT}$2y$10$wZtIn5uHAsbsMgMmOdBdU.qbRgrQxfeej65G63aUxMaDNEHfb8P2e' } # Password: changeme
        - { name: '', path: '/srv/mail/john' }
        - { name: '', path: '/srv/mail/jane' }
        # a self-referencing alias is needed if the mail_transports is used
        - { for: '', destination: '' }
        # normal aliases
        - { for: '', destination: '' }
        - for: ''
            - ''
            - ''
        # Catch-Alls:
        - { for: '', destination: '' }
        - { for: '', destination: '' }
        - { for: '', destination: '' }
        - for: ''
          action: 'REJECT This address is not supposed to receive mails!'
        - for: ''
          nexthop: ''
        greylisting_delay: 5min
        thresholds: # Requirement: greylist < add_header < reject
          greylist: 4
          add_header: 6
          reject: 15
          # Controller worker is used to manage rspamd stats, to learn rspamd and to serve WebUI.
          # If you access the WebUI from localhost, you won't be asked for the password as localhost is a "secure_ip"
          # > rspamadm pw
          password: '$2$c75qgo1b8brudgq7wokg8wxr5qiby84p$ye6ss3ymc4h4u4swk3fhx3ph7jesahqrzw8kkxwhyfb14g4rkfhb' # Password: changeme
          bind_socket: 'localhost:11334' 
        # Regexps are supported
          - foobar.test
          - /.*@important.test/

The defaults of the variables are defined in defaults/main.yml. All variables refering to or similar are expected to be explicitly declared in your playbook.

The playbook tests/testfixtures/vms/sut.yml used by the tests is a good example, too.


I recommend to set up a Python environment using pipenv. On macOS, pipenv can be installed using Homebrew:

$ brew install pipenv

To use the Python environment with pipenv, just enter the following commands:

$ pipenv install --dev
$ pipenv shell

In order to run the tests, VirtualBox and Vagrant are required. On macOS, these dependencies can be installed using Homebrew as well:

$ brew install --cask virtualbox
$ brew install --cask vagrant

For managing your Vagrant virtual machines, I can recommend the use of Vagrant-Manager, a small utility app for the menu bar.

$ brew install --cask vagrant-manager

Additional information about the tests can be found in the corresponding document.




Ansible role for an all-in-one mail server based on opensSUSE Leap 15.4







No packages published