How To Secure Apache with mod_md Let’s Encrypt on Ubuntu 20.04 LTS

last updated in Categories , ,

How do I secure Apache with mod_md Let’s Encrypt on Ubuntu 20.04 and obtain a free TLS/SSL certificate? How do I secure Apache 2 with Let’s Encrypt on Ubuntu 20.04 LTS server?

Apache server comes with a module named mod_md. We can use this for certificate provisioning via the ACME protocol. This page explains how to install, set up and configure Apache with a mod_md module to secure traffic with Let’s Encrypt free TLS/SSL certificate on Ubuntu 20.04 LTS server.


How to Secure Apache with mod_md Let’s Encrypt on Ubuntu 20.04

Letís Encrypt is a CA that follows the ACME protocol. One can use Letís Encrypt to issue free TLS/SSL certificates for Apache, Nginx, and other servers. In this tutorial, you will use mod_md to obtain a free TLS/SSL certificate for Apache 2 on Ubuntu 20.4 and set up your certificate to renew automatically too. Our sample set up is as follows:

  • Domain – www42.cyberciti.biz
  • HTTPS port – 443
  • Virtual domain config file – /etc/apache2/sites-available/www42.cyberciti.biz.conf

Make sure Apache installed by following How to install Apache on Ubuntu 20.04 guide.

Step 1 – Installing mod_md for Let’s Encrypt

First, apply updates using the apt command:
sudo apt update
sudo apt upgrade

Then, install the mod_md by typing the following command:
sudo apt install libapache2-mod-md
Install Apache with mod_md Let's Encrypt on Ubuntu Linux 20.04 LTS

Enabling mod_md on Ubuntu 20.04 LTS

Turn on mod_md, type:
sudo a2enmod md
Sample outputs:

Enabling module md.
To activate the new configuration, you need to run:
  systemctl restart apache2

Make sure you activate the mod_ssl too, run:
sudo a2enmod ssl
Outputs:

Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Enabling module socache_shmcb.
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
  systemctl restart apache2

Apache 2 must be reloaded or restarted with the help of the systemctl command”
sudo systemctl reload apache2.service

Step 2 – Set up the SSL certificate

Make sure your Apache 2 is working and listens on port 80. Verify using the ss command or netstat command:
sudo netstat -tulpn | grep ':80'
## or ##
sudo ss -tulpn | grep ':80'

Sample outputs:

tcp    LISTEN  0       128                        *:80                  *:*      users:(("apache2",pid=2550,fd=4),("apache2",pid=2549,fd=4),("apache2",pid=2548,fd=4))

All clients must connect to your server over port 80. Otherwise, you will not get validated for Let’s Encrypt certificate. From your desktop, run:
curl -I http://www42.cyberciti.biz
curl command outputs validting that we can connect to the port TCP port 80:

HTTP/1.1 200 OK
Date: Wed, 06 May 2020 19:30:43 GMT
Server: Apache/2.4.41 (Ubuntu)
Last-Modified: Wed, 06 May 2020 19:15:29 GMT
ETag: "15e-5a4ff965902a3"
Accept-Ranges: bytes
Content-Length: 350
Vary: Accept-Encoding
Connection: close
Content-Type: text/html

Let us edit the /etc/apache2/sites-available/www42.cyberciti.biz.conf, enter:
sudo nano /etc/apache2/sites-available/www42.cyberciti.biz.conf
At the top of file add the following three mod_md directives:

## Secure Apache with mod_md Let's Encrypt directives ##
ServerAdmin webmaster@cyberciti.biz
MDCertificateAgreement accepted
MDomain www42.cyberciti.biz

Where,

  • ServerAdmin webmaster@cyberciti.biz : mod_md will use this email address when registering your domains at Let’s Encrypt.
  • MDCertificateAgreement accepted : You must accept the Terms of Service conditions as set by Let’s Encrypt.
  • MDomain www42.cyberciti.biz : Declare a domain named that should be manged by mod_md to issue and renew certificates. You can use full domain name such as www.cyberciti.biz or cyberciti.biz or www42.cyberciti.biz. Make sure it matches to ServerName.

Here is my complete config file :

## Apache with mod_md Let's Encrypt ##
## mod_md config for Let's Encrypt ##
ServerAdmin webmaster@cyberciti.biz
MDCertificateAgreement accepted
MDomain www42.cyberciti.biz
 
## HTTP port 80 config ##
<VirtualHost *:80>
    ServerAdmin webmaster@cyberciti.biz
    ServerName www42.cyberciti.biz
    DocumentRoot /home/cyberciti.biz/html
    DirectoryIndex index.html
    ErrorLog ${APACHE_LOG_DIR}/www42.cyberciti.biz-error.log
    CustomLog ${APACHE_LOG_DIR}/www42.cyberciti.biz-access.log combined
    # Redirect all http requests to HTTPS (uncomment the following two lines when HTTPS issued) 
    # RewriteEngine On
    # RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>
 
## HTTPS Config ##
<VirtualHost *:443>
    SSLEngine on
    ServerAdmin webmaster@cyberciti.biz
    ServerName www42.cyberciti.biz
    DocumentRoot /home/cyberciti.biz/html
    DirectoryIndex index.html
    ErrorLog ${APACHE_LOG_DIR}/www42.cyberciti.biz-ssl-error.log
    CustomLog ${APACHE_LOG_DIR}/www42.cyberciti.biz-ssl-access.log combined
    # Turn on HTTP/2 
    Protocols h2 http/1.1
    # Set HTTP Strict Transport Security
    Header always set Strict-Transport-Security "max-age=63072000"
</VirtualHost>
## Only enable TLS v1.3 and avoid older protocols ##
SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1 -TLSv1.2
SSLHonorCipherOrder     off
SSLSessionTickets       off
 
## Turn on OCSP Stapling ##
SSLUseStapling On
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
 
## Permission for our DocumentRoot  ##
<Directory /home/cyberciti.biz/html>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

Turn on Apache’s mod_rewrite and mod_headers under Ubuntu

We have already declared a rewrite rule in our config, so we need mod_rewrite. Hence, type the following command:
sudo a2enmod rewrite
Enabling module rewrite.
To activate the new configuration, you need to run:
systemctl restart apache2

Turn on mod_headers too:
sudo a2enmod headers
Enabling module headers.
To activate the new configuration, you need to run:
systemctl restart apache2

Check for config errors, run:

sudo apache2ctl configtest
Syntax OK

Step 3 – Open HTTPS (TCP port 443) using the UFW firewall on Ubuntu

Run the following ufw command to open TCP port 443 for everyone:
sudo ufw allow 443/tcp comment 'accept secure Apache connections'
Verify it rules:
sudo ufw status
See “How To Configure Firewall with UFW on Ubuntu 20.04 LTS” for more info.

Step 4 – Obtaining an SSL certificate using mod_md

So far, we installed mod_md for Apache on Ubuntu, turned on all essential modules, and open required TCP ports using a firewall. It is time to restart our Apache 2 server to obtain the free TLS/SSL certificate using Let’s Encrypt certificate authority (CA). Therefore, restart the Apache 2 server:
sudo systemctl restart apache2.service
As soon as Apache 2 restarted mod_md will contact Let’s Encrypt and request a certificate for your domain. Typically it takes up to one minute. You can check the server error log or Apache’s mod_status page to see if the request was successful or not. Here is what you will see in erro.log file:
sudo tail -f /var/log/apache2/error.log
One can use the grep command too:
sudo grep 'The Managed Domain' /var/log/apache2/error.log
Sample outputs indicating that LE has issued us a free TLS/SSL certificate:

[Wed May 06 20:17:38.112849 2020] [md:notice] [pid 21777:tid 139807872861952] AH10059: The Managed Domain www42.cyberciti.biz has been setup and changes will be activated on next (graceful) server restart.

Of course we can visit server-status url too. For example:
http://www42.cyberciti.biz/server-status
http://your-public-ip-here/server-status

Managed Domain Status for Apache with mod_md Let's Encrypt
Click to enlarge

A graceful Apache 2 server restart now is recommended to activate the certificate:
sudo systemctl reload apache2.service

Step 5 – Test secure Apache 2 connection

All you have to do is type the following command or use a web browser such as Firefox/Chrome to make sure you are getting HTTPS connection:
curl -I https://www42.cyberciti.biz

mod_md status
curl command in action verify that our HTTPS connection is working and traffic is secured and encrypted

Here is outputs from SSL Lab’s test:
How To Secure Apache with Let's Encrypt on Ubuntu 20.04 LTS
My secure Apache server with Let’s Encrypt TLS/SSL running on Ubuntu 20.04 LTS and verified by SSL Lab’s test

Step 6 – Automatically renewing an SSL certificate using mod_md and watchdog_module

The mod_md uses mod_watchdog module, which provides programmatic hooks for other modules to run tasks such as renewing TLS/SSL certificates and more periodically. In other words, auto-renew mode requires mod_watchdog to be active in your server. Hence, verify that mod_watchdog is activated using the following command:
sudo apache2ctl -M
sudo apache2ctl -M | grep mod_watchdog

Loaded Modules:

 core_module (static)
 so_module (static)
 watchdog_module (static)
 http_module (static)
 unixd_module (static)
 access_compat_module (shared)
 alias_module (shared)
 auth_basic_module (shared)
 authn_core_module (shared)
 ....
 ..
 ...
 ssl_module (shared)
 status_module (shared)

Step 7 – Monitoring certificate status

Now we set up Apache with mod_md and got a free TLS/SSL from Let’s Encrypt. It is time to monitor status of our certificate. There are two ways. First open /server-status URL:
https://www42.cyberciti.biz/server-status
https://your-public-ip-here/server-status

Managed Domains Apache Status
Click to enlarge

Edit your server config file, run:
sudo nano /etc/apache2/sites-available/www42.cyberciti.biz.conf
Append the following:

<Location "/md-status">
  SetHandler md-status
</Location>

Save and close the file. Restart the server and run:
sudo systemctl restart apache2.service
curl https://www42.cyberciti.biz/md-status

Sample outputs:

{
  "version": "2.0.10",
  "managed-domains": [
    {
      "name": "www42.cyberciti.biz",
      "domains": [
        "www42.cyberciti.biz",
        "www43.cyberciti.biz"
      ],
      "contacts": [
        "mailto:webmaster@cyberciti.biz"
      ],
      "transitive": 1,
      "ca": {
        "proto": "ACME",
        "url": "https://acme-v02.api.letsencrypt.org/directory",
        "agreement": "accepted"
      },
      "state": 2,
      "renew-mode": 1,
      "renew-window": "33%",
      "warn-window": "10%",
      "must-staple": false,
      "cert": {
        "valid-from": "Wed, 06 May 2020 19:17:37 GMT",
        "valid-until": "Tue, 04 Aug 2020 19:17:37 GMT",
        "serial": "040E339A0A7D2224819A550BBB4596279F67",
        "sha256-fingerprint": "d78933fa946cb71810111876049defa4feb6820c319c69918ba925b463bbd11c"
      },
      "renew": false
    }
  ]
}

Conclusion

In this tutorial, you learned how to secure Apache with mod_md Let’s Encrypt module to issue and auto-renew free TLS/SSL certificate on Ubuntu Linux 20.04 LTS server. For more information, see mod_md documentation here.

This entry is 2 of 2 in the Linux, Apache, MySQL, PHP (LAMP) stack on Ubuntu 20.04 Tutorial series. Keep reading the rest of the series:
  1. How to install Apache on Ubuntu 20.04 LTS
  2. Secure Apache with mod_md Let’s Encrypt on Ubuntu 20.04 LTS

ADVERTISEMENTS

Posted by: Vivek Gite

The author is the creator of nixCraft and a seasoned sysadmin, DevOps engineer, and a trainer for the Linux operating system/Unix shell scripting. Get the latest tutorials on SysAdmin, Linux/Unix and open source topics via RSS/XML feed or weekly email newsletter.

Start the discussion at www.nixcraft.com