Let’s Encrypt on CentOS 7 and Amazon AMI

The last few weeks were super busy at work, so I accidentally let a few SSL certificates expire.  Renewing them is always annoying and time consuming, so I was pushing it until the last minute, and then some.

Instead of going the usual way for the renewal, I decided to try to the Let’s Encrypt deal.  (I’ve covered Let’s Encrypt before here and here.)  Basically, Let’s Encrypt is a new Certification Authority, created by Electronic Frontier Foundation (EFF), with the backing of Google, Cisco, Mozilla Foundation, and the like.  This new CA is issuing well recognized SSL certificates, for free.  Which is good.  But the best part is that they’ve setup the process to be as automated as possible.  All you need is to run a shell command to get the certificate and then another shell command in the crontab to renew the certificate automatically.  Certificates are only issued for 3 months, so you’d really want to have them automatically updated.

It took me longer than I expected to figure out how this whole thing works, but that’s because I’m not well versed in SSL, and because they have so many different options, suited for different web servers, and different sysadmin experience levels.

Eventually I made it work, and here is the complete process, so that I don’t have to figure it out again later.

We are running a mix of CentOS 7 and Amazon AMI servers, using both Nginx and Apache.   Here’s what I had to do.

First things first.  Install the Let’s Encrypt client software.  Supposedly there are several options, but I went for the official one.  Manual way:

# Install requirements
yum install git bc
cd /opt
git clone https://github.com/certbot/certbot letsencrypt

Alternatively, you can use geerlingguy’s lets-encrypt-role for Ansible.

Secondly, we need to get a new certificate.  As I said before, there are multiple options here.  I decided to use the certonly way, so that I have better control over where things go, and so that I would minimize the web server downtime.

There are a few things that you need to specify for the new SSL certificate.  These are:

  • The list of domains, which the certificate should cover.  I’ll use example.com and www.example.com here.
  • The path to the web folder of the site.  I’ll use /var/www/vhosts/example.com/
  • The email address, which Let’s Encrypt will use to contact you in case there is something urgent.  I’ll use [email protected] here.

Now, the command to get the SSL certificate is:

/opt/letsencrypt/certbot-auto certonly --webroot --email [email protected] --agree-tos -w /var/www/vhosts/example.com/ -d example.com -d www.example.com

When you run this for the first time, you’ll see that a bunch of additional RPM packages will be installed, for the virtual environment to be created and used.  On CentOS 7 this is sufficient.  On Amazon AMI, the command will run, install things, and will fail with something like this:

WARNING: Amazon Linux support is very experimental at present...
if you would like to work on improving it, please ensure you have backups
and then run this script again with the --debug flag!

This is useful, but insufficient.  Before you can run successfully, you’ll also need to do the following:

yum install python26-virtualenv

Once that is done, run the certbot command with the –debug parameter, like so:

/opt/letsencrypt/certbot-auto certonly --webroot --email [email protected] --agree-tos -w /var/www/vhosts/example.com/ -d example.com -d www.example.com --debug

This should produce a success message, with “Congratulations!” and all that.  The path to your certificate (somewhere in /etc/letsencrypt/live/example.com/) and its expiration date will be mentioned too.

If you didn’t get the success message, make sure that:

  • the domain, for which you are requesting a certificate, resolves back to the server, where you are running the certbot command.  Let’s Encrypt will try to access the site for verification purposes.
  • that public access is allowed to the /.well-known/ folder.  This is where Let’s Encrypt will store temporary verification files.  Note that the folder starts with dot, which in UNIX means hidden folder, which are often denied access to by many web server configurations.

Just drop a simple hello.txt to the /.well-known/ folder and see if you can access it with the browser.  If you can, then Let’s Encrypt shouldn’t have any issues getting you a certification.  If all else fails, RTFM.

Now that you have the certificate generated, you’ll need to add it to the web server’s virtual host configuration.  How exactly to do this varies from web server to web server, and even between the different versions of the same web server.

For Apache version >= 2.4.8 you’ll need to do the following:

SSLEngine on
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem

For Apache version < 2.4.8 you’ll need to do the following:

SSLEngine on
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem

For Nginx >= 1.3.7 you’ll need to do the following:

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

You’ll obviously need the additional SSL configuration options for protocols, ciphers and the like, which I won’t go into here, but here are a few useful links:

Once your SSL certificate is issued and web server is configured to use it, all you need is to add an entry to the crontab to renew the certificates which are expiring in 30 days or less.  You’ll only need a single entry for all your certificates on this machine.  Edit your /etc/crontab file and add the following (adjust for your web server software, obviously):

# Renew Let's Encrypt certificates at 6pm every Sunday
0 18 * * 0 root (/opt/letsencrypt/certbot-auto renew &amp;&amp; service httpd restart)

That’s about it.  Once all is up and running, verify and adjust your SSL configuration, using Qualys SSL Labs excellent tool.

On test strings

I’ve seen my fair share of test strings, varying from simple ‘test’, ‘foo’, and ‘blah’ to automatically re-generated Lorem Ipsum paragraphs.  But I don’t really remember seeing anything more weird than this one:

$string = "I am not a question. How was your day? Sex On Hard Concrete Always Hurts The Orgasmic Area. Why does custard taste so lumpy when you use breast milk?";

From this StackOverflow answer.  Is there a tool that does this?  I wouldn’t mind using it in my daily work.

How Voice Search Will Forever Change SEO

Search Engine Optimization is not one of my favorite subjects to talk about. But I think this article is worth the time.  It explains some of the challenges with voice search in very simple terms, and shows how voice search is growing and affecting the web.

Voice search is the fastest growing type of search, according to the keynote speech given by Behshad Behzadi at SMX West in March, Principal Engineer at Google Zurich. Already, 55% of teens and 41% of adults use voice search on a daily basis, and that number is only growing. The allure of voice chat is undeniable—it’s faster, it’s hands-free, it lets you multi-task, and (especially among millennials) it’s considered cool.

Voice chat is also becoming increasingly reliable as technology improves. In fact, two years ago word error rate was over 20%, but current speech recognition word error rate is as low as 8%—a huge leap in a short amount of time.

How would you write a C program to print 1 to 100 without loop, recursion and goto?

I came across this Quora question today – “How would you write a C program to print 1 to 100 without loop, recursion and goto?”  As always, there is a plethora of answers, of which I liked the following two.

Jonathan Day goes into how the specification can be misinterpreted in a variety of ways, and how garbage in (specification) means garbage out (implementation).  I like it so much, I’m going to quote the whole thing here, so that I can easily find it in the future:

{
  printf(“1 to 100\n”);
}

You actually want the numbers, not just that particular string? That’s the problem with poor specifications. Managers have no consideration for us poor programmers…

No loops of any kind, no recursion of any kind, no goto (or comefrom) of any kind… This is the opposite extreme, taking the question absolutely literally as it is given rather than as it might be intended. This would have to include loops, recursion and gotos in all libraries, external programs and even the kernel itself, if taken to this degree.

Which creates a problem. You have to treat all such things as black boxes. You do not know if the kernel parses system calls by looping through the operands. That would be a loop that any printing function must call. The question says nothing about YOU not using loops, it says no loops.

Again, this is why specifications must be exact in programming. Poor specifications will get you what you asked for, but not what you want, just as that code snippet above did. No, I don’t care what was in someone’s mind, nor does the computer. GIGO is the law to which all in IT must obey whether they like it or not. That is why you MUST say what you mean and mean what you say, in positives and negatives.

It’s also why a lot of highly autistic people are highly successful. Literalism is, very literally, in their genes.

Ok, let’s use a third possible interpretation, that you want the numbers 1 through to 100, without the code using loops, recursion or gotos, but where calls may.

Most of the other answers are very acceptable, although some were implicit loops rather than explicit loops. Again, are implicit loops allowed or not allowed, under the specification? The specification simply doesn’t provide enough information to say.

Nor does the specification say if I can use loops, recursion or gotos in generating the data, versus printing it. I could generate the string very easily, just malloc enough space, convert the number into text, then place the characters into the string, with a space or control-linefeed as separator. The print itself is then a single command. Nothing else is needed.

Nothing says if this is a permissible option or not, you have to interpret. And interpretation is not how you should ever program. GIGO.

By loops, I am interpreting this as meaning any sort of iterative process, regardless of formulation. That is the standard meaning. But it occurs to me that repeat/until (while) and until/repeat (do) loops aren’t always seen as loops as they’re conditional on an event. Well, in C, so is a for loop. In many languages, for is fixed-length and so is regarded as a different sort of beast.

Also, the “goto” should be regarded with suspicion. Some languages have deliberately replaced “goto” with “comefrom” to ensure that the language complies with the requirement of not having gotos. I don’t think many SE’s regard that as anything other than slightly snarky humour, but there is no indication in the question as to whether a comefrom command would be disallowed if someone could code it into a header file. This is why sane programmers would interpret the question as prohibiting any form of condition/jump operation, regardless of the nature of the condition or the jump.

This leaves grammars. If the sequence from 1 to 100 can be specified in a grammar, then an external library performs the loop and you can print the result. There’s still iteration, but it’s both implicit and indirect. (When abstraction and black-box design is used to hide things from a boss, it’s time to ask if the boss is suitable for you. These should only ever be used to clarify.)

Ok, nothing in the question specifies a sequence, only the presence of the numbers. Nor does anything specify that numbers can’t appear more than once. So if I use grammars to generate absolutely every permutation of the digits 0 to 9 and a space, then I am guaranteed every number from 0 to 100. There are other regexp functions that let us remove specific patterns, so if I remove all patterns in which one, two or three 0s have a space either side, I can eliminate 0. This just leaves 1 to 100, albeit with a great many single digit and double digit repeats. Repeats aren’t talked about and we’ve already screwed with the interpretation badly enough to make the question pointless, so we assume they’re allowed.

Questions of this kind are usually asked to analyze the methodology of thinking rather than the conclusion itself. They have to be, because the question means so many possible things that it is meaningless. The result you get is, thus, equally meaningless.

And then, this obvious Vim solution by Gilles Castel:

i#include <stdio.h><CR>int main(){<CR>
printf("%d ",1);<ESC>qq0yyp<C-A>q98@qoreturn 0;

Not only he provided the explanation of what’s going on, but also  an animated GIF of how it looks:

vim-macro

And, yes, I’m not really interested in the actual C solutions to this problem.

diff-so-fancy – the best-lookin’ diffs

Here is a cool tool to spice up your regular boring looking diffs – diff-so-fancy.  Don’t get spooked by the npm installation instructions – the meat of it is all in perl/shell and you can install it as any other ~/bin/ script.  Have a look at what you are missing:

diff-so-fancy