<-
Apache > HTTP Server > Documentation > Version 2.4 > Modules

Apache Module mod_md

Available Languages:  en  |  fr 

Description:Managing domains across virtual hosts, certificate provisioning via the ACME protocol
Status:Experimental
Module Identifier:md_module
Source File:mod_md.c
Compatibility:Available in version 2.4.30 and later

Summary

This module manages common properties of domains for one or more virtual hosts. Its serves two main purposes: for one, supervise/renew TLS certificates via the ACME protocol (RFC 8555). Certificates will be renewed by the module ahead of their expiration to account for disruption in internet services. There are ways to monitor the status of all certififcates managed this way and configurations that will run your own notification commands on renewal, expiration and errors.

Second, mod_md offers an alternate OCSP Stapling implementation. This works with managed certificates as well as with certificates you configure yourself. OCSP Stapling is a necessary component for any https: site, influencing page load times and, depending on other setups, page availability. More in the stapling section below.

The default ACME Authority for managing certificates is Let's Encrypt, but it is possible to configure another CA that supports the protocol.

Simple configuration example:

TLS in a VirtualHost context

MDomain example.org

<VirtualHost *:443>
    ServerName example.org
    DocumentRoot htdocs/a

    SSLEngine on
    # no certificates specification
</VirtualHost>

This setup will, on server start, contact Let's Encrypt to request a certificate for the domain. If Let's Encrypt can verify the ownership of the domain, the module will retrieve the certificate and its chain, store it in the local file system (see MDStoreDir) and provide it, on next restart, to mod_ssl.

This happens while the server is already running. All other hosts will continue to work as before. While a certificate is not available, requests for the managed domain will be answered with a '503 Service Unavailable'.

Prerequisites

This module requires mod_watchdog to be loaded as well.

Certificate sign-up and renewal with Let's Encrypt requires your server to be reachable on port 80 (http:) and/or port 443 (https:) from the public internet. (Unless your server is configured to use DNS for challenges - more on that under 'wildcard certificates')

The module will select from the methods offered by Let's Encrypt. Usually LE offers challenges on both ports and DNS and Apache chooses a method available.

To determine which one is available, the module looks at the ports Apache httpd listens on. If those include port 80, it assumes that the http: challenge (named http-01) is available. If the server listens on port 443, the https: challenge (named tls-alpn-01) is also added to the list. (And if MDChallengeDns01 is configured, the challenge dns-01 is added as well.)

If your setup is not so straight forward, there are two methods available to influence this. First, look at MDPortMap if the server is behind a portmapper, such as a firewall. Second, you may override the module's guesswork completely by configuring MDCAChallenges directly.

https: Challenges

For domain verification via the TLS protocol `tls-alpn-01` is the name of the challenge type. It requires the Apache server to listen on port 443 (see MDPortMap if you map that port to something else).

Let's Encrypt will open a TLS connection to Apache using the special indicator `acme-tls/1` (this indication part of TLS is called ALPN, therefore the name of the challenge. ALPN is also used by browsers to request a HTTP/2 connection).

As with the HTTP/2 protocol, to allow this, you configure:

Protocols h2 http/1.1 acme-tls/1

And the `tls-alpn-01` challenge type is available.

Wildcard Certificates

Wildcard certificates are possible, but not straight-forward to use out of the box. Let's Encrypt requires the `dns-01` challenge verification for those. No other is considered good enough.

The difficulty here is that Apache cannot do that on its own. As the name implies, `dns-01` requires you to show some specific DNS records for your domain that contain some challenge data. So you need to _write_ your domain's DNS records.

If you know how to do that, you can integrated this with mod_md. Let's say you have a script for that in `/usr/bin/acme-setup-dns` you configure Apache with:

MDChallengeDns01 /usr/bin/acme-setup-dns

and Apache will call this script when it needs to setup/teardown a DNS challenge record for a domain.

Assuming you want a certificate for `*.mydomain.com`, mod_md will call:

/usr/bin/acme-setup-dns setup mydomain.com challenge-data
# this needs to remove all existing DNS TXT records for 
# _acme-challenge.mydomain.com and create a new one with 
# content "challenge-data"

and afterwards it will call

/usr/bin/acme-setup-dns teardown mydomain.com
# this needs to remove all existing DNS TXT records for 
# _acme-challenge.mydomain.com

Monitoring

Apache has a standard module for monitoring: mod_status. mod_md contributes a section and makes monitoring your domains easy.

You see all your MDs listed alphabetically, the domain names they contain, an overall status, expiration times and specific settings. The settings show your selection of renewal times (or the default), the CA that is used, etc.

The 'Renewal' column will show activity and error descriptions for certificate renewals. This should make life easier for people to find out if everything is all right or what went wrong.

If there is an error with an MD it will be shown here as well. This let's you assess problems without digging through your server logs.

There is also a new 'md-status' handler available to give you the MD information from 'server-status' in JSON format. You configure it as

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

on your server. As with 'server-status' you will want to add authorization for this.

If you just want to check the JSON status of a specific domain, simply append that to your status url:

> curl https://<yourhost>/md-status/another-domain.org
{
  "name": "another-domain.org",
  "domains": [
    "another-domain.org",
    "www.another-domain.org"
  ],
  ...

This JSON status also shows a log of activities when domains are renewed:

{
"when": "Wed, 19 Jun 2019 14:45:58 GMT",
"type": "progress", "detail": "The certificate for the managed domain has been renewed successfully and can be used. A graceful server restart now is recommended."
},{
"when": "Wed, 19 Jun 2019 14:45:58 GMT",
"type": "progress", "detail": "Retrieving certificate chain for test-901-003-1560955549.org"
},{
"when": "Wed, 19 Jun 2019 14:45:58 GMT",
"type": "progress", "detail": "Waiting for finalized order to become valid"
},{
"when": "Wed, 19 Jun 2019 14:45:50 GMT",
"type": "progress", "detail": "Submitting CSR to CA for test-901-003-1560955549.org"
},
...

You will also find this information in the file `job.json` in your staging and, when activated, domains directory. This allows you to inspect these at any later point in time as well.

In addition, there is MDCertificateStatus which gives access to relevant certificate information in JSON format.

Stapling

If you want to try the stapling in one Managed Domain alone at first, configure:

<MDomain mydomain.net>
  MDStapling on
</MDomain>

and use the 'server-status' and/or MDMessageCmd to see how it operates. You will see if Stapling information is there, how long it is valid, from where it came and when it will be refreshed.

If this all works to your satisfaction, you can switch it on for all your certificates or just your managed ones.

The existing stapling implementation by mod_ssl is used by many sites for years. There are two main differences between the mod_ssl and mod_md one:

  1. On demand vs. scheduled: mod_ssl retrieves the stapling information when it is requested, e.g. on a new connection. mod_md retrieves it right at server start and after 2/3rds of its lifetime.
  2. In memory vs. persisted: mod_ssl can persist this information, but most example configurations use a memory cache. mod_md always stores in the file system.

If you are unlucky and restart your server during an outage of your CA's OCSP service, your users may no longer reach your sites. Without persistence your server cannot provide the client with the data and the client browser cannot get it as well, since the OCSP service is not responding.

The implementation in mod_md will have persisted it, load it again after restart and have it available for incoming connections. A day or two before this information expires, it will renew it, making it able to cope with a long OCSP service downtime.

Due to backward compatibility, the existing implementation in mod_ssl could not be changed drastically. For example, mod_ssl is unable to add a dependency to mod_watchdog without braking many existing installations (that do not load it).

tailscale

Since version 2.4.14 of the module, you can use it to get certificates for your tailscale domains.

<MDomain mydomain.some-thing.ts.net>
  MDCertificateProtocol tailscale
  MDCertificateAuthority file://localhost/var/run/tailscale/tailscaled.sock",
</MDomain>

Tailscale provides secure networking between your machines, where ever they are, and can provide domain names in the *.ts.net space for them. For those, it will then provide Let's Encrypt certificates as well, so you can open these domains in your browser securely.

The directives listed above tell Apache to contact the local tailscale demon for obtaining and renewing certificates. This will only work for the domain name that tailscale assigns to your machine.

Otherwise, these certificates work exactly like the ones retrieved via the ACME protocol from Lets Encrypt. You see them in status reporting and MDMessageCmd directives are executed for them as well.

More details are available at the mod_md github documentation.

Note that this feature only works on machines where the tailscale demon provides a unix domain socket. This, so far, seems only the case on *nix systems.

Support Apache!

Directives

Bugfix checklist

See also

top

MDActivationDelay Directive

Description:How long to delay activation of new certificates
Syntax:MDActivationDelay duration
Context:server config
Status:Experimental
Module:mod_md
Compatibility:Available in version 2.4.42 and later

top

MDBaseServer Directive

Description:Control if base server may be managed or only virtual hosts.
Syntax:MDBaseServer on|off
Default:MDBaseServer off
Context:server config
Status:Experimental
Module:mod_md

Controls if the base server, the one outside all VirtualHosts should be managed by mod_md or not. By default, it will not. For the very reason that it may have confusing side-effects. It is recommended that you have virtual hosts for all managed domains and do not rely on the global, fallback server configuration.

top

MDCAChallenges Directive

Description:Type of ACME challenge used to prove domain ownership.
Syntax:MDCAChallenges name [ name ... ]
Default:MDCAChallenges tls-alpn-01 http-01 dns-01
Context:server config
Status:Experimental
Module:mod_md

Sets challenge types (in order of preference) when proving domain ownership. Supported by the module are the challenge methods 'tls-alpn-01', 'dns-01' and 'http-01'. The module will look at the overall configuration of the server to find out which methods can be used.

If the server listens on port 80, for example, the 'http-01' method is available. The prerequisite for 'dns-01' is a configured MDChallengeDns01 command. 'tls-alpn-01' is described above in 'https: Challenges'.

This auto selection works for most setups. But since Apache is a very powerful server with many configuration options, the situation is not clear for all possible cases. For example: it may listen on multiple IP addresses where some are reachable on `https:` and some not.

If you configure MDCAChallenges directly, this auto selection is disabled. Instead, the module will use the configured challenge list when talking to the ACME server (a challenge type must be offered by the server as well). This challenges are examined in the order specified.

top

MDCertificateAgreement Directive

Description:You confirm that you accepted the Terms of Service of the Certificate Authority.
Syntax:MDCertificateAgreement accepted
Context:server config
Status:Experimental
Module:mod_md

When you use mod_md to obtain a certificate, you become a customer of the CA (e.g. Let's Encrypt). That means you need to read and agree to their Terms of Service, so that you understand what they offer and what they might exclude or require from you. mod_md cannot, by itself, agree to such a thing.

top

MDCertificateAuthority Directive

Description:The URL(s) of the ACME Certificate Authority to use.
Syntax:MDCertificateAuthority url
Default:MDCertificateAuthority letsencrypt
Context:server config
Status:Experimental
Module:mod_md

The URL(s) where the CA offers its service. Instead of the actual URL, you may use 'letsencrypt' or 'buypass'.

If you configure more than one URL, each one is tried in a round-robin fashion after a number of failures. You can configure how quickly or delayed that happens via the MDRetryDelay and MDRetryFailover directives. The default setting makes a failover after about half a day of trying.

All other settings apply to each of these URLs. It is therefore not possible to have two with different MDExternalAccountBindings, for example.

For testing, CAs commonly offer a second service URL. The 'test' service does not give certificates valid in a browser, but are more relaxed in regard to rate limits. This allows for verfication of your own setup before switching to the production service URL.

LE Test Setup

MDCertificateAuthority https://acme-staging-v02.api.letsencrypt.org/directory
top

MDCertificateCheck Directive

Description:Set name and URL pattern for a certificate monitoring sitSet name and URL pattern for a certificate monitoring sitee
Syntax:MDCertificateCheck name url
Context:server config
Status:Experimental
Module:mod_md
Compatibility:Available in version 2.4.42 and later