all repos — site @ 10d7c9d593bd3ede5e1022f1c3e233f9930eb665

source for my site, found at icyphox.sh

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
<!DOCTYPE html>
<html lang=en>
<link rel="stylesheet" href="/static/style.css" type="text/css">
<link rel="stylesheet" href="/static/syntax.css" type="text/css">
<link rel="shortcut icon" type="images/x-icon" href="/static/favicon.ico">
<meta name="description" content="This is probably a terrible idea…">
<meta name="viewport" content="initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta content="#021012" name="theme-color">
<meta name="HandheldFriendly" content="true">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@icyphox">
<meta name="twitter:title" content="Setting up my personal mailserver">
<meta name="twitter:description" content="This is probably a terrible idea…">
<meta name="twitter:image" content="/static/icyphox.png">
<meta property="og:title" content="Setting up my personal mailserver">
<meta property="og:type" content="website">
<meta property="og:description" content="This is probably a terrible idea…">
<meta property="og:url" content="https://icyphox.sh">
<meta property="og:image" content="/static/icyphox.png">
<html>
  <title>
    Setting up my personal mailserver
  </title>
<div class="container-text">
  <header class="header">
    
        <a href="/">home</a>
        <a href="/blog">blog</a>
        <a href="/reading">reading</a>
        <a href="https://twitter.com/icyphox">twitter</a>
        <a href="/about">about</a>

  </header>
<body> 
   <div class="content">
    <div align="left">
      <code>2019-08-15</code>
      <h1>Setting up my personal mailserver</h1>
      <h2>This is probably a terrible idea…</h2>
      <p>A mailserver was a long time coming. I&#8217;d made an attempt at setting one up
around ~4 years ago (ish), and IIRC, I quit when it came to DNS. And
I almost did this time too.<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p>

<p>For this attempt, I wanted a simpler approach. I recall how terribly
confusing Dovecot &amp; Postfix were to configure and hence I decided to look
for a containerized solution, that most importantly, runs on my cheap $5 
Digital Ocean VPS &#8212; 1 vCPU and 1 GB memory. Of which only around 500 MB
is actually available. So yeah, <em>pretty</em> tight.</p>

<h3 id="whats-available">What&#8217;s available</h3>

<p>Turns out, there are quite a few of these OOTB, ready to deply solutions.
These are the ones I came across:</p>

<ul>
<li><p><a href="https://poste.io">poste.io</a>: Based on an &#8220;open core&#8221; model. The base install is open source 
and free (as in beer), but you&#8217;ll have to pay for the extra stuff.</p></li>
<li><p><a href="https://mailu.io">mailu.io</a>: Free software. Draws inspiration from poste.io, 
but ships with a web UI that I didn&#8217;t need. </p></li>
<li><p><a href="https://mailcow.email">mailcow.email</a>: These fancy domains are getting ridiculous. But more importantly
they need 2 GiB of RAM <em>plus</em> swap?! Nope.</p></li>
<li><p><a href="https://mailinabox.email">Mail-in-a-Box</a>: Unlike the ones above, not a Docker-based solution but definitely worth
a mention. It however, needs a fresh box to work with. A box with absolutely 
nothing else on it. I can&#8217;t afford to do that.</p></li>
<li><p><a href="https://github.com/tomav/docker-mailserver/">docker-mailserver</a>: <strong>The winner</strong>. </p></li>
</ul>

<h3 id="so-docker-mailserver">So… <code>docker-mailserver</code></h3>

<p>The first thing that caught my eye in the README:</p>

<blockquote>
  <p>Recommended:</p>
  
  <ul>
  <li>1 CPU</li>
  <li>1GB RAM</li>
  </ul>
  
  <p>Minimum:</p>
  
  <ul>
  <li>1 CPU</li>
  <li>512MB RAM</li>
  </ul>
</blockquote>

<p>Fantastic, I can somehow squeeze this into my existing VPS.
Setup was fairly simple &amp; the docs are pretty good. It employs a single
<code>.env</code> file for configuration, which is great.
However, I did run into a couple of hiccups here and there.</p>

<p>One especially nasty one was <code>docker</code> / <code>docker-compose</code> running out
of memory.</p>

<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
</code></pre>

<p>But it eventually worked after a couple of attempts.</p>

<p>The next thing I struggled with &#8212; DNS. Specifically, the with the step where
the DKIM keys are generated<sup class="footnote-ref" id="fnref-2"><a href="#fn-2">2</a></sup>. The output under <br />
<code>config/opendkim/keys/domain.tld/mail.txt</code> <br />
isn&#8217;t exactly CloudFlare friendly; they can&#8217;t be directly copy-pasted into
a <code>TXT</code> record. </p>

<p>This is what it looks like.</p>

<pre><code>mail._domainkey IN  TXT ( "v=DKIM1; h=sha256; k=rsa; "
      "p=&lt;key&gt;"
      "&lt;more key&gt;" )  ; ----- DKIM key mail for icyphox.sh
</code></pre>

<p>But while configuring the record, you set &#8220;Type&#8221; to <code>TXT</code>, &#8220;Name&#8221; to <code>mail._domainkey</code>,
and the &#8220;Value&#8221; to what&#8217;s inside the parenthesis <code>(  )</code>, <em>removing</em> the quotes <code>""</code>. 
Also remove the part that appears to be a comment <code>; ----- ...</code>.</p>

<p>To simplify debugging DNS issues later, it&#8217;s probably a good idea to
point to your mailserver using a subdomain like <code>mail.domain.tld</code> using an 
<code>A</code> record.
You&#8217;ll then have to set an <code>MX</code> record with the &#8220;Name&#8221; as <code>@</code> (or whatever your DNS provider
uses to denote the root domain) and the &#8220;Value&#8221; to <code>mail.domain.tld</code>.
And finally, the <code>PTR</code> (pointer record, I think), which is the reverse of 
your <code>A</code> record &#8212; &#8220;Name&#8221; as the server IP and &#8220;Value&#8221; as <code>mail.domain.tld</code>.
I learnt this part the hard way, when my outgoing email kept getting
rejected by Tutanota&#8217;s servers.</p>

<p>Yet another hurdle &#8212; SSL/TLS certificates. This isn&#8217;t very properly
documented, unless you read through the <a href="https://github.com/tomav/docker-mailserver/wiki/Installation-Examples">wiki</a>
and look at an example. In short, install <code>certbot</code>, have port 80 free,
and run </p>

<div class="codehilite"><pre><span></span><code>$ certbot certonly --standalone -d mail.domain.tld
</code></pre></div>

<p>Once that&#8217;s done, edit the <code>docker-compose.yml</code> file to mount <code>/etc/letsencrypt</code> in 
the container, something like so:</p>

<div class="codehilite"><pre><span></span><code><span class="nn">...</span>

<span class="nt">volumes</span><span class="p">:</span>
    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">maildata:/var/mail</span>
    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">mailstate:/var/mail-state</span>
    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">./config/:/tmp/docker-mailserver/</span>
    <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">/etc/letsencrypt:/etc/letsencrypt</span>

<span class="nn">...</span>
</code></pre></div>

<p>With this done, you shouldn&#8217;t have mail clients complaining about 
wonky certs for which you&#8217;ll have to add an exception manually.</p>

<h3 id="why-would-you">Why would you…?</h3>

<p>There are a few good reasons for this:</p>

<h4 id="privacy">Privacy</h4>

<p>No really, this is <em>the</em> best choice for truly private
email. Not ProtonMail, not Tutanota. Sure, they claim so and I don&#8217;t 
dispute it. Quoting Drew Devault<sup class="footnote-ref" id="fnref-3"><a href="#fn-3">3</a></sup>,</p>

<blockquote>
  <p>Truly secure systems do not require you to trust the service provider.</p>
</blockquote>

<p>But you have to <em>trust</em> ProtonMail. They run open source software, but
how can you really be sure that it isn&#8217;t a backdoored version of it?</p>

<p>When you host your own mailserver, you truly own your email without having to rely on any
third-party.
This isn&#8217;t an attempt to spread FUD. In the end, it all depends on your
threat model™.</p>

<h4 id="decentralization">Decentralization</h4>

<p>Email today is basically run by Google. Gmail has over 1.2 <em>billion</em>
active users. That&#8217;s obscene.
Email was designed to be decentralized but big corps swooped in and
made it a product. They now control your data, and it isn&#8217;t unknown that
Google reads your mail. This again loops back to my previous point, privacy.
Decentralization guarantees privacy. When you control your mail, you subsequently
control who reads it.</p>

<h4 id="personalization">Personalization</h4>

<p>Can&#8217;t ignore this one. It&#8217;s cool to have a custom email address to flex.</p>

<p><code>x@icyphox.sh</code> vs <code>gabe.newell4321@gmail.com</code></p>

<p>Pfft, this is no competition.</p>

<div class="footnotes">
<hr />
<ol>
<li id="fn-1">
<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>
</li>

<li id="fn-2">
<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>
</li>

<li id="fn-3">
<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>
</li>
</ol>
</div>
 
    </div>
    <hr />
    <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>
    <footer>
      <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
        <img src="https://licensebuttons.net/l/by-nc-sa/4.0/80x15.png">
        </a>
    </footer>
  </body>
  </div>
 </html>