LetsEncrypt recently entered into a public beta. Thanks to the work of the LetsEncrypt team and Fedora packagers, the official LetsEncrypt client is now available in both Fedora 23 and Rawhide. To learn how LetsEncrypt works or what it is, you can read more in the Fedora Magazine article announcing the public beta launch. In this article, we provide a basic configuration to secure an Apache HTTPD-based site with a LetsEncrypt certificate.

Using letsencrypt

in Fedora

The official letsencrypt client is can be installed in Fedora 23 or later with this command:

dnf install letsencrypt

In the official client, there are three methods to prove ownership of your domain(s).

Manual verification : The secret needs to be put in place by hand.

: The secret needs to be put in place by hand. Standalone verification : The LetsEncrypt client listens on port 80 or 443 and responds to the server itself.

: The LetsEncrypt client listens on port 80 or 443 and responds to the server itself. Web root verification: The client is pointed to the web root (e.g. /var/www/html ) and writes files directly.

At the time of writing, full automatic configuration of Apache and nginx are in progress.

Once the package is installed, you will be able to see a list of available options using the –help flag:

letsencrypt --help all

Manual verification

Manual verification has the most overhead, but lets you run the LetsEncrypt client on a separate system from the web server. Depending on the security model you prefer, you may find this desirable.

The default uses an ncurses interface, but text-only is also possible.

$ letsencrypt --text --email recovery@example.com \ --domains www.example.com,example.com,foo.example.com \ --agree-tos --renew-by-default --manual certonly

The email address is used only if you lose the account details. This will allow you to verify your identity to revoke a certificate and request a new one.

If multiple domains are listed, these will be included as SubjectAltNames in a single certificate.

The client then prompts for a secret per domain to be stored at specific locations. Run the following commands to set the secret location.

$ cd /var/www/html $ mkdir -p .well-known/acme-challenge $ echo "somethingrandomgivenbyservergoeshere" > .well-known/acme-challenge/anotherrandomthinghere

Once you acknowledge the secret has been put in place, the ACME server tests the site for this secret. If the secret matches, LetsEncrypt will provide the certificate. The certificate should then be either moved, or symbolically linked to facilitate automatic renewing, to the right location.

Standalone verification

Standalone verification automatically responds to the challenge, which allows for some automated behavior. The downside of this method is that the web server must be temporarily stopped so LetsEncrypt can listen with its own HTTP server and respond to the challenge.

The IP requesting standalone configuration must match the A record for the domain requested, so this has to run on the target web server.

$ letsencrypt --text --renew-by-default --email recovery@example.com \ --domains www.example.com,example.com,foo.example.com \ --agree-tos --standalone --standalone-supported-challenges http-01 certonly

No interaction is required on the user’s part. This allows automation if either ports 80 or 443 are not already in use on the system, or if a short downtime can be tolerated. For example, this could be an initial provisioning step in an automated management system like Ansible before the main web server is actually started.

Once the certificate is acquired, the server must be configured to use it in some manner.

Web root verification

This method of verification is a nice middle ground. If an existing web server is running, LetsEncrypt can refer to the HTML document root and the client will automatically create the response to the ACME challenge. This method also must run on the same system that matches the A record for the domain.

$ letsencrypt --text --renew-by-default --email recovery@example.com \ --domains www.example.com,example.com,foo.example.com \ --agree-tos --webroot --webroot-path /var/www/html certonly

Using the LetsEncrypt certificate

When the verification selected is complete, /etc/letsencrypt is populated with a configuration matching the method chosen for the domain, along with the keys, certificate, and signing request used.

The files could be copied to an appropriate location for the web server to use. An even better idea is to symbolically link them, so in the future, renewals pick up the new files with no other configuration.

An example for a mod_ssl configuration would be as follows:

$ ln -s /etc/letsencrypt/live/www.example.com/cert.pem /etc/pki/tls/certs/www.example.com.crt $ ln -s /etc/letsencrypt/live/www.example.com/chain.pem /etc/pki/tls/certs/www.example.com.chain.crt $ ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /etc/pki/tls/private/www.example.com.key $ cp /etc/httpd/conf.d/ssl.conf{,.backup} $ sed -i 's@\(SSLCertificateFile\) .*@\1 /etc/pki/tls/certs/www.example.com.crt@' /etc/httpd/conf.d/ssl.conf $ sed -i 's@\(SSLCertificateKeyFile\) .*@\1 /etc/pki/tls/private/www.example.com.key@' /etc/httpd/conf.d/ssl.conf $ sed -i 's@#\(SSLCertificateChainFile\) .*@\1 /etc/pki/tls/certs/www.example.com.chain.crt@' /etc/httpd/conf.d/ssl.conf

Once you restart the web server, it should make use of the new certificates.

The certificates in their default location will get an selinux context of type etc_t. This is readable by httpd and nginx so they can start with this configuration. However, until the base selinux policy includes the Let’s Encrypt certificates, it’s sensible to label them manually to prevent exploitation.

$ semanage fcontext -a -t cert_t '/etc/letsencrypt/(archive|live)(/.*)?' $ restorecon -Rv /etc/letsencrypt

Renewing a certificate

The lifetime of these certificates is only 90 days, to mitigate the impact of any rogue certificates that may end up existing. There are even discussions to lower this in the future. The expectation for the user is to create an automated job to run every 30 to 60 days in order to fetch a fresh certificate valid for another 90 days.

All that’s required to request a new certificate is to run the letsencrypt command again, with a new verification of some nature, and a new key and certificate will be generated.

The files in the live directory are actually symbolic links to the current versions in /etc/letsencrypt/archive. This lets you check the history of changes and rollback if needed.

$ ls -1 /etc/letsencrypt/archive/www.example.com cert1.pem cert2.pem chain1.pem chain2.pem fullchain1.pem fullchain2.pem privkey1.pem privkey2.pem

$ ls -lGg /etc/letsencrypt/live/www.example.com lrwxrwxrwx. 1 41 Dec 2 23:19 cert.pem -> ../../archive/www.example.com/cert2.pem lrwxrwxrwx. 1 42 Dec 2 23:19 chain.pem -> ../../archive/www.example.com/chain2.pem lrwxrwxrwx. 1 46 Dec 2 23:19 fullchain.pem -> ../../archive/www.example.com/fullchain2.pem lrwxrwxrwx. 1 44 Dec 2 23:19 privkey.pem -> ../../archive/www.example.com/privkey2.pem

To make use of new files, just reload the web server. If you use a method that requires no interaction such as webroot, this can be trivially automated via cron or a systemd timer.

An example with a timer would be:

# cd /etc/systemd/system # cat > www-example-com-renewal.service <<EOF [Unit] Description=Automatically renew the www.example.com certificate [Service] Type=oneshot ExecStart=/usr/bin/letsencrypt -d www.example.com --renew-by-default -m recovery@example.com --agree-tos -t --webroot -w /var/www/html certonly ExecStart=/usr/sbin/systemctl reload httpd EOF # cat > www-example-com-renewal.timer <<EOF [Unit] Description=Trigger an automatic renewal every month [Timer] OnCalendar=monthly Persistent=true [Install] WantedBy=multi-user.target EOF systemctl daemon-reload

Revoking a certificate

Sometimes things go wrong and a private key is disclosed. If this happens, it’s important to revoke the certificate so no one can impersonate the web server. Note that certificates are not revoked during renewal, to give grace to restart services or distribute files.

To revoke, use the same client with the revoke option:

$ letsencrypt revoke --cert-path /etc/letsencrypt/archive/www.example.com/cert1.pem

If there is an error carrying out the revocation, it will be displayed. Otherwise, that is it!

Final words

The LetsEncrypt platform only just entered its open beta stage recently and remains under heavy development. It is important to check the upstream documentation to stay current on the expected behavior and see if any options have changed. Note that there are a few commands and items described upstream that are not in Fedora, such as the auto-updating version and the Apache configuration plugin.

If any issues are encountered with the Fedora-packaged version, please report them to Bugzilla so they can be properly tracked and ensure a great experience for those using it in the future.