Let's Encrypt certificates - ghomem/legacy_puppet_infrastructure GitHub Wiki
Introduction
This article documents an example where Let's Encrypt certificates are automatically managed via Puppet. This requires automatic management of DNS records for proof of domain ownership. Currently two providers are supported: Digital Ocean and Hetzner.
Module installation
In case you didn't install the puppet-letsencrypt
module in the Puppet master installation, you can just install it with:
sudo /opt/puppetlabs/bin/puppet module install puppet-letsencrypt --version 9.2.0
Puppet node configuration
In order to install the Letsencrypt client on the Puppet node we need to declare the following Puppet resources:
- The Letsencrypt client
- The Puppet class that holds all of the SSL certificate declarations
Following is a Puppet declaration example:
node 'puppet' {
# The actual DO API token to be written to the file above
$dns_api_token = lookup('puppet::letsencrypt_token')
( . . . )
# this installs the Letsencrypt client and required dependencies
class { 'puppet_infrastructure::letsencrypt_base':
email => '[email protected]',
dns_api_token => $dns_api_token,
domains => ['solidangle.eu'],
renew_cron_monthday => [5,10,15,20,25],
provider => "your_provider", # We currently support only digitalocean and hetzner
}
# this class will contain all the SSL certificate declarations
class { 'ssl_certificates':
provider => 'your_provider',
require => Class['puppet_infrastructure::letsencrypt_base'],
}
}
SSL Certificate creation
All the SSL certificates should be declared in the ssl_certificates
class.
The SSL certificate wrapper class has the following mandatory parameters:
domain
- the SSL certificate domainprovider
- the dns provider
The following parameters are optional:
certificate_path
- sets a different certificate path from the domain if necessary, useful for wildcard certificates so we don't get a*
in the file path.credentials_path
- sets a different path for the file that contains the API token. The default is at /opt/puppet-infrastructure/etc/dns-creds.ini
Following is an example ssl_certificates
declaration:
class ssl_certificates ( String $provider )
{
# creates a wildcard certificate for '*.solidangle.eu'
# in the following path: /etc/letsencrypt/live/star.solidangle.eu/
puppet_infrastructure::letsencrypt_certificate { 'star.solidangle.eu' :
domain => '*.solidangle.eu',
provider => $provider,
certificate_path => 'star.solidangle.eu',
include_root => true
}
# creates a certificate for 'domain.solidangle.eu'
# in the following path: /etc/letsencrypt/live/domain.solidangle.eu/
puppet_infrastructure::letsencrypt_certificate { 'domain.solidangle.eu':
domain => 'domain.solidangle.eu',
provider => $provider
}
}
After a certificate is created the certificate files must be copied over to the Puppet extra_files
directory in order to be available to the nodes. In order to perform this copy we need to execute the following script:
sudo /opt/puppet-infrastructure/bin/deploy_maintained_certificates.sh
Whenever the certificates are (see below) renewed a similar copy is performed automatically.
Certificate renewal
Automated procedure
The Let's Encrypt client is installed along with a cronjob that will attempt to renew all the Letsencrypt certificates every 5 days and will only renew the ones that need to be renewed. Another cronjob is in charge of copying the renewed certificated to the puppet extra_files
directory. Therefore, under normal conditions nothing needs to be done manually and as long as the DNS token remains valid the renewal + redeploy process will be performed automatically.
Manual procedure
In case we want to manually renew the certificates we can run: sudo certbot renew
To check the amount of time until the expiration of a certificate run: sudo certbot certificates --cert-name domain.solidangle.eu
Following is an example output:
$ sudo certbot certificates --cert-name domain.solidangle.eu
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following matching certs:
Certificate Name: domain.solidangle.eu
Domains:domain.solidangle.eu
Expiry Date: 2022-08-15 16:26:28+00:00 (VALID: 88 days)
Certificate Path: /etc/letsencrypt/live/domain.solidangle.eu/fullchain.pem
Private Key Path: /etc/letsencrypt/live/domain.solidangle.eu/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certificates are renewed 30 days prior to the expiration date of the certificate as commented here.
If a certificate is renewed execute the same script in the section above to move it to the Puppet extra_files
directory.
Certificate deletion
To remove certificates we can run the following command: sudo certbot delete
A prompt will appear listing all of the Letsencrypt certificates currently present on the server, from which we can choose to delete.
After deleting the certificates with sudo certbot delete
we must manually remove the directory where the certificates reside so that we get no facter errors when running the Puppet agent. We can execute the following script to do so:
CERT_PATH=domain.solidangle.eu
sudo rm -r /etc/letsencrypt/live/$CERT_PATH
Use with Nginx related classes
For Let's Encrypt cerificates to be used with the nginx_frontend
and nginx_static
classes, the letsencrypt_certificate
boolean needs to be made true
in the class declaration. The same applies do the hasman_web
class which includes the nginx_frontend
class:
class { 'puppet_infrastructure::hashman_web' : letsencrypt_certificate => true }