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.
Tutorial requirements
Operating system/appUbuntu Linux with Apache 2
Root privileges requiredYes
DifficultyEasy (rss)
Estimated completion time15m
Table of contents

ADVERTISEMENTS


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
MDPrivateKeys RSA 4096

Where,

  • ServerAdmin webmaster@cyberciti.biz : mod_md will use this email address when registering your domains at Let’s Encrypt.
  • MDCertificateAgreement accepted[donotprint][/donotprint] : 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.
  • MDPrivateKeys RSA 4096 : Set type and size of the private keys generated.

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
MDPrivateKeys RSA 4096
 
## 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 20.04 LTS Linux server. For more information, see mod_md documentation here. Keep reading read of the series:

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

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.


ADVERTISEMENTS

2 comment

  1. I am getting the following error when installing Let’s Encrypt SSL on my domain:

    Waiting for verification…
    Challenge failed for domain linuxbuz.com
    dns-01 challenge for linuxbuz.com
    Cleaning up challenges
    Some challenges have failed.

Leave a Comment