Apache behind nginx reverse proxy, setting the correct Host header

Solution 1:

Instead of having Apache do that leg work, have NGINX do it before it even hands off the data to Apache by setting the Host header that Apache is expecting as part of the proxy_pass handoff with an extra configuration option.

NGINX has the following variable for proxy_set_header to augment what is passed to the proxy in the backend. So you'd have something like this:

...

location / {
    proxy_pass http://10.20.30.40;
    proxy_set_header Host example.com;
}
...

in your NGINX configuration for the reverse proxy. Then, Apache won't care about X-Forwarded-Host because you'd set the Host header instead which Apache should prioritize serving.

This should fix things - I use multiple NGINX systems in this way when the domain reached by the Browser is different from teh backend's responding host - and so far it works with Django backends, PHP backends, Apache, even a Python HTTP server I use for testing things. And my understanding of Apache is it'll prioritize teh Host header over X-Forwarded-Host.

Solution 2:

I solved this issue by defining a new environment variable called APP_HOST in the Google Cloud Run control panel and setting it to example.com.

Then I added the following configuration to the .htaccess file in the document root:

<IfModule mod_env.c>
    PassEnv APP_HOST
</IfModule>

<IfModule mod_headers.c>
    RequestHeader set Host %{APP_HOST}e env=APP_HOST
</IfModule>

This allowed me to override the Host header from example-8gnm1aqrns-lz.a.run.app to example.com based on the environment variable APP_HOST.

I could have of course hardcoded the hostname but I think that using an environment variable gives you more flexibility if you want to use the same .htaccess file in different contexts, such as on a staging server.

Edit

Here's how you can solve this using X-Forwarded-Host, for example if you run virtual hosts and you need to site to be accessible from multiple domains

<IfModule mod_setenvif.c>
    SetEnvIf X-Forwarded-Host (.*) REAL_HOST_HEADER=$1
    <IfModule mod_headers.c>
        RequestHeader set Host "%{REAL_HOST_HEADER}e"
    </IfModule>
</IfModule>

This will grab the header from X-Forwarded-Host and set the Host header based on the value.