Title: Full featured Slackware email server with sendmail and
       cyrus-imapd
       Author: Solène
       Date: 14 November 2020
       Tags: slackware email
       Description: 
       
       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*.
       
       *While some people use fossil fuel cars, some people use Slackware.*
       
       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=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5iBUyQ02H5sfS54hg155eQBxtMuhc
       wB4b896S7o97pPGZEiteby/RtCOz9VV2TOgGckz8eOEeYHnONdlnYWGv8HqVwngPWJmiU7x
       byoH489ZkG397ouEJI4mBrU9ZTjULbweT2sVXpiMFCalNraKHMVjqgZWxzqoE3ETGpMNNSw
       IDAQAB" )
       
       But the content I used for my entry at gandi is:
       
           v=DKIM1; k=rsa; t=y; "
       "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5iBUyQ02H5sfS54hg155eQBxtMuhc
       wB4b896S7o97pPGZEiteby/RtCOz9VV2TOgGckz8eOEeYHnONdlnYWGv8HqVwngPWJmiU7x
       byoH489ZkG397ouEJI4mBrU9ZTjULbweT2sVXpiMFCalNraKHMVjqgZWxzqoE3ETGpMNNSw
       IDAQAB
       
       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
       
       *Unfortunately Slackware team dropped sendmail in favor to postfix* in
       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/sendm
       ail/
       
       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
       
       **Slackware** ships with dovecot in the default installation, but
       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.
       
           -VERSION=${VERSION:-2.5.11}
           +VERSION=${VERSION:-2.5.16}
            BUILD=${BUILD:-1}
            TAG=${TAG:-_SBo}
       
              $DATABASE \
              --build=$ARCH-slackware-linux
       
           +
            make PERL_MM_OPT='INSTALLDIRS=vendor'
            make install DESTDIR=$PKG
       
       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.g
       z"
           -MD5SUM="674083444c36a786d9431b6612969224"
          
       +DOWNLOAD="https://github.com/cyrusimap/cyrus-imapd/releases/download/c
       yrus-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/slackb
       uilds/).