by Michael Hampicke
Obtaining an SSL Certificate with Certbot from Let's Encrypt
An SSL certificate from Let's Encrypt provides secure, encrypted communication between your website and its visitors. Certbot is a popular tool that simplifies the process of obtaining and renewing these certificates. In this guide, we'll walk you through the steps to obtain an SSL certificate for the domain example.com using Certbot with the webroot parameter.
The webroot plugin is a good fit whenever a web server is already running and serving the domain. Certbot simply drops the ACME challenge file into the existing document root and never touches your web server configuration – your vhosts stay exactly as you wrote them.
Prerequisites
- A domain name (e.g., example.com) pointed to the server where you want to install the SSL certificate.
- A web server (e.g., Apache or Nginx) installed and configured on your server. In this guide we will use Apache.
- Port 80 reachable from the internet. The HTTP-01 challenge behind the webroot plugin is always validated over plain HTTP.
- Root access on the server.
Step 1: Install Certbot
If you haven't already, install Certbot on your server. The method may vary depending on your operating system and web server. You can find specific instructions on the Certbot website: https://certbot.eff.org/.
On Debian-based systems just run this command:
apt install certbot
Step 2: Verify the DocumentRoot
Make sure you know the DocumentRoot of your domain. In this case, the DocumentRoot is /var/www/example.com/htdocs. Certbot will place a temporary file below /var/www/example.com/htdocs/.well-known/acme-challenge/, so this has to be the directory that is actually served for http://example.com.
Step 3: Obtain the SSL Certificate
Open a terminal or command prompt and run the following command:
certbot certonly --webroot -w /var/www/example.com/htdocs -d example.com -d www.example.com
Explanation:
- certonly: Requests a new certificate but doesn't install it.
- --webroot: Use the webroot plugin for authentication.
- -w /var/www/example.com/htdocs: Specifies the webroot directory.
- -d example.com -d www.example.com: Specifies the domain names you want to secure. You can add more domain names here.
Certbot will contact Let's Encrypt, perform the necessary challenges, and obtain the SSL certificate. On the first run it asks for an e-mail address and for your agreement to the terms of service. To run it unattended, for example from a provisioning script, add -n --agree-tos -m admin@example.com.
Step 4: Certificate Location
Upon successful completion, the SSL certificate and private key will be stored on your server. The location is typically something like:
- Certificate: /etc/letsencrypt/live/example.com/fullchain.pem
- Private Key: /etc/letsencrypt/live/example.com/privkey.pem
Always point your configuration at the live directory. Those paths are symlinks that Certbot updates on every renewal, so the file names stay the same for the lifetime of the domain and the vhost never has to be edited again.
Step 5: Configure Apache
Update your web server configuration to use the obtained SSL certificate. The exact steps depend on your web server software. Below is an example for Apache:
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/example.com/htdocs
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# Additional SSL configurations go here...
# Rest of your configuration...
</VirtualHost>
Step 6: Check the Configuration and Restart
Now it's time to restart your web server and test if everything works.
# check apache configuration for errors
apachectl -t
# restart if syntax is OK
systemctl restart apache2
Verify Your SSL Configuration
To perform a deep analysis of the configuration of any SSL web server on the public Internet you can use: https://www.ssllabs.com/ssltest/
Step 7: Set Up Automatic Renewal
Let's Encrypt certificates are valid for 90 days, so renewal is not an optional extra – it is the part that keeps the site reachable. The good news: Certbot has already written down everything it needs, including the webroot path you passed with -w, into a per-domain renewal configuration:
cat /etc/letsencrypt/renewal/example.com.conf
Because of that, a renewal never needs the original command line again. certbot renew reads the stored parameters and renews every certificate that is due, which means older than 60 days. On Debian-based systems the package already ships a systemd timer that runs this twice a day. Check that it is active:
systemctl list-timers | grep certbot
Before relying on it, do a dry run. It runs the complete challenge against the Let's Encrypt staging environment without issuing a certificate and without counting against the rate limits:
certbot renew --dry-run
One thing the timer does not do on its own: Apache keeps the old certificate in memory until it is reloaded. A deploy hook takes care of that, and it only fires when a certificate was actually renewed:
# store the hook permanently, it then applies to every certificate
cat > /etc/letsencrypt/renewal-hooks/deploy/reload-apache.sh <<'EOF'
#!/bin/sh
systemctl reload apache2
EOF
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-apache.sh
# or pass it for a single run
certbot renew --deploy-hook "systemctl reload apache2"
Troubleshooting the Webroot Challenge
- The challenge fails with 404. The webroot you passed is not the directory that is served for the domain. Verify it by hand: write a test file to /var/www/example.com/htdocs/.well-known/acme-challenge/test and open http://example.com/.well-known/acme-challenge/test in a browser.
- A rule blocks the challenge. Deny rules or rewrites for dot-directories will happily block /.well-known/ as well. That path has to stay publicly readable over HTTP.
- Timeout or connection refused. Port 80 must be reachable from the internet. HTTP-01 cannot be validated over HTTPS only, and it cannot be validated from behind a firewall.
- Too many certificates already issued. Let's Encrypt allows 5 duplicate certificates per week for an identical set of domains. Use --dry-run while you are still testing, it does not count against that limit.
- Wildcard certificates such as *.example.com cannot be issued over HTTP-01 at all. They require the DNS-01 challenge, and therefore a DNS provider that Certbot can write TXT records to.
Optional: Force HTTPS in .htaccess
Once the certificate works you will probably want to send HTTP visitors to HTTPS. Keeping that out of the vhost and putting it into the document root's .htaccess keeps the redirect together with the site it belongs to. The first condition leaves the ACME challenge path on plain HTTP. Certbot does follow redirects, but this way a renewal still succeeds even if the certificate has already expired or the HTTPS vhost is broken:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
This requires AllowOverride FileInfo (or All) for the directory in your Apache configuration, otherwise the .htaccess file is ignored.
Related reading: Apache Reverse Proxy as Load Balancer for Exchange DAG
Comments
Add a comment