Confconsole - Let's Encrypt


Confconsole Let's Encrypt plugin provides a simple way to get free legitimate SSL certs via Let's Encrypt. It uses a custom mini webserver to host the challenges required by Let's Encrypt (to prove your ownership of the domain name). That means that the same tool will work with any webserver included with any TurnKey appliance, regardless of webserver configuration.

Confconsole - Let's Encrypt

Currently support webservers are:

  • Apache
  • LigHTTPd
  • Nginx
  • Tomcat7/Tomcat8

Cert auto renew

Selecting this option makes the default SSL certificate renewal cron job (/etc/cron.daily/confconsole-dehydrated) executable (or not). Only executable files within /etc/cron.daily are triggered automatically by cron.

Note: Until you get your initial certificate (which also configures dehydarated), the cron job doesn't exist in the cron.daily directory. This ensures that the cron job can't be enabled until the dehydrated-wrapper has been run (and hopefully a Let's Encrypt SSL cert has been generated).

For more info about what the cron job actually does, please see Cron job details below.

Get certificate

Selecting this option will allow you to set a single fully qualified domain name (FQDN) for you server.

You may optionally set a root domain and up to 4 separate subdomains.

If you wish to set more than one root domain and/or more than 4 subdomains, manual configuration is required. Please see Advanced - usage with multiple domain names below.

Note: Please ensure that you have your Domain nameservers correctly configured prior to running this. Failure to do so will cause the Let's Encrypt challenges to fail (so you won't get a certificate). Repeated failures may cause your server to be blocked (for a week) from further attempts.

Getting a certificate - Behind the scenes

The process goes like this:

  • Confconsole Let's Encrypt plugin writes the domain (and subdomains) to /etc/dehydrated/
  • Confconsole calls dehydrated-wrapper
  • dehydrated-wrapper stops webserver listening on port 80
  • dehydrated-wrapper checks for /etc/dehydrated/confconsole.config (config file); if it doesn't exist, it copies it the default file from: /usr/share/confconsole/letsencrypt/dehydrated-confconsole.config
  • dehydrated-wrapper checks for /etc/dehydrated/ (hook script); if it doesn't exist, it copies it the default file from: /usr/share/confconsole/letsencrypt/
  • dehydrated-wrapper checks for /etc/cron.daily/confconsole-dehydrated (cron script); if it doesn't exist, it copies it the default file from: /usr/share/confconsole/letsencrypt/dehydrated-confconsole.cron
  • dehydrated-wrapper calls dehydrated, passing confconsole.config, & (all stored within /etc/dehydrated/)
  • dehydrated contacts Let's Encrypt and gets the challenge (to prove you control the domain)
  • Whilst hosting the challenge, add-water temporarily redirects all web traffic except for the challenge (i.e. 304 - temporarily moved) to the web root. A simple "Under Maintence" message is displayed. To provide a custom html page, please see Advanced - custom maintence message below.
  • via the hook script, dehydrated serves Let's Encrypt challenges using add-water server (minimalist python webserver)
  • when done, add-water is killed (via hook script)
  • dehydrated writes certificate to /etc/ssl/private/cert.pem (via hook script); original certs generated by dehydrated remain in /var/lib/dehydrated/certs/DOMAIN
  • dehydrated hands back to dehydrated-wrapper
  • dehydrated-wrapper restarts webserver
  • dehydrated-wrapper restarts stunnel (so Webmin & Webshell also use new cert)
  • dehydrated-wrapper hands back to confconsole

Cron job details

The cron job checks the expiry date of the default certificate (/etc/ssl/private/cert.pem) and if it will expire within 30 days or less, it runs dehydrated-wrapper (using the --force switch).

Advanced - custom maintence message

As noted, whilst it is serving the challenges, add-water will redirect all other urls to the web root. By default it will display a simple "Maintenance" message via a basic index.html file.

If you wish to display a custom message, then you can add a custom index.html file to /var/lib/confconsole/letsencrypt/. E.g. to copy across the default and then tweak it:

mkdir -p /var/lib/confconsole/letsencrypt/
cp /usr/share/confconsole/letsencrypt/index.html \

add-water will serve /var/lib/confconsole/letsencrypt/index.html if it exists, or otherwise will fall back to the default.

Note: The custom file must be named index.html and contain only valid HTML (and CSS). PHP or other server side languages are not supported. Embedded (i.e. "inline") JavaScript is also supported as that is processed client side.

Advanced - usage with multiple domain names

The interactive Confconsole plugin only supports a single domain with up to 4 subdomains. However, the dehydrated-wrapper can handle multiple root domains, plus multiple subdomains. To support that you will need to manually make configuration adjustments in a number of places:

  • add additional domains to /etc/dehydrated/
    • ensure that each line starts with the base domain, followed by a space separated list of any subdomains.
    • WARNING: If you re-run confconsole's Let's Encrypt plugin, your custom additional domains will be removed!
  • adjust your webserver virtual hosts to use the relevant certificates in /var/lib/dehydrated/certs/DOMAIN. Each domain will have it's own subdirectory under /var/lib/dehydrated/certs/.
  • By default, the last domain (and any subdomains) configured, will be the one which will work for Webmin & Webshell (and Adminer, if it's included). To change this behaviour, you can adjust the hook script, or simply rearange the order of your domains and put the one you want Webmin & Webshell available from, last.
  • Note: the cron job only checks the expiry of /etc/ssl/private/cert.pem. So if you adjust the hook script to no longer update /etc/ssl/private/cert.pem, you will also need to adjust the cron job to check the expiry of a certificate you are updating. Failure to do so will result in daily certificate updates, which may get your server temporarily blocked from accessing the Let's Encrypt servers.


Andi Northrop's picture

OK, I may be missing something obvious but I can't see what I should be doing after the first bullet point to make dehydrated pick up the additional domains and run the wrapper to get certificates for those new domains?

Will it just pick up the changes when the daily cron runs or do I need to invoke it myself somehow?

Cheers for any help!

Bill Carney's picture

Andi, did you ever figure out how to get the system to pick up the additional domains? My system retrieves the certs only for the first domain listed, and none of the others.

Jeremy Davis's picture

Hi Bill

Andi also posted in the forums. I probably should have noted the forum thread in response to Andi's question here (I missed this post at the time).

Hopefully that resolves your questions too Bill?! If you need more clarification or it's directly relevant, perhaps post on his thread. If it's not directly relevant to that thread, please open a new thread (perhaps link to Andi's in your new thread to as I'm sure it'll be at least vaguely relevant).

Dilshan Dissanayake's picture

Its fantastic that TKL now supports the offline Let's Encrypt Plugin. I wanted to know if the plugin can accommodate servers which are not exposed to the internet? Lets Encrypt supports this using different options for challenges such as DNS (txt) records. I was wandering on setting up the same or the possibility of doing this through TKL? I do have access to my public DNS records so I can setup the same but need to know how to configure the TKL Appliance. Im running your LAMP stack to host an intranet and would very like it to be SSL enabled but inadvertently, I don't want to expose the intranet to the internet to obtain the initial certificate and then every time I need to renew the same! I'm also using the Redmine stack as well and would like the same for that as well.   Please TKL guru's, provide me some insight!
Jeremy Davis's picture

It looks like your post got picked up by the spam filter and I completely missed it. Sorry about that...

Unfortunately, Confconsole doesn't currently support certificates where the server isn't publicly available. It'd be nice to do, but we currently leverage the Debian package of Dehydrated, which is a older version, 0.3.1.

I note that newer versions of Dehydrated now supports dns01 challenges. And it appears that this newer version of Dehydrated is packaged as a Debian backport.

So it should be possible to update to the backported version and then use the dns01 challenge to get a certificate. However, the Confconsole plugin was never designed to be used in that way, so you'd need to leverage Dehydrated directly.

Obviously there are other Let's Encrypt client options, but personally, I quite like Dehydrated...

Bill Carney's picture

By default, the last domain (and any subdomains) configured, will be the one which will work for Webmin & Webshell (and Adminer, if it's included). To change this behaviour, you can adjust the hook script, or simply rearange the order of your domains and put the one you want Webmin & Webshell available from, last.

Following these directions, I've kept my domains for Webmin and Webshell as the very last line in the config file.  However, every time I add a new line (at the top) for another website I'm hosting, I get certificate errors because Webmin and Webshell start using the most recently created cert.  It's not a problem for me as I'm a one-person shop and I recognize that I've just added a new certificate, but this may be an issue for others.

Bill Carney's picture

My management cert (was) a subdomain, and I had the top domain and subdomains as the last line.  When I moved the management subdomain to the last line, by itself, the issue appears to go away.


now it's:

Jeremy Davis's picture

And thanks tons for posting back with your info.

FWIW I need to update these docs for v15.0 as the Let's Encrypt Confconsole plugin actually works slightly differently in v15.0 (Confconsole 1.1.0+). IIRC the source of the docs (on GH) should be up to date.