| 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 [email protected] | |
| ### 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:[email protected];" | |
| This will tell the recipient that we don't give specific instruction | |
| to what to do with suspicious mails from our domain and tell | |
| [email protected] 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/). |