Skip to content

Allow HTTP/2 with HTTP/1.1 Fallback

This guide explains how to configure Apache to prefer HTTP/2 (h2) while still allowing fallback to HTTP/1.1 for clients that do not support the newer protocol. This ensures optimal performance for modern browsers while maintaining compatibility with legacy systems. Alternatively, if you want to enforce HTTP/2 only and completely disable HTTP/1.1, the guide also shows how to configure Apache, ensuring that only clients supporting HTTP/2 can connect.

It includes all necessary steps, explanations, configuration examples, and verification commands based on the official Apache documentation.

This setup applies to Linux-based systems, especially Debian-based distributions such as Ubuntu, where Apache is installed via package managers and modules are managed using a2enmod.

It may also be adapted for other Unix-like systems (e.g. CentOS, Fedora, Arch), but paths and module management commands may differ slightly.

Prerequisites

  • Apache version 2.4.17 or higher (required for HTTP/2 support)
  • SSL certificate already configured
  • Root access to your server

Summary: If the HTTP/2 module is active, you can view an example of how the configuration file default-ssl.conf might look.


Step 1: Verify if mod_http2 is Installed and Enabled

Apache requires the mod_http2 module to support HTTP/2. To check if it’s enabled, open a terminal on your server and run:

apache2ctl -M | grep http2

If you see http2_module (shared), it means the module is active, and you can proceed to Step 2.

If there is no output, enable the module with:

sudo a2enmod http2
sudo systemctl restart apache2
After activation, it is important to verify once more that the http2_module is correctly loaded by running the above check command again. This ensures that the module was successfully enabled and Apache restarted properly.

On Ubuntu/Debian systems, enabling the module via a2enmod automatically loads it, so you don’t need to manually add the LoadModule line. However, for reference, the module is loaded via:

LoadModule http2_module modules/mod_http2.so


Step 2: Understand the Protocols Directive

Note: This chapter is for informational purposes. If you are already familiar with Apache’s protocol negotiation and the Protocols directive, you may safely skip Step 2 and move directly to Step 3 or just read the Apache Protocol Selection Overview.

Apache’s Protocols directive controls which HTTP versions your server supports and in which order.

The official documentation often shows configurations like:

Protocols h2 http/1.1
This means the server supports both HTTP/2 (h2) and HTTP/1.1, with HTTP/2 preferred. The order is important: the first protocol is the preferred one.

You might also see:

Protocols h2 h2c http/1.1
which enables all HTTP/2 variants (secure h2 and cleartext h2c) plus HTTP/1.1 fallback.

You can place the Protocols directive globally or inside specific virtual hosts. For example:

Protocols http/1.1

<VirtualHost *:443>
    ServerName test.example.org
    Protocols h2 http/1.1
</VirtualHost>
This configuration enables only HTTP/1.1 globally but HTTP/2 plus HTTP/1.1 fallback on the test.example.org SSL host. If you want a particular site to use a different protocol setup, you can override the global settings within its <VirtualHost> block.

You can also add the ProtocolsHonorOrder directive together with Protocols, which controls whether Apache strictly enforces your preferred protocol order or allows clients to choose their preferred protocol.

Protocols http/1.1
ProtocolsHonorOrder off

<VirtualHost *:443>
    ServerName test.example.org
    Protocols h2
    ProtocolsHonorOrder On
</VirtualHost>

This configuration sets HTTP/2 and HTTP/1.1 as globally available protocols, with ProtocolsHonorOrder off, meaning Apache allows clients to choose their preferred protocol rather than strictly following the server’s order. In practice, this means a client that supports both HTTP/2 and HTTP/1.1 might still choose to use HTTP/1.1 globally — even if HTTP/2 is listed first.

However, for the virtual host test.example.org, the configuration explicitly enables only HTTP/2 and sets ProtocolsHonorOrder On. This instructs Apache to strictly enforce the server’s protocol preference for that host, ensuring that clients connecting to test.example.org will use HTTP/2 if they support it, regardless of their own preferences.

This setup is useful when you want to offer flexible protocol negotiation globally, while enforcing modern protocol usage like HTTP/2 for specific hosts or services.

Apache Protocol Selection Overview

To clarify how Apache selects the protocol based on your configuration, here’s a summary of common Protocols directive setups:

Protocols Directive Behavior
Protocols h2 http/1.1 Prefers HTTP/2, allows fallback to HTTP/1.1
Protocols http/1.1 h2 Prefers HTTP/1.1, uses HTTP/2 only if client insists
Protocols h2 Allows only HTTP/2, disables HTTP/1.1 completely

The following table explains how the ProtocolsHonorOrder directive affects enforcement of your protocol preferences:

ProtocolsHonorOrder Effect
ProtocolsHonorOrder On Apache enforces your specified protocol order, ignoring client preferences
ProtocolsHonorOrder Off Client may override your order and choose a different protocol (e.g., HTTP/1.1)

Step 3: Prefer HTTP/2 with HTTP/1.1 Fallback

Open a terminal on your server and edit the SSL VirtualHost configuration file with your preferred editor (e.g. nano, vim, code):

sudo nano /etc/apache2/sites-available/default-ssl.conf
⚠️ Note: Depending on your system setup or if configuration files have been renamed or moved, the exact path may vary. Adjust accordingly to match your environment.

Inside the <VirtualHost *:443> block, add or modify the following lines to enable only HTTP/2:

  • Protocols h2 http/1.1

  • ProtocolsHonorOrder On

Make sure you are editing the correct block. If your server hosts multiple virtual hosts, check the ServerName or ServerAlias directives to ensure you are applying the change to the intended domain. Otherwise, the configuration might affect the wrong site or have no effect at all.

default-ssl.conf

Use the following as a reference for your configuration:

<VirtualHost *:443>
    ServerName example.com

    Protocols h2 http/1.1
    ProtocolsHonorOrder On

    # Additional SSL and server configurations...
</VirtualHost>
Save the file and exit the editor. Then test your Apache configuration:
sudo apachectl configtest
This command checks the Apache web server’s configuration files for syntax errors or misconfigurations. If the output says Syntax OK, restart Apache to apply the changes:
sudo systemctl restart apache2

Step 4: Check if HTTP/2 is Active

Option 1: Using curl

Open a terminal and run the following command to test whether your server is using HTTP/2:

curl --http2 -sI https://your-server-ip -w '%{http_version}\n'
Replace your-server-ip with your actual server's IP address or domain name (e.g., example.com or 192.168.1.100). This command will return the HTTP version used in the response, allowing you to verify if HTTP/2 is active.

Note: If you're using a self-signed certificate, the -k option disables certificate verification, allowing the request to proceed without validating the SSL certificate.

curl --http2 -k -sI https://your-server-ip -w '%{http_version}\n'

Output meanings:

  • 2 → ✅ HTTP/2 is active
  • 1.1 → ⚠️ HTTP/1.1 is in use
  • 0 or error → ❌ Certificate not accepted or HTTP/2 not enabled

Option 2: Using openssl

Open a terminal and run the following command to test whether your server is using HTTP/2:

openssl s_client -connect your-server-ip:443 -alpn h2 </dev/null 2>/dev/null | grep -i "ALPN"
Replace your-server-ip with the actual IP address or domain name of your server (e.g., example.com or 192.168.1.100).

Expected output:

  • ALPN protocol: h2 → ✅ HTTP/2 is active
  • No output or different protocol → ❌ HTTP/2 not supported or not negotiated