From 7b5cd2ef61f6ea5b01a9587feb167393777033a3 Mon Sep 17 00:00:00 2001 From: Johannes Löthberg Date: Sun, 10 May 2015 23:50:47 +0200 Subject: journal: Add #14: Mail setup --- src/journal/14-mail-setup.rst | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/journal/14-mail-setup.rst diff --git a/src/journal/14-mail-setup.rst b/src/journal/14-mail-setup.rst new file mode 100644 index 0000000..9c46c17 --- /dev/null +++ b/src/journal/14-mail-setup.rst @@ -0,0 +1,75 @@ +.. frontmatter + title: Mail setup + date: 2015-05-10 + author: Johannes Löthberg + author_link: /~kyrias/about.html + +.. role:: sc + +:sc:`My old mail setup has` been a bit suboptimal. +It has worked for a long time, but how it was set up wasn’t as good as it could have been. +It was set up as follows: + +There are two mail servers, my server, theos, and my old classmate zephcom’s server, lucifer. +Both servers received email for the :sc:`kyriasis.com` domain, but only theos had the full user list, so lucifer forwarded all email to theos which then relayed all emails to zephcom back to lucifer. +This means that if theos goes down all email will be received by lucifer, which is good, but it also means that zephcom won’t receive his emails until theos gets back up again, even though they are on lucifer already. + +To solve this I wanted to firstly use a common users table for :sc:`OpenSMTPD` so that it would be easier to maintain and deploy to both servers. The format for the plain-text tables is as follows: + +.. code:: + + johannes: kyrias + gmail: demizide@gmail.com + @kyriasis.com: bar + +That user table will cause ``smtpd`` to deliver emails to ``johannes@kyriasis.com`` to the system user ``kyrias``, emails to ``gmail@kyriasis.com`` will be relayed to ``demizide@gmail.com``, and anything else will be delivered to the system user ``bar`` due to the last line which is a catch-all rule. + +That’s all rather simple, but what if I want to be able to use the same file on two servers, and have each server handle just a subset of the users? +What I ended up doing was something like the following: + +.. code:: + + johannes: kyrias@theos.kyriasis.com + erik: sysbunny@lucifer.kyriasis.com + +Instead of delivering directly to a local users this config will instead relay the email to the proper server using that server’s :sc:`fqdn`. +Both servers are then configured to just deliver everything received at their :sc:`fqdn` to any system users, and to act as a backup server for the other, just relaying it to the proper server when it comes up. + +Since ``theos`` will handle email sent to ``lucifer.kyriasis.com`` differently from how ``lucifer`` will, they can not share the exact same ``smtpd.conf``, but they can have a very similar one. + +Additionally, to make deploying to both servers easier I wrote the following ``fabfile``, which lets me just run eg, ``fab upload_conf`` which will upload the config and restart ``smtpd`` on both servers, if necessary: + +.. code:: python + + from fabric.api import env, local, put, run, sudo, task + + env.hosts = ['theos.kyriasis.com', 'lucifer.kyriasis.com'] + + def checksum_match(local_file, remote_file): + md5 = '/usr/bin/md5sum {}' + local_sum = local(md5.format(local_file), capture=True).split()[0] + remote_sum = run(md5.format(remote_file)).split()[0] + + return local_sum == remote_sum + + @task + def upload_conf(): + local_file = '{}/smtpd.conf'.format(env.host) + + if not checksum_match(local_file, '/etc/smtpd/smtpd.conf'): + print("Config changed, uploading new file...") + put(local_path=local_file, remote_path='/etc/smtpd/smtpd.conf') + sudo('systemctl restart smtpd.service') + + @task + def upload_users(): + local_file = 'common/users' + + if not checksum_match(local_file, '/etc/smtpd/users'): + print("Users changed, uploading new file...") + put(local_path=local_file, remote_path='/etc/smtpd/users') + sudo('smtpctl update table users') + +And of course all of it now resides in a nice `Git repository`__ with a history of all future changes. + +.. __: https://git.kyriasis.com/smtpd-conf -- cgit v1.2.3-70-g09d2