[GH-ISSUE #127] Allow forward with the Host header equaling the target server #114

Open
opened 2026-02-26 05:34:39 +03:00 by kerem · 20 comments
Owner

Originally created by @WizADSL on GitHub (Apr 23, 2019).
Original GitHub issue: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/127

It appears that the contents of /etc/nginx/conf.d/include/proxy.conf are incorrect and result in the wrong host header being set in proxied requests. The file currently contains:

add_header       X-Served-By $host;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Proto  $scheme;
proxy_set_header X-Forwarded-For    $remote_addr;
proxy_pass       $forward_scheme://$server:$port;

It should probably contain:

add_header       X-Served-By $server;
proxy_set_header Host $server;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Proto  $scheme;
proxy_set_header X-Forwarded-For    $remote_addr;
proxy_pass       $forward_scheme://$server:$port;

The problem is in the first two lines where the variable being used $host which resolves to the SOURCE URL for the proxy rather than the destination which is incorrectly setting the Host header of the proxied request rather than the destination (in $server).

Originally created by @WizADSL on GitHub (Apr 23, 2019). Original GitHub issue: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/127 It appears that the contents of /etc/nginx/conf.d/include/proxy.conf are incorrect and result in the wrong host header being set in proxied requests. The file currently contains: ```` add_header X-Served-By $host; proxy_set_header Host $host; proxy_set_header X-Forwarded-Scheme $scheme; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_pass $forward_scheme://$server:$port; ```` It should probably contain: ```` add_header X-Served-By $server; proxy_set_header Host $server; proxy_set_header X-Forwarded-Scheme $scheme; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_pass $forward_scheme://$server:$port; ```` The problem is in the first two lines where the variable being used $host which resolves to the SOURCE URL for the proxy rather than the destination which is incorrectly setting the Host header of the proxied request rather than the destination (in $server).
Author
Owner

@jc21 commented on GitHub (Apr 23, 2019):

I disagree. The Host header should normally be the same domain that you'll see in your browser, no matter how many proxies it passes through. If you require the Host to be different because your upstream server is expecting something different, that is outside of the norm and you can choose to override the default behaviour with the advanced configuration in the UI.

<!-- gh-comment-id:485977281 --> @jc21 commented on GitHub (Apr 23, 2019): I disagree. The Host header should normally be the same domain that you'll see in your browser, no matter how many proxies it passes through. If you require the Host to be different because your upstream server is expecting something different, that is outside of the norm and you can choose to override the default behaviour with the advanced configuration in the UI.
Author
Owner

@WizADSL commented on GitHub (Apr 23, 2019):

The Host header that is sent to the destination site needs to match the destination domain. If it does not and the destination site is using a shared IP then the request will fail or you may receive a default/unexpected page. The purpose of the Host header in to indicate to the remote server which website you are trying to access and is critical if an IP address is being shared with multiple sites. Go ahead and try it for yourself. One of the several pages I tested with was "http://neverssl.com". If you try to proxy that without making the indicated it won't work correctly.

<!-- gh-comment-id:485984030 --> @WizADSL commented on GitHub (Apr 23, 2019): The Host header that is sent to the destination site needs to match the destination domain. If it does not and the destination site is using a shared IP then the request will fail or you may receive a default/unexpected page. The purpose of the Host header in to indicate to the remote server which website you are trying to access and is critical if an IP address is being shared with multiple sites. Go ahead and try it for yourself. One of the several pages I tested with was "http://neverssl.com". If you try to proxy that without making the indicated it won't work correctly.
Author
Owner

@WizADSL commented on GitHub (Apr 23, 2019):

I should clarify that when I say "destination site", "destination domain" and "remote" I am referring to the site being proxied ("Forward Hostname" in the UI). The way proxy.conf is currently configured you are passing the domain being assigned as the proxy host (the value in "Domain Names" in the UI) as the Host header which is incorrect.

<!-- gh-comment-id:485986655 --> @WizADSL commented on GitHub (Apr 23, 2019): I should clarify that when I say "destination site", "destination domain" and "remote" I am referring to the site being proxied ("Forward Hostname" in the UI). The way proxy.conf is currently configured you are passing the domain being assigned as the proxy host (the value in "Domain Names" in the UI) as the Host header which is incorrect.
Author
Owner

@jc21 commented on GitHub (Apr 23, 2019):

I think you're missing the point of this project. It's not to proxy to other peoples public domains.

The host header being sent to upstream services listed here tells those services to use that host in various ways including but not limited to links being sent in emails.

But like I've said, you can change the configuration to match your circumstance.

<!-- gh-comment-id:485986744 --> @jc21 commented on GitHub (Apr 23, 2019): I think you're missing the point of this project. It's not to proxy to other peoples public domains. The host header being sent to [upstream services listed here](https://github.com/jc21/nginx-proxy-manager/issues/101) tells those services to use that host in various ways including but not limited to links being sent in emails. But like I've said, you can change the configuration to match your circumstance.
Author
Owner

@WizADSL commented on GitHub (Apr 23, 2019):

In my case I'm not trying to proxy an external site, I just suggested that as an example to illustrate my point. Basically as long as the source and destination hostnames of the proxy match then it works fine the way it is BUT if your internal site is configured with a different hostname then it will not work. If I create an Apache site as "www.mydomain.local" and want to expose it publicly as "www.myexternaldomain.com" that won't work. The way it is working now forces the "internal" and "external" names to be the same where what I am suggesting works fine whether they match or not (including links; as long as they don't include the full URL). Having read your last comment I understand that forcing the names to match is the way you intend it to work but I believe this approach is more flexible and does not affect the current functionality.

<!-- gh-comment-id:485992668 --> @WizADSL commented on GitHub (Apr 23, 2019): In my case I'm not trying to proxy an external site, I just suggested that as an example to illustrate my point. Basically as long as the source and destination hostnames of the proxy match then it works fine the way it is BUT if your internal site is configured with a different hostname then it will not work. If I create an Apache site as "www.mydomain.local" and want to expose it publicly as "www.myexternaldomain.com" that won't work. The way it is working now forces the "internal" and "external" names to be the same where what I am suggesting works fine whether they match or not (including links; as long as they don't include the full URL). Having read your last comment I understand that forcing the names to match is the way you intend it to work but I believe this approach is more flexible and does not affect the current functionality.
Author
Owner

@badihi commented on GitHub (Nov 24, 2021):

@jc21
There is a lot of use cases that needs to change the domain name. I do not know what are you talking about! This is so common that every CDN in the market has this feature.
Also adding proxy_set_header Host ... will not work since another one exists in the default configuration and cannot be removed.

<!-- gh-comment-id:978068253 --> @badihi commented on GitHub (Nov 24, 2021): @jc21 There is a lot of use cases that needs to change the domain name. I do not know what are you talking about! This is so common that every CDN in the market has this feature. Also adding `proxy_set_header Host ...` will not work since another one exists in the default configuration and cannot be removed.
Author
Owner

@kroese commented on GitHub (Jun 9, 2022):

This should really be implemented.. Just a simple toggle in the UI called "Override hostname" would be enough..

<!-- gh-comment-id:1150779477 --> @kroese commented on GitHub (Jun 9, 2022): This should really be implemented.. Just a simple toggle in the UI called "Override hostname" would be enough..
Author
Owner

@12ozCode commented on GitHub (Jul 13, 2022):

People really need it, just a toggle to make it target server or override field.
In my case, I've spent several hours to understand why my proxy returns 404 instead of site that is working everywhere.
The problem was, I was trying to proxy k8s nginx-ingress resource, and ingress does it's dispatch based on host header.
So initial target was discarded and ProxyManager placed current browser url to the host, which does absolutely no sense to k8s nginx ingress, so it returned 404. Thanks I've managed to fix it in advanced overrides, but that was not straightforward at all...

Adding another proxy_set_header Host into Custom locations doesn't help because it produces 2 Host headers as result.

<!-- gh-comment-id:1183635730 --> @12ozCode commented on GitHub (Jul 13, 2022): People really need it, just a toggle to make it target server or override field. In my case, I've spent several hours to understand why my proxy returns 404 instead of site that is working everywhere. The problem was, I was trying to proxy k8s nginx-ingress resource, and ingress does it's dispatch based on host header. So initial target was discarded and ProxyManager placed current browser url to the host, which does absolutely no sense to k8s nginx ingress, so it returned 404. Thanks I've managed to fix it in advanced overrides, but that was not straightforward at all... Adding another proxy_set_header Host into Custom locations doesn't help because it produces 2 Host headers as result.
Author
Owner

@kt767 commented on GitHub (Aug 15, 2022):

@12ozCode would you mind sharing how you were able to set the Host header to the target server? It seems like I just need to delete the line "proxy_set_header Host $host;" from "/etc/nginx/conf.d/include/proxy.conf" (since by default Nginx puts the target server in the Host header) but I don't know how to do that.

For now, I just manually edited 1.conf to remove the line "include conf.d/include/proxy.conf;" and add "proxy_pass [target domain]." But I'm afraid NPM is going to overwrite 1.conf at some point (maybe at cert renewal?). Thanks!

<!-- gh-comment-id:1215223220 --> @kt767 commented on GitHub (Aug 15, 2022): @12ozCode would you mind sharing how you were able to set the Host header to the target server? It seems like I just need to delete the line "proxy_set_header Host $host;" from "/etc/nginx/conf.d/include/proxy.conf" (since [by default Nginx puts the target server in the Host header](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/)) but I don't know how to do that. For now, I just manually edited 1.conf to remove the line "include conf.d/include/proxy.conf;" and add "proxy_pass [target domain]." But I'm afraid NPM is going to overwrite 1.conf at some point (maybe at cert renewal?). Thanks!
Author
Owner

@jboolean commented on GitHub (Nov 13, 2022):

Wow I wasted a lot of time to find this. There should be a way to override it.

<!-- gh-comment-id:1312749530 --> @jboolean commented on GitHub (Nov 13, 2022): Wow I wasted a lot of time to find this. There should be a way to override it.
Author
Owner

@m33ts4k0z commented on GitHub (May 1, 2023):

Hello,

I suppose after all these years this is still not addressed?

<!-- gh-comment-id:1529501121 --> @m33ts4k0z commented on GitHub (May 1, 2023): Hello, I suppose after all these years this is still not addressed?
Author
Owner

@badihi commented on GitHub (May 1, 2023):

@m33ts4k0z
Yes, the people here seem to be really arrogant.

<!-- gh-comment-id:1529516939 --> @badihi commented on GitHub (May 1, 2023): @m33ts4k0z Yes, the people here seem to be really arrogant.
Author
Owner

@HackerYunen commented on GitHub (Jun 14, 2023):

I start to use caddy to replace NPM because of this stupid problem.

<!-- gh-comment-id:1590891245 --> @HackerYunen commented on GitHub (Jun 14, 2023): I start to use caddy to replace NPM because of this stupid problem.
Author
Owner

@HackerYunen commented on GitHub (Jun 14, 2023):

@12ozCode would you mind sharing how you were able to set the Host header to the target server? It seems like I just need to delete the line "proxy_set_header Host $host;" from "/etc/nginx/conf.d/include/proxy.conf" (since by default Nginx puts the target server in the Host header) but I don't know how to do that.

For now, I just manually edited 1.conf to remove the line "include conf.d/include/proxy.conf;" and add "proxy_pass [target domain]." But I'm afraid NPM is going to overwrite 1.conf at some point (maybe at cert renewal?). Thanks!

Here is my way:

1, edit the /app/templates/_location.conf,change

proxy_set_header Host $host;

to

proxy_set_header Host $myhost;

2, Set $myhost variable when you add Proxy Host on popover form.

set $myhost "www.example.com";

on Advanced -> Custom Nginx Configuration.

<!-- gh-comment-id:1590937461 --> @HackerYunen commented on GitHub (Jun 14, 2023): > @12ozCode would you mind sharing how you were able to set the Host header to the target server? It seems like I just need to delete the line "proxy_set_header Host $host;" from "/etc/nginx/conf.d/include/proxy.conf" (since [by default Nginx puts the target server in the Host header](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/)) but I don't know how to do that. > > For now, I just manually edited 1.conf to remove the line "include conf.d/include/proxy.conf;" and add "proxy_pass [target domain]." But I'm afraid NPM is going to overwrite 1.conf at some point (maybe at cert renewal?). Thanks! Here is my way: 1, edit the /app/templates/_location.conf,change ``` proxy_set_header Host $host; ``` to ``` proxy_set_header Host $myhost; ``` 2, Set $myhost variable when you add Proxy Host on popover form. ``` set $myhost "www.example.com"; ``` on Advanced -> Custom Nginx Configuration.
Author
Owner

@pellas commented on GitHub (Jun 18, 2023):

This worked for me with version 2.9.17. Under Advanced -> Custom Nginx Configuration you specify the whole "location"-block.
https://github.com/NginxProxyManager/nginx-proxy-manager/issues/2076#issuecomment-1553988175

<!-- gh-comment-id:1596223679 --> @pellas commented on GitHub (Jun 18, 2023): This worked for me with version 2.9.17. Under Advanced -> Custom Nginx Configuration you specify the whole "location"-block. https://github.com/NginxProxyManager/nginx-proxy-manager/issues/2076#issuecomment-1553988175
Author
Owner

@HackerYunen commented on GitHub (Jun 18, 2023):

This worked for me with version 2.9.17. Under Advanced -> Custom Nginx Configuration you specify the whole "location"-chunk. #2076 (comment)

Get your mean, just write the whole location block in "Under Advanced -> Custom Nginx Configuration" right?

<!-- gh-comment-id:1596251187 --> @HackerYunen commented on GitHub (Jun 18, 2023): > This worked for me with version 2.9.17. Under Advanced -> Custom Nginx Configuration you specify the whole "location"-chunk. [#2076 (comment)](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/2076#issuecomment-1553988175) Get your mean, just write the whole location block in "Under Advanced -> Custom Nginx Configuration" right?
Author
Owner

@pellas commented on GitHub (Jun 18, 2023):

This worked for me with version 2.9.17. Under Advanced -> Custom Nginx Configuration you specify the whole "location"-chunk. #2076 (comment)

Get your mean, just write the whole location block in "Under Advanced -> Custom Nginx Configuration" right?
Correct!

image

<!-- gh-comment-id:1596258281 --> @pellas commented on GitHub (Jun 18, 2023): > > This worked for me with version 2.9.17. Under Advanced -> Custom Nginx Configuration you specify the whole "location"-chunk. [#2076 (comment)](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/2076#issuecomment-1553988175) > > Get your mean, just write the whole location block in "Under Advanced -> Custom Nginx Configuration" right? Correct! ![image](https://github.com/NginxProxyManager/nginx-proxy-manager/assets/24375191/f7af37cd-2170-4352-a849-f78cf463b6e8)
Author
Owner

@github-actions[bot] commented on GitHub (Apr 3, 2024):

Issue is now considered stale. If you want to keep it open, please comment 👍

<!-- gh-comment-id:2033392855 --> @github-actions[bot] commented on GitHub (Apr 3, 2024): Issue is now considered stale. If you want to keep it open, please comment :+1:
Author
Owner

@mehmetaydogduu commented on GitHub (Jan 26, 2025):

This is a must feature. I usually reverse proxy to white label some 3rd party service.

<!-- gh-comment-id:2614243754 --> @mehmetaydogduu commented on GitHub (Jan 26, 2025): This is a must feature. I usually reverse proxy to white label some 3rd party service.
Author
Owner

@github-actions[bot] commented on GitHub (Nov 13, 2025):

Issue is now considered stale. If you want to keep it open, please comment 👍

<!-- gh-comment-id:3524830190 --> @github-actions[bot] commented on GitHub (Nov 13, 2025): Issue is now considered stale. If you want to keep it open, please comment :+1:
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/nginx-proxy-manager-NginxProxyManager#114
No description provided.