Google Cloud Run HTTP\2

1. The problem I’m having:

I am trying to get HTTP\2 working with Google Cloud Run. I have it working with HTTP\2 disabled, but can’t seem to get it working enabled. In NGINX, I got this working with the X-Forwarded-Proto header, but that doesn’t seem to work.

2. Error messages and/or full log output:

Bad Gateway

3. Caddy version:

v2.CustomVersion=FrankenPHP

4. How I installed and ran Caddy:

I am running Caddy through FrankenPHP

a. System environment:

Alpine Linux / Docker

d. My complete Caddy config:

{
        {$CADDY_GLOBAL_OPTIONS}
        http_port 8080

        frankenphp {
                #worker /path/to/your/worker.php
                {$FRANKENPHP_CONFIG}
        }

        # https://caddyserver.com/docs/caddyfile/directives#sorting-algorithm
        order mercure after encode
        order vulcain after reverse_proxy
        order php_server before file_server
        order php before file_server
}

{$CADDY_EXTRA_CONFIG}

:8080 {
        log {
                # Redact the authorization query parameter that can be set by Mercure
                format filter {
                        wrap console
                        fields {
                                uri query {
                                        replace authorization REDACTED
                                }
                        }
                }
        }

        root * public/
        encode zstd gzip

        {$CADDY_SERVER_EXTRA_DIRECTIVES}                                                        
        header X-Forwarded-Proto http                                                           
                                                                                                
                                                                                                
        php_server                                                                              
}  

Dockerfile:

# Composer Build
FROM composer:latest AS build

# App Build
FROM dunglas/frankenphp


WORKDIR /app
ENV SERVER_NAME=:8080
ENV PORT=8080

RUN sed -i 's/{$SERVER_NAME:localhost}/:'"$PORT"'/' /etc/caddy/Caddyfile && \
    sed -i '/CADDY_GLOBAL_OPTIONS/a http_port '"$PORT" /etc/caddy/Caddyfile && \
    sed -i '/CADDY_SERVER_EXTRA_DIRECTIVES/a\\theader X-Forwarded-Proto https\n' /etc/caddy/Caddyfile

# Add application
COPY . .

# Add Composer
COPY --from=build /usr/bin/composer /usr/bin/composer

# Install Dependencies
RUN composer install --optimize-autoloader --no-dev

Problem is solved!

After a bit of research, I realized in order to enable the Use HTTP/2 end-to-end option in Cloud Run, I need to accept requests in HTTP/2 cleartext.

This is done by setting the protocols in global options, specifically this block:

servers :8080 {
    protocols h2c
}

Here is my full Caddyfile that is working on Google Cloud Run with end-to-end HTTP/2 enabled, and using the FrankenPHP module: (Using Port 8080 via Cloud Run)

{
    {$CADDY_GLOBAL_OPTIONS}
    http_port 8080
    auto_https off

    frankenphp {
        #worker /path/to/your/worker.php

        {$FRANKENPHP_CONFIG}
    }

    servers :8080 {
        protocols h1 h2c
    }

    # https://caddyserver.com/docs/caddyfile/directives#sorting-algorithm
    order mercure after encode
    order vulcain after reverse_proxy
    order php_server before file_server
    order php before file_server
}

{$CADDY_EXTRA_CONFIG}

:8080 {
    log {
        # Redact the authorization query parameter that can be set by Mercure
        format filter {
            wrap console
            fields {
                uri query {
                    replace authorization REDACTED
                }
            }
        }
    }

    root * public/
    encode zstd gzip
    {$CADDY_SERVER_EXTRA_DIRECTIVES}

    header X-Forwarded-Proto https

    php_server
}

This sets a response header. This doesn’t do what you want. Remove it.

Caddy’s proxy (and FrankenPHP which uses the same logic) sets this header by default when sending the request upstream: reverse_proxy (Caddyfile directive) — Caddy Documentation

You don’t need either of these, because you use :8080 as your site address already. If you’re using any port other than the HTTPS port (443) and you’re not using a domain name, Caddy will use HTTP.

You are absolutely right on the X-Forwarded-Proto header. I noticed the same and removed it shortly after my post.

I also just tested without the auto-https and it works great, thanks for the tip!

Removing http_port resulted in a Bad Gateway error, however. Do you know why this is? I am technically using a domain name, but it’s hitting Cloud Run first, which handles the SSL, then forwards it directly to my container. Could this be why?

Please show your logs. Impossible to say without seeing the actual result.

You have a bunch of env vars to inject config in your Caddyfile. What do those have?

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.