all repos — site @ master

source for my site, found at icyphox.sh

pages/blog/mailserver.md (view raw)

  1---
  2template: text.html
  3title: Setting up my personal mailserver
  4subtitle: This is probably a terrible idea…
  5date: 2019-08-15
  6slug: mailserver
  7---
  8
  9A mailserver was a long time coming. I'd made an attempt at setting one up
 10around ~4 years ago (ish), and IIRC, I quit when it came to DNS. And
 11I almost did this time too.[^1]
 12
 13For this attempt, I wanted a simpler approach. I recall how terribly
 14confusing Dovecot & Postfix were to configure and hence I decided to look
 15for a containerized solution, that most importantly, runs on my cheap $5 
 16Digital Ocean VPS  --  1 vCPU and 1 GB memory. Of which only around 500 MB
 17is actually available. So yeah, *pretty* tight.
 18
 19## What's available
 20
 21Turns out, there are quite a few of these OOTB, ready to deply solutions.
 22These are the ones I came across:
 23
 24- [poste.io](https://poste.io): Based on an "open core" model. The base install is open source 
 25and free (as in beer), but you'll have to pay for the extra stuff.
 26
 27- [mailu.io](https://mailu.io): Free software. Draws inspiration from poste.io, 
 28but ships with a web UI that I didn't need. 
 29
 30- [mailcow.email](https://mailcow.email): These fancy domains are getting ridiculous. But more importantly
 31they need 2 GiB of RAM *plus* swap?! Nope.
 32
 33- [Mail-in-a-Box](https://mailinabox.email): Unlike the ones above, not a Docker-based solution but definitely worth
 34a mention. It however, needs a fresh box to work with. A box with absolutely 
 35nothing else on it. I can't afford to do that.
 36
 37- [docker-mailserver](https://github.com/tomav/docker-mailserver/): **The winner**. 
 38
 39## So… `docker-mailserver`
 40
 41The first thing that caught my eye in the README:
 42
 43> Recommended:
 44> 
 45> - 1 CPU
 46> - 1GB RAM
 47> 
 48> Minimum:
 49> 
 50> - 1 CPU
 51> - 512MB RAM
 52
 53Fantastic, I can somehow squeeze this into my existing VPS.
 54Setup was fairly simple & the docs are pretty good. It employs a single
 55`.env` file for configuration, which is great.
 56However, I did run into a couple of hiccups here and there.
 57
 58One especially nasty one was `docker` / `docker-compose` running out
 59of memory.
 60```
 61Error response from daemon: cannot stop container: 2377e5c0b456: Cannot kill container 2377e5c0b456226ecaa66a5ac18071fc5885b8a9912feeefb07593638b9a40d1: OCI runtime state failed: runc did not terminate sucessfully: fatal error: runtime: out of memory
 62```
 63But it eventually worked after a couple of attempts.
 64
 65The next thing I struggled with  --  DNS. Specifically, the with the step where
 66the DKIM keys are generated[^2]. The output under  
 67`config/opendkim/keys/domain.tld/mail.txt`  
 68isn't exactly CloudFlare friendly; they can't be directly copy-pasted into
 69a `TXT` record. 
 70
 71This is what it looks like.
 72```
 73mail._domainkey	IN	TXT	( "v=DKIM1; h=sha256; k=rsa; "
 74	  "p=<key>"
 75	  "<more key>" )  ;  -- -- DKIM key mail for icyphox.sh
 76```
 77But while configuring the record, you set "Type" to `TXT`, "Name" to `mail._domainkey`,
 78and the "Value" to what's inside the parenthesis `(  )`, *removing* the quotes `""`. 
 79Also remove the part that appears to be a comment `;  -- -- ...`.
 80
 81To simplify debugging DNS issues later, it's probably a good idea to
 82point to your mailserver using a subdomain like `mail.domain.tld` using an 
 83`A` record.
 84You'll then have to set an `MX` record with the "Name" as `@` (or whatever your DNS provider
 85uses to denote the root domain) and the "Value" to `mail.domain.tld`.
 86And finally, the `PTR` (pointer record, I think), which is the reverse of 
 87your `A` record  --  "Name" as the server IP and "Value" as `mail.domain.tld`.
 88I learnt this part the hard way, when my outgoing email kept getting
 89rejected by Tutanota's servers.
 90
 91Yet another hurdle  --  SSL/TLS certificates. This isn't very properly
 92documented, unless you read through the [wiki](https://github.com/tomav/docker-mailserver/wiki/Installation-Examples)
 93and look at an example. In short, install `certbot`, have port 80 free,
 94and run 
 95
 96``` shell
 97$ certbot certonly --standalone -d mail.domain.tld
 98```
 99
100Once that's done, edit the `docker-compose.yml` file to mount `/etc/letsencrypt` in 
101the container, something like so:
102```yaml
103...
104
105volumes:
106    - maildata:/var/mail
107    - mailstate:/var/mail-state
108    - ./config/:/tmp/docker-mailserver/
109    - /etc/letsencrypt:/etc/letsencrypt
110
111...
112```
113
114With this done, you shouldn't have mail clients complaining about 
115wonky certs for which you'll have to add an exception manually.
116
117## Why would you…?
118There are a few good reasons for this:
119
120### Privacy 
121No really, this is *the* best choice for truly private
122email. Not ProtonMail, not Tutanota. Sure, they claim so and I don't 
123dispute it. Quoting Drew Devault[^3],
124
125> Truly secure systems do not require you to trust the service provider.
126
127But you have to *trust* ProtonMail. They run open source software, but
128how can you really be sure that it isn't a backdoored version of it?
129
130When you host your own mailserver, you truly own your email without having to rely on any
131third-party.
132This isn't an attempt to spread FUD. In the end, it all depends on your
133threat model™.
134
135### Decentralization
136Email today is basically run by Google. Gmail has over 1.2 *billion*
137active users. That's obscene.
138Email was designed to be decentralized but big corps swooped in and
139made it a product. They now control your data, and it isn't unknown that
140Google reads your mail. This again loops back to my previous point, privacy.
141Decentralization guarantees privacy. When you control your mail, you subsequently
142control who reads it.
143
144### Personalization
145Can't ignore this one. It's cool to have a custom email address to flex.
146
147`x@icyphox.sh` vs `gabe.newell4321@gmail.com`
148
149Pfft, this is no competition.
150
151[^1]: My [tweet](https://twitter.com/icyphox/status/1161648321548566528) of frustration.
152[^2]: [Link](https://github.com/tomav/docker-mailserver#generate-dkim-keys) to step in the docs.
153[^3]: From his [article](https://drewdevault.com/2018/08/08/Signal.html) on why he doesn't trust Signal.