About | Blog

From HTTP/1.1 to HTTP/2 with Apache2

July 23, 2020

Almost two years ago I switched from HTTP/1.1 to HTTP/2 with Apache2. Here is what I did. If you want to know more about HTTP/2, read HTTP/1.1 vs HTTP/2: What's the Difference?.

Setup HTTPS

As most of the browsers supports HTTP/2 over TLS only, we first need to setup HTTPS. For instance, Firefox claims:

Firefox will only be implementing HTTP/2 over TLS - and so far that means for https:// schemed URLs (...).

Therefore, we'll use Let's Encrypt, which is a free, automated and open certificate authority and Certbot a free, open source software tool for automatically using Let’s Encrypt certificates on manually-administrated websites to enable HTTPS.

First, install Certbot:

# aptitude install certbot

To obtain a SSL certificate, launch:

certbot --apache -d yourdomain -d www.yourdomain

Just let you guide, and at the question Redirect non secure connection to secure connection?, answer Yes.

Maybe you have a firewall on your server that blocks SSL connexions. In my case, I had to configure my ferm firewall to open the 443 port:

# /etc/ferm/ferm.conf
domain (ip ip6) {
    table filter {
        chain INPUT {
            policy DROP;
            // ...
            proto tcp dport 443 ACCEPT;
            // ...

And that's it, it works out of the box! Cerbot updated the Apache configuration and provides a cron task to renew the certificate automatically before it expires (check the file /etc/cron.d/certbot).

For a more detailed guide about using Certbot with Apache, refer to How To Secure Apache with Let's Encrypt on Debian 9.

Setup HTTP/2

OK, now we have HTTPS on our domain, we can set up HTTP/2.

First you need to enable the http2 mode for Apache:

# a2enmod http2

Then you need to configure your virtual host:

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName yourdomain
    ServerAlias yourdomain.com
    Protocols h2 h2c http/1.1
    # ...

Reload Apache:

# systemctl reload apache2

Yeah, it should work! Let's check:

$ curl -I https://www.yourdomain
HTTP/1.1 200 OK
Date: Thu, 29 Nov 2018 22:45:14 GMT
Server: Apache
Cache-Control: no-cache, private
Upgrade: h2,h2c
Connection: Upgrade
Content-Type: text/html; charset=UTF-8

Houston, we've got a problem... The response tells us we are still using HTTP/1.1 🤔

Setup Apache2 with mpm-event

The answer is in the logs:

[Thu Nov 29 22:42:18.344846 2018] [http2:warn] [pid 2849] AH10034: The mpm module (prefork.c) is not supported by mod_http2. The mpm determines how things are processed in your server. HTTP/2 has more demands in this regard and the currently selected mpm will just not do. This is an advisory warning. Your server will continue to work, but the HTTP/2 protocol will be inactive.

HTTP/2 is not "supported" by MPM Prefork. I chose to use Event instead:

a2dismod mpm_prefork
a2enmod mpm_event
systemctl restart apache2

Check again if it works 🤞

$ curl -I https://www.jjanvier.com
HTTP/2 200 
date: Thu, 29 Nov 2018 22:51:20 GMT
server: Apache
cache-control: no-cache, private
content-type: text/html; charset=UTF-8

Perfect!

I didn't try yet to tweak it further, thanks to the H2PushResource directive for instance. That's enough for that blog.