Version information
This version is compatible with:
- Puppet Enterprise 2023.8.x, 2023.7.x, 2023.6.x, 2023.5.x, 2023.4.x, 2023.3.x, 2023.2.x, 2023.1.x, 2023.0.x, 2021.7.x, 2021.6.x, 2021.5.x, 2021.4.x, 2021.3.x, 2021.2.x, 2021.1.x, 2021.0.x
- Puppet >= 7.0.0 < 9.0.0
- , , , , , , , ,
Start using this module
Add this module to your Puppetfile:
mod 'puppet-letsencrypt', '11.1.0'
Learn more about managing modules with a PuppetfileDocumentation
Let's Encrypt
This module installs the Let's Encrypt client (certbot) and allows you to request certificates.
Support
This module is currently only written to work on Debian and RedHat based operating systems, although it may work on others. The supported Puppet versions are defined in the metadata.json
Dependencies
On EL (Red Hat, CentOS etc.) systems, the EPEL repository needs to be enabled for the Let's Encrypt client package.
The module can integrate with puppet/epel
to set up the repo by setting the configure_epel
parameter to true
(the default for RedHat) and
installing the module.
Usage
Setting up the Let's Encrypt client
To install the Let's Encrypt client with the default configuration settings you must provide your email address to register with the Let's Encrypt servers:
class { 'letsencrypt':
email => 'foo@example.com',
}
You can enforce upgrade of package to the latest available version (in your repositories):
class { 'letsencrypt':
email => 'foo@example.com',
package_ensure => 'latest',
}
If using EL7 without EPEL-preconfigured, add configure_epel
:
class { 'letsencrypt':
configure_epel => true,
email => 'foo@example.com',
}
(If you manage epel some other way, disable it with configure_epel => false
.)
This will install the Let's Encrypt client and its dependencies, agree to the Terms of Service, initialize the client, and install a configuration file for the client.
Alternatively, you can specify your email address in the $config hash:
class { 'letsencrypt':
config => {
email => 'foo@example.com',
server => 'https://acme-v01.api.letsencrypt.org/directory',
}
}
During testing, you probably want to direct to the staging server instead with
server => 'https://acme-staging-v02.api.letsencrypt.org/directory'
If you don't wish to provide your email address, you can set the
unsafe_registration
parameter to true
(this is not recommended):
class { 'letsencrypt':
unsafe_registration => true,
}
To request a wildcard certificate, you must use the ACME v2 endpoint and use a DNS-01 challenge. See https://community.letsencrypt.org/t/acme-v2-production-environment-wildcards/55578
class { 'letsencrypt':
config => {
email => 'foo@example.com',
server => 'https://acme-v02.api.letsencrypt.org/directory',
}
}
Issuing certificates
Create letsencrypt::certonly
defines. See the letsencrypt::certonly
examples in the REFERENCE.md for more details.
Renewing certificates
There are two ways to automatically renew certificates with cron using this module.
cron using certbot renew
All installed certificates will be renewed using certbot renew
using their
original settings, including any not managed by Puppet.
renew_cron_ensure
manages the cron resource. Set topresent
to enable. Default:absent
renew_cron_minute
sets minute(s) to run the cron job. Default: Seeded random minuterenew_cron_hour
sets hour(s) to run the cron job. Default: Seeded random hourrenew_cron_monthday
sets month day(s) to run the cron job. Default: Every day
class { 'letsencrypt':
config => {
email => 'foo@example.com',
server => 'https://acme-v01.api.letsencrypt.org/directory',
},
renew_cron_ensure => 'present',
}
With Hiera, at 6 AM (roughly) every other day:
---
letsencrypt::renew_cron_ensure: 'present'
letsencrypt::renew_cron_minute: 0
letsencrypt::renew_cron_hour: 6
letsencrypt::renew_cron_monthday: '1-31/2'
cron using certbot certonly
Only specific certificates will be renewed using certbot certonly
.
manage_cron
can be used to automatically renew the certificatecron_success_command
can be used to run a shell command on a successful renewalcron_before_command
can be used to run a shell command before a renewalcron_monthday
can be used to specify one or multiple days of the month to run the cron job (defaults to every day)cron_hour
can be used to specify hour(s) to run the cron job (defaults to a seeded random hour)cron_minute
can be used to specify minute(s) to run the cron job (defaults to a seeded random minute)cron_output
can be used to disable output (and resulting emails) generated by the cron command
letsencrypt::certonly { 'foo':
domains => ['foo.example.com', 'bar.example.com'],
manage_cron => true,
cron_hour => [0,12],
cron_minute => '30',
cron_before_command => 'service nginx stop',
cron_success_command => '/bin/systemctl reload nginx.service',
cron_output => 'suppress',
}
Deprovisioning
If a domain needs to be removed for any reason this can be done by setting
ensure
to 'absent', this will remove the certificates for this domain from
the server. If manage_cron
is set to true, the certificate renewal cronjob
and shell scripts for the domain will also be removed.
letsencrypt::certonly { 'foo':
ensure => 'absent',
domains => ['foo.example.com', 'bar.example.com'],
manage_cron => true,
}
Hooks
Certbot supports hooks since certbot v0.5.0, however this module uses the newer
--deploy-hook
replacing the deprecated --renew-hook
. Because of this the
minimum version you will need to manage hooks with this module is v0.17.0.
All hook command parameters support both string and array.
Note on certbot hook behavior: Hooks created by letsencrypt::certonly
will be
configured in the renewal config file of the certificate by certbot (stored in
CONFIGDIR/renewal/), which means all hooks created this way are used when running
certbot renew
without hook arguments. This allows you to easily create individual
hooks for each certificate with just one cron job for renewal. HOWEVER, when running
certbot renew
with any of the hook arguments (setting any of the
`letsencrypt::renew*_hook_commandsparameters), hooks of the corresponding types in all renewal configs will be ignored by certbot. It's recommended to keep these two ways of using hooks mutually exclusive to avoid confusion. Cron jobs created by
letsencrypt::certonlyare unaffected as they renew certificates directly using
certbot certonly`.
certbot certonly
Hooks created with letsencrypt::certonly
will behave the following way:
pre
hooks will be run before each certificate is attempted issued or renewed, even if the action fails.post
hooks will be run after each certificate is attempted issued or renewed, even if the action fails.deploy
hooks will be run after successfully issuing or renewing each certificate. It will not be run if no action is taken or if the action fails.
letsencrypt::certonly { 'foo':
domains => ['foo.example.com', 'bar.example.com'],
pre_hook_commands => ['...'],
post_hook_commands => ['...'],
deploy_hook_commands => ['...'],
}
certbot renew
Hooks passed to certbot renew
will behave the following way:
pre
hook will be run once total before any certificates are attempted issued or renewed. It will not be run if no actions are taken. Overrides all pre hooks created byletsencrypt::certonly
.post
hook will be run once total after all certificates are issued or renewed. It will not be run if no actions are taken. Overrides all post hooks created byletsencrypt::certonly
.deploy
hook will be run once for each successfully issued or renewed certificate. It will not be run otherwise. Overrides all deploy hooks created byletsencrypt::certonly
.
class { 'letsencrypt':
config => {
email => 'foo@example.com',
server => 'https://acme-v01.api.letsencrypt.org/directory',
},
renew_pre_hook_commands: [...],
renew_post_hook_commands: [...],
renew_deploy_hook_commands: [...],
}
With Hiera:
---
letsencrypt::renew_pre_hook_commands:
- '...'
letsencrypt::renew_post_hook_commands:
- '...'
letsencrypt::renew_deploy_hook_commands:
- '...'
Facts
Fact: certbot_version
A fact that contains the current version of certbot installed on your operating system/distribution.
Fact: letsencrypt_directory
Facts about your live certificates are available through facter. You can query the list of live certificates from puppet using $facts['letsencrypt_directory']
in your puppet code, hiera data or from the command line.
facter -p letsencrypt_directory
{
legacyfiles.ijc.org => "/etc/letsencrypt/live/legacyfiles.ijc.org",
static.ijc.org => "/etc/letsencrypt/live/static.ijc.org",
ijc.org => "/etc/letsencrypt/live/ijc.org",
new.ijc.org => "/etc/letsencrypt/live/new.ijc.org",
www.ijc.org => "/etc/letsencrypt/live/ijc.org",
training.ijc.org => "/etc/letsencrypt/live/training.ijc.org"
}
Puppet Functions
This module profiles a custom puppet function letsencrypt::letsencrypt_lookup
which allows you to load information about your certificates into puppet.
This returns the same information as in the facts but for a particular domain. It accepts a single argument for your domain or wildcard domain.
Development
- Fork it
- Create a feature branch
- Write a failing test
- Write the code to make that test pass
- Refactor the code
- Submit a pull request
We politely request (demand) tests for all new features. Pull requests that contain new features without a test will not be considered. If you need help, just ask!
Reference
Table of Contents
Classes
Public Classes
letsencrypt
: Install and configure Certbot, the LetsEncrypt clientletsencrypt::plugin::dns_cloudflare
: Installs and configures the dns-cloudflare pluginletsencrypt::plugin::dns_rfc2136
: Installs and configures the dns-rfc2136 pluginletsencrypt::plugin::dns_route53
: Installs and configures the dns-route53 pluginletsencrypt::plugin::nginx
: install and configure the Let's Encrypt nginx pluginletsencrypt::renew
: Configures renewal of Let's Encrypt certificates using Certbot
Private Classes
letsencrypt::config
: Configures the Let's Encrypt client.letsencrypt::install
: Installs the Let's Encrypt client.letsencrypt::scripts
: Deploy helper scripts scripts
Defined types
letsencrypt::certonly
: Request a certificate using thecertonly
installerletsencrypt::hook
: Creates hook scripts.
Functions
Data types
Letsencrypt::Cron::Hour
: mimic hour setting in cron as defined in man 5 crontabLetsencrypt::Cron::Minute
: mimic minute setting in cron as defined in man 5 crontabLetsencrypt::Cron::Monthday
: mimic monthday setting in cron as defined in man 5 crontabLetsencrypt::Plugin
: List of accepted plugins
Classes
letsencrypt
Install and configure Certbot, the LetsEncrypt client
Examples
class { 'letsencrypt' :
email => 'letsregister@example.com',
config => {
'server' => 'https://acme-staging-v02.api.letsencrypt.org/directory',
},
}
Parameters
The following parameters are available in the letsencrypt
class:
email
environment
package_name
package_ensure
package_command
config_file
config
cron_scripts_path
cron_owner_group
manage_config
manage_install
configure_epel
agree_tos
unsafe_registration
config_dir
key_size
certificates
renew_pre_hook_commands
renew_post_hook_commands
renew_deploy_hook_commands
renew_additional_args
renew_cron_ensure
renew_cron_hour
renew_cron_minute
renew_cron_monthday
renew_cron_environment
certonly_pre_hook_commands
certonly_post_hook_commands
certonly_deploy_hook_commands
email
Data type: Optional[String]
The email address to use to register with Let's Encrypt. This takes precedence over an 'email' setting defined in $config.
Default value: undef
environment
Data type: Array
An optional array of environment variables
Default value: []
package_name
Data type: String
Name of package and command to use when installing the client package.
Default value: 'certbot'
package_ensure
Data type: String[1]
The value passed to ensure
when installing the client package.
Default value: 'installed'
package_command
Data type: String
Path or name for letsencrypt executable.
Default value: 'certbot'
config_file
Data type: String
The path to the configuration file for the letsencrypt cli.
Default value: "${config_dir}/cli.ini"
config
Data type: Hash
A hash representation of the letsencrypt configuration file.
Default value: { 'server' => 'https://acme-v02.api.letsencrypt.org/directory' }
cron_scripts_path
Data type: String
The path for renewal scripts called by cron
Default value: "${facts['puppet_vardir']}/letsencrypt"
cron_owner_group
Data type: String
Group owner of cron renew scripts.
Default value: 'root'
manage_config
Data type: Boolean
A feature flag to toggle the management of the letsencrypt configuration file.
Default value: true
manage_install
Data type: Boolean
A feature flag to toggle the management of the letsencrypt client installation.
Default value: true
configure_epel
Data type: Boolean
A feature flag to include the 'epel' class and depend on it for package installation.
Default value: false
agree_tos
Data type: Boolean
A flag to agree to the Let's Encrypt Terms of Service.
Default value: true
unsafe_registration
Data type: Boolean
A flag to allow using the 'register-unsafely-without-email' flag.
Default value: false
config_dir
Data type: Stdlib::Unixpath
The path to the configuration directory.
Default value: '/etc/letsencrypt'
key_size
Data type: Integer[2048]
Size for the RSA public key
Default value: 4096
certificates
Data type: Hash[String[1],Hash]
A hash containing certificates. Each key is the title and each value is a hash, both passed to letsencrypt::certonly.
Default value: {}
renew_pre_hook_commands
Data type: Variant[String[1], Array[String[1]]]
Array of commands to run in a shell before obtaining/renewing any certificates.
Default value: []
renew_post_hook_commands
Data type: Variant[String[1], Array[String[1]]]
Array of commands to run in a shell after attempting to obtain/renew certificates.
Default value: []
renew_deploy_hook_commands
Data type: Variant[String[1], Array[String[1]]]
Array of commands to run in a shell once for each successfully issued/renewed certificate. Two environmental variables are supplied by certbot:
- $RENEWED_LINEAGE: Points to the live directory with the cert files and key. Example: /etc/letsencrypt/live/example.com
- $RENEWED_DOMAINS: A space-delimited list of renewed certificate domains. Example: "example.com www.example.com"
Default value: []
renew_additional_args
Data type: Variant[String[1], Array[String[1]]]
Array of additional command line arguments to pass to 'certbot renew'.
Default value: []
renew_cron_ensure
Data type: String[1]
Intended state of the cron resource running certbot renew.
Default value: 'absent'
renew_cron_hour
Data type: Letsencrypt::Cron::Hour
Optional string, integer or array of hour(s) the renewal command should run. E.g. '[0,12]' to execute at midnight and midday. hour.
Default value: fqdn_rand(24)
renew_cron_minute
Data type: Letsencrypt::Cron::Minute
Optional string, integer or array of minute(s) the renewal command should run. E.g. 0 or '00' or [0,30].
Default value: fqdn_rand(60)
renew_cron_monthday
Data type: Letsencrypt::Cron::Monthday
Optional string, integer or array of monthday(s) the renewal command should run. E.g. '2-30/2' to run on even days.
Default value: '*'
renew_cron_environment
Data type: Variant[String[1], Array[String[1]]]
Optional string or array of environments(s) the renewal command should have. E.g. PATH=/sbin:/usr/sbin:/bin:/usr/bin
Default value: []
certonly_pre_hook_commands
Data type: Array[String[1]]
Array of commands to run in a shell before obtaining/renewing any certificates.
Default value: []
certonly_post_hook_commands
Data type: Array[String[1]]
Array of commands to run in a shell after attempting to obtain/renew certificates.
Default value: []
certonly_deploy_hook_commands
Data type: Array[String[1]]
Array of commands to run in a shell once for each successfully issued/renewed certificate. Two environmental variables are supplied by certbot:
- $RENEWED_LINEAGE: Points to the live directory with the cert files and key. Example: /etc/letsencrypt/live/example.com
- $RENEWED_DOMAINS: A space-delimited list of renewed certificate domains. Example: "example.com www.example.com"
Default value: []
letsencrypt::plugin::dns_cloudflare
This class installs and configures the Let's Encrypt dns-cloudflare plugin. https://certbot-dns-cloudflare.readthedocs.io
Parameters
The following parameters are available in the letsencrypt::plugin::dns_cloudflare
class:
package_name
Data type: Optional[String[1]]
The name of the package to install when $manage_package is true.
Default value: undef
api_key
Data type: Optional[String[1]]
Optional string, cloudflare api key value for authentication.
Default value: undef
api_token
Data type: Optional[String[1]]
Optional string, cloudflare api token value for authentication.
Default value: undef
email
Data type: Optional[String[1]]
Optional string, cloudflare account email address, used in conjunction with api_key.
Default value: undef
config_path
Data type: Stdlib::Absolutepath
The path to the configuration directory.
Default value: "${letsencrypt::config_dir}/dns-cloudflare.ini"
manage_package
Data type: Boolean
Manage the plugin package.
Default value: true
propagation_seconds
Data type: Integer
Number of seconds to wait for the DNS server to propagate the DNS-01 challenge.
Default value: 10
letsencrypt::plugin::dns_rfc2136
This class installs and configures the Let's Encrypt dns-rfc2136 plugin. https://certbot-dns-rfc2136.readthedocs.io
Parameters
The following parameters are available in the letsencrypt::plugin::dns_rfc2136
class:
server
key_name
key_secret
key_algorithm
port
propagation_seconds
manage_package
package_name
config_dir
server
Data type: Stdlib::Host
Target DNS server.
key_name
Data type: String[1]
TSIG key name.
key_secret
Data type: String[1]
TSIG key secret.
key_algorithm
Data type: String[1]
TSIG key algorithm.
Default value: 'HMAC-SHA512'
port
Data type: Stdlib::Port
Target DNS port.
Default value: 53
propagation_seconds
Data type: Integer
Number of seconds to wait for the DNS server to propagate the DNS-01 challenge. (the plugin defaults to 60)
Default value: 10
manage_package
Data type: Boolean
Manage the plugin package.
Default value: true
package_name
Data type: String[1]
The name of the package to install when $manage_package is true.
config_dir
Data type: Stdlib::Absolutepath
The path to the configuration directory.
Default value: $letsencrypt::config_dir
letsencrypt::plugin::dns_route53
This class installs and configures the Let's Encrypt dns-route53 plugin. https://certbot-dns-route53.readthedocs.io
Parameters
The following parameters are available in the letsencrypt::plugin::dns_route53
class:
propagation_seconds
Data type: Integer
Number of seconds to wait for the DNS server to propagate the DNS-01 challenge.
Default value: 10
manage_package
Data type: Boolean
Manage the plugin package.
Default value: true
package_name
Data type: String[1]
The name of the package to install when $manage_package is true.
letsencrypt::plugin::nginx
install and configure the Let's Encrypt nginx plugin
Parameters
The following parameters are available in the letsencrypt::plugin::nginx
class:
manage_package
Data type: Boolean
Manage the plugin package.
Default value: true
package_name
Data type: String[1]
The name of the package to install when $manage_package is true.
Default value: 'python3-certbot-nginx'
letsencrypt::renew
Configures renewal of Let's Encrypt certificates using the certbot renew command.
Note: Hooks set here will run before/after/for ALL certificates, including any not managed by Puppet. If you want to create hooks for specific certificates only, create them using letsencrypt::certonly.
Parameters
The following parameters are available in the letsencrypt::renew
class:
pre_hook_commands
post_hook_commands
deploy_hook_commands
additional_args
cron_ensure
cron_hour
cron_minute
cron_monthday
cron_environment
pre_hook_commands
Data type: Variant[String[1], Array[String[1]]]
Array of commands to run in a shell before obtaining/renewing any certificates.
Default value: $letsencrypt::renew_pre_hook_commands
post_hook_commands
Data type: Variant[String[1], Array[String[1]]]
Array of commands to run in a shell after attempting to obtain/renew certificates.
Default value: $letsencrypt::renew_post_hook_commands
deploy_hook_commands
Data type: Variant[String[1], Array[String[1]]]
Array of commands to run in a shell once for each successfully issued/renewed certificate. Two environmental variables are supplied by certbot:
- $RENEWED_LINEAGE: Points to the live directory with the cert files and key. Example: /etc/letsencrypt/live/example.com
- $RENEWED_DOMAINS: A space-delimited list of renewed certificate domains. Example: "example.com www.example.com"
Default value: $letsencrypt::renew_deploy_hook_commands
additional_args
Data type: Array[String[1]]
Array of additional command line arguments to pass to 'certbot renew'.
Default value: $letsencrypt::renew_additional_args
cron_ensure
Data type: Enum['present', 'absent']
Intended state of the cron resource running certbot renew
Default value: $letsencrypt::renew_cron_ensure
cron_hour
Data type: Letsencrypt::Cron::Hour
Optional string, integer or array of hour(s) the renewal command should run. E.g. '[0,12]' to execute at midnight and midday. Default: fqdn-seeded random hour.
Default value: $letsencrypt::renew_cron_hour
cron_minute
Data type: Letsencrypt::Cron::Minute
Optional string, integer or array of minute(s) the renewal command should run. E.g. 0 or '00' or [0,30]. Default: fqdn-seeded random minute.
Default value: $letsencrypt::renew_cron_minute
cron_monthday
Data type: Letsencrypt::Cron::Monthday
Optional string, integer or array of monthday(s) the renewal command should run. E.g. '2-30/2' to run on even days. Default: Every day.
Default value: $letsencrypt::renew_cron_monthday
cron_environment
Data type: Variant[String[1], Array[String[1]]]
Optional string or array of environment variables the renewal command should have. E.g. PATH=/sbin:/usr/sbin:/bin:/usr/bin
Default value: $letsencrypt::renew_cron_environment
Defined types
letsencrypt::certonly
This type can be used to request a certificate using the certonly
installer.
Examples
standalone authenticator
# Request a certificate for `foo.example.com` using the `certonly`
# installer and the `standalone` authenticator.
letsencrypt::certonly { 'foo.example.com': }
Multiple domains
# Request a certificate for `foo.example.com` and `bar.example.com` using
# the `certonly` installer and the `standalone` authenticator.
letsencrypt::certonly { 'foo':
domains => ['foo.example.com', 'bar.example.com'],
}
Apache authenticator
# Request a certificate for `foo.example.com` with the `certonly` installer
# and the `apache` authenticator.
letsencrypt::certonly { 'foo.example.com':
plugin => 'apache',
}
Nginx authenticator
# Request a certificate for `foo.example.com` with the `certonly` installer
# and the `nginx` authenticator.
letsencrypt::certonly { 'foo.example.com':
plugin => 'nginx',
}
webroot authenticator
# Request a certificate using the `webroot` authenticator. The paths to the
# webroots for all domains must be given through `webroot_paths`. If
# `domains` and `webroot_paths` are not the same length, the last
# `webroot_paths` element will be used for all subsequent domains.
letsencrypt::certonly { 'foo':
domains => ['foo.example.com', 'bar.example.com'],
plugin => 'webroot',
webroot_paths => ['/var/www/foo', '/var/www/bar'],
}
dns-rfc2136 authenticator
# Request a certificate using the `dns-rfc2136` authenticator. Ideally the
# key `secret` should be encrypted, eg. with eyaml if using Hiera. It's
# also recommended to only enable access to the specific DNS records needed
# by the Let's Encrypt client.
#
# [Plugin documentation](https://certbot-dns-rfc2136.readthedocs.io)
class { 'letsencrypt::plugin::dns_rfc2136':
server => '192.0.2.1',
key_name => 'certbot',
key_secret => '[...]==',
}
letsencrypt::certonly { 'foo.example.com':
plugin => 'dns-rfc2136',
}
dns-route53 authenticator
# Request a certificate for `foo.example.com` with the `certonly` installer
# and the `dns-route53` authenticator.
letsencrypt::certonly { 'foo.example.com':
plugin => 'dns-route53',
}
Additional arguments
# If you need to pass a command line flag to the `certbot` command that
# is not supported natively by this module, you can use the
# `additional_args` parameter to pass those arguments.
letsencrypt::certonly { 'foo.example.com':
additional_args => ['--foo bar', '--baz quuz'],
}
Parameters
The following parameters are available in the letsencrypt::certonly
defined type:
ensure
domains
custom_plugin
plugin
webroot_paths
letsencrypt_command
additional_args
environment
key_size
manage_cron
cron_output
cron_before_command
cron_success_command
cron_hour
cron_minute
cron_monthday
config_dir
pre_hook_commands
post_hook_commands
deploy_hook_commands
cert_name
ensure
Data type: Enum['present','absent']
Intended state of the resource
Will remove certificates for specified domains if set to 'absent'. Will
also remove cronjobs and renewal scripts if manage_cron
is set to 'true'.
Default value: 'present'
domains
Data type: Array[String[1]]
An array of domains to include in the CSR.
Default value: [$title]
custom_plugin
Data type: Boolean
Whether to use a custom plugin in additional_args and disable -a flag.
Default value: false
plugin
Data type: Letsencrypt::Plugin
The authenticator plugin to use when requesting the certificate.
Default value: 'standalone'
webroot_paths
Data type: Array[Stdlib::Unixpath]
An array of webroot paths for the domains in domains
.
Required if using plugin => 'webroot'
. If domains
and
webroot_paths
are not the same length, the last webroot_paths
element will be used for all subsequent domains.
Default value: []
letsencrypt_command
Data type: String[1]
Command to run letsencrypt
Default value: $letsencrypt::command
additional_args
Data type: Array[String[1]]
An array of additional command line arguments to pass to the letsencrypt
command.
Default value: []
environment
Data type: Array[String[1]]
An optional array of environment variables
Default value: []
key_size
Data type: Integer[2048]
Size for the RSA public key
Default value: $letsencrypt::key_size
manage_cron
Data type: Boolean
Indicating whether or not to schedule cron job for renewal. Runs daily but only renews if near expiration, e.g. within 10 days.
Default value: false
cron_output
Data type: Optional[Enum['suppress', 'log']]
How to treat cron output
suppress
- Suppress all output
log
- Forward cron output to syslog
undef - Do nothing with cron output (default)
Default value: undef
cron_before_command
Data type: Optional[String[1]]
Representation of a command that should be run before renewal command
Default value: undef
cron_success_command
Data type: Optional[String[1]]
Representation of a command that should be run if the renewal command succeeds.
Default value: undef
cron_hour
Data type: Variant[Integer[0,23], String, Array]
Optional hour(s) that the renewal command should execute. e.g. '[0,12]' execute at midnight and midday. Default - seeded random hour.
Default value: fqdn_rand(24, $title)
cron_minute
Data type: Variant[Integer[0,59], String, Array]
Optional minute(s) that the renewal command should execute. e.g. 0 or '00' or [0,30]. Default - seeded random minute.
Default value: fqdn_rand(60, $title)
cron_monthday
Data type: Array[Variant[Integer[0, 59], String[1]]]
Optional string, integer or array of monthday(s) the renewal command should run. E.g. '2-30/2' to run on even days. Default: Every day.
Default value: ['*']
config_dir
Data type: Stdlib::Unixpath
The path to the configuration directory.
Default value: $letsencrypt::config_dir
pre_hook_commands
Data type: Variant[String[1], Array[String[1]]]
Array of commands to run in a shell before attempting to obtain/renew the certificate.
Default value: $letsencrypt::certonly_pre_hook_commands
post_hook_commands
Data type: Variant[String[1], Array[String[1]]]
Array of command(s) to run in a shell after attempting to obtain/renew the certificate.
Default value: $letsencrypt::certonly_post_hook_commands
deploy_hook_commands
Data type: Variant[String[1], Array[String[1]]]
Array of command(s) to run in a shell once if the certificate is successfully issued. Two environmental variables are supplied by certbot:
- $RENEWED_LINEAGE: Points to the live directory with the cert files and key. Example: /etc/letsencrypt/live/example.com
- $RENEWED_DOMAINS: A space-delimited list of renewed certificate domains. Example: "example.com www.example.com"
Default value: $letsencrypt::certonly_deploy_hook_commands
cert_name
Data type: String[1]
the common name used for the certificate
Default value: $domains[0]
letsencrypt::hook
This type is used by letsencrypt::renew and letsencrypt::certonly to create hook scripts.
Parameters
The following parameters are available in the letsencrypt::hook
defined type:
type
Data type: Enum['pre', 'post', 'deploy']
Hook type.
hook_file
Data type: String[1]
Path to deploy hook script.
commands
Data type: Variant[String[1],Array[String[1]]]
Bash commands to execute when the hook is run by certbot.
Functions
letsencrypt::letsencrypt_lookup
Type: Ruby 4.x API
The letsencrypt::letsencrypt_lookup function.
letsencrypt::letsencrypt_lookup(Any $common_name)
The letsencrypt::letsencrypt_lookup function.
Returns: Any
common_name
Data type: Any
Data types
Letsencrypt::Cron::Hour
mimic hour setting in cron as defined in man 5 crontab
Alias of
Variant[Integer[0,23], String[1], Array[
Variant[
Integer[0,23],
String[1],
]
]]
Letsencrypt::Cron::Minute
mimic minute setting in cron as defined in man 5 crontab
Alias of
Variant[Integer[0,59], String[1], Array[
Variant[
Integer[0,59],
String[1],
]
]]
Letsencrypt::Cron::Monthday
mimic monthday setting in cron as defined in man 5 crontab
Alias of
Variant[Integer[0,31], String[1], Array[
Variant[
Integer[0,31],
String[1],
]
]]
Letsencrypt::Plugin
List of accepted plugins
Alias of Enum['apache', 'standalone', 'webroot', 'nginx', 'dns-azure', 'dns-route53', 'dns-google', 'dns-cloudflare', 'dns-rfc2136', 'manual']
Changelog
All notable changes to this project will be documented in this file. Each new release typically also includes the latest modulesync defaults. These should not affect the functionality of the module.
v11.1.0 (2024-09-09)
Implemented enhancements:
- remove the 'root' group and replace with group 0 #355 (rtprio)
- Add support for FreeBSD 14 #350 (smortex)
- Add environment parameter to renew cron #288 (gmenuel)
v11.0.0 (2023-12-04)
Breaking changes:
- Add support for Fedora 39, drop support for Fedora 36 #336 (kenyon)
- certonly: Use the first domain for
$cert_name
instead of the$title
#220 (saimonn)
Implemented enhancements:
- Add Puppet 8 support #324 (bastelfreak)
Fixed bugs:
Merged pull requests:
- Mark
install.pp
as private #338 (kenyon) - move
letsencrypt::configure_epel
from hiera toinit.pp
#337 (kenyon) - Remove legacy top-scope syntax #335 (smortex)
v10.1.0 (2023-10-18)
Implemented enhancements:
v10.0.0 (2023-09-27)
Breaking changes:
- Drop support for Debian 10 (EOL) #330 (evgeni)
- Drop support for Ubuntu 18.04 (EOL) #329 (evgeni)
- Drop Puppet 6 support #318 (bastelfreak)
Implemented enhancements:
- Allow puppetlabs/inifile 6.x, puppet/epel 5.x #327 (evgeni)
- puppetlabs/stdlib: Allow 9.x #323 (bastelfreak)
- Add a
certbot_version
fact #322 (martijndegouw)
Fixed bugs:
- Propagate the package_ensure parameter to all plugins #321 (martijndegouw)
v9.2.0 (2023-04-04)
Implemented enhancements:
- Add missing datatypes and documentation #315 (bastelfreak)
- Add EL9 support #314 (bastelfreak)
- Add CentOS 8 support #313 (bastelfreak)
- Add Rocky 8 support #312 (bastelfreak)
- certonly: Implement default hook commands #311 (bastelfreak)
- Remove unnecessary exec #309 (deric)
v9.1.0 (2023-01-15)
Implemented enhancements:
v9.0.1 (2022-12-02)
Fixed bugs:
Closed issues:
- Documentation/examples for certonly
suppress_cron_output
not updated after removal of parameter #302
v9.0.0 (2022-11-21)
Breaking changes:
- Drop Fedora 32, add Fedora 36 support #301 (treydock)
- Update FreeBSD package names #296 (smortex)
- Support logging cron output #277 (treydock)
Implemented enhancements:
- Add support for ubuntu 22.04 #297 (cible)
- Allow using the 'manual' plugin #292 (smokris)
- Reduce acceptance test duplication #282 (ekohl)
- Configure Debian as an OS family #280 (ekohl)
- Add Cloudflare DNS plugin support #279 (bkuebler)
Fixed bugs:
v8.0.2 (2022-02-01)
Fixed bugs:
v8.0.1 (2022-01-20)
Fixed bugs:
v8.0.0 (2022-01-19)
Implemented enhancements:
- create certificates from class parameter (hiera) #271 (nod0n)
- FreeBSD dns plugin packages #268 (nod0n)
- install and use the certbot nginx plugin #267 (nod0n)
Merged pull requests:
- generate REFERENCE.md #266 (nod0n)
- Drop obsolete operating system version check in acceptance tests #265 (nod0n)
v7.0.0 (2021-12-10)
Breaking changes:
- Drop VCS install method support #246
- Update FreeBSD package name #253 (smortex)
- Drop support for Debian 9, Ubuntu 16.04 and FreeBSD 11 (EOL) #251 (smortex)
- modulesync 4.1.0 / Drop EoL Puppet 5 / Drop VCS install method #235 (bastelfreak)
Implemented enhancements:
Closed issues:
- Raise compatible puppet version from \<7.0 to \<8.0 #245
- certbot-auto no longer works on any OS #240
- Logrotate for the letsencrypt logs #237
- RHEL8 support for dns-rfc2136 #236
- Cut new version with puppet-epel dependency? #232
- module complains about missing provider variable #209
- wrong initialize script #154
Merged pull requests:
- Allow epel 4 #261 (msalway)
- remove .sync.yml with only Travis settings #260 (kenyon)
- docs: wording updates due to removal of VCS install method #259 (kenyon)
- init.pp: remove unused param $manage_dependencies #258 (kenyon)
- README: not installing from source anymore; fix staging URL #257 (kenyon)
- dns_rfc2136_spec, dns_route53_spec: add Fedora 32, drop Fedora 30, 31 #256 (kenyon)
- Add support for RHEL 8 and AlmaLinux 8 #254 (yachub)
- Allow up-to-date dependencies #248 (smortex)
- Add quote marks to class names in readme #242 (thebeanogamer)
v6.0.0 (2020-09-11)
Breaking changes:
Implemented enhancements:
- add manifest to install dns-route53 plugin, along with tests #225 (aripringle)
- Add
cert_name
parameter toletsencrypt::certonly
#219 (saimonn)
Closed issues:
Merged pull requests:
- modulesync 3.0.0 & puppet-lint updates #229 (bastelfreak)
- fix typo in renew example #228 (milesstoetzner)
- Use voxpupuli-acceptance #224 (ekohl)
- Ensure EPEL is configured before installing plugin #222 (alexjfisher)
- #218 Switch to puppet-epel #221 (kallies)
- Add Fedora 31, drop Fedora 29 #216 (ekohl)
- delete legacy travis directory #214 (bastelfreak)
- add --keep-until-expiring closer to letsencrypt command in cron #211 (pulecp)
- allow puppetlabs/inifile 4.x #210 (bastelfreak)
v5.0.0 (2019-10-09)
Breaking changes:
- remove params.pp and change some defaults values #205 (Dan33l)
- Drop Ubuntu 14.04 & add Debian 9/10 / Fedora 29/30 support #193 (ekohl)
Implemented enhancements:
- replace server urls with v2 urls #196
- Option to clean up cronjobs for removed domains #175
- update version shiped with vcs method to 0.39.0 #207 (Dan33l)
- use ACME API v2 #206 (Dan33l)
- feat(facts): add facts about certificates #187 (minorOffense)
Fixed bugs:
- fix modulesync config file #201 (bastelfreak)
Closed issues:
- python2-certbot-dns-rfc2136 doesn't exist in debian buster #191
- letsencrypt failed to generate certificate #184
$letsencrypt::venv_path
is undocumented #21
Merged pull requests:
- use puppet strings #204 (Dan33l)
- Raise upper bound version of stdlib & vcsrepo #202 (mfaure)
- Fix type in readme: deploy_hooks_commands -> deploy_hook_commands #188 (2ZZ)
- Allow puppetlabs/inifile 3.x #186 (dhoppe)
v4.0.0 (2019-03-29)
Breaking changes:
- Rework letsencrypt::certonly for #175 #177 (cFire)
- Certonly: Refactor manage_cron to ensure_cron with appropriate data type #161 (craigwatson)
Implemented enhancements:
- Add support for certbot renew and hooks #174 (Rathios)
- Add support for wildcard certs #171 (Rathios)
- Add support for dns-rfc2136 plugin #169 (Rathios)
- Add ability to control keysize. Default to 4096. #165 (treveradams)
Fixed bugs:
- Fix for $live_path variable #180 (cFire)
- #178 Add single quote around all domains names in shell commands #179 (Turgon37)
- Fedora doesn't use EPEL for certbot/letsencrypt. #166 (treveradams)
- Fix exec onlyif logic #151 (baurmatt)
Closed issues:
- Domain wildcard should be escaped or quoted in shell commands #178
- Upgrade letsencrypt to 0.30.2 #172
- Disabling manage-cron does not remove crontab record #139
- Add support for certbot hooks #56
Merged pull requests:
- surfacing package_ensure in README #181 (Dan33l)
- Upgrade vcs version to 0.30.2 #173 (baurmatt)
- Add Fedora to tested systems list. #168 (treveradams)
v3.0.0 (2019-01-14)
Breaking changes:
- vcs method, bump version of certbot to v0.30.0 #159 (Dan33l)
- modulesync 2.5.0 and drop Puppet4 support #156 (bastelfreak)
Implemented enhancements:
- Update to support puppetlabs/vcsrepo 2 #98
- Update to support puppetlabs/inifile 2 #97
- Improve performance of unless #148 (baurmatt)
- Add cron day of month parameter #146 (brigriffin)
- Added support for dns-cloudflare CertBot plugin. #145 (nick-dasilva)
- make the module compatible with FreeBSD #143 (Wayneoween)
- Allow wildcard domains for certonly::domains #142 (Wimmesberger)
- Add cron time parameters #122 (matonb)
Fixed bugs:
- Using a space in the letsencrypt::certonly title creates a cron script that will never run. #91
- #91: Cron should also run with space in certonly title #113 (siebrand)
Closed issues:
- wrong repository for EFF's tool to obtain certs from Let's Encrypt #153
- Add support for Certbot dns_cloudflare plugin. #144
- Cronjob needs the options --text --non-interactive #55
- This module should not manage git package #53
- Add dependencies as a parameter #52
- Spec tests break on the "certbot -h" command #44
- Testing: Change the server or use --staging? #43
- letsencrypt package is now called certbot #41
- No letsencrypt package for centos 6? #31
- rebuild module #20
Merged pull requests:
v2.5.0 (2018-10-14)
Implemented enhancements:
- Migrate letsencrypt::config::ini helper to native Puppet 4 #136 (baurmatt)
- Add support for dns-google plugin support #134 (jocado)
Fixed bugs:
Closed issues:
Merged pull requests:
- modulesync 2.2.0 and allow puppet 6.x #140 (bastelfreak)
- allow puppetlabs/stdlib 5.x #135 (bastelfreak)
- Fix cron environment leaking #126 (baurmatt)
v2.4.0 (2018-06-19)
Implemented enhancements:
- Support dns-route53 plugin #123 (jwm)
- Allow custom config dir; FreeBSD support #117 (a01fe)
- Fixes #81 added -n flag to certbot to run in unattended mode. #112 (K0HAX)
Closed issues:
- route53 plugin support #118
Merged pull requests:
- Remove docker nodesets #121 (bastelfreak)
- drop EOL OSs; fix puppet version range #120 (bastelfreak)
v2.3.0 (2018-02-28)
Implemented enhancements:
- Add OpenBSD support #114 (arthurbarton)
Closed issues:
- Run fails on prompt during certonly if certs are not yet due for renewal #81
v2.2.0 (2018-01-04)
Merged pull requests:
- bump inifile dependency to allow 2.x #109 (bastelfreak)
- release 2.2.0 #108 (bastelfreak)
- Update vcsrepo requirement (smaller 3) #107 (kallies)
- Remove EOL operatingsystems #106 (ekohl)
v2.1.0 (2017-11-13)
Implemented enhancements:
Closed issues:
- Puppet support in readme and metadata.json conflicts #102
- Could not find declared class letsencrypt #101
- Please issue a new release #54
v2.0.1 (2017-09-17)
Merged pull requests:
- fixed randomness if the domain is almost same #96 (ashish1099)
v2.0.0 (2017-06-22)
Merged pull requests:
- release 2.0.0 #95 (bastelfreak)
- replace validate_* with proper puppet4 datatypes #93 (bastelfreak)
- Use the correct package names on Debian #88 (ekohl)
- fix "-":12: command too long. errors in crontab file, can't install. #87 (saimonn)
- Added ability to suppress cron output #79 (grega)
v1.1.0 (2017-02-11)
Merged pull requests:
- Removing --quiet from certonly cron #74 (craigwatson)
- unbreak console output by ensuring actual text output #65 (igalic)
- Add cron_before_command #48 (gkopylov)
v1.0.1 (2016-12-23)
Merged pull requests:
- Bump minimum version dependencies (for Puppet 4) #72 (juniorsysadmin)
- release 1.0.1 #71 (bastelfreak)
v999.999.999 (2016-12-20)
Closed issues:
- 1.0.0 and 0.4.0 packages in puppetforge broken #46
- undefined method `cycle' #37
- Duplicate declaration: Package[git] is already declared in file #29
- Using certonly in webroot mode fails with "can't convert Enumerable::Enumerator into Array" #28
- Command Questions #26
- Invalid resource type ini_setting #22
- Folders "~/.local..." bug #19
- vcs-installed letsencrypt-auto creates '~' directory #16
- Update to the latest lets-encrypt version: v0.4.0 #14
- Alternative Puppet Module #4
Merged pull requests:
- Bump LetsEncrypt version to 0.9.3 (latest as of Oct 2016) #61 (jethrocarr)
- Fix cronspam #60 (jethrocarr)
- Fix failing builds #57 (jethrocarr)
- Remove webroot_paths cycling to match domains list #42 (danzilio)
- Validate presence of webroot_paths with webroot plugin #39 (domcleal)
- Fix validation of letsencrypt_command #38 (domcleal)
- Various smaller fixes. #36 (thomasvs)
- Change EL7 package and command to certbot #35 (domcleal)
- Add a way to change package name and command #34 (glorpen)
- Defaults for el7 #33 (danzilio)
- Closes #18: merging @mheistermann's changes #32 (danzilio)
- Added optional 'environment' parameter to init and certonly. Specced. #30 (tomgillett)
- Split letsencrypt commands, so -auto is only used once #27 (lazyfrosch)
- Fixing test failures when STRICT_VARIABLES is set to true #25 (danzilio)
- Update client #24 (lazyfrosch)
- Fix #16 by specifying VENV_PATH when running letsencrypt. #17 (mheistermann)
- Changing default version to 0.4.0 #15 (serialh0bbyist)
v1.0.0 (2016-02-22)
Merged pull requests:
- updating changelog and prepping metadata for release as 1.0 #13 (danzilio)
- Change Puppet 4 specifics to support 3.4+ #12 (domcleal)
- Install LE package on EL7, Ubuntu 16.04 and Debian 9+ #11 (domcleal)
v0.4.0 (2016-02-01)
Merged pull requests:
- Added webroot_paths parameter #10 (stephenwade)
- Add --agree-tos to commands #9 (stephenwade)
- add optional cron job for certificate renewal #8 (hdeadman)
v0.3.2 (2015-12-14)
Merged pull requests:
- use -a to define plugin #7 (timogoebel)
- Replace package with ensure_packages #6 (AndreaGiardini)
v0.3.1 (2015-12-08)
v0.3.0 (2015-12-08)
Merged pull requests:
- Adding support for RedHat and improving config #5 (danzilio)
- Fix style in examples #3 (ghoneycutt)
- Fix test context with not supported operating systems #2 (AndreaGiardini)
- A collection of commits working toward getting this to v1 #1 (ghoneycutt)
v0.2.0 (2015-12-03)
v0.1.0 (2015-12-03)
* This Changelog was automatically generated by github_changelog_generator
Dependencies
- puppetlabs/stdlib (>= 4.13.1 < 10.0.0)
- puppetlabs/inifile (>= 2.5.0 < 7.0.0)
- puppet/epel (>= 3.0.1 < 6.0.0)
Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and 2. You must cause any modified files to carry prominent notices stating that You changed the files; and 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2013 Gareth Rushgrove Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.