DEBOPS.RSPAMD(5)

NAME
debops.rspamd - Manage rspamd with Ansible

SYNOPSIS

debops run service/rspamd [--limit group,host,...] [--diff] [--check] [--tags tag1,tag2,...] [--skip-tags tag1,tag2,...] [<ansible-playbook options>] ...

DESCRIPTION

The rspamd daemon, maintained by the Rspamd Project <https://rspamd.com/>, is a modern spam filtering daemon which can be integrated with any MTA which supports milters. It provides an advanced spam filtering system that allows evaluation of messages by a number of rules including regular expressions, statistical analysis and custom services such as URL black lists. A web-based user interface is also provided.

The debops.rspamd Ansible role can be used to configure the rspamd service on a host and automatically setup the debops.postfix role to use it for spam filtering.

GETTING STARTED

  Example inventory

To enable the rspamd service on a host, you need to add it to the [debops_service_rspamd] Ansible inventory group. The host should also be configured with a Redis server via the debops.redis_server role (see its documentation for more details), unless a Redis server already exists somewhere in the network:

[debops_service_redis_server]
hostname
[debops_service_rspamd]
hostname

  Example playbook

If you are using this role without DebOps, here's an example Ansible playbook that uses the debops.rspamd role:

---
# SPDX-License-Identifier: GPL-3.0-only
- name: Manage rspamd service
  collections: [ 'debops.debops', 'debops.roles01',
                 'debops.roles02', 'debops.roles03' ]
  hosts: [ 'debops_service_rspamd' ]
  become: True
  environment: '{{ inventory__environment | d({})
                   | combine(inventory__group_environment | d({}))
                   | combine(inventory__host_environment  | d({})) }}'
  pre_tasks:
    - name: Prepare postfix environment
      ansible.builtin.import_role:
        name: 'postfix'
        tasks_from: 'main_env'
      vars:
        postfix__dependent_maincf:
          - role: 'rspamd'
            config: '{{ rspamd__postfix__dependent_maincf }}'
      tags: [ 'role::postfix' ]
  roles:
    - role: keyring
      tags: [ 'role::keyring', 'skip::keyring', 'role::nginx' ]
      keyring__dependent_apt_keys:
        - '{{ nginx__keyring__dependent_apt_keys }}'
    - role: apt_preferences
      tags: [ 'role::apt_preferences', 'skip::apt_preferences' ]
      apt_preferences__dependent_list:
        - '{{ nginx__apt_preferences__dependent_list }}'
    - role: etc_services
      tags: [ 'role::etc_services', 'skip::etc_services' ]
      etc_services__dependent_list:
        - '{{ rspamd__etc_services__dependent_list }}'
    - role: ferm
      tags: [ 'role::ferm', 'skip::ferm' ]
      ferm__dependent_rules:
        - '{{ nginx__ferm__dependent_rules }}'
        - '{{ rspamd__ferm__dependent_rules }}'
    - role: python
      tags: [ 'role::python', 'skip::python' ]
      python__dependent_packages3:
        - '{{ nginx__python__dependent_packages3 }}'
      python__dependent_packages2:
        - '{{ nginx__python__dependent_packages2 }}'
    - role: cron
      tags: [ 'role::cron', 'skip::cron' ]
    - role: logrotate
      tags: [ 'role::logrotate', 'skip::logrotate' ]
      logrotate__dependent_config:
        - '{{ rspamd__logrotate__dependent_config }}'
    - role: nginx
      tags: [ 'role::nginx', 'skip::nginx' ]
      nginx__dependent_servers:
        - '{{ rspamd__nginx__dependent_servers }}'
      when: rspamd__nginx_enabled | d(False) | bool
    - role: rspamd
      tags: [ 'role::rspamd', 'skip::rspamd' ]
    - role: postfix
      tags: [ 'role::postfix', 'skip::postfix' ]
      postfix__dependent_maincf:
        - role: 'rspamd'
          config: '{{ rspamd__postfix__dependent_maincf }}'

  Ansible tags

You can use Ansible --tags or --skip-tags parameters to limit what tasks are performed during Ansible run. This can be used after host is first configured to speed up playbook execution, when you are sure that most of the configuration has not been changed.

Available role tags:

role::rspamd
    Main role tag, should be used in the playbook to execute all of the role tasks as well as role dependencies.

  Other resources

List of other useful resources related to the debops.rspamd Ansible role:

•   Manual pages: rspamd(8) <https://manpages.debian.org/rspamd(8)>, rspamc(1) <https://manpages.debian.org/rspamc(1)>, rspamadm(1) <https://manpages.debian.org/rspamadm(1)> and rspamd_stats(8)

•   The website of the Rspamd Project <https://rspamd.com/>, in particular the configuration documentation <https://rspamd.com/doc/configuration/index.html>

DEFAULT VARIABLE DETAILS

Some of the debops.rspamd default variables have more extensive configuration than simple strings or lists, here you can find documentation and examples for them.

  rspamd__configuration

The rspamd__*_configuration variables define the contents of the /etc/rspamd/local.d and /etc/rspamd/override.d configuration directories. The variables are merged in the order defined by the rspamd__combined_local_configuration and rspamd__combined_override_configuration variables, which allows modification of the default configuration through the Ansible inventory.

Note that files which are not configured via the rspamd__*_configuration variables will be deleted from the /etc/rspamd/local.d and /etc/rspamd/override.d directories, to ensure that the Rspamd configuration is predictable.

See the Rspamd configuration documentation <https://rspamd.com/doc/configuration/index.html> and, in particular, the modules documentation <https://rspamd.com/doc/modules/> for details on the possible configuration files and the relevant parameters for each file.

  Examples

See the rspamd__default_local_configuration and rspamd__default_override_configuration variables for examples of existing configuration.

Configure another RBL (Runtime Black List <https://rspamd.com/doc/modules/rbl.html>) check:

rspamd__local_configuration:
  - file: 'rbl.conf'
    comment: |
      RBL configuration
      https://rspamd.com/doc/modules/rbl.html
    options:
      - name: 'rules'
        options:
          - name: 'SIMPLE_RBL'
            options:
              - name: 'rbl'
                value: 'rbl.example.net'
              - name: 'checks'
                value: [ 'from' ]

This will result in /etc/rspamd/local.d/rbl.conf being created with the following content:

...
rules {
    SIMPLE_RBL {
        rbl = "rbl.example.net";
        checks = ["from"];
    }
}

  Syntax

The variables contain a list of YAML dictionaries, each dictionary can have the following parameters:

file
    Required. Name of the file to create in the /etc/rspamd/local.d or /etc/rspamd/override.d directory. This parameter is used as an "anchor", configuration entries with the same file are combined together and affect each other in order of appearance.

comment
    Optional. This parameter can be used to provide a short description which will be included in the generated configuration file.

state
    Optional. If not specified or present, the configuration file will be generated. If absent or init, the configuration file will not be generated and if any old configuration file with the same name exists on the target host, it will be removed. If ignore, the configuration file will not be generated and old configuration files, if any, will not be removed.

weight
    Optional. A positive or negative number which can be used to affect the order of files to be generated. Positive numbers add more "weight" to the section making it appear "lower" in the list; negative numbers subtract the "weight" and therefore move the file up in the list.

options
    Required. A list of rspamd configuration options for a given file. The options parameters from configuration entries with the same file parameter are merged together in order of appearance and can affect each other.

    Note that the options parameters can be used recursively to generate configuration blocks of arbitrary depth (as illustrated in the example above).

    The options can be specified in a simple form as key/value pairs, where the key is the option name and value is the option value. Alternatively, if the name and value parameters are used, the entries can use an extended format with specific parameters:

name
    Required. The name of a given rspamd configuration option for a given file. Options with the same file and name will be merged in order of appearance.

value
    Either value or options is required. This defines the value of a given configuration option. It can be either a string, a boolean, a number, or a YAML list.

options
    Either value or options is required. This parameters takes a list of configuration sub-options, thus allowing options to be used recursively to generate configuration blocks of arbitrary depth (as illustrated in the example above).

raw Optional. String or YAML text block which will be included in the configuration file "as is". If this parameter is specified, the name and value parameters are ignored - you need to specify the entire line(s) with configuration option names as well.

state
    Optional. If not defined or present, a given configuration option or section will be included in the generated configuration file. If absent, ignore or init, a given configuration option or section will not be included in the generated file. If comment, the option will be included but commented out and inactive.

comment
    Optional. String or YAML text block that contains comments about a given configuration option.

  DKIM

DomainKeys Identified Mail (DKIM) <https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail> is an email authentication method designed to sign outgoing messages using keys which are published in the DNS zone of the sending domain. This allows the recipient to check that a received email was indeed sent from the given domain.

rspamd includes support for both checking DKIM signatures and for generating DKIM signatures for outgoing email messages. In order to do the signing, suitable keys have to be generated and published in the right DNS zone(s). In addition, the keys used for signing the emails should be replaced on a regular basis (as explained e.g. in this document <http://www.m3aawg.org/DKIMKeyRotation>), a process which is often referred to as key rollover.

Unfortunately, the step of publishing/removing DNS records cannot be fully automated as there is no universal means for doing so, neither in the generic case, nor in DebOps. The support for DKIM signing therefore defaults to being disabled in the debops.rspamd role, but the recommendation is to go through the steps of manually enabling and configuring it.

In order to simplify this task, the debops.rspamd role includes two tools, rspamd-dkim-keygen and rspamd-dkim-update which, after some initial configuration, can automate the key rollover process.

To enable DKIM signing, first check that rspamd__dkim_domains lists all the domains that will be used to send email and then override the rspamd__dkim_enabled parameter:

rspamd__dkim_enabled: True
rspamd__dkim_domains: [ "example.com", "example.net" ]

  rspamd-dkim-keygen

The rspamd-dkim-keygen script takes care of generating keys for the domains listed in rspamd__dkim_domains and will be executed on a monthly basis via a cron job. The configuration for rspamd-dkim-keygen is stored in /etc/rspamd/dkim-keygen.json, which is controlled via the rspamd__dkim_keygen_*_configuration variables. These variables are merged in the order defined by the rspamd__dkim_keygen_combined_configuration variable, which allows modification of the default configuration through the Ansible inventory in a manner similar to the rspamd__configuration and with a simplified version of the Syntax, since options are not supported.

In the default configuration, RSA and ed25519 keys will be generated in /var/lib/rspamd/dkim/. Three time periods are defined by the future_period, active_period and expired_period (in months). These are the stages of the key rollover that keys go through. Keys are generated future_period number of months before they are made active (in order to allow for the keys to be published in the DNS). Then they are in active use (i.e. used to sign outgoing emails) during the active_period. Finally, keys enter the expired_period where they are no longer used to sign emails (but the records are still published in the DNS to make sure that in-flight emails are still valid). Finally, upon expiry of the expired_period, when no emails should be in-flight any more, the keys can be archived (to /var/lib/rspamd/dkim-archive/ and removed from the DNS.

The one exception is when rspamd-dkim-keygen is first executed (usually the first time the debops.rspamd role is run for a given host), in which case the initial keys will immediately go live.

Whenever rspamd-dkim-keygen detects that a new key should be published in the DNS, or that a stale key needs to be removed, it will call out to the complimentary tool rspamd-dkim-update.

  rspamd-dkim-update

The rspamd-dkim-update script takes care of publishing/removing DNS resource records for DKIM keys generated/expired by the rspamd-dkim-keygen script.

The most important variable for rspamd-dkim-update is the rspamd__dkim_update_method, which defaults to sending emails to the administrator for manual handling of DNS updates.

In the alternative, the process can be automated using the nsupdate tool. This requires configuration changes to the DNS server (e.g. bind), either to trust the IP address of the rspamd host (not recommended), or to generate suitable keys (for example, TSIG keys <https://bind9.readthedocs.io/en/latest/advanced.html#tsig>) and to configure these keys to have the appropriate permissions to add/remove DNS resource records (for example, using bind's fine-grained update-policy options <https://bind9.readthedocs.io/en/latest/reference.html#dynamic-update-policies>). Alternatively, the server can be configured to allow a given Kerberos principal <https://bind9.readthedocs.io/en/latest/advanced.html#dynamic-update> to perform updates (in which case a keytab needs to be generated instead of a TSIG key file and the references to the key file below should then be read as referring to the keytab file).

The key file needs to be stored on the rspamd host, by default at /etc/rspamd/dkim_dns_key (preferably with 0640 permissions and root:_rspamd ownership). This can be automated by transferring the key file to the Ansible controller and putting it in the appropriate override directory (e.g. project-dir/ansible/overrides/files/etc/rspamd/dkim_dns_key as explained below in the Overriding rspamd-dkim-keygen/update section).

Once the keyfile has been prepared, check the values of nsupdate_* in the configuration for rspamd-dkim-update, stored in /etc/rspamd/dkim-update.json, which is controlled via the rspamd__dkim_update_*_configuration variables. These variables are merged in the order defined by the rspamd__dkim_update_combined_configuration variable, which allows modification of the default configuration through the Ansible inventory in a manner similar to the rspamd__configuration and with a simplified version of the Syntax, since options are not supported.

  Overriding rspamd-dkim-keygen/update

The reason why there are two separate scripts for key generation and DNS updates is that it allows the administrator to override the default scripts by providing their alternative script in the files_path override directory defined in the .debops.cfg file (see Configuration).

For example, if .debops.cfg reads:

...
[override_paths]
files_path = ansible/overrides/files
...

Then the custom script(s) should be placed in project-dir/ansible/overrides/files/usr/local/sbin/rspamd-dkim-update and/or project-dir/ansible/overrides/files/usr/local/sbin/rspamd-dkim-keygen.

AUTHOR
David Härdeman

COPYRIGHT
2014-2024, Maciej Delmanowski, Nick Janetakis, Robin Schneider and others