Encrypting the traffic for websites has long become a standard, and most users simply expect websites to offer it. Setting up SSL certificates for web sites and servers used to be a cumbersome and costly process, but with the release of LetsEncrypt service and their certbot
tool, it is now a fast, automated and free process.
Prerequisites
Before we can start fetching SSL certificates, a little setup is required. First of all, we obviously need a domain with the A (or AAA for IPv6) record pointing to our server's IP address. Since we are focusing on the HTTP-based confirmation challenge, no further DNS changes are necessary (certbot
supports verification through DNS as well, but this can be trickier to set up and may not work for all DNS providers).
For the rest of this article we assume you are running a recent version of a debian-based distribution (linux debian, ubuntu etc) and are using either apache2
or nginx
as your web server of choice. All needed packages can be installed from official repositories
sudo apt install certbot python3-certbot-apache
Note the second package, containing the apache2
plugin for certbot
. This allows it to natively read virtualhost configuration files and automatically detect domain names and document root paths. If you are using nginx
as your webserver, you need to install python-certbot-nginx
instead.
Preparing certbot
The first time you run certbot
, it will prompt you to register with the LetsEncrypt service with your email address. You can do this manually with
certbot register
The email is necessary to inform you of technical issues like root certificate revocations that may invalidate your certificates. Be sure to use an email that you regularly check for new messages. You will not receive spam or advertisements, unless you agreed to it in the prompt.
The official LetsEncrypt service is heavily rate-limited to ensure good quality of service for all users. Since DNS updates may take some time (sometimes several days!) to reach all servers, your changed DNS record may not (yet) be visible for LetsEncrypt. Blindly trying to fetch certificates in this state may quickly get your ip temporarily banned, resulting in even longer delays.
To prevent this, LetsEncrypt offers staging servers, which you can use to check if a certificate could be successfully issued:
certbot --apache --staging --dry-run certonly
This command communicates with LetsEncrypt's staging servers (--staging
) and doesn't change any files on disk (--dry-run
), while using the apache2 plugin for web server configuration (--apache
; use --nginx
instead if your webserver is nginx). Saving the test certificate isn't useful, since it isn't officially valid anyways (it is similar to a self-signed certificate). Select the domain(s) you want to test from the prompt and watch the output. A successful test will end with the message
The dry run was successful.
If you see this confirmation, your DNS changes are visible and correct, and you can safely start issuing real certificates.
Protecting web servers
Retrieving certificates for common web servers with certbot is extremely simple: All you have to do is set up a basic http-only virtualhost configuration like this
sample_apache_vhost.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com ww2.example.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
This tiny snippet is all that certbot needs to get you a certificate. Your configuration may be longer, likely including logging setup, proper security and support for a scripting language like PHP. Make sure to provide a virtualhost that includes all the configuration you need for your website, because certbot will slightly adjust it and generate a second one based on it's contents. Using a proper config to begin with saves you lots of manual editing time later.
To have certbot automatically fetch and configure the SSL certificate, simply run
certbot --apache
(Replace --apache
with --nginx
if you are using nginx)
It will print a list of numbered domains and ask you which ones you want to include in the certificate:
Which names would you like to activate HTTPS for?
We recommend selecting either all domains, or all domains in a VirtualHost/server block.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: example.com
2: www.example.com
3: ww2.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
Make sure to supply all domains for your target virtualhost (three in the sample above, one primary and two alternative subdmains). If you only include some of the domains in the certificate, then SSL will be enabled for all of them, but some domains will show security warnings when opened in a browser.
Select domains by typing their number into the prompt, separating multiple numbers with a comma.
For our example, you would type 1,2,3
:
blank to select all options shown (Enter 'c' to cancel): 1,2,3
To include all three domains from our config. After a few seconds, the command should report success:
Requesting a certificate for example.com and 2 more domains
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2025-07-22.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for example.com to /etc/apache2/sites-available/sample_apache_vhost-le-ssl.conf
Successfully deployed certificate for www.example.com to /etc/apache2/sites-available/sample_apache_vhost-le-ssl.conf
Successfully deployed certificate for ww2.example.com to /etc/apache2/sites-available/sample_apache_vhost-le-ssl.conf
Congratulations! You have successfully enabled HTTPS on https://example.com, https://www.example.com, and https://ww2.example.com
And you are done! The certificate is now installed, but certbot also configured SSL-related settings to sane modern defaults and installed a scheduled background task (typically a ystemd service+timer) to automatically renew the certificate when it nears expiration. It also configured the virtualhost to redirect all incoming http requests to switch to https instead using a permanent redirect.
If you have tried certbot in the past, you may remember having to supply domains at the command line and issues with document root paths. These issues have largely been resolved for the apache2 and nginx plugins nowadays, allowing them to even work seamlessly with reverse proxy configurations that do not serve static files. The plugins will temporarily reconfigure the virtualhost to serve challenge validation files for paths under /.well-known/acme-challenge/
and clean up after the certificate is installed. No more need for pseudo-webroots or path aliases in your configuration files.
Managing certificates
While you don't have to touch certificates directly under normal circumstances, certbot includes a few convenience tools to manage them as well. You can list all installed certificates with:
certbot certificates
The list includes information about domains the certificate covers, storage path on disk and expiration date.
For most installations, certificates should be renewed automatically without any need for manual intervention. You can of course handle this step yourself if you like using
certbot renew
The command will check all available certificates and renew them if they are going to expire soon (skipping them if they are still valid for a reasonable time period). If you have problems renewing certificates, running the command manually may provide important hints why something fails.
Finally, installed certificates can also be deleted if you no longer need them anymore:
certbot delete
The command provides you with a list and prompts you to select the certificate(s) you want to uninstall. Note that uninstalling a certificate only removes the certificate file, it does not reconfigure your virtualhost(s), which will now be broken and need manual adjustment for non-SSL usage again