Apache mod_md configuration

This guide assumes that you know how to edit the apache configuration file

This guide helps you to configure mod_md for automatic certificate enrollment and status reporting. More details about the module can be found in the official documentation. This configuration uses example.(com|org) as domain name. Substitute those with your own domain name(s). The #comments are merely for your information and you don't need to add them to your configuration files if you don't want to.

About mod_md

mod_md allows you to automatically request and renew certificates for the websites you host on an Apache server. It removes the reliance on a 3rd party component to handle certificates. It writes certificates to a configurable location and can call upon scripts when it performs actions, essentially allowing you to configure other services like an e-mail server to use the same certificates.

mod_md works well but is still experimental and requires Apache 2.4

Basic configuration

First, enable mod_md and mod_watchdog.

#Modules are normally loaded alphabetically,
#but the watchdog module must come before the md module
LoadModule watchdog_module modules/mod_watchdog.so
LoadModule md_module modules/mod_md.so

Note: If you use apache as a reverse proxy, make sure mod_rewrite is also enabled.

After enabling the module, add these lines to the global scope of your server configuration:

#License agreement for letsencrypt (default)
MDCertificateAgreement https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
#You can also use "RSA 3072". Supported for letsencrypt: RSA [size], secp256r1, secp384r1
MDPrivateKeys secp384r1 RSA 4096
#Set this to "permanent" once you verified that everything works.
MDRequireHttps temporary
#Set to "off" if you use buypass.com as a CA, or if OCSP fails too often.
MDMustStaple on
MDStapling on
#The section below can also be inside of a virtual host if you don't want the status available globally.
<Location "/md-status">
    SetHandler md-status
    #This is optional but it's a good idea to not expose your certificate setup to everybody.
    #Currently it contains localhost and the address range that the certificate monitor uses.
    Require local
    Require ip 46.140.111.80/28
</Location>

Make sure certificate stapling is disabled in mod_ssl. To do so, check for the line SSLUseStapling on and remove it, or set it to off

Virtual hosts

For every SSL virtual host you have and want managed by mod_md:

  1. Delete the lines SSLCertificateFile and SSLCertificateKeyFile
  2. Ensure the host has exactly one ServerName line in the format ServerName example.com. This domain must resolve to your server. It will be the one that's primarily shown in the certificate, so put your most important domain here (the one people will most likely have in their address bar).
  3. Add all other domains and subdomains via ServerAlias www.example.com example.org test.example.org. These domains must resolve to your server. They will all be included in the SSL certificate as alias names.
  4. Add the line MDomain example.com in the global scope, either directly above the virtual host, or back where you added the basic mod_md configuration values. The domain name must match the one from step 2

Restarting and checking results

After all these changes, restart apache. It will take a minute for the certificates to be issued. If you have the status module enabled, you can check the status page. You can also monitor the apache error log file. Certificate messages (success and failure) will be reported there. If you get error messages, the full json response from the CA is also included in the error line. It should contain more information about what went wrong. In most cases, the CA can't connect to your server because your firewall blocks their IP range, or you supplied a domain name that does not resolves back to you. You can use a tool like DNS watch to quickly check your domain.

<Location> vs. reverse proxies

If Apache answers a request it prefers RewriteRule and ProxyPass instructions over the "Location" entry for mod_md. This means a virtual host that acts as a reverse proxy will not be able to serve the certificate status data. This is only a problem if all virtual hosts are reverse proxies. You can access the "/md-status" URL on any host that serves regular files, and every status URL will report the status of all certificates. Because of that, no configuration change is necessary. You can try to access this URL yourself. If it works, you will be greeted with JSON data and you don't have to do the steps outlined below.

If all hosts that are usable for certificate status are reverse proxies, you need to either create a virtual host just for the status page, or change the configuration of one host to allow this URL to be bypassed. This is only necessary if /md-status would be passed through the reverse proxy as well. If your reverse proxy setup only handles some subdirectories, the md-status should work as-is.

Let's assume you have two virtual hosts, both configured as a reverse proxy as follows:

#Virtual host of (www.)example.org
<VirtualHost *:443>
    SSLEngine On
    ServerName example.org
    ServerAlias www.example.org
    DocumentRoot "${SRVROOT}/htdocs/null"
    #Method 1 of implementing a reverse proxy: using "ProxyPass"
    ProxyPass "/" "http://127.0.0.1:81/"
</VirtualHost>

#Virtual host of (www.)example.com
<VirtualHost *:443>
    SSLEngine On
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot "${SRVROOT}/htdocs/null"
    RewriteEngine On
    #Method 2 of implementing a reverse proxy: using "RewriteRule and P flag"
    RewriteRule "^.*$" "http://127.0.0.1:8080/$0" [P,L]
</VirtualHost>

If your reverse proxy is configured like in example 1, you have to change that virtual host to use the method in example 2. Conversion is simple:

  1. Add RewriteEngine On somewhere to the top of your virtual host
  2. Replace ProxyPass with RewriteRule
  3. Replace "/" with "^.*$"
  4. Add $0 to the end of the URL
  5. Add [P,L] to the end of the line
  6. Restart Apache and check if proxy functionality is retained

After you've made the changes, you want to add a few lines. First, add the entire "<Location>" block, then add the line RewriteRule "^/md-status" - [L] before the other rule. The final host will look like this:

<VirtualHost *:443>
    SSLEngine On
    RewriteEngine On
    ServerName example.org
    ServerAlias www.example.org
    DocumentRoot "${SRVROOT}/htdocs/null"
    #This is now in here instead of the global configuration
    <Location "/md-status">
        SetHandler md-status
        Require local
        Require ip 46.140.111.80/28
    </Location>
    #- The next line gets run if the URL begins with "/md-status"
    #- Let it handle the URL normally ("-" location)
    #- Makes Apache stop applying any other rules ("L" flag)
    RewriteRule "^/md-status" - [L]
    #If the previous rule is not executed, it lands here and is sent to the reverse proxy unconditionally.
    RewriteRule "^.*$" "http://127.0.0.1:8080/$0" [P,L]
</VirtualHost>

Don't forget to restart apache. If it refuses to start up, check the error log. You likely just made some syntax mistake.

Access restriction

All HTTP requests made by this system will originate from 46.140.111.80/28. This application passes the client IP address via the X-Forwarded-For header.
You can use the combination of these two to restrict access. A common example is to allow only your companies IP address to view MD status messages.

Since this header is easy to fake, do not evaluate it unless you verified that the connection originates from the given IP subnet.

Copyright © 2021 by Kevin Gut 📧 | More services | Generated for 3.15.25.34