Full featured Slackware email server with sendmail and cyrus-imapd

Comment on Mastodon

This article is about making your own mail server using Slackware

linux distribution, sendmail and cyrus-imap. This choice is because I

really love Slackware and I also enjoy non-mainstream stacks. While

everyone would recommend postfix/dovecot, I prefer using

sendmail/cyrus-imap. Please not this article contain ironical

statements, I will try to write them with some *emphasis*.

If you are used to clean, reproducible and automated deployments, the

present how-to is the totally opposite. *This is the /Slackware/ way*.

Slackware

Slackware is one of the oldest (maybe the oldest with debian) linux

distribution out there and it's still usable. The last release (14.2)

is 4 years old but there are still security updates. I choose to use

the development branch slackware-current for this article.

I discovered an alternative to Windows in the early 2000' with a

friend showing me a « Linux » magazine, featuring Slackware

installation CDs and the instructions to install. It was my very first

contact with Linux and open source ever. I used Slackware multiple

times over time, and it was always a great system for me on my main

laptop.

The Slackware specifics could be said as: "not changing much" and

"quite limited". Slackware never change much between releases, from

2010 to 2020, it's pretty much the same system when you use it. I say

it's rather limited, package wise, the default Slackware installation

requires like 15 GB on your disk because it bundles KDE and all the

kde apps, a bunch of editors (emacs,vim,vs,elvis), lot of

compilers/interpreter (gcc, llvm, ada, scheme, python, ruby

etc..). While it provides a LOT of things out of the box, you really

get all Slackware can offer. If something isn't in the packages, you

need to install it yourself.

Full Disk Encryption or nothing

I recommend to EVERYONE the practice of having a full disk encryption

(phone, laptop, workstation, servers). If your system get stolen, you

will only lose hardware when you use full disk encryption.

Without encryption, the thief can access all your data forever.

Slackware provides a file `README_CRYPT.txt` explaining how to install

on an encrypted partition. Don't forget to tell the bootloader *LILO*

about the initrd, and keep in mind the initrd must be recreated after

kernel upgrade

Use ntpd

It's important to have a correct time on your server.

# chmod +x /etc/rc.d/rc.ntpd

# /etc/rc.d/rc.ntpd start

Disable ssh password authentication

In `/etc/ssh/sshd_config` there are two changes to do:

Turn `UsePam yes` into `UsePam no` and add `PasswordAuthentication`.

Changes can be applied by restarting ssh with `/etc/rc.d/rc.sshd

restart`.

Before enabling this, don't forget to deploy your public key to an

user who is able to become to root.

Get a SSL certificate

We need a SSL certificate for the infrastructure, so we will install

[certbot](https://certbot.eff.org/). Unfortunately, certbot-auto

doesn't work on Slackware because the system is unsupported. So we

will use pip and call certbot in standalone mode so we don't need a

web server.

# pip3 install certbot

# certbot certonly --standalone -d mydomain.foobar -m usernam@example

My domain being `kongroo.eu` the files are generated under

`/etc/letsencrypt/live/kongroo.eu/`.

Configure the DNS

Three DNS entries have to be added for a working email server.

1. SPF to tell the world which addresses have the right send your

emails

2. MX to tell the world which addresses will receive the emails and in

which order

3. DKIM (a public key) to allow recipients to check your emails really

comes from your servers (signed used a private key)

4. DMARC to tell recipient what to do with mails not respecting SPF

SPF

Simple, add an entry with `v=spf1 mx` if you want to allow your MX

servers to send emails. Basically, for simple setups, the same server

receive and send emails.

@ 1800 IN SPF "v=spf1 mx"

MX

My server with the address `kongroo.eu` will receive the emails.

@ 10800 IN MX 50 kongroo.eu.

DKIM

This part will be a bit more complicated. We have to generate a pair

of public and private keys and run a daemon that will sign outgoing

emails with the private key, so recipients can verify the emails

signature using the public key available in the DNS. We will use

opendkim, I found this

[very good](https://philio.me/setting-up-dkim-with-sendmail-on-ubuntu-14-04/)

article explaining how to use opendkim with sendmail.

Opendkim isn't part of slackware base packages, fortunately it is

available in [slackbuilds](https://slackbuilds.org/), you can check my

previous article explaining how to setup slackbuilds.

# groupadd -g 305 opendkim

# useradd -r -u 305 -g opendkim -d /var/run/opendkim/ -s /sbin/nologin \

-c "OpenDKIM Milter" opendkim

# sboinstall opendkim

We want to enable opendkim at boot, as it's not a service from the

base system, so we need to "register" it in rc.local and enable both.

Add the following to `/etc/rc.d/rc.local`:

if [ -x /etc/rc.d/rc.opendkim ]; then

/etc/rc.d/rc.opendkim start

fi

Make the scripts executable so they will be run at boot:

# chmod +x /etc/rc.d/rc.local

# chmod +x /etc/rc.d/rc.opendkim

Create the key pair:

# mkdir /etc/opendkim

# cd /etc/opendkim

# opendkim-genkey -t -s default -d kongroo.eu

Get the content of `default.txt`, we will use it as a content for a

TXT entry in the DNS, select only the content between parenthesis

without double quotes: your DNS tool (like on Gandi) may take

everything without warning which would produce an invalid DKIM

signature. *Been there, done that.*

The file should looks like:

default._domainkey IN TXT ( "v=DKIM1; k=rsa; t=y; " "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5iBUyQ02H5sfS54hg155eQBxtMuhcwB4b896S7o97pPGZEiteby/RtCOz9VV2TOgGckz8eOEeYHnONdlnYWGv8HqVwngPWJmiU7xbyoH489ZkG397ouEJI4mBrU9ZTjULbweT2sVXpiMFCalNraKHMVjqgZWxzqoE3ETGpMNNSwIDAQAB" )

But the content I used for my entry at gandi is:

v=DKIM1; k=rsa; t=y; " "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5iBUyQ02H5sfS54hg155eQBxtMuhcwB4b896S7o97pPGZEiteby/RtCOz9VV2TOgGckz8eOEeYHnONdlnYWGv8HqVwngPWJmiU7xbyoH489ZkG397ouEJI4mBrU9ZTjULbweT2sVXpiMFCalNraKHMVjqgZWxzqoE3ETGpMNNSwIDAQAB

Now we need to configure opendkim to use our keys. Edit

`/etc/opendkim.conf` to changes the following lines already

there:

Domain kongroo.eu

KeyFile /etc/opendkim/default.private

ReportAddress postmaster@kongroo.eu

Dmarc

We have to tell DMARC, this may help being accepted by big corporate

mail servers.

_dmarc.kongroo.eu. IN TXT "v=DMARC1;p=none;pct=100;rua=mailto:postmaster@kongroo.eu;"

This will tell the recipient that we don't give specific instruction

to what to do with suspicious mails from our domain and tell

postmaster@kongroo.eu about the reports. **Expect daily mail from

every mail server reached in the day to arrive on that address.**

Install Sendmail

the default install, this may be a good thing but I want

sendmail. *Good news: sendmail is still in the extra directory*.

I wanted to use [citadel](https://citadel.org/) but *it was really

complicated, so I went to sendmail.*

Installation

Download the two sendmail txz packages on a mirror in the "extra"

directory:

https://mirrors.slackware.com/slackware/slackware64-current/extra/sendmail/

Run `/sbin/installpkg` on both packages.

Configuration

We will disable postfix.

# sh /etc/rc.d/rc.postfix stop

# chmod -x /etc/rc.d/rc.postfix

Enable sendmail and saslauthd

# chmod +x /etc/rc.d/rc.sendmail

# chmod +x /etc/rc.d/rc.saslauthd

All the configuration will be done in `/usr/share/sendmail/cf/cf`, we

will use a default template from the package. As explained in the cf

files, we need to use a template and rebuild from this directory

containing all the macros.

# cp sendmail-slackware-tls-sasl.mc /usr/share/sendmail/cf/cf/config.mc

Every time we want to rebuild the configuration file, we need to apply

the m4 macros to have the real configuration file.

# sh Build config.mc

# cp config.cf /etc/mail/sendmail.cf

My `config.mc` file looks like this (I stripped the comments):

include(`../m4/cf.m4')

VERSIONID(`TLS supporting setup for Slackware Linux')dnl

OSTYPE(`linux')dnl

define(`confCACERT_PATH', `/etc/letsencrypt/live/kongroo.eu/')

define(`confCACERT', `/etc/letsencrypt/live/kongroo.eu/cert.pem')

define(`confSERVER_CERT', `/etc/letsencrypt/live/kongroo.eu/fullchain.pem')

define(`confSERVER_KEY', `/etc/letsencrypt/live/kongroo.eu/privkey.pem')

define(`confPRIVACY_FLAGS', `authwarnings,novrfy,noexpn,restrictqrun')dnl

define(`confTO_IDENT', `0')dnl

FEATURE(`use_cw_file')dnl

FEATURE(`use_ct_file')dnl

FEATURE(`mailertable',`hash -o /etc/mail/mailertable.db')dnl

FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable.db')dnl

FEATURE(`access_db', `hash -T<TMPF> /etc/mail/access')dnl

FEATURE(`blocklist_recipients')dnl

FEATURE(`local_procmail',`',`procmail -t -Y -a $h -d $u')dnl

FEATURE(`always_add_domain')dnl

FEATURE(`redirect')dnl

FEATURE(`no_default_msa')dnl

EXPOSED_USER(`root')dnl

LOCAL_DOMAIN(`localhost.localdomain')dnl

INPUT_MAIL_FILTER(`opendkim', `S=inet:8891@localhost')

MAILER(local)dnl

MAILER(smtp)dnl

MAILER(procmail)dnl

define(`confAUTH_OPTIONS', `A p y')dnl

define(`confAUTH_MECHANISMS', `LOGIN PLAIN DIGEST-MD5 CRAM-MD5')dnl

TRUST_AUTH_MECH(`LOGIN PLAIN DIGEST-MD5 CRAM-MD5')dnl

DAEMON_OPTIONS(`Port=smtp, Name=MTA')dnl

DAEMON_OPTIONS(`Port=smtps, Name=MSA-SSL, M=Esa')dnl

LOCAL_CONFIG

O CipherList=ALL:!ADH:!NULL:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:+SSLv3:+TLSv1:-SSLv2:+EXP:+eNULL

Create the file `/etc/sasl2/Sendmail.conf` with this content:

pwcheck_method:saslauthd

This will tell sendmail to use saslauthd for PLAIN and LOGIN

connections. Any SMTP client will have to use either PLAIN or LOGIN.

If you start sendmail and saslauthd, you should be able to send

e-mails with authentication.

We need to edit `/etc/mail/local-host-names` to tell sendmail for

which domain it should accept local deliveries.

Simply add your email domain:

kongroo.eu

The mail logs are located under `/var/log/maillog`, every mail sent

well signed with DKIM should appear under a line like this:

[time] [host] sm-mta[2520]: 0AECKet1002520: Milter (opendkim) insert (1): header: DKIM-Signature: [whole signature]

Configure DKIM

This has been explained in a subsection of sendmail configuration. If

you didn't read this step because you don't want to setup dkim, you

missed information required for the next steps.

Install cyrus-imap

cyrus-imapd is available in slackbuilds.

The bad news is that the slackbuild is outdated, so here it a simple

patch to apply in `/usr/sbo/repo/network/cyrus-imapd`. This patch also

fixes a compilation issue.

diff --git a/network/cyrus-imapd/cyrus-imapd.SlackBuild b/network/cyrus-imapd/cyrus-imapd.SlackBuild

index 48e2c54e55..251ca5f207 100644

--- a/network/cyrus-imapd/cyrus-imapd.SlackBuild

+++ b/network/cyrus-imapd/cyrus-imapd.SlackBuild

@@ -23,7 +23,7 @@

# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

PRGNAM=cyrus-imapd

-VERSION=${VERSION:-2.5.11}

+VERSION=${VERSION:-2.5.16}

BUILD=${BUILD:-1}

TAG=${TAG:-_SBo}

@@ -107,6 +107,8 @@ CXXFLAGS="$SLKCFLAGS" \

$DATABASE \

--build=$ARCH-slackware-linux

+sed -i'' 's/gettid/_gettid/g' lib/cyrusdb_berkeley.c

+

make PERL_MM_OPT='INSTALLDIRS=vendor'

make install DESTDIR=$PKG

diff --git a/network/cyrus-imapd/cyrus-imapd.info b/network/cyrus-imapd/cyrus-imapd.info

index 99b2c68075..6ae26365dc 100644

--- a/network/cyrus-imapd/cyrus-imapd.info

+++ b/network/cyrus-imapd/cyrus-imapd.info

@@ -1,8 +1,8 @@

PRGNAM="cyrus-imapd"

VERSION="2.5.11"

HOMEPAGE="https://www.cyrusimap.org/"

-DOWNLOAD="ftp://ftp.cyrusimap.org/cyrus-imapd/cyrus-imapd-2.5.11.tar.gz"

-MD5SUM="674083444c36a786d9431b6612969224"

+DOWNLOAD="https://github.com/cyrusimap/cyrus-imapd/releases/download/cyrus-imapd-2.5.16/cyrus-imapd-2.5.16.tar.gz"

+MD5SUM="d5667e91d8e094ef24560a148e39c462"

DOWNLOAD_x86_64=""

MD5SUM_x86_64=""

REQUIRES=""

You can apply it by carefully copying the content in a file and use

the command `patch`.

We can now proceed with cyrus-imapd compilation and installation.

# env DATABASE=sqlite sboinstall cyrus-imapd

As explained in the README file shown during installation, we need to

do a few instructions.

# mkdir -m 750 -p /var/imap /var/spool/imap /var/sieve

# chown cyrus:cyrus /var/imap /var/spool/imap /var/sieve

# su - cyrus

# /usr/doc/cyrus-imapd-2.5.16/tools/mkimap

# logout

Add the following to `/etc/rc.d/rc.local` to enable cyrus-imapd at

boot:

if [ -x /etc/rc.d/rc.cyrus-imapd ]; then

/etc/rc.d/rc.cyrus-imapd start

fi

And make the rc script executable:

# chmod +x /etc/rc.d/rc.cyrus-imapd

[The official](https://www.cyrusimap.org/imap/installing.html) cyrus

documentation is very well done and was very helpful while writing this.

The configuration file is `/etc/imapd.conf`:

configdirectory: /var/imap

partition-default: /var/spool/imap

sievedir: /var/sieve

admins: cyrus

sasl_pwcheck_method: saslauthd

allowplaintext: yes

tls_server_cert: /etc/letsencrypt/cyrus/fullchain.pem

tls_server_key: /etc/letsencrypt/cyrus/privkey.pem

tls_client_ca_dir: /etc/ssl/certs

There is another file `/etc/cyrusd.conf` used but we don't need to

make changes in it.

We will have to copy the certificates into a separate place and allow

cyrus user to read them. This will have to be done every time the

certificate are renewed. Let's add the certbot command so we can use

this script as a cron.

#!/bin/sh

DOMAIN=kongroo.eu

LIVEDIR=/etc/letsencrypt/live/$DOMAIN/

DESTDIR=/etc/letsencrypt/cyrus/

certbot certonly --standalone -d $DOMAIN -m usernam@example

mkdir -p $DESTDIR

install -o cyrus -g cyrus -m 400 $LIVEDIR/fullchain.pem $DESTDIR

install -o cyrus -g cyrus -m 400 $LIVEDIR/privkey.pem $DESTDIR

/etc/rc.d/rc.sendmail restart

/etc/rc.d/rc.cyrus-imapd restart

Add a crontab entry to run this script once a day, using `crontab -e`

to change root crontab.

MAILTO=""

PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin

0 5 * * * sh /root/renew_certs.sh

Starting the mail server

We prepared the mail server to be working on reboot, but the services

aren't started yet.

# /etc/rc.d/rc.saslauthd start

# /etc/rc.d/rc.sendmail start

# /etc/rc.d/rc.cyrus-imapd start

# /etc/rc.d/rc.opendkim start

Adding a new user

Add a new user to your system.

# useradd $username

# passwd $username

For some reasons the user mailboxes must be initialized. The same

password must be typed twice (or passed as parameter using `-w

$password`).

# USER=foobar

# DOMAIN=kongroo.eu

# echo "cm INBOX" | rlwrap cyradm -u $USER $DOMAIN

Password:

IMAP Password:

Voila! The user should be able to connect using IMAP and receive

emails.

Check your email setup

You can use the web service [Mail

tester](https://www.mail-tester.com/) by sending an email. You could

copy/paste a real email to avoid having a bad mark due to spam

recognition (which happens if you send a mail with a few words). The

bad spam core isn't relevant anyway as long as it's due to the content

of your email.

Conclusion

I had real fun writing this article, digging hard in Slackware and

playing with unusual programs like sendmail and cyrus-imapd. I hope

you will enjoy too as much as I enjoyed writing it!

If you find mistakes or bad configuration settings, please contact me

so, I will be happy to discuss about the change and fix this how-to.

Nota Bene: Slackbuilds aren't mean to be used on the current version,

but really on the last release. There is a github repository carrying

the -current changes on a github repository

[https://github.com/Ponce/slackbuilds/](https://github.com/Ponce/slackbuilds/).