Puppet module for centralized CSR signing using Let’s Encrypt™ and lukas2511/dehydrated - keeping your keys safe on the host they belong to.
Switch branches/tags
Clone or download
Pull request Compare This branch is 1 commit behind bzed:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.



Puppet Forge Build Status

Centralized CSR signing using Let’s Encrypt™ - keeping your keys safe on the host they belong to.

Table of Contents

  1. Description
  2. Setup - The basics of getting started with dehydrated
  3. Usage - Configuration options and additional functionality
  4. Migrating from bzed-letsencrypt
  5. Limitations - OS compatibility, etc.
  6. Development - Guide for contributing to the module


bzed-dehydrated creates private keys and CSRs, transfers the CSR to a central host (for example your puppetmaster) where it is signed using the well known dehydrated https://github.com/lukas2511/dehydrated

Signed certificates are shipped back to the requesting host.

You need to provide an appropriate hook script for dehydrated. The default is to use the DNS-01 challenge, but if your hook supports it you could also create the necessary files for http-01.

Let’s Encrypt is a trademark of the Internet Security Research Group. All rights reserved.

Deprecation of bzed-letsencrypt

With the release of bzed-dehydrated my old module bzed-letsencrypt will be depricated. Renaming the module to avoid trademark related troubles is one of the reasons for a new module, the other is that I did not want to break the API for all users of the old module. If there is enough interest I'll change bzed-letsencrypt to become a wrapper around the new module, but with all the new features and options I don't think that makes much sense. So I'm sorry for the extra trouble of migrating an existing installation (to make it easier, see below), but I hope that the extra amount of flexibility and less hacks in the code make it worth to migrate.


What dehydrated affects

dehydrated needs to use facter to retrieve the signed certificates and other data from your central signing hosts if you are not using a puppet master host to handle it. Although only certificates which need to be renewed are transferred, it is unknown how well this approach scales if you plan to request lots of certificates. Using a (designated) puppet master is the better option.

Setup Requirements

You need to ensure that exported ressources are working and pluginsync is enabled.

Beginning with dehydrated

Basic things you need:

  • a host with internet access, preferable a puppet master. This will be known as dehydrated_host now.
  • a working hook script for dehydrated, for exampes and documentation see lukas2511/dehydrated
  • bzed-dehydrated installed as dehydrated module in your Puppet environment. You will also need recent versions of puppetlabs-stdlib, puppetlabs-concat, puppetlabs-vcsrepo. For puppet >= 6.0 you'll also need puppetlabs-cron_core.
  • I'd assume at least puppet version 4.8. Not tested or developed for older version.
  • Working exportable ressources. Make sure your puppetdb is working well, this module heavily depends on it.


This only describes the very basic usage. Almost all things are configurable, see the reference for details. So for a basic setup, the following steps should give you a running setup.

  1. Do a basic setup of your dehydrated_host:

        class { 'dehydrated' :
            dehydrated_host => 'your.dehydrated.host.example.com',
  2. As example we'll use the dehydrated hook for Cloudflare®. Take socram8888/dehydrated-hook-cloudflare and on your dehydrated_host install it into /opt/dehydrated/hooks.d/dns-01.sh

  3. Add the hook configuration to your config from above:

    class { 'dehydrated' :
        dehydrated_host => 'your.dehydrated.host.example.com',
        dehydrated_environment => {
            'CF_EMAIL' => 'your@email.address',
            'CF_KEY'   => 'your-long-Cloudflare-api-key',
  4. On the host that needs a new certificate, add this to your puppet code:

    class { 'dehydrated' :
        dehydrated_host => 'your.dehydrated.host.example.com',
        challengetype   => 'dns-01',
    ::dehydrated::certificate { 'my-https-host.example.com' :
        subject_alternative_names => [ 'example.com', 'host2.example.com' ],
  5. Wait.... it will take a few puppet runs until your certificate will appear. The certificates will be requestd by a cronjob, not directly from puppet. Otherwise puppet runs will take way too much time.

Using hiera

To use hiera, make sure you include your dehdrated class somewhere. As default configuration for all hosts setup the defaults, in this case we are using dehydrated in the way to be compatible to the old bzed-letsencrypt setup:

dehydrated::dehydrated_host: 'my.dehydrated.host'
dehydrated::base_dir: '/etc/letsencrypt'
dehydrated::group: 'letsencrypt'
dehydrated::letsencrypt_ca: 'v2-production'
dehydrated::challengetype: 'dns-01'
dehydrated::dehydrated_hook: 'tophosting_hook.py'
dehydrated::dehydrated_domain_validation_hook: 'domain_validation_hook.sh'

And to request certificates:

    - "*.subdomain.example.com"
    - "subdomain.example.com"
    - - "san.example.com"
      - [ "second_domain.san.example.com", "third_domain.san.example.com" ]

With the yaml snippet above you'd request the following certificates:

  • wildcard certificate *.subdomain.example.com
  • "normal" certificate subdomain.example.com
  • SAN certificate san.example.com with second_domain.san.example.com and third_domain.san.example.com as subject alternative names.

Monitoring & debugging

  • usual Puppet debugging rules apply >:-)

  • you'll find the output and errors from the last cronjob run in /opt/dehydrated/status.json. Unfortunately proper logging and maybe a better error handling is not implemented yet. Pull requests are welcome :-)

  • monitoring the cronjob results is possible by using check_statusfile. On Debian and derivates this is available in the nagios-plugins-contrib package. Or find the source here: check_statusfile

    # /usr/lib/nagios/plugins/check_statusfile /opt/dehydrated/monitoring.status
    dehydrated certificates: OK: 2, FAILED: 1
    foo.example.com (from bar.example.com): OCSP update failed

Migrating from bzed-letsencrypt

If you were using the bzed-letsencrypt module before, I'd suggest to use the following settings on the hosts that request certificates:

class { 'dehydrated' :
    group    => 'letsencrypt',
    base_dir => '/etc/letsencrypt',

Migrating the files on the dehydrated_host (former letsencrypt_host) is a harder task and not implemented. A new setup or manual migration is preferred.


An html version of the reference is available here: https://bzed.github.io/bzed-dehydrated/ There is also a markdown version in REFERENCE.md


The cron-triggered dehydrated worker creates a status file in a format compatible with check_statusfile, which is - in Debian and derivates - packaged in the nagios-plugins-contrib package. If you ar enot using Debian you can retrieve the source code here: check_statusfile


Don't forget that Let’s Encrypt limits apply! Also: this code might not work for your use-case out of the box, please test it properly against the Let’s Encrypt testing CA instead of running into the limit for failed authorizations and blaiming me for it ;)


Please use the github issue tracker and send pull requests. Make sure that your pull requests keep travis happy!

For a release:

  • Update gh_pages:

    bundle exec rake strings:gh_pages:update
  • Update REFERENCE.md:

    puppet strings generate --format markdown --out REFERENCE.md
  • Create changelog:

    bundle exec rake changelog
  • Release:

    pdk build
  • Bump version number: bump/change the version in metadata.json.