Dehydrated: a bash client for Let’s Encrypt

Dehydrated was firstly known as but because letsencrypt is a trademark, they decided to rename the project, but keep the excellent features.


If you’re already familiar with let’s encrypt and the ACME protocol, you can go directly to the next section on how to use Dehydrated.

Let’s encrypt give you the possibility to automatize the creation and renewal of SSL certificate. Those certificates and keys can be used for anything that uses SSL protocol like to activate https on your website, TLS on your SMTP/IMAP server, etc … everywhere you can use an SSL cert; you can use let’s encrypt.

Let’s Encrypt is an authorised CA which mean all the certificate generated by it are considered verified and will be recognised as it by the different clients (browser, email client, etc …). This is one of the biggest advantages against self-signed certificates, and your users won’t have to bypass a security warning or add a security exception.

Not only the generated certificate are valid, but let’s encrypt is an entirely automatize protocol, there is no need of human interaction to create and renew a certificate, all you need is a client compatible with the ACME protocol, and that were Dehydrated enter.



Either you take one of the release packages, or you clone the repository. I advise creating a symlink after to /usr/local/sbin/dehydrated it’s easier like this for setting the cronjob after. You also need to have the OpenSSL package installed for dehydrated to work. You also need a web server, Apache or Nginx will do fine.

GitHub Reposidget for WordPress

lukas2511 / dehydrated

letsencrypt/acme client implemented as a shell-script – just add water


First, create a configuration folder only accessible by root: /etc/dehydrated/ You also need to create /var/www/dehydrated that will contain the challenge files for website verification.

Conf File

Now create a configuration file named config using their template:

Configuration File
In the configuration file, you need absolutely to set the CONTACT_EMAIL to an email address you own. You should also set the HOOK  variable to HOOK=/etc/dehydrated/ We’ll create the script just after; this hook script is called at each step of the certificate renewal/creation process.

Hook file

Now let’s create the I’m providing you with my hook file based on their template.  The idea is to reload your webserver when a new certificate gets deployed, in my case it’s Nginx, if you use any other one, replace Nginx by yours. I also added a line for my Dovecot and Postfix server only to restart when their certificate is generated. Fell free to use this file and modify it for your needs.

Hook File

Domain file

Now in the same directory, create a domains.txt file containing the list of domains you want a certificate for. You need to have already a web server setup with those domains.

You can set multiple domains on the same line; they will be then put on the same certificate. I advise you to use this to keep subdomain and domain together.

Domains.txt Example



With http-01-type verification (default in this script, there is also support for DNS-based verification) Let’s Encrypt (or the ACME-protocol in general) is checking if you are in control of a domain by accessing a verification file on a URL similar to
It will do that for any (sub-)domain you want to sign a certificate for.

At the moment you’ll need to have that location available over standard HTTP on port 80 (redirect to HTTPS will work, but the starting point is always HTTP!).

Dehydrated has a config variable called WELLKNOWNwhich corresponds to the directory which should be served under /.well-known/acme-challenge on your domain. So in the above example, the token would have been saved as $WELLKNOWN/m4g1C-t0k3n.

If you only have one docroot on your server, you could easily do something like WELLKNOWN=/var/www/.well-known/acme-challenge for anything else look at the example below.

Example Usage

If you have more than one docroot (or you are using your server as a reverse proxy/load balancer), the simple configuration mentioned above won’t work, but with just a few lines of web server configuration, this can be solved.

An example would be to create a directory /var/www/dehydrated and set WELLKNOWN=/var/www/dehydrated in the scripts config.

You’ll need to configure aliases on your Webserver:

Nginx example config

With Nginx you’ll need to add this to any of your server/VHost config blocks:

server {
  location /.well-known/acme-challenge {
    alias /var/www/dehydrated;

Apache example config

With Apache just add this to your config and it should work in any VHost:

Alias /.well-known/acme-challenge /var/www/dehydrated

<Directory /var/www/dehydrated>
        Options None
        AllowOverride None

        # Apache 2.x
        <IfModule !mod_authz_core.c>
                Order allow,deny
                Allow from all

        # Apache 2.4
        <IfModule mod_authz_core.c>
                Require all granted

 Lighttpd example config

With Lighttpd just add this to your config, and it should work in any VHost:

modules += "alias"

alias.url += (
 "/.well-known/acme-challenge/" => "/var/www/dehydrated/"

DNS Server

Dehydrated can also configure for you (using the hooks) the DNS records of your domain to use the dns-01 type verification.


I’ve covered in another blog post the DNS-01 validation in great details.

dns-01 challenge

This script also supports the new dns-01-type verification. This type of verification requires you to be able to create a specific TXT DNS record for each hostname included in the certificate.

You need a hook script that deploys the challenge to your DNS server!

The hook script (indicated in the config file or the –hook/-k command line argument) gets four arguments: an operation name (clean_challenge, deploy_challenge, or deploy_cert) and some operands for that. For deploy_challenge $2 is the domain name for which the certificate is required, $3 is a “challenge token” (which is not needed for dns-01), and $4 is a token which needs to be inserted in a TXT record for the domain.

Typically, you will need to split the subdomain name in two, the subdomain name and the domain name separately. For example, for “”, you’ll need “my” and “” separately. You then have to prefix “_acme-challenge.” before the subdomain name, as in “” and set a TXT record for that on the domain (e.g. “”) which has the value supplied in $4

_acme-challenge IN TXT $4 IN TXT $4

That could be done manually (as most providers don’t have a DNS API), by having your hook script echo $1, $2 and $4 and then wait (read -s -r -e < /dev/tty) – give it a little time to get into their DNS system. Usually, providers give you a box to put “” and the token value in, and a dropdown to choose the record type, TXT.

Or when you do have a DNS API, pass the details accordingly to achieve the same thing.

You can delete the TXT record when called with operation clean_challenge, when $2 is also the domain name.

Here are some examples: Examples for DNS-01 hooks

First Run

Now that you have configured everything, that you have a set your web server (and restarted/reloaded it after the configuration changes). You’re set to run the command for the first time; it will create your account, generate your private key and create all the certificate your needs with their keys.

dehydrated -f -c /etc/dehydrated/config


Now you should find a folder /etc/dehydrated/certs/ with a folder for each of your domain set in your domains.txt file.

In each of those folders, you’ll find two important symbolic links that you need to use in all your application that rely on that certificate-key pair.

  1. fullchain.pem :  /etc/dehydrated/certs/
  2. privkey.pem :  /etc/dehydrated/certs/

The first one is your certificate will the different root certificates prepended to it, in other words, the one you need to set for your service. The second one is the private key of the certificate.


Using your favourite cron editor, add a new cron to be run every week. By default dehydrated will renew the certificates 30 days before their expiration, you can change that in the configuration if you want, keep in mind a let’s encrypt cert has an expiration of 3 months. This cron run it every Sunday at 2:05 AM.

5 2 * * 6 /usr/local/sbin/dehydrated -c -f /etc/dehydrated/config

More info

GitHub Reposidget for WordPress

lukas2511 / dehydrated

letsencrypt/acme client implemented as a shell-script – just add water


Antoine Aflalo Written by:

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *