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