Issues with gRPC Proxying through Caddy: TLS and h2c Problems

1. The problem I’m having:

I am trying to configure Caddy as a reverse proxy for a gRPC service running on localhost:9190. The gRPC service is using HTTP/2 (h2c) for communication, and I need to make it accessible at https://service.grpc.example.com. However, I am encountering TLS errors when attempting to use grpcurl to make a simple request, as well as issues when testing with curl. I’m not sure if my configuration is correct for this use case.


2. Error messages and/or full log output:

Here’s the output from curl:

curl -v https://service.grpc.examle.com
* Host service.grpc.example.com:443 was resolved.
* IPv6: (none)
* IPv4: 11.111.1.111
*   Trying 11.111.1.111:443...
* Connected to service.grpc.example.com (11.111.1.111) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* LibreSSL/3.3.6: error:1404B460:SSL routines:ST_CONNECT:reason(1120)
* Closing connection
curl: (35) LibreSSL/3.3.6: error:1404B460:SSL routines:ST_CONNECT:reason(1120)

Caddy debug logs do not show any apparent issues with certificate selection, but the error persists.


3. Caddy version:

v2.9.1

4. How I installed and ran Caddy:

a. System environment:

  • OS: Ubuntu 22.04
  • Caddy installed using the official package manager
  • Systemd used to manage Caddy service

b. Command:

sudo systemctl start caddy

c. Service/unit/compose file:

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target

[Service]
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
Restart=on-failure
StartLimitInterval=500
StartLimitBurst=5

[Install]
WantedBy=multi-user.target

d. My complete Caddy config:

https://service.grpc.example.com {
        reverse_proxy {
        to localhost:9190
        transport http {
            versions h2c
        }
    }

    tls {
        alpn h2
    }

    log {
        output file /var/log/caddy/access.log
        format json
        level DEBUG
    }
}

5. Links to relevant resources:

  1. grpcurl documentation
  2. Caddy reverse_proxy documentation

I’ve successfully proxied grpc through Caddy before without any issues. That curl error is only ever reported by you, so there isn’t even leads to search with :sweat_smile:

Any reason for this? I’m suspecting this breaks something, especially that curl complains after ALPN negotiation. Remove these.

I removed tls field, and got: “No ALPN negotiated”

openssl s_client -connect service.grpc.example.com:443 -alpn h2

Connecting to 11.111.1.111
CONNECTED(00000005)
40B88CEC01000000:error:0A000126:SSL routines::unexpected eof while reading:ssl/record/rec_layer_s3.c:693:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 356 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Protocol: TLSv1.3
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

That’s not an error though, is it? Does it fail when you use gRPC client? It shouldn’t.

Could you tell me how to configure the caddy file so that I can proxy my grpc service? I need to share my service on 443 and 80 ports

What have you tried that didn’t work?