How to enable HTTP/2 in Apache 2.4 on Gentoo Linux

I recently added support for the HTTP/2 protocol on this server and I am really pleased with the additional performance gains. This VPS was already running a functional LAMP stack, so the following steps describe the necessary configuration changes for my setup which relies on Apache with PHP-FPM.

HTTP2 on Gentoo Linux

blog.paranoidpenguin.net responding over the HTTP/2 (h2) protocol.

This guide is more extensive than necessary. The USE flags will obviously pull in the needed dependencies so strictly speaking, there is really no need to split the process down to installing individual packages. The threads USE flag can also be set globally instead of per package.

Additional packages

To build Apache with HTTP/2 support we need to add the HTTP/2 C library. Install the nghttp2 package and its dependencies with the command:

emerge -av net-libs/nghttp2

PHP-FPM

Before rebuilding Apache with HTTP/2 support, I’ll add the threads USE flag to PHP. Add the threads USE flag to your existing list of PHP flags by editing /etc/portage/package.use/php:

# /etc/portage/package.use/php
dev-lang/php cli curl exif fpm ftp gd mysql mysqli pdo threads zip xmlwriter

The additional PHP USE flags I’ve selected are needed for my WordPress installation but your taste may differ.

Apache

To use HTTP/2, it’s necessary to switch from the default prefork implementation to the Apache event or worker MPM. The Gentoo Wiki provides additional details here.

With nghttp2 installed, let’s switch to the Apache event MPM and add http2 to the list of Apache modules we want to build. Edit /etc/portage/make.conf:

# /etc/portage/make.conf

# Profile used for building.
USE="bindist mmx sse sse2 -pulseaudio -systemd apache2 php"

# Build PHP extensions
PHP_TARGETS="php7-0 php7-1"

# Use Apache MPM event
APACHE2_MPMS="event"

# Build the following Apache modules
APACHE2_MODULES="$APACHE2_MODULES http2 log_forensic proxy proxy_fcgi"

The proxy and proxy_fcgi Apache modules are needed for running Apache with PHP-FPM. Make sure PHP_TARGETS reflects your installed PHP version(s) if needed. I also recommend having apache2 and php defined as global USE flags.

We also need to enable the Apache threads USE flag by adding the following directive to /etc/portage/package.use/apache:

# /etc/portage/package.use/apache
www-servers/apache threads

Rebuild and configure the system

Finally, the system has to be updated to reflect the necessary changes. Run the following emerge command to rebuild packages with new USE flags:

emerge -avuND @world

For a fresh install, emerging PHP will also pull in Apache provided that apache2 is defined as a global USE flag.

emerge -av dev-lang/php

Enable the http2_module

The last step required is to edit /etc/conf.d/apache2 and to add the HTTP2 variable to your APACHE2_OPTS section.

APACHE2_OPTS="-D DEFAULT_VHOST -D SSL -D SSL_DEFAULT_VHOST -D LANGUAGE -D SECURITY -D PHP -D PROXY -D HTTP2"

Adding -D HTTP2 will toggle the following section to true and load the module:

# /etc/apache2/httpd.conf
<IfDefine HTTP2>
LoadModule http2_module modules/mod_http2.so
</IfDefine>

You’ll find the configuration file for HTTP/2 located under /etc/apache2/modules.d/41_mod_http2.conf. It enables the HTTP/2 protocol for all SSL enabled sites.

# /etc/apache2/modules.d/41_mod_http2.conf 
<IfDefine SSL>
  <IfModule http2_module>    
    Protocols h2 h2c http/1.1
  </IfModule>
</IfDefine>

Restart Apache and verify that everything is working as intended.

/etc/init.d/apache2 restart

ModSecurity

Older implementations of ModSecurity might block HTTP/2 requests due to an unknown protocol versions. Let’s add a “fix” to the core rule set by modifying the section specifying allowed http versions. Modify /etc/apache2/modules.d/80_modsecurity-crs.conf and append HTTP/2.0 to the allowed http version list:

# /etc/apache2/modules.d/80_modsecurity-crs.conf
setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2.0', \

Restart Apache, and we should be good.