LetsEncrypt now available in Fedora

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

LetsEncrypt provides free SSL certificates for all

LetsEncrypt provides free SSL certificates for all.

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.
  • Standalone verification: 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

Webroot authentication of a domain

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.

For System Administrators Using Software

17 Comments

  1. I didn’t realise that there was manual verification too – I’ve got it running on my site, but I didn’t need to use the option, so I guess I missed it. This actually quashes the one biggest issues that was leveraged to me about LE, because you need root access for the other methods.

    I’m extremely tempted now to create a really small VM which runs LE in virtualbox, so that those with little knowledge of Linux can download it, and execute it themselves.

    This does beg the question though – why don’t LE create a web page for doing this?

    • Sander Hoentjen

      How would a web page work? You need the private key, and the private key needs to remain, well, private.

      • Hmmm, what do you mean? LetsEncrypt does generate a private key and you can implement it like a traditional SSL certificate.

        • Sander Hoentjen

          What I said was in reply to:
          “This does beg the question though – why don’t LE create a web page for doing this?”

          Maybe I misunderstood what “this” is, but I understood it to mean that you wouldn’t need something local, LE creates a webpage where you can fill all stuff in, respond correctly to the challenge and then get your certificates. However to do this LE would need to create your private key (because if they don’t, you will have to so then what is the whole point of the web page?). But if LE creates the private key, it isn’t really private after all.

          Not sure if I just made myself clearer, or even more unclear 🙂

  2. Torsten

    “dnf search letsencrypt” gets an error
    on my machine run fedora 23 with fedora and update repo

  3. andrei

    SSL? Isn’t SSL less secure than TLS?

    • It’s an X.509 certificate. You can use it for SSL or TLS. TLS is basically SSL 3.1 and newer. As I understand it, the name was changed to avoid possible issues with rights to the name, not for any technical reason.

  4. Thank you much for this indeep article + the systemd timer.
    Please take note that when running Nginx, it is the fullchain.pem which must be used. Otherwise, Nginx will complain and not start.

  5. Jason

    Lets encrypt is the best thing since sliced bread and it is great that you have picked it up so early. I already have it on my site running Fedora and Docker. Fedora has to be the best distro for me from both a professional and personal perspective.

    Great work Guys

  6. Also already available in Debian, and therefore soon in Debian derivatives like Ubuntu.

    We’re all in this together!

  7. Peter

    Hi,
    you are talking about current development of ‘full automatic configuration of Apache and nginx beeing developed’ currently. Where could one find these?
    Thanks in advance

  8. Berend

    Thanks for writing this. I was already using letsencrypt, but more integration and automation is always useful.

  9. I would suggest the following:

    – add a require in the unit file this way:

    Requires=httpd.service

    After=httpd.service

    This avoid let’s encrypt to fail in case server is not running

    Then, I would remove the
    ExecStart=/usr/sbin/systemctl reload httpd
    from service file. Why? Because of say 10 virtual server with different root path, you will need 10 service+timer. Best is thus to restart only once the server when all renewal are done. In this case, play with the OnCalendar=
    to be sure httpd restart once all renewal are done.

  10. LE’s CentOS branch is broken so this came super handy. The only thing I would say is to avoid complex bash statements. Or explain them if you have to because if they fail then users have no idea what happened. Thanks for writing this.

Comments are Closed

The opinions expressed on this website are those of each author, not of the author's employer or of Red Hat. Fedora Magazine aspires to publish all content under a Creative Commons license but may not be able to do so in all cases. You are responsible for ensuring that you have the necessary permission to reuse any work on this site. The Fedora logo is a trademark of Red Hat, Inc. Terms and Conditions