Let’s Encrypt on …. any Linux distro!
February 13, 2016

Let’s Encrypt on …. any Linux distro!

Posted on February 13, 2016  •  4 minutes  • 849 words  •  Suggest Changes

If you did not know yet, I’m a huge fan of Let’s Encrypt, however, we need to give them some slack, they only publicly announced 1 year, 2 months, 26 days, 18 hours and 13 minutes ago.  In that time they created the entire backbone, code and structure to start giving out validated certificates, for free.  They currently have a beta sticker on still, and I do agree, there github account is still very active with over 150 contributors pitching in.  The official client however has many dependencies, that many in fact that Centos 6 has only recently been supported. But what about Centos 5 ? or older Ubuntu LTS ? or any other Linux Distro ? What about when my apps are using a not supported python ?  Well that is where the Linux community shines most, someone thinks I can do this different and so Lukas Schauer (personal website) created a super tiny (821 lines) low-requirement shell script called dehydrated.  I still have little experience when it comes to certificates and https in general, but getting you’re visitors a encrypted line to visit is now easier then ever !


Most Linux distro’s will have this already installed, so this should not make a problem. I’m using a Centos 32bit VPS for this example, but this should be doable for pretty much any Linux distro.

yum install nano wget curl sed grep mktemp git

That’s it, for me only nano and _wget _had to be installed on a Centos minimal! (note : nano or …)


Its a bash script! Either download and chmod or download the entire package using git.

cd /opt
git clone
cd dehydrated/


You could run everything from console, but for automation it might be a good idea to configure it in a script itself. For that purpose it uses a file named There is also a file domains.txt for the domain names. I copied the example :

cp docs/examples/config
ln -s config

In remove the # (hashtag) from all value’s, the defaults should work well. The only exceptions are :


and (change the e-mail address in to a working one!)

CONTACT_EMAIL="[email protected]"

Now we need to create a file /opt/dehydrated/domains.txt there you need to add domain names you wanne get a certificate for. I tested it with one subdomain :

and that worked, however if you want multiple use :

Would validate, and in one certificate, as alternatives. You can also read up on the github , That’s it for configuration!

Setting up the environment

For this server I am using Apache, you will have to find how to get this working with others webservers. First make the directory (WELLKNOWN) we have used in the configuration :

mkdir /var/www/dehydrated/

warning : using /home as WELLKNOWN might give problems on a default Apache installation. (you would need mod_userdir) On a clean install this was the config I used, most likely parts will already be there: (read comments)

# allow multiple hosts on 1 IP
NameVirtualHost *:80

<VirtualHost *:80>
# documentroot
DocumentRoot /var/www/html

# servername
# vital :
Alias /.well-known/acme-challenge /var/www/dehydrated/

# this might not be needed
<Directory "/var/www/dehydrated/">
   Header add Content-Type text/plain


Restart apache with service httpd restart , and then go ahead and create you’re certificate!


Now getting to the easy part, getting the certificate :

./dehydrated -c

This should result in something as :

This will generate :

├── certs
│   └── domain.tld
│       ├── cert.csr
│       ├── cert.pem
│       ├── fullchain.pem
│       └── privkey.pem
├── domains.txt
├── dehydrated
├── private_key.pem

From there you could just use this tutorial for adding it to apache.


During the testing I made some errors, you might encounter them as well.

Challenge invalid

ERROR: Challenge is invalid! (returned: invalid) (result: {"type":"http-01","status":"invalid","error":{"type":"urn:acme:error:unauthorized","detail":"Invalid response from http://domain.tld/.well-known/acme-challenge/[]: 500"},"uri":"","token":"","keyAuthorization":".-","validationRecord":[{"url":"http://domain.tld/.well-known/acme-challenge/","hostname":"domain.tld","port":"80","addressesResolved":[""],"addressUsed":""}]})

This happened for me when the directory was not accessible. Settings where wrong, be sure to test it with creating test files  (touch /my/.well-known/test.html) and then hitting them on the webserver.

Challenge invalid

./dehydrated --cron
# INFO: Using main config file /opt/dehydrated/
Processing domain.tld
 + Signing domains...
 + Creating new directory /opt/dehydrated/certs/domain.tld ...
 + Generating private key...
 + Generating signing request...
 + Requesting challenge for domain.tld...
  + ERROR: An error occurred while sending post-request to (Status 403)

{"type":"urn:acme:error:unauthorized","detail":"No registration exists matching provided key","status":403}

This weird one happened when 1) I did not enter a valid e-mail address and 2) an e-mail adres that was used by another domain.


While the official method surely should be default, due to the way ACME is setup, Let’s Encrypt allows for other clients, one of these is a very simple shell script, and that works in even the most variable environments.  A big thanks to lukas2511 and Let’s Encrypt for making this possible! Happy Encrypting ! Changes :


If you enjoyed this website, consider buying me a Dr. Pepper

Buy me a Dr PepperBuy me a Dr Pepper