envoy as http 2 front proxy – enabling http 2 for envoy (aka h2)

Out of the box envoy is not configured to set up connections with clients connecting to it with the new HTTP/2.

HTTP/2 is optimized for the modern web, with binary headers, etc. – higher speed.

Since envoy is capable of speaking HTTP/2 to clients, it is a no-brainer to set it up.

And the setup is really easy, too. You just add one line in the common_tls_context of your listener:

alpn_protocols: [ "h2,http/1.1" ]

That’s it. (The quotes should be normal quotes, in case WordPress messes these up)

ALPN stands for Application-Layer Protocol Negotiation  – it is apparently needed for HTTP/2 to work.

By default, the http_connection_manager envoy filter will support both HTTP1 and HTTP2 in the mode AUTO.

By adding the alpn_protocols you allow this functionality to actually be used.

My envoy.yaml for your reference

I’m going to reproduce my entire envoy.yaml so you see the context the line has to be put in:

static_resources:
   listeners:
   – address:
       socket_address:
         address: 0.0.0.0
         port_value: 80
     filter_chains:
     – filters:
       – name: envoy.http_connection_manager
         config:
           codec_type: auto
           stat_prefix: ingress_http
           route_config:
             virtual_hosts:
             – name: backend
               domains: [“*”]
               routes:
               – match: { prefix: “/” }
                 redirect:
                   path_redirect: “/”
                   https_redirect: true
           http_filters:
           – name: envoy.router
             config: {}
   – address:
       socket_address:
         address: 0.0.0.0
         port_value: 443
     filter_chains:
     – tls_context:
         common_tls_context:
           tls_certificates:
           – certificate_chain: { filename: “/etc/example-com.crt” }
             private_key: { filename: “/etc/example-com.key” }
           alpn_protocols: [ “h2,http/1.1” ]
       filters:
       – name: envoy.http_connection_manager
         config:
           stat_prefix: ingress_https
           route_config:
             virtual_hosts:
             – name: backend
               domains: [“*”]
               routes:
               – match: { prefix: “/” }
                 route: { cluster: target_taxgod }
           http_filters:
           – name: envoy.router
             config: {}
   clusters:
   – name: target_taxgod
     connect_timeout: 0.25s
     type: strict_dns
     lb_policy: round_robin
     hosts:
     – socket_address:
         address: taxgod
         port_value: 3000
admin:
   access_log_path: “/tmp/envoy.log”
   address:
     socket_address:
       address: 0.0.0.0
       port_value: 9901

This envoy.yaml listens on port 80 and port 443. HTTP requests to port 80 are redirected to port 443. All traffic is sent to a docker container “taxgod” on the same docker network. Refer to this article by me for details.

Please don’t expect copy pasting this whole thing to work – WordPress unfortunately is too clever for it’s own good sometimes, and messes up all kinds of characters and code formatting.

References: