Q:

Is it possible to run HTTP/2 on NGINX port 443 without ssl?

I have Envoy Proxy handling SSL termination. Nginx (1.17.0 in a docker container, compiled --with-http_v2_module) is one of several upstream services. As a result, Nginx receives traffic on port 443 but does not use the ssl module:
server {
    listen 443;
    server_name example.com www.example.com;
    root /var/www/html;

...

This works fine, but if I try to add http2 to the end of the listen line I receive:
curl: (1) Received HTTP/0.9 when not allowed

... not just for example.com in question, but all servers.
I would like Envoy to speak with Nginx via HTTP/2 for obvious performance reasons.
Is there some trick to make nginx use http2 on port 443 without SSL termination?

Edit:
The core nginx.conf:
user  nginx;
worker_processes  2;

pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    client_max_body_size 64M;

    sendfile        on;

    keepalive_timeout  65;

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=multipress:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    fastcgi_cache_use_stale error timeout invalid_header http_500;
    fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

    gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

Note that I can successfully curl the current Envoy HTTP2 server with an explicit curl --http2 command. The problem is the HTTP2 connection between Envoy and Nginx.

A:

Nginx only supports h2c (which is what HTTP/2 without HTTPS is called), so you can not connect using HTTP/1.1 and then upgrade.
In fact if you try to connect using HTTP/1.1 then nginx will error as it doesn’t support HTTP/1.1 and HTTP/2 on the same port unless you are using HTTPS.
So for curl you have to use this syntax to jump straight into HTTP/2:
curl --http2-prior-knowledge localhost:80

Not sure if there is a similar config in Envoy as don’t use that but if the above works with curl and still get same error with Envoy then at least you’ve got the answer to your Nginx question.
However I’m not at all sure it’s necessary or even wise to enable h2c for your back end server. For a start that disables HTTP/1.1 as discussed above and any other applications, services, or even curl test commands that use HTTP/1.1 will break.
In addition the benefits of HTTP/2 at the back end are questionable, and the main benefit is for client to server connections rather than server to server back end connections.

