all repos — site @ 58d53f1dae3afb6ec351fdc76bba8d95ac2127e0

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<script src="//instant.page/1.1.0" type="module" integrity="sha384-EwBObn5QAxP8f09iemwAJljc+sU+eUXeL9vSBw1eNmVarwhKk2F9vBEpaN9rsrtp"></script>
 26<div class="container-text">
 27  <header class="header">
 28    
 29        <a href="/">home</a>
 30        <a href="/blog">blog</a>
 31        <a href="/reading">reading</a>
 32        <a href="https://twitter.com/icyphox">twitter</a>
 33        <a href="/about">about</a>
 34
 35  </header>
 36<body> 
 37   <div class="content">
 38    <div align="left">
 39      <p> 2019-08-15 </p>
 40      <h1> Setting up my personal mailserver </h1>
 41      <h2> This is probably a terrible idea… </h2>
 42      <p>A mailserver was a long time coming. I&#8217;d made an attempt at setting one up
 43around ~4 years ago (ish), and IIRC, I quit when it came to DNS. And
 44I almost did this time too.<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p>
 45
 46<p>For this attempt, I wanted a simpler approach. I recall how terribly
 47confusing Dovecot &amp; Postfix were to configure and hence I decided to look
 48for a containerized solution, that most importantly, runs on my cheap $5 
 49Digital Ocean VPS &#8212; 1 vCPU and 1 GB memory. Of which only around 500 MB
 50is actually available. So yeah, <em>pretty</em> tight.</p>
 51
 52<h3 id="whats-available">What&#8217;s available</h3>
 53
 54<p>Turns out, there are quite a few of these OOTB, ready to deply solutions.
 55These are the ones I came across:</p>
 56
 57<ul>
 58<li><p><a href="https://poste.io">poste.io</a>: Based on an &#8220;open core&#8221; model. The base install is open source 
 59and free (as in beer), but you&#8217;ll have to pay for the extra stuff.</p></li>
 60<li><p><a href="https://mailu.io">mailu.io</a>: Free software. Draws inspiration from poste.io, 
 61but ships with a web UI that I didn&#8217;t need. </p></li>
 62<li><p><a href="https://mailcow.email">mailcow.email</a>: These fancy domains are getting ridiculous. But more importantly
 63they need 2 GiB of RAM <em>plus</em> swap?! Nope.</p></li>
 64<li><p><a href="https://mailinabox.email">Mail-in-a-Box</a>: Unlike the ones above, not a Docker-based solution but definitely worth
 65a mention. It however, needs a fresh box to work with. A box with absolutely 
 66nothing else on it. I can&#8217;t afford to do that.</p></li>
 67<li><p><a href="https://github.com/tomav/docker-mailserver/">docker-mailserver</a>: <strong>The winner</strong>. </p></li>
 68</ul>
 69
 70<h3 id="so-docker-mailserver">So… <code>docker-mailserver</code></h3>
 71
 72<p>The first thing that caught my eye in the README:</p>
 73
 74<blockquote>
 75  <p>Recommended:</p>
 76  
 77  <ul>
 78  <li>1 CPU</li>
 79  <li>1GB RAM</li>
 80  </ul>
 81  
 82  <p>Minimum:</p>
 83  
 84  <ul>
 85  <li>1 CPU</li>
 86  <li>512MB RAM</li>
 87  </ul>
 88</blockquote>
 89
 90<p>Fantastic, I can somehow squeeze this into my existing VPS.
 91Setup was fairly simple &amp; the docs are pretty good. Especially the single
 92<code>.env</code> file for configuration, which is great.
 93However, I did run into a couple of hiccups here and there.</p>
 94
 95<p>One especially nasty one was <code>docker</code> / <code>docker-compose</code> running out
 96of memory.</p>
 97
 98<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
 99</code></pre>
100
101<p>But it eventually worked after a couple of attempts.</p>
102
103<p>The next thing I struggled with &#8212; DNS. Especially with the step where
104the DKIM keys are generated<sup class="footnote-ref" id="fnref-2"><a href="#fn-2">2</a></sup>. The output under <code>config/opendkim/keys/domain.tld/mail.txt</code>
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 <code>certbot certonly --standalone -d mail.domain.tld</code>. Once that&#8217;s 
133done, edit the <code>docker-compose.yml</code> file to mount <code>/etc/letsencrypt</code> in 
134the container, something like so:</p>
135
136<div class="codehilite"><pre><span></span><code><span class="nn">...</span>
137
138<span class="nt">volumes</span><span class="p">:</span>
139    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">maildata:/var/mail</span>
140    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">mailstate:/var/mail-state</span>
141    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">./config/:/tmp/docker-mailserver/</span>
142    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">/etc/letsencrypt:/etc/letsencrypt</span>
143
144<span class="nn">...</span>
145</code></pre></div>
146
147<p>With this done, you shouldn&#8217;t have mail clients complaining about 
148wonky certs for which you&#8217;ll have to add an exception manually.</p>
149
150<h3 id="why-would-you">Why would you…?</h3>
151
152<p>There are a few good reasons for this:</p>
153
154<h4 id="privacy">Privacy</h4>
155
156<p>No really, this is <em>the</em> best choice for truly private
157email. Not ProtonMail, not Tutanota. Sure, they claim so and I don&#8217;t 
158dispute it. Quoting Drew Devault<sup class="footnote-ref" id="fnref-3"><a href="#fn-3">3</a></sup>,</p>
159
160<blockquote>
161  <p>Truly secure systems do not require you to trust the service provider.</p>
162</blockquote>
163
164<p>But you have to <em>trust</em> ProtonMail. They run open source software, but
165how can you really be sure that it isn&#8217;t a backdoored version of it?</p>
166
167<p>When you host your own mailserver, you truly own your email without having to rely on any
168third-party.
169This isn&#8217;t an attempt to spread FUD. In the end, it all depends on your
170threat model™.</p>
171
172<h4 id="decentralization">Decentralization</h4>
173
174<p>Email today is basically run by Google. Gmail has over 1.2 <em>billion</em>
175active users. That&#8217;s obscene.
176Email was designed to be decentralized but big corps swooped in and
177made it a product. They now control your data, and it isn&#8217;t unknown that
178Google reads your mail. This again loops back to my previous point, privacy.
179Decentralization guarantees privacy. When you control your mail, you subsequently
180control who reads it.</p>
181
182<h4 id="personalization">Personalization</h4>
183
184<p>Can&#8217;t ignore this one. It&#8217;s cool to have a custom email address to flex.</p>
185
186<p><code>x@icyphox.sh</code> vs <code>gabe.newell4321@gmail.com</code></p>
187
188<p>Pfft, this is no competition.</p>
189
190<div class="footnotes">
191<hr />
192<ol>
193<li id="fn-1">
194<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>
195</li>
196
197<li id="fn-2">
198<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>
199</li>
200
201<li id="fn-3">
202<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>
203</li>
204</ol>
205</div>
206 
207    </div>
208    <hr />
209    <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>
210    <footer>
211      <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
212        <img src="https://licensebuttons.net/l/by-nc-sa/4.0/80x15.png">
213        </a>
214    </footer>
215  </body>
216  </div>
217 </html>