Automatic HTTPS configuration for Apache
Recent versions of Apache contain a module,
mod_md
, which
will automatically obtain and renew HTTPS certificates from the Let’s
Encrypt project. If you are using a supported version of Apache, TIG
strongly recommends that you use this mechanism rather than manually
requesting certificates from InCommon as described in “Requesting an
SSL certificate”, although there
are a few caveats:
- Let’s Encrypt applies a rate limit across the whole
mit.edu
domain of 50 new domains per week, so depending on what other people are doing on campus, you might have to wait. (This limit does not apply to renewals.) mod_md
does not currently (July, 2020) support generating Elliptic Curve keys, which are nowadays preferred over RSA keys. This is expected to be rectified in the future.- If you are using Ubuntu, 18.04LTS (“Bionic”) has too old an Apache
release to support
mod_md
. You will need to upgrade to 20.04 (“Focal”) first. - If you are sharing the same certificate between multiple services (say, a web server and an IMAP server) this is probably not the best approach, and you should obtain InCommon certificates instead.
On the positive side, Let’s Encrypt works with any domain name you can
arrange to point to your server, even if it’s not a subdomain of
csail.mit.edu
, which makes it the only practical way to have HTTPS
for example.csail.mit.edu
, example.mit.edu
, and example.org
on
the same server.
Procedure
The following steps assume you are using Apache 2.4.41 as packaged for Ubuntu 20.04LTS (“Focal”). The same concepts will apply to other operating systems but you may have to perform some of the steps manually or using other tools. If you have 2.4.42 or later, you should turn OCSP stapling on in the configuration as described in a comment below.
Fix the default server configuration
Check all of the Apache configuration files in
/etc/apache2/sites-enabled
for a ServerAdmin
directive.
Make certain that the ServerAdmin
directive is present and contains
your valid email address.
(mod_md
cannot sign up for a Let’s Encrypt account on your behalf
without a valid email address.)
Enable the requisite Apache modules
sudo a2enmod md
sudo a2enmod ssl
sudo a2enmod http2
Create a configuration for the HTTPS virtual host
You will need both server-global configuration and some directives
that are specific to a VirtualHost
container, but in the normal case
these can all go in one file, such as
/etc/apache2/sites-enabled/000-ssl.conf
:
# This tells Let's Encrypt who you are, and may be used to send
# notifications to you if the renewal automation breaks for some
# reason.
ServerAdmin YOUR-EMAIL-HERE@csail.mit.edu
# This is the primary server name of the certificate. While you can
# list other names on this line, usually "auto" will do the thing you
# want -- it will find all the ServerName and ServerAlias directives
# in your server configuration and get certificates for all of them.
MDomain SERVER-NAME-HERE.csail.mit.edu auto
# This is your consent to Let's Encrypt's terms and conditions.
MDCertificateAgreement accepted
# This automatically configures your HTTP virtual hosts to redirect to
# HTTPS and sets a `Strict-Transport-Security:` HTTP header to tell
# browsers to always use HTTPS even if the user follows an `http://` link.
MDRequireHttps permanent
# Override the poor choice of `SSLCipherSuite` in the default Ubuntu
# mod_ssl configuration. Must be all on one line.
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
# Disable a low-security session resumption feature.
SSLSessionTickets off
# Enable HTTP/2 in addition to regular HTTP and the TLS-based ACME
# server identity verification protocol.
Protocols h2 http/1.1 acme-tls/1
# Modern HTTPS uses the server name given in the ServerName directive
# to distinguish virtual hosts. All VirtualHost containers should
# specify the same argument (usually "*:443") and MUST have different
# ServerName directives. Usually you only need one.
<VirtualHost *:443>
ServerName SERVER-NAME-HERE.csail.mit.edu
DocumentRoot /var/www/html
# mod_md will take care of obtaining certificates via Let's Encrypt
# so this directive is all you need in each VirtualHost container
SSLEngine on
# Ubuntu 20.04 focal has Apache 2.4.41, which is one release too
# early to support OCSP stapling. If you have 2.4.42 or later,
# uncomment the following:
#MDStapling on
</VirtualHost>
Restart Apache and wait
sudo systemctl restart apache2
tail -f /var/log/apache2/error.log
Note that you must fully restart
Apache for the new configuration to
take effect; a reload
is not sufficient.
Wait for mod_md
to log the following message to
/var/log/apache2/error.log
:
AH10059: The Managed Domain SERVER-NAME-HERE.csail.mit.edu has been setup and changes will be activated on next (graceful) server restart.
If mod_md
fails to set itself up with Let’s Encrypt for some reason,
Apache will log an error like the following:
AH10085: Init: SERVER-NAME-HERE.csail.mit.edu:443 will respond with '503 Service Unavailable' for now. There are no SSL certificates configured and no other module contributed any.
Check error.log
for more information about why it failed—probably
you either had an invalid ServerAdmin
directive in your
configuration somewhere, or else mit.edu
is being rate-limited.
Restart Apache again
This step is necessary to load the newly obtained certificates into the server and start serving HTTPS.
sudo apache2ctl graceful
Testing your server
TIG recommends that you use Qualys SSL Server Test to check your server configuration for known security flaws. As of this writing, the configuration shown above is sufficient to get an “A+” grade from Qualys.