Simplify - Articles tagged with Let's EncryptPersonal website of Saša Jovanićhttps://www.simplify.ba/articles/tags/let-s-encrypt/2021-12-17T19:12:00+01:00Saša JovanićMoving from Let's Encrypt to Amazon Certificate Managerhttps://www.simplify.ba/articles/2019/11/17/moving-from-lets-encrypt-to-acm/2019-11-17T15:42:00+01:002019-11-17T16:52:06+01:00Saša Jovanić<p>After three and half years I decided to move from using Let's Encrypt to using <abbr title="Amazon Certificate Manager">ACM</abbr> to manage SSL certificate on this site. The reason is simple, I keep forgeting to renew my Let's Encrypt certificates after 2-3 monthes all the time. <abbr title="Amazon Certificate Manager">ACM</abbr> gives me certificate that is valid for a year and apperently they will automatically renew it.</p>
Let's Encrypt certificate renewal with Legohttps://www.simplify.ba/articles/2016/05/22/lets-encrypt-renewal-with-lego/2016-05-22T16:26:00+02:002019-11-17T16:52:37+01:00Saša Jovanić<p>Three months ago <a href="/articles/2016/02/23/lets-encrypt-second-try/">I created Let's Encrypt certificate using Lego</a>. Today was the time to renew it.</p>
<p><a href="https://github.com/xenolf/lego">Lego</a> is now even better than before. At the time of certificate creation, renew option was not working, but now is fully supported. This time I didn't build Lego from source, I just downloaded binary and replaced old one. Renewal is easy as creation:</p>
<pre class="highlight plaintext"><code>$ ./lego --email="[my e-mail]" --domains="simplify.ba" --domains="www.simplify.ba" --dns="route53" renew
</code></pre>
<p>Again, Lego did two <abbr title="Automatic Certificate Management Environment">ACME</abbr> challenges, for both domains and I got certificates for both domains in <code>.logo/certificates</code>and used <code>aws</code> <abbr title="Command line interface">cli</abbr> to install certificate on CloudFront CDN (this require <code>AWS_SECRET_ACCESS_KEY</code>, <code>AWS_ACCESS_KEY_ID</code> and <code>AWS_REGION</code> environment variables set):</p>
<pre class="highlight plaintext"><code>$ aws iam upload-server-certificate --server-certificate-name simplify.ba-ssl-20160522 --certificate-body file://simplify.ba.crt --private-key file://simplify.ba.key --path /cloudfront/prod/
</code></pre>
<p>After changing certificate for CloudFront distribution on <abbr title="Amazon Web Services">AWS</abbr> console and confirming that certificate work, I removed old one:</p>
<pre class="highlight plaintext"><code>$ aws iam delete-server-certificate --server-certificate-name simplify.ba-ssl
</code></pre>
<p>I'm definitively sticking with Lego for any work with Let's Encrypt certificates.</p>
Let's Encrypt - Second tryhttps://www.simplify.ba/articles/2016/02/23/lets-encrypt-second-try/2016-02-23T20:34:00+01:002016-02-25T14:11:10+01:00Saša Jovanić<p>Today I gave another go on Let's Encrypt. <a href="/articles/2016/02/22/lets-encrypt-s3-and-cloudfront/">Yesterday</a> I tried with official client and even I succeed, there was no feeling of any success. It had to be easier and faster.</p>
<p>After some research on alternative clients I came across <a href="https://github.com/xenolf/lego">lego</a>. It's written in <a href="https://golang.org/">GO programming language</a>, provides single binary file, have option to provide <abbr title="Automatic Certificate Management Environment">ACME</abbr> challenge using <abbr title="Domain Name System">DNS</abbr> and saves everything inside <code>.lego</code> directory in your working directory. You can download precompiled binaries on github, but at the time of writing those binaries ware too old and without <abbr title="Domain Name System">DNS</abbr> acme challenge support. So compilation from the source was needed. If you don't have go installed, download installer from <a href="https://golang.org/">official website</a>.</p>
<pre class="highlight plaintext"><code>$ export GOPATH=`pwd`
$ go get -u github.com/xenolf/lego
</code></pre>
<p>That will create <code>lego</code> executable inside <code>bin</code> directory. You can copy that file wherever you want to run it from.</p>
<p>Then I created <abbr title="Identity and Access Management">IAM</abbr> policy in <abbr title="Amazon Web Services">AWS</abbr> console, as explained on lego's github page. After that it was easy:</p>
<pre class="highlight plaintext"><code>$ ./lego --email="[my e-mail]" --domains="simplify.ba" --domains="www.simplify.ba" --dns="route53" run
</code></pre>
<p>In a few minutes I got <abbr title="Subject Alternative Name">SAN</abbr> certificate for both domains in <code>.logo/certificates</code>. Same as yesterday, from that directory I used <code>aws</code> <abbr title="Command line interface">cli</abbr> to install certificate on CloudFront <abbr title="Content Delivery Network">CDN</abbr>:</p>
<pre class="highlight plaintext"><code>$ aws iam upload-server-certificate --server-certificate-name simplify.ba-ssl --certificate-body file://simplify.ba.crt --private-key file://simplify.ba.key --path /cloudfront/prod/
</code></pre>
<p>After confirming that this work I removed old one:</p>
<pre class="highlight plaintext"><code>$ aws iam delete-server-certificate --server-certificate-name www.simplify.ba-ssl
</code></pre>
<p>Everything took about 20 minutes. After loosing several hours yesterday with "official" Let's Encrypt client, this was like a vacation! No need to create any files on <abbr title="Simple Storage Service">S3</abbr>, <code>lego</code> solved <abbr title="Domain Name System">DNS</abbr> <abbr title="Automatic Certificate Management Environment">ACME</abbr> challenge without any intervention on my side.</p>
Let's Encrypt, S3 and CloudFronthttps://www.simplify.ba/articles/2016/02/22/lets-encrypt-s3-and-cloudfront/2016-02-22T19:34:00+01:002016-03-07T17:10:27+01:00Saša Jovanić<p>My current wild-cart <abbr title="Secure Socket Layer">SSL</abbr> certificate will expire in a couple of days and I decide to try <a href="https://letsencrypt.org/">Let's Encrypt</a> beta and move this website to Amazon <abbr title="Simple Storage Service">S3</abbr> and CloudFront.</p>
<h2 id="old-situation">Old situation</h2>
<p>Until today, I hosted this website on DigitalOcean. Service that they provided was always great, but I don't use most of sub-domains configured on that server any more, this website is static HTML generated with <a href="https://middlemanapp.com/">Middleman</a> and I have no longer need for any Server-Side work. Basically, I now only need to host static files somewhere, but with secure connection. Apparently Google, values <abbr title="HTTP (Hypertext Transfer Protocol) Secure">HTTPS</abbr> sites more than standard <abbr title="Hypertext Transfer Protocol">HTTP</abbr> now and if you care about your page rank, you need to use secure connection.</p>
<h2 id="what-is-lets-encrypt">What is Let's Encrypt?</h2>
<p>According to their <a href="https://letsencrypt.org//about/">about page</a>: "Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit". You can get free <abbr title="Secure Socket Layer">SSL</abbr> certificate, valid for three months (they suggest renewal every 2 months), just by using command line utility (letsencrypt client) and easily setup certificate renewal. You'll also need to prove that domain is yours by solving <abbr title="Automatic Certificate Management Environment">ACME</abbr> challenge.</p>
<h2 id="enter-aws">Enter <abbr title="Amazon Web Services">AWS</abbr></h2>
<p>I'm big fan of <abbr title="Amazon Web Services">AWS</abbr>, with exception of how they (re)name things, but that is a story for another time I guess. Here is complete architecture of the site:</p>
<ul>
<li>Whole site is made of static files and only <abbr title="Hypertext Transfer Protocol">HTTP</abbr> method needed is GET, so <abbr title="Simple Storage Service">S3</abbr> is perfect for hosting.</li>
<li>Unfortunately, <abbr title="HTTP (Hypertext Transfer Protocol) Secure">HTTPS</abbr> is not supported on <abbr title="Simple Storage Service">S3</abbr>, but I can use CloudFront (read: Amazon <abbr title="Content Delivery Network">CDN</abbr>) with my own certificate.</li>
<li>I also decided to mode <abbr title="Domain Name System">DNS</abbr> from <a href="http://freedns.afraid.org">afraid.org</a> to Amazon Route 53, but after everything else work correctly.</li>
</ul>
<p>I will not go into details of creating everything on <abbr title="Amazon Web Services">AWS</abbr>, just list all steps involved:</p>
<ul>
<li>Create <abbr title="Simple Storage Service">S3</abbr> bucket.</li>
<li>Enable "Static web hosting" for that bucket and name 'index.html' as 'Index Document'.</li>
<li>Upload all files into bucket and make them public.</li>
<li>Create CloudFront distribution:
<ul>
<li>Point 'origin' field to your <abbr title="Simple Storage Service">S3</abbr> bucket.</li>
<li>Add your domain in 'CNAMEs' field.</li>
<li>Enable both <abbr title="Hypertext Transfer Protocol">HTTP</abbr> and <abbr title="HTTP (Hypertext Transfer Protocol) Secure">HTTPS</abbr>.</li>
</ul>
</li>
<li>Wait until distribution is created by <abbr title="Amazon Web Services">AWS</abbr>.</li>
<li>Check if everything works correctly using <abbr title="Universal Resource Locator">URL</abbr> for your distribution.</li>
<li>Point your domain to your CloudFront distribution. If you are on Amazon Route 53, just create alias. Otherwise, you can use <abbr title="Canonical Name record">CNAME</abbr>.</li>
</ul>
<h2 id="installing-lets-encrypt">Installing Let's Encrypt</h2>
<p>Normally, <code>letsencrypt</code> has to run on the server where <abbr title="Secure Socket Layer">SSL</abbr> certificate have to be installed. In this case is that CloudFront and only way to do that is to use <abbr title="Application programming interface">API</abbr>'s. There is already tool to do that, <a href="https://github.com/dlapiduz/letsencrypt-s3front">letsencrypt-s3front</a>. Both this tool and official Let's Encrypt library are written in Python programming language and installable with <code>pip</code>. If you are on <abbr title="GNU is Not Unix">GNU</abbr>/Linux, you probably have both Python and pip installed. On OS X, you will have Python, but without pip. I installed it with <code>sudo easy_install pip</code>.</p>
<p>I tried to fallow instruction on letsencrypt-s3front README, but did not manage to install it correctly. It appears that <code>pip</code> try to uninstall some Python libraries and even if you run <code>pip</code> with sudo it does not work on OS X. I should probably try to install <code>pyenv</code> (fork of <code>rbenv</code> for Python) and install local version of Python and try it that way. Unfortunately, my lack of any Python knowledge (one of the few programming languages I never touched in my life) prevented me to do that at this point. There is a chance that there is obvious solution if you know Python.</p>
<p>At the end, I was following instructions on 'letsencrypt' <a href="https://github.com/letsencrypt/letsencrypt">github page</a>:</p>
<pre class="highlight plaintext"><code>$ git clone https://github.com/letsencrypt/letsencrypt
$ cd letsencrypt
$ ./letsencrypt-auto
</code></pre>
<p><code>letsencrypt-auto</code> quit on me, telling me that OS X support is experimental and that I need to ran with <code>--debug</code> flag. <code>letsencrypt-auto</code> is a wrapper around <code>letsencrypt</code> command, that also checks for updates and. After running with <code>--debug</code>, <code>letsencrypt-auto</code> started to install some packages using 'homebrew'. I'm quiet sure that I had 'libxml' already installed ('nokogiri' ruby gem uses that), but I saw it between installed packages. After homebrew part, <code>letsencrypt-auto</code> failed big time trying to install yet another Python package using <code>pip</code>. Then I run same command with sudo and package got installed, but yet another error was generated (uninstall package thing again). After all that I was able to use <code>letsencrypt-auto</code> to generate <abbr title="Secure Socket Layer">SSL</abbr> certificate with following:</p>
<pre class="highlight plaintext"><code>$ sudo ./letsencrypt-auto certonly --debug -a manual -d www.simplify.ba
</code></pre>
<p><code>certonly</code> option will just generate SLL certificate. If I used <code>apache</code> option, Let's encrypt client will also try to install certificate in Apache web server. In my case, <code>certonly</code> is exactly what I need.</p>
<p>I had to do this three times. First time it failed because of domain validation. During the process, they ask you to place specific file (.well-knows/acme-challenge/(some-hash-as-file-name)) with another longer hash inside it. I forgot to change mime type of that file to 'text/plain'. Personally, I think that they need to add alternative to this file placement, for example adding TXT record into <abbr title="Domain Name System">DNS</abbr>. Maybe there is, with plug-ins.</p>
<p>Can't remember what was the problem second time, but after third try <abbr title="Secure Socket Layer">SSL</abbr> certificates are generated into <code>/etc/letsencrypt/live/www.simplify.ba/</code>. Let's Encrypt tries to use the best security standards, and makes directories with <abbr title="Secure Socket Layer">SSL</abbr> certificates available only to 'root' user. Another frustrating thing if you are on OS X (run <code>sudo su</code> to become 'root' user and get access to certificates).</p>
<h2 id="placing-ssl-certificate-into-cloudfront">Placing <abbr title="Secure Socket Layer">SSL</abbr> certificate into CloudFront</h2>
<p>The easiest way seem to be using <code>aws</code> utility. Another Python, install with <code>pip</code> thing… Run <code>sudo pip install awscli</code>. I got an error running that (another uninstall thing) but <code>aws</code> utility was installed.</p>
<p>I placed <abbr title="Secure Socket Layer">SSL</abbr> certificate in CloudFront with:</p>
<pre class="highlight plaintext"><code>$ aws iam upload-server-certificate --server-certificate-name www.simplify.ba-ssl --certificate-body file://cert1.pem --private-key file://privkey1.pem --certificate-chain file://chain1.pem --path /cloudfront/prod/
</code></pre>
<p>After that, <abbr title="Secure Socket Layer">SSL</abbr> certificate with name 'www.simplify.ba-ssl' appeared in CloudFront distribution settings and I was able to select it. Just don't forget to set <code>AWS_ACCESS_KEY_ID</code> and <code>AWS_SECRET_ACCESS_KEY</code> in your ENV.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This is most frustrating thing I did in a last few months. I know that Lets's Encrypt is still in beta and things will change with time and after other clients emerge, but right now it's barely working on OS X. It's clear that their focus now is on <abbr title="GNU is Not Unix">GNU</abbr>/Linux servers and that they expect that you run <code>letsencrypt</code> on same machine where <abbr title="Secure Socket Layer">SSL</abbr> certificate needs to be installed. I think that if I had any Python knowledge things would go faster.</p>
<p>I'm going to investigate better ways to do this (using <code>pyenv</code>, run on <abbr title="GNU is Not Unix">GNU</abbr>/Linux or on a small Vegrant vm or even better option, to try <a href="https://community.letsencrypt.org/t/list-of-client-implementations/2103">alternative client</a>) and most importantly find a way to automatically renew certificate every two or three months. Apparently, you can use <abbr title="Amazon Web Services">AWS</abbr> Lambda to do that, so I'll maybe give it a try soon.</p>
<p><strong>UPDATE: 2016-02-23:</strong> Found <a href="/articles/2016/02/23/lets-encrypt-second-try/">a much better solution</a>.</p>