Joxit/docker-registry-ui

reason for proxy_set_header Host $http_host; ?

ttr opened this issue · 6 comments

ttr commented

Hi - could not find "general query template"

For static build, in nginx there is:
proxy_set_header Host $http_host;
this will override host header send to registry to whatever we use to establish connection to UI.
In situation when REGISTRY_URL points directly do registry, it all works as intended, however, if registry is hidden behind rev-proxy (eg haproxy - in my case for ACL and multi tenancy purposes) we will get 404.

This is happening because haproxy does backend/routing based on host header and this one is being override.

Joxit commented

Hi, thank you for your issue.

The Host header has been added in order to fix #88
In the nominal usage, when we do not set the Host header to the registry, the registry will give a wrong URL to the docker client when we do a docker push.

You can override the Host header with NGINX_PROXY_HEADER_* commands, see the example.

I encountered some issue with Host header being set to $http_host as well, since I wanted to proxy the requests to the registry through the UI container but the registry itself is behind another Nginx proxy which has multiple server blocks each with unique server_name (aka virtual hosts).
Since UI is running on different host than the actual proxy/registry, the proxy in front of registry is unable to determine proper server block which to use to serve registry requests due to non matching Host header, resulting in 404 responses being returned to the UI proxy.

I tried to solve this by setting NGINX_PROXY_HEADER_Host but this merely adds additional proxy_add_header Host <my_host> to the configuration. Nginx then actually uses the original line proxy_add_header Host $http_host when proxying requests and not the one defined through environment variable.

I've worked around this by modifying the entrypoint block where replacements in default.conf are being made to include additional variable substitution:

if [ -n "${REGISTRY_URL}" ] ; then
  sed -i "s,\${REGISTRY_HOST},${REGISTRY_HOST:-"\$http_host"}," /etc/nginx/conf.d/default.conf
  sed -i "s,\${REGISTRY_URL},${REGISTRY_URL}," /etc/nginx/conf.d/default.conf
  sed -i "s^\${NGINX_PROXY_HEADERS}^$(get_nginx_proxy_headers)^" /etc/nginx/conf.d/default.conf
  sed -i "s,#!,," /etc/nginx/conf.d/default.conf
fi

Additionally I modified nginx/default.conf where Host header is being set to #! proxy_set_header Host ${REGISTRY_HOST};

No the most elegant solution since I now have to run image with REGISTRY_URL, REGISTRY_HOST, PULL_URL all being set but containing very similar values. But it works for me and retains compatibility with original code. If this might be beneficial in general please suggest whether I should open a separate issue describing scenario in detail and proposed solution.

Joxit commented

Hi,
Thank you for your ideas and tests.
So the NGINX_PROXY_HEADER_Host will not work.... I have another solution, I remove the line proxy_set_header Host $http_host; from the nginx conf and set the default env value of NGINX_PROXY_HEADER_Host to $http_host, this should be better ? By default it will be $http_host and if you want a custom host... It will be your new value 😄

I think that sounds like a good solution that would definitely solve my case and retain same default behavior as before.

Joxit commented

Should be fixed in 1.4.2 :) I'm pushing new docker images !

Joxit commented

Welcome to my contributors list @Cvetk0 -> https://joxit.dev/docker-registry-ui/CONTRIBUTORS 👏