Blog/Let's Encrypt with Apache and GnuTLS

From Forza's ramblings

2021-08-05: Let’s Encrypt with Apache httpd and mod_gnutls[edit | edit source]

Let's Encrypt is today the de-facto free and open certificate authority (CA). It provides users with free TLS certificates so they can enable HTTPS on their web servers and other services that uses TLS. Let's Encrypt has really helped the Internet as a whole to move to secure HTTPS communication.

Using tools such as Certbot it is possible to automate requesting new TLS certificates as well as automatically renew them when they are about to expire.

To learn more about how Let's Encrypt works, head over to https://letsencrypt.org/how-it-works/

mod_gnutls[edit | edit source]

mod_gnutls is an extension for ​Apache's httpd which uses the ​GnuTLS library to provide HTTPS (HTTP over TLS). It is an alternative to the more common mod_ssl. mod_gnutls supports:

mod_gnutls 0.12.0 contains important fixes that are needed to fully work with Let's Encrypt.

Certbot[edit | edit source]

If you have an Apache webserver, then Certbot is very easy to use. The basic command line to request a new TLS certificate would be:

# certbot --apache

This will present you a list of domains from your Apache config and asks you which one you want to enable HTTPS for.

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: tnonline.net
2: wiki.tnonline.net
3: www.tnonline.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):

Simply select the domain you want to create and install a TLS certificate for. This will update your corresponding Apache /etc/apache/vhosts.d/*.conf files with certificates and SSL settings:

# VirtualHost HTTPS (with SSL)
<VirtualHost *:443>
  ServerName    wiki.tnonline.net
  DocumentRoot  /var/www/domains/wiki.tnonline.net/htdocs/
 
###
# Certbot added config
# Adds certificates and SSL config.
###
  SSLCertificateFile    /etc/letsencrypt/live/wiki.tnonline.net/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/wiki.tnonline.net/privkey.pem
  Include               /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

# HTTP (no SSL)
<VirtualHost *:80>
  ServerName    wiki.tnonline.net
  DocumentRoot  /var/www/domains/wiki.tnonline.net/htdocs/

###
# Certbot added config
# Redirects visitors from HTTP to HTTPS
###
  RewriteEngine On
  RewriteCond   %{HTTPS} off
  RewriteCond   %{REQUEST_URI} !^/.well-known
  RewriteCond   %{SERVER_NAME} =wiki.tnonline.net
  RewriteRule   ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

The file /etc/letsencrypt/options-ssl-apache.conf contains OpenSSL specific settings such as what Cipher Suites and TLS protocols that should be enabled.

Certbot with GnuTLS[edit | edit source]

Unfortunately, Certbot's Apache installer does not support mod_gnutls which uses GnuTLS instead of OpenSSL for HTTPS. The Apache installer is able to look in apache config files to determine what domain names you have. It also uses a temporary vhost definition during certificate creation process. At the end it instructs Apache to reload its configuration, enabling the new certificates.

In order to use Certbot with GnuTLS you have to use the webroot authenticator which instructs certbot to use the http-01 challenge method using a pre-existing directory in your webserver. You also need to add the certificates and SSL configuration manually to your Apache VirtualHost config.

Using Certbot webroot installer[edit | edit source]

The command line for certbot webroot installer is:

# certbot certonly --webroot -w <DocumentRoot> -d <domain-name> --deploy-hook "<command>"

The Webroot installer needs the full path to your websites root. Usually this would be the DocumentRoot from you VirtualHost definition. In my case it is DocumentRoot /var/www/domains/wiki.tnonline.net/htdocs/.

# certbot certonly --dry-run --webroot -w /var/www/domains/wiki.tnonline.net/htdocs -d wiki.tnonline.net --deploy-hook "apache2ctl -k graceful"
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Simulating renewal of an existing certificate for wiki.tnonline.net
The dry run was successful.

NEXT STEPS:
- The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.

Certbot will create the directory /var/www/domains/wiki.tnonline.net/htdocs/.well-known/acme-challenge from which Let's Encrypt is fetching the challenge response needed to issue the certificate.

The --dry-run option is used to test the configuration and see that Let's Encrypt servers can access the challenge response in the .well-known directory, etc. Once you see that everything is working you run the command line without it.

Apache configuration[edit | edit source]

Activate mod_gnutls[edit | edit source]

After you have installed mod_gnutls you should make sure it is loaded instead of mod_ssl in your apache config. On my system I am loading mod_gnutls through the file /etc/apache2/modules.d/47_mod_gnutls.conf.

<IfDefine GNUTLS>
   LoadModule gnutls_module  modules/mod_gnutls.so
   LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
   
   # These options are used to improve TLS session and OCSP stapling.
   GnuTLSCache shmcb:/var/run/apache2/gnutls_cache(512000)
   GnuTLSOCSPCache shmcb:/var/run/apache2/gnutls_oscp_cache(512000)
</IfDefine>

IfDefine checks if apache was started with -D GNUTLS. Check with your distribution how to set it. Otherwise you can simply omit the <IfDefine> parts.

SSL Options[edit | edit source]

We also need to specify what SSL options your webserver should use and enable them for your virtual hosts/domains.

Create the file /etc/letsencrypt/options-gnutls-apache.conf with the following content:

# Enable mod_gnutls
GnuTLSEnable			on

# Use secure SSL options. These will enable TLS1.2, TLS 1.3 and secure cipher suites that are compatible with all modern browsers.
GnuTLSPriorities		PFS:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:+VERS-DTLS1.2:-GROUP-ALL:+GROUP-X25519:+GROUP-X448:+GROUP-SECP521R1:+GROUP-SECP384R1:+GROUP-SECP256R1:-SHA1:-MD5:-AES-256-CBC:-AES-256-CCM:-AES-128-CBC:-AES-128-CCM:-CIPHER-ALL:+CHACHA20-POLY1305:+AES-256-GCM:+AES-128-GCM:+SHA384:+SHA256:+AES-256-GCM:+ECDHE-ECDSA:+ECDHE-RSA:%SERVER_PRECEDENCE

# We need to turn off nonce checking as that isn't used by Let's Encrypt
GnuTLSOCSPCheckNonce	off

# How long to cache a TLS session, in seconds.
GnuTLSCacheTimeout		600

# How long to cache OCSP responses, in seconds.
GnuTLSOCSPCacheTimeout	259200
VirtualHost configuration[edit | edit source]

You need to include the GnuTLS options and the Let's Encrypt certificates in each of your VirtualHost sections.

For the wiki I use /etc/apache2/vhosts.d/wiki.tnonline.net.conf

# VirtualHost HTTPS (with SSL)
<VirtualHost *:443>
  ServerName    wiki.tnonline.net
  DocumentRoot  /var/www/domains/wiki.tnonline.net/htdocs/
 
###
# Add certificates and GnuTLS SSL config.
###
  SSLCertificateFile    /etc/letsencrypt/live/wiki.tnonline.net/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/wiki.tnonline.net/privkey.pem
  Include               /etc/letsencrypt/options-gnutls-apache.conf
</VirtualHost>

# HTTP (no SSL)
<VirtualHost *:80>
  ServerName    wiki.tnonline.net
  DocumentRoot  /var/www/domains/wiki.tnonline.net/htdocs/

###
# Redirect visitors from HTTP to HTTPS
###
  RewriteEngine On
  RewriteCond   %{HTTPS} off
  RewriteCond   %{REQUEST_URI} !^/.well-known
  RewriteCond   %{SERVER_NAME} =wiki.tnonline.net
  RewriteRule   ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

Apache Logging[edit | edit source]

GnuTLS uses different variables for logging. If you convert from mod_ssl to mod_gnutls you may need to change any LogFormat definitions using %{SSL_PROTOCOL}x %{SSL_CIPHER}x into %{SSL_PROTOCOL}e %{SSL_CIPHER}e

LogFormat "%v %h %t \"%r\" %>s %b %{SSL_PROTOCOL}e %{SSL_CIPHER}e \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined

Automatic renewal[edit | edit source]

It is important to set up a cron job that automatically renews your certificate before it expires. Let's Encrypt has a life-time of 90 days for their certificates.

Simply create a daily cronjob as:

/etc/cron.daily/certbot-renew
#!/bin/bash
/usr/bin/certbot renew 2>&1

Certbot will only renew certificates that are close to expiry, so it is recommended to let it run every day.

Renewal Hooks - reload Apache after renewal[edit | edit source]

A renewal hook is a script or program that certbot runs after a certificate is successfully renewed. You need to add a command that reloads the Apache config files. On most systems it would be apache2ctl -k graceful, systemctl reload apache2 or systemctl reload httpd. Check your distribution's manual to be sure.

Edit the file /etc/letsencrypt/renewal/wiki.tnonline.net.conf and make sure it has the renew_hook, authenticator, webroot_path and [webroot_map] sections specified.

version = 1.15.0
archive_dir = /etc/letsencrypt/archive/wiki.tnonline.net
cert = /etc/letsencrypt/live/wiki.tnonline.net/cert.pem
privkey = /etc/letsencrypt/live/wiki.tnonline.net/privkey.pem
chain = /etc/letsencrypt/live/wiki.tnonline.net/chain.pem
fullchain = /etc/letsencrypt/live/wiki.tnonline.net/fullchain.pem

# Options used in the renewal process
[renewalparams]
account = *redacted*
rsa_key_size = 4096
renew_hook = apache2ctl -k graceful
authenticator = webroot
server =  https://acme-v02.api.letsencrypt.org/directory
webroot_path = /var/www/domains/wiki.tnonline.net/htdocs

[webroot_map]
wiki.tnonline.net = /var/www/domains/wiki.tnonline.net/htdocs

Testing that HTTPS is working[edit | edit source]

You can use Qualys SSL Labs SSL Server test https://www.ssllabs.com/ssltest/index.html to check how well your server is performing. If all is OK you should receive an "A+" rating.

Getting Help[edit | edit source]

You can get help on the mod_gnutls mailing list or on IRC #mod_gnutls on the Libera.chat network. You can use the webchat to connect if you don't have an IRC client.

Let's Encrypt also has a big community forum over at https://community.letsencrypt.org

The full manual and source code can be found on https://github.com/airtower-luna/mod_gnutls/blob/main/doc/mod_gnutls_manual.md