blog/_posts/2018-11-18-how-to-enable-ht...

169 lines
7.2 KiB
Markdown

---
title: "How to enable HTTP2 on Apache (Debian 9) ?"
date: 2018-11-18
url: how-to-enable-http2-on-apache-debian-9
layout: post
category: Tutorials
image: /img/blog/how-to-enable-http2-on-apache-debian-9_1.png
description: "A complete guide to enable HTTP/2 on Apache (httpd) and Debian 9"
---
[![A missing blog post image](/img/blog/how-to-enable-http2-on-apache-debian-9_1.png)](/img/blog/how-to-enable-http2-on-apache-debian-9_1.png)
### Introduction
The [release notes of Debian 9 (Stretch)](https://www.debian.org/News/2017/20170617) announced an interesting major upgrade among the others : Apache 2.4.25 .
Why "interesting" though ? :thinking:
Mostly because it was the first release containing an Apache package >= 2.4.17, the pivot version introducing HTTP/2 (**SPDY**) support, with [`mod_http2`](https://httpd.apache.org/docs/2.4/mod/mod_http2.html).
If you are still wondering whether your web servers or reverse proxies should offer this protocol, I invite you to read [this famous FAQ](https://http2.github.io/faq/).
> Pro hint : Have you ever wonder why Google or YouTube are _that_ fast ? :smirk:
At the end of this post, you will have (I hope) a running Apache with HTTP/2 enabled globally (on all your served websites).
Ready ? Let's go then !
### Setup procedure
#### One new module, one new configuration
Before anything else, let's check that you are running a decent Apache version for HTTP/2 :
`# apache2ctl -v`
This should give you (at the very least) something like :
`Server version: Apache/2.4.25 (Debian)`
Now, we will enable the `mod_http2` module presented above :
`# a2enmod http2`
Before restarting Apache (as the command output has just advised you), we will indicate to use the new protocol through configuration (as good sysadmins, we will preserve the modularity :wink:) :
`# nano /etc/apache2/conf-available/http2.conf`
... and copy-paste this configuration :
{% highlight apache %}
<IfModule http2_module>
Protocols h2 h2c http/1.1
H2Direct On
</IfModule>
{% endhighlight %}
And here, we only have to enable our new configuration :
`# a2enconf http2`
> Pro tip : The configuration above would enable HTTP/2 **globally**.
> If you want to enable it for a specific VHOST only, please do paste the configuration above inside it directly !
> Pro tip 2 : `h2` is for HTTP/2 over TLS & ALPN, and `h2c` is for clear text HTTP/2 negotiation (usually you won't need it, but who knows ?).
So, now, you could already restart your web server (`# systemctl restart apache2`) and check the results, but I tell you this : The odds might not be good.
> _\[http2:warn\] \[pid XXXX\] 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._
#### The MPM problem
Apache 2.4 works by default with the **MPM prefork** module, which stands for **Multi-Processing Module prefork** module (yeah I know, there is "module" two times within the sentence :woman_shrugging:).
And guess what ? **MPM** is not compatible with HTTP/2 :joy:
So, as we really really want to offer HTTP/2, we will be using the PHP's **FPM** interpreter (standing for **FastCGI Process Manager**) which is... compatible with HTTP/2 !
#### The FPM "solution"
Below is the recipe to follow (see sources at the end of the post) :
1. Install the PHP's FPM package (I assume here that you have kept the [official Stretch PHP version](https://packages.debian.org/stretch/php7.0)) : `# apt install php7.0-fpm`
2. Enable some required modules : `# a2enmod proxy_fcgi setenvif`
3. Enable the PHP's FPM new configuration : `# a2enconf php7.0-fpm`
4. Disable the old modules that won't be used anymore : `# a2dismod php7.0 mpm_prefork`
5. Enable the [MPM `event` module](https://httpd.apache.org/docs/current/mod/event.html), as a substitute to `prefork` : `# a2enmod mpm_event`
Now, you can restart your web server with more guarantees :relieved:
`# systemctl restart apache2`
### Verification time !
At this step, I assume you have enforced the HTTP/2 configuration above and correctly restarted Apache !
Now is the time to verify our setup, this is X-mas, so many ways to achieve so :
#### Basic `curl` queries
With a verbose `curl`, assuming it has been compiled against HTTP/2 module of course, you may easily check that HTTP/2 is being (or will be) used :
`$ curl -v https://your.domain.name/`
Just watch for HTTP version written down along verbs or status codes.
For a HTTPS VHOST, this is a typical output that you may expect :
{% highlight text %}
[...]
* ALPN, offering h2
* ALPN, offering http/1.1
[...]
* ALPN, server accepted to use h2
[...]
* Using HTTP2, server supports multi-use
[...]
> GET / HTTP/2
[...]
< HTTP/2 200
[...]
{% endhighlight %}
#### A pretty handy web tool available anywhere
<https://http2.pro/> allows you to check remotely whether HTTP/2 is enforced or not.
It is also able to check if ALPN and PUSH are well-supported.
[![A missing blog post image](/img/blog/how-to-enable-http2-on-apache-debian-9_2.png)](/img/blog/how-to-enable-http2-on-apache-debian-9_2.png)
**TL;DR** : Click on the link and write down your URL :smirk:
#### Firefox Developer's toolbox
Open your favorite developer tool panel, and jump into the **Network** category. Then, reload your page, and click on a request (example with <https://peertube.xyz>) :
[![A missing blog post image](/img/blog/how-to-enable-http2-on-apache-debian-9_3.png)](/img/blog/how-to-enable-http2-on-apache-debian-9_3.png)
You should watch for the `X-Firefox-Spdy` response header (with a `h2` value over TLS), or the `Version` field specified under the `Status code` :heart_eyes:
#### A Firefox add-on !
Generally, if you want to know during your browsing whether your hosts run HTTP/2 or not, I advise you [this browser extension](https://addons.mozilla.org/en-US/firefox/addon/http2-indicator/).
> The image of this very blog post has been taken from their source code repository ; All credits go to its authors !
### "It still does not work..."
> Yeah it's possible, you may have a custom specific configuration :man_shrugging:
But this is what I can tell you : [HTTP/2 requires TLS 1.2, without compression, without renegotiation, and without some holed ciphers](https://tools.ietf.org/html/rfc7540#section-9.2).
Anyway, I invite you to take a look at my Apache hardening guide [here]({% post_url 2017-11-14-hardening-apache-all-in-one-place %}) !
### Conclusion
To conclude, I'd say that we had to wait for a 2018 Linux distribution to enable HTTP/2, whereas its RFC has been drafted in 2015.
Nevertheless, I couldn't publish this post without mentioning the fact that HTTP/3 (**QUIC**) ~~again originally designed by Google~~ is currently in [the process of being accepted by the IETF](https://www.zdnet.com/article/http-over-quic-to-be-renamed-http3/).
I hope (as always) this helped you, don't hesitate to send a feedback or a fix below :bow:
### Sources (additionally to all the links above)
* [how to h2 in apache](https://icing.github.io/mod_h2/howto.html)
* [How to enable HTTP/2 support in Apache](https://http2.pro/doc/Apache)