Debian exim/dovecot email server with Saltstack – Exim

srv/salt/exim.sls

This YAML file is responsible for installing and configuring exim. First thing is to install SASL to handle authentication – exim needs access to the passwords and SASL is one of the standard ways to do this.

As discussed previously I’ve chosen to install the SSL certificates centrally in /etc/ssl; I’ve set up a group ssl-cert to allow access to these. Exim also needs to run under the sasl group to get access to the authentication daemon.

Debian uses a complex configuration system for exim. This makes it easy to configure with Saltstack – we can just add our configuration to the default and Debian will put it all together for us. However it must be noted that there appears to be a bug in Saltstack at present – it should be able to tell Debian to update the configuration when a file changes but at present I’m getting infinite recursion so that bit is commented out for now.

# Ensure we have the SSL certs available
include:
  - sslcerts

# Install sasl2-bin for SMTP authentication
sasl2-bin:
  pkg:
    - installed

# Edit the /etc/default/saslauthd file to get sasl running on boot
/etc/default/saslauthd-comment:
  file.comment:
    - name: /etc/default/saslauthd
    - regex: 'START=no'

/etc/default/saslauthd-blockreplace:
  file.blockreplace:
    - name: /etc/default/saslauthd
    - marker_start: '# ------- SALTSTACK EXIM START -------'
    - marker_end:   '# ------- SALTSTACK EXIM END -------'
    - prepend_if_not_found: True
    - content: 'START=yes'

# Run the sasl daemon
saslauthd:
  service.running:
    - enable: True
    - require:
      - file: /etc/default/saslauthd

# Ensure exim4 is installed. Need heavy version to integrate 
# with Spam Assassin
exim4:
  pkg.installed:
    - name: exim4-daemon-heavy

# Ensure exim4 user can read the SSL key file by being a member 
# of the ssl-cert group
ssl-cert-group:
  group.present:
    - name: ssl-cert
    - addusers:
        - Debian-exim

# Ensure exim4 user can access SASL
sasl-group:
  group.present:
    - name: sasl
    - addusers:
        - Debian-exim

# Configure exim - extra parameters 
# (must be in conf.d directory to work with split config)
/etc/exim4/conf.d/main/00_exim4-config_localmacros:
  file.managed:
    - source: salt://exim4/main-00_exim4-config_localmacros
    - user: root
    - group: root
    - mode: '0644' # rw-r--r--

# Configure exim - Debian template parameters
/etc/exim4/update-exim4.conf.conf:
  file.managed:
    - source: salt://exim4/update-exim4.conf.conf
    - user: root
    - group: root
    - mode: '0644' # rw-r--r--

# Custom configuration to hook into Spam Assassin
/etc/exim4/conf.d/acl/40_exim4-config_check_data:
  file.managed:
    - source: salt://exim4/acl-40_exim4-config_check_data
    - user: root
    - group: root
    - mode: '0644' # rw-r--r--

# Custom configuration to hook into SASL for SMTP authentication
/etc/exim4/conf.d/auth/40_exim4-config_sasl_auth:
  file.managed:
    - source: salt://exim4/auth-40_exim4-config_sasl_auth
    - user: root
    - group: root
    - mode: '0644' # rw-r--r--

# Ensure that the Debian config template system gets updated 
# if the template changes
# Commented out at present as this results in an infinite 
# recursion in SaltStack
#exim4-config:
#  cmd.run:
#    - name: /usr/sbin/update-exim4.conf
#    - onchanges_any:
#        - file: /etc/exim4/conf.d/main/00_exim4-config_localmacros
#        - file: /etc/exim4/update-exim4.conf.conf
#        - file: /etc/exim4/conf.d/acl/acl-40_exim4-config_check_data
#        - file: /etc/exim4/conf.d/auth/40_exim4-config_sasl_auth

# Ensure exim restarts if any config file changes or the template is changed
# Last line commented out to prevent infinite recursion in SaltStack.
exim4-service:
  service.running:
    - name: exim4
    - enable: True
    - watch:
        - file: /etc/ssl/certs/info.river-innovations.com.cert
        - file: /etc/ssl/private/info.river-innovations.com.key
#        - cmd: exim4-config

# Adds extra records to the /etc/aliases file
/etc/aliases:
  file.blockreplace:
    - marker_start: '# ------- SALTSTACK EXIM START -------'
    - marker_end:   '# ------- SALTSTACK EXIM END -------'
    - append_if_not_found: True
    - content: |
        joe: blogsj
        joe.blogs: blogsj
        logcheck: blogsj

Note that I always use file.blockreplace where possible when editing files. Otherwise any changes in future are far more tricky. The marker at the start and end include the name of the .sls file making the edit so that other .sls files can edit the same configuration file if necessary.

srv/salt/exim4/acl-40_exim4-config_check_data

This file updates the exim configuration to check emails via Spam Assassin.

Copied from /etc/exim4/conf.d/acl/40_exim4-config_check_data with this bit uncommented:

# *** START MWB ***:
  warn
    remove_header = X-Spam_score: X-Spam_score_int : X-Spam_bar : \
                    X-Spam_report

  warn
    condition = ${if <{$message_size}{120k}{1}{0}}
    # ":true" to add headers/acl variables even if not spam
    spam = nobody:true
    add_header = X-Spam_score: $spam_score
    add_header = X-Spam_bar: $spam_bar
    # Do not enable this unless you have shorted SpamAssassin's report
    #add_header = X-Spam_report: $spam_report

# *** END MWB ***

srv/salt/exim4/auth-40_exim4-config_sasl_auth

This file allows exim to authenticate against the SASL daemon.

Copied to /etc/exim4/conf.d/auth/40_exim4-config_sasl_auth

# MWB custom file
# Authenticate SMTP against SASL authentication daemon

plain_saslauthd_server:
   driver = plaintext
   public_name = PLAIN
   server_condition = ${if saslauthd{{$auth2}{$auth3}}{1}{0}}
   server_set_id = $auth2
   server_prompts = :

login_saslauthd_server:
   driver = plaintext
   public_name = LOGIN
   server_prompts = "Username:: : Password::"
   # don't send system passwords over unencrypted connections
   server_condition = ${if saslauthd{{$auth1}{$auth2}}{1}{0}}
   server_set_id = $auth1

srv/salt/exim4/main-00_exim4-config_localmacros

Sets up the macros for TLS/SSL.

Copied to /etc/exim4/conf.d/main/00_exim4-config_localmacros

MAIN_TLS_ENABLE = true
MAIN_TLS_CERTIFICATE = /etc/ssl/certs/my-certificate.cert
MAIN_TLS_PRIVATEKEY  = /etc/ssl/private/my-certificate.key

srv/salt/exim4/update-exim4.conf.conf

Copied to /etc/exim4/update-exim4.conf.conf. Original file was generated by the Debian configuration system. This defines the basic operation of the SMTP server, plus specifies that we are using the split config – which allows us to replace parts of the configuration using Saltstack.

dc_eximconfig_configtype='internet'
dc_other_hostnames='mwbrown.org;river-innovations.com;riverinnovations.com;river-innovation.com;riverinnovation.com;info20.default.mwbrown.uk0.bigv.io'
dc_local_interfaces=''
dc_readhost=''
dc_relay_domains=''
dc_minimaldns='false'
dc_relay_nets=''
dc_smarthost=''
CFILEMODE='644'
dc_use_split_config='true'
dc_hide_mailname=''
dc_mailname_in_oh='true'
dc_localdelivery='maildir_home'

Manual intervention

The section in exim.sls that automatically runs the utility that updates the Debian exim configuration is commented out for now as this triggers infinite recursion within SaltStack and I haven’t had time to get to the bottom of it. Thus it is necessary to run the following commands manually once SaltStack has finished to get the configuration updated:

/usr/sbin/update-exim4.conf
systemctl restart exim4

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.