all repos — site @ 661c71b94445d02bb456b1b8d41603f513834de9

source for my site, found at icyphox.sh

build/blog/mailserver/index.html (view raw)

  1<!DOCTYPE html>
  2<html lang=en>
  3<link rel="stylesheet" href="/static/style.css" type="text/css">
  4<link rel="stylesheet" href="/static/syntax.css" type="text/css">
  5<link rel="shortcut icon" type="images/x-icon" href="/static/favicon.ico">
  6<meta name="description" content="This is probably a terrible idea…">
  7<meta name="viewport" content="initial-scale=1">
  8<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  9<meta content="#021012" name="theme-color">
 10<meta name="HandheldFriendly" content="true">
 11<meta name="twitter:card" content="summary_large_image">
 12<meta name="twitter:site" content="@icyphox">
 13<meta name="twitter:title" content="Setting up my personal mailserver">
 14<meta name="twitter:description" content="This is probably a terrible idea…">
 15<meta name="twitter:image" content="/static/icyphox.png">
 16<meta property="og:title" content="Setting up my personal mailserver">
 17<meta property="og:type" content="website">
 18<meta property="og:description" content="This is probably a terrible idea…">
 19<meta property="og:url" content="https://icyphox.sh">
 20<meta property="og:image" content="/static/icyphox.png">
 21<html>
 22  <title>
 23    Setting up my personal mailserver
 24  </title>
 25<div class="container-text">
 26  <header class="header">
 27    
 28        <a href="/">home</a>
 29        <a href="/blog">blog</a>
 30        <a href="/reading">reading</a>
 31        <a href="https://twitter.com/icyphox">twitter</a>
 32        <a href="/about">about</a>
 33
 34  </header>
 35<body> 
 36   <div class="content">
 37    <div align="left">
 38      <code>2019-08-15</code>
 39      <h1>Setting up my personal mailserver</h1>
 40      <h2>This is probably a terrible idea…</h2>
 41      <p>A mailserver was a long time coming. I&#8217;d made an attempt at setting one up
 42around ~4 years ago (ish), and IIRC, I quit when it came to DNS. And
 43I almost did this time too.<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p>
 44
 45<p>For this attempt, I wanted a simpler approach. I recall how terribly
 46confusing Dovecot &amp; Postfix were to configure and hence I decided to look
 47for a containerized solution, that most importantly, runs on my cheap $5 
 48Digital Ocean VPS &#8212; 1 vCPU and 1 GB memory. Of which only around 500 MB
 49is actually available. So yeah, <em>pretty</em> tight.</p>
 50
 51<h3 id="whats-available">What&#8217;s available</h3>
 52
 53<p>Turns out, there are quite a few of these OOTB, ready to deply solutions.
 54These are the ones I came across:</p>
 55
 56<ul>
 57<li><p><a href="https://poste.io">poste.io</a>: Based on an &#8220;open core&#8221; model. The base install is open source 
 58and free (as in beer), but you&#8217;ll have to pay for the extra stuff.</p></li>
 59<li><p><a href="https://mailu.io">mailu.io</a>: Free software. Draws inspiration from poste.io, 
 60but ships with a web UI that I didn&#8217;t need. </p></li>
 61<li><p><a href="https://mailcow.email">mailcow.email</a>: These fancy domains are getting ridiculous. But more importantly
 62they need 2 GiB of RAM <em>plus</em> swap?! Nope.</p></li>
 63<li><p><a href="https://mailinabox.email">Mail-in-a-Box</a>: Unlike the ones above, not a Docker-based solution but definitely worth
 64a mention. It however, needs a fresh box to work with. A box with absolutely 
 65nothing else on it. I can&#8217;t afford to do that.</p></li>
 66<li><p><a href="https://github.com/tomav/docker-mailserver/">docker-mailserver</a>: <strong>The winner</strong>. </p></li>
 67</ul>
 68
 69<h3 id="so-docker-mailserver">So… <code>docker-mailserver</code></h3>
 70
 71<p>The first thing that caught my eye in the README:</p>
 72
 73<blockquote>
 74  <p>Recommended:</p>
 75  
 76  <ul>
 77  <li>1 CPU</li>
 78  <li>1GB RAM</li>
 79  </ul>
 80  
 81  <p>Minimum:</p>
 82  
 83  <ul>
 84  <li>1 CPU</li>
 85  <li>512MB RAM</li>
 86  </ul>
 87</blockquote>
 88
 89<p>Fantastic, I can somehow squeeze this into my existing VPS.
 90Setup was fairly simple &amp; the docs are pretty good. It employs a single
 91<code>.env</code> file for configuration, which is great.
 92However, I did run into a couple of hiccups here and there.</p>
 93
 94<p>One especially nasty one was <code>docker</code> / <code>docker-compose</code> running out
 95of memory.</p>
 96
 97<pre><code>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
 98</code></pre>
 99
100<p>But it eventually worked after a couple of attempts.</p>
101
102<p>The next thing I struggled with &#8212; DNS. Specifically, the with the step where
103the DKIM keys are generated<sup class="footnote-ref" id="fnref-2"><a href="#fn-2">2</a></sup>. The output under <br />
104<code>config/opendkim/keys/domain.tld/mail.txt</code> <br />
105isn&#8217;t exactly CloudFlare friendly; they can&#8217;t be directly copy-pasted into
106a <code>TXT</code> record. </p>
107
108<p>This is what it looks like.</p>
109
110<pre><code>mail._domainkey IN  TXT ( "v=DKIM1; h=sha256; k=rsa; "
111      "p=&lt;key&gt;"
112      "&lt;more key&gt;" )  ; ----- DKIM key mail for icyphox.sh
113</code></pre>
114
115<p>But while configuring the record, you set &#8220;Type&#8221; to <code>TXT</code>, &#8220;Name&#8221; to <code>mail._domainkey</code>,
116and the &#8220;Value&#8221; to what&#8217;s inside the parenthesis <code>(  )</code>, <em>removing</em> the quotes <code>""</code>. 
117Also remove the part that appears to be a comment <code>; ----- ...</code>.</p>
118
119<p>To simplify debugging DNS issues later, it&#8217;s probably a good idea to
120point to your mailserver using a subdomain like <code>mail.domain.tld</code> using an 
121<code>A</code> record.
122You&#8217;ll then have to set an <code>MX</code> record with the &#8220;Name&#8221; as <code>@</code> (or whatever your DNS provider
123uses to denote the root domain) and the &#8220;Value&#8221; to <code>mail.domain.tld</code>.
124And finally, the <code>PTR</code> (pointer record, I think), which is the reverse of 
125your <code>A</code> record &#8212; &#8220;Name&#8221; as the server IP and &#8220;Value&#8221; as <code>mail.domain.tld</code>.
126I learnt this part the hard way, when my outgoing email kept getting
127rejected by Tutanota&#8217;s servers.</p>
128
129<p>Yet another hurdle &#8212; SSL/TLS certificates. This isn&#8217;t very properly
130documented, unless you read through the <a href="https://github.com/tomav/docker-mailserver/wiki/Installation-Examples">wiki</a>
131and look at an example. In short, install <code>certbot</code>, have port 80 free,
132and run </p>
133
134<div class="codehilite"><pre><span></span><code>$ certbot certonly --standalone -d mail.domain.tld
135</code></pre></div>
136
137<p>Once that&#8217;s done, edit the <code>docker-compose.yml</code> file to mount <code>/etc/letsencrypt</code> in 
138the container, something like so:</p>
139
140<div class="codehilite"><pre><span></span><code><span class="nn">...</span>
141
142<span class="nt">volumes</span><span class="p">:</span>
143    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">maildata:/var/mail</span>
144    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">mailstate:/var/mail-state</span>
145    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">./config/:/tmp/docker-mailserver/</span>
146    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">/etc/letsencrypt:/etc/letsencrypt</span>
147
148<span class="nn">...</span>
149</code></pre></div>
150
151<p>With this done, you shouldn&#8217;t have mail clients complaining about 
152wonky certs for which you&#8217;ll have to add an exception manually.</p>
153
154<h3 id="why-would-you">Why would you…?</h3>
155
156<p>There are a few good reasons for this:</p>
157
158<h4 id="privacy">Privacy</h4>
159
160<p>No really, this is <em>the</em> best choice for truly private
161email. Not ProtonMail, not Tutanota. Sure, they claim so and I don&#8217;t 
162dispute it. Quoting Drew Devault<sup class="footnote-ref" id="fnref-3"><a href="#fn-3">3</a></sup>,</p>
163
164<blockquote>
165  <p>Truly secure systems do not require you to trust the service provider.</p>
166</blockquote>
167
168<p>But you have to <em>trust</em> ProtonMail. They run open source software, but
169how can you really be sure that it isn&#8217;t a backdoored version of it?</p>
170
171<p>When you host your own mailserver, you truly own your email without having to rely on any
172third-party.
173This isn&#8217;t an attempt to spread FUD. In the end, it all depends on your
174threat model™.</p>
175
176<h4 id="decentralization">Decentralization</h4>
177
178<p>Email today is basically run by Google. Gmail has over 1.2 <em>billion</em>
179active users. That&#8217;s obscene.
180Email was designed to be decentralized but big corps swooped in and
181made it a product. They now control your data, and it isn&#8217;t unknown that
182Google reads your mail. This again loops back to my previous point, privacy.
183Decentralization guarantees privacy. When you control your mail, you subsequently
184control who reads it.</p>
185
186<h4 id="personalization">Personalization</h4>
187
188<p>Can&#8217;t ignore this one. It&#8217;s cool to have a custom email address to flex.</p>
189
190<p><code>x@icyphox.sh</code> vs <code>gabe.newell4321@gmail.com</code></p>
191
192<p>Pfft, this is no competition.</p>
193
194<div class="footnotes">
195<hr />
196<ol>
197<li id="fn-1">
198<p>My <a href="https://twitter.com/icyphox/status/1161648321548566528">tweet</a> of frustration.&#160;<a href="#fnref-1" class="footnoteBackLink" title="Jump back to footnote 1 in the text.">&#8617;</a></p>
199</li>
200
201<li id="fn-2">
202<p><a href="https://github.com/tomav/docker-mailserver#generate-dkim-keys">Link</a> to step in the docs.&#160;<a href="#fnref-2" class="footnoteBackLink" title="Jump back to footnote 2 in the text.">&#8617;</a></p>
203</li>
204
205<li id="fn-3">
206<p>From his <a href="https://drewdevault.com/2018/08/08/Signal.html">article</a> on why he doesn&#8217;t trust Signal.&#160;<a href="#fnref-3" class="footnoteBackLink" title="Jump back to footnote 3 in the text.">&#8617;</a></p>
207</li>
208</ol>
209</div>
210 
211    </div>
212    <hr />
213    <p class="muted">Questions or comments? Open an issue at <a href="https://github.com/icyphox/site">this repo</a>, or send a plain-text email to <a href="mailto:x@icyphox.sh">x@icyphox.sh</a>.</p>
214    <footer>
215      <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
216        <img class="footimgs" src="/static/cc.svg">
217        </a>
218        <a href="https://webring.xxiivv.com/#random" target="_blank">
219        <img class="footimgs" alt="xxiivv webring" src="/static/webring.svg">
220        </a>
221        
222    </footer>
223  </body>
224  </div>
225 </html>