Cannot customise X-Forwarded-Host header for nginx-ingress-controller

Hey :slight_smile:

We’re running nginx-ingress-controller installed from the Bitnami Helm chart
The controller is placed behind AWS CloudFront and AWS NLB
On CloudFront we set http header “X-Forwarded-Host” equal to the original Hostname of the AWS CDN distribution.
By default, the controller overrides this header to “Host” one when forwarding the request to backend application, in our case the “Host” and “X-Forwarded-Host” are not the same( for example the original hostname: “main-cdn.domain.com” and the ingress listening for “main-cdn.team.stage.domain.com” which is AWS CDN origin for this particular behaviour)

What I want to do is to customise nginx configuration and keep using original X-Forwarded-Host if it’s set or set it to “Host” header in case of missing “X-Forwarded-Host”.
The way I’m trying to do so is to create map in http context

    map $http_x_forwarded_host $real_x_forwarded_host {
        default $http_x_forwarded_host;
        "" $http_host;
    }

and then use it in the location

            {{ $proxySetHeader }} X-Forwarded-Host       $real_x_forwarded_host;

The problem is - I receive the following error

F0310 11:04:31.489486       1 nginx.go:172] Invalid NGINX configuration template: template: nginx.tmpl:1260: undefined variable "$http_x_forwarded_host"

According to the documentation, controller moves all custom headers to http_ variables that can be further used in nginx.conf.
I can also see that default config contains something similar

    # Reverse proxies can detect if a client provides a X-Request-ID header, and pass it on to the backend server.
    # If no such header is provided, it can provide a random value.
    map $http_x_request_id $req_id {
        default   $http_x_request_id;
        {{ if $cfg.GenerateRequestID }}
        ""        $request_id;
        {{ end }}
    }

We also use the http_x_forwarded_host variable in nginx logs format

    log-format-upstream: '{"time": "$time_iso8601", "remote_addr": "$proxy_protocol_addr", "x-forward-for": "$proxy_add_x_forwarded_for", "request_id": "$req_id", "remote_user": "$remote_user", "bytes_sent": $bytes_sent, "request_time": $request_time, "status":$status, "vhost": "$host", "request_proto": "$server_protocol", "path": "$uri", "request_query": "$args", "request_length": $request_length, "duration": $request_time,"method": "$request_method", "http_referrer": "$http_referer", "http_user_agent": "$http_user_agent", "proxy_upstream_name": "$proxy_upstream_name", "upstream_addr": "$upstream_addr", "upstream_response_time": $upstream_response_time, "upstream_status": $upstream_status, **"x-forwarded-host": "$http_x_forwarded_host"** }'

and it works perfectly fine

{"time": "2023-03-10T12:01:00+00:00", "remote_addr": "", "x-forward-for": "***", "request_id": "73242aedab19699a8b48660caa7e3f77", "remote_user": "", "bytes_sent": 279, "request_time": 0.001, "status":404, "vhost": "****", "request_proto": "HTTP/1.1", "path": "/", "request_query": "", "request_length": 440, "duration": 0.001,"method": "GET", "http_referrer": "", "http_user_agent": "Amazon CloudFront", "proxy_upstream_name": "upstream-default-backend", "upstream_addr": "****", "upstream_response_time": 0.000, "upstream_status": 404, **"x-forwarded-host": "some-domain here"** }

So I really don’t understand why it works in some cases and not in others. I would really appreciate it if someone could help me…

Docker image version

  image:
    repository: bitnami/nginx-ingress-controller
    tag: 1.6.4

Chart version

  - name: nginx-ingress-controller
    version: 9.3.32
    repository: https://charts.bitnami.com/bitnami

Nginx version

nginx -v
nginx version: nginx/1.21.6

K8S version

Server Version: version.Info{Major:"1", Minor:"24+", GitVersion:"v1.24.8-eks-ffeb93d", GitCommit:"abb98ec0631dfe573ec5eae40dc48fd8f2017424", GitTreeState:"clean", BuildDate:"2022-11-29T18:45:03Z", GoVersion:"go1.18.8", Compiler:"gc", Platform:"linux/amd64"}