all repos — site @ ad28962572b038bc5c79f825a30acc21fc6772b3

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