mirror of
https://github.com/thib8956/nginx-proxy
synced 2025-04-16 18:51:01 +00:00
Merge pull request #2533 from nginx-proxy/2529
fix: use sha1 hash for config files name when using regex host
This commit is contained in:
commit
a3db62bb14
@ -181,8 +181,9 @@ In this example, the incoming request `http://example.tld/app1/foo` will be prox
|
||||
### Per-VIRTUAL_PATH location configuration
|
||||
|
||||
The same options as from [Per-VIRTUAL_HOST location configuration](#Per-VIRTUAL_HOST-location-configuration) are available on a `VIRTUAL_PATH` basis.
|
||||
The only difference is that the filename gets an additional block `HASH=$(echo -n $VIRTUAL_PATH | sha1sum | awk '{ print $1 }')`. This is the sha1-hash of the `VIRTUAL_PATH` (no newline). This is done filename sanitization purposes.
|
||||
The used filename is `${VIRTUAL_HOST}_${HASH}_location`
|
||||
The only difference is that the filename gets an additional block `HASH=$(echo -n $VIRTUAL_PATH | sha1sum | awk '{ print $1 }')`. This is the sha1-hash of the `VIRTUAL_PATH` (no newline). This is done for filename sanitization purposes.
|
||||
|
||||
The used filename is `${VIRTUAL_HOST}_${PATH_HASH}_location`, or when `VIRTUAL_HOST` is a regex, `${VIRTUAL_HOST_HASH}_${PATH_HASH}_location`.
|
||||
|
||||
The filename of the previous example would be `example.tld_8610f6c344b4096614eab6e09d58885349f42faf_location`.
|
||||
|
||||
@ -328,7 +329,7 @@ See the [nginx keepalive documentation](https://nginx.org/en/docs/http/ngx_http_
|
||||
|
||||
## Basic Authentication Support
|
||||
|
||||
In order to be able to secure your virtual host, you have to create a file named as its equivalent `VIRTUAL_HOST` variable in directory
|
||||
In order to be able to secure your virtual host, you have to create a file named as its equivalent `VIRTUAL_HOST` variable (or if using a regex `VIRTUAL_HOST`, as the sha1 hash of the regex) in directory
|
||||
`/etc/nginx/htpasswd/{$VIRTUAL_HOST}`
|
||||
|
||||
```console
|
||||
@ -738,7 +739,7 @@ docker run -d -p 80:80 -p 443:443 -v /path/to/my_proxy.conf:/etc/nginx/conf.d/my
|
||||
|
||||
### Per-VIRTUAL_HOST
|
||||
|
||||
To add settings on a per-`VIRTUAL_HOST` basis, add your configuration file under `/etc/nginx/vhost.d`. Unlike in the proxy-wide case, which allows multiple config files with any name ending in `.conf`, the per-`VIRTUAL_HOST` file must be named exactly after the `VIRTUAL_HOST`.
|
||||
To add settings on a per-`VIRTUAL_HOST` basis, add your configuration file under `/etc/nginx/vhost.d`. Unlike in the proxy-wide case, which allows multiple config files with any name ending in `.conf`, the per-`VIRTUAL_HOST` file must be named exactly after the `VIRTUAL_HOST`, or if `VIRTUAL_HOST` is a regex, after the sha1 hash of the regex.
|
||||
|
||||
In order to allow virtual hosts to be dynamically configured as backends are added and removed, it makes the most sense to mount an external directory as `/etc/nginx/vhost.d` as opposed to using derived images or mounting individual configuration files.
|
||||
|
||||
@ -762,7 +763,7 @@ If you want most of your virtual hosts to use a default single configuration and
|
||||
|
||||
### Per-VIRTUAL_HOST location configuration
|
||||
|
||||
To add settings to the "location" block on a per-`VIRTUAL_HOST` basis, add your configuration file under `/etc/nginx/vhost.d` just like the previous section except with the suffix `_location`.
|
||||
To add settings to the "location" block on a per-`VIRTUAL_HOST` basis, add your configuration file under `/etc/nginx/vhost.d` just like the per-`VIRTUAL_HOST` section except with the suffix `_location` (like this section, if your `VIRTUAl_HOST` is a regex, use the sha1 hash of the regex instead, with the suffix `_location` appended).
|
||||
|
||||
For example, if you have a virtual host named `app.example.com` and you have configured a proxy_cache `my-cache` in another custom file, you could tell it to use a proxy cache as follows:
|
||||
|
||||
@ -790,7 +791,7 @@ The `${VIRTUAL_HOST}_${PATH_HASH}_location`, `${VIRTUAL_HOST}_location`, and `de
|
||||
/etc/nginx/vhost.d/${VIRTUAL_HOST}_${PATH_HASH}_location_override
|
||||
```
|
||||
|
||||
where `${VIRTUAL_HOST}` is the name of the virtual host (the `VIRTUAL_HOST` environment variable) and `${PATH_HASH}` is the SHA-1 hash of the path, as [described above](#per-virtual_path-location-configuration).
|
||||
where `${VIRTUAL_HOST}` is the name of the virtual host (the `VIRTUAL_HOST` environment variable), or the sha1 hash of `VIRTUAL_HOST` when it's a regex, and `${PATH_HASH}` is the SHA-1 hash of the path, as [described above](#per-virtual_path-location-configuration).
|
||||
|
||||
For convenience, the `_${PATH_HASH}` part can be omitted if the path is `/`:
|
||||
|
||||
|
31
nginx.tmpl
31
nginx.tmpl
@ -289,7 +289,7 @@
|
||||
auth_basic "Restricted {{ .Host }}{{ .Path }}";
|
||||
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s_%s" .Host (sha1 .Path)) }};
|
||||
{{- else if (exists (printf "/etc/nginx/htpasswd/%s" .Host)) }}
|
||||
auth_basic "Restricted {{ .Host }}";
|
||||
auth_basic "Restricted {{ .HostIsRegexp | ternary "access" .Host }}";
|
||||
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" .Host) }};
|
||||
{{- end }}
|
||||
|
||||
@ -570,7 +570,9 @@ proxy_set_header Proxy "";
|
||||
|
||||
{{- /* Loop over $globals.vhosts and update it with the remaining informations about each vhost. */}}
|
||||
{{- range $hostname, $vhost_data := $globals.vhosts }}
|
||||
{{- $is_regexp := hasPrefix "~" $hostname }}
|
||||
{{- $vhost_containers := list }}
|
||||
|
||||
{{- range $path, $vpath_data := $vhost_data.paths }}
|
||||
{{- $vpath_containers := list }}
|
||||
{{- range $port, $vport_containers := $vpath_data.ports }}
|
||||
@ -644,6 +646,7 @@ proxy_set_header Proxy "";
|
||||
"https_method" $https_method
|
||||
"http2_enabled" $http2_enabled
|
||||
"http3_enabled" $http3_enabled
|
||||
"is_regexp" $is_regexp
|
||||
"acme_http_challenge_legacy" $acme_http_challenge_legacy
|
||||
"acme_http_challenge_enabled" $acme_http_challenge_enabled
|
||||
"server_tokens" $server_tokens
|
||||
@ -785,6 +788,23 @@ server {
|
||||
{{- end }}
|
||||
|
||||
server {
|
||||
{{- if $vhost.is_regexp }}
|
||||
{{- if or
|
||||
(printf "/etc/nginx/vhost.d/%s" $hostname | exists)
|
||||
(printf "/etc/nginx/vhost.d/%s_location" $hostname | exists)
|
||||
(printf "/etc/nginx/vhost.d/%s_location_override" $hostname | exists)
|
||||
(printf "/etc/nginx/htpasswd/%s" $hostname | exists)
|
||||
}}
|
||||
# https://github.com/nginx-proxy/nginx-proxy/issues/2529#issuecomment-2437609249
|
||||
# Support for vhost config file(s) named like a regexp ({{ $hostname }}) has been removed from nginx-proxy.
|
||||
# Please name your vhost config file(s) with the sha1 of the regexp instead ({{ $hostname }} -> {{ sha1 $hostname }}) :
|
||||
# - /etc/nginx/vhost.d/{{ sha1 $hostname }}
|
||||
# - /etc/nginx/vhost.d/{{ sha1 $hostname }}_location
|
||||
# - /etc/nginx/vhost.d/{{ sha1 $hostname }}_location_override
|
||||
# - /etc/nginx/htpasswd/{{ sha1 $hostname }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
server_name {{ $hostname }};
|
||||
{{- if $vhost.server_tokens }}
|
||||
server_tokens {{ $vhost.server_tokens }};
|
||||
@ -865,8 +885,10 @@ server {
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if (exists (printf "/etc/nginx/vhost.d/%s" $hostname)) }}
|
||||
include {{ printf "/etc/nginx/vhost.d/%s" $hostname }};
|
||||
{{- $vhostFileName := $vhost.is_regexp | ternary (sha1 $hostname) $hostname }}
|
||||
|
||||
{{- if (exists (printf "/etc/nginx/vhost.d/%s" $vhostFileName)) }}
|
||||
include {{ printf "/etc/nginx/vhost.d/%s" $vhostFileName }};
|
||||
{{- else if (exists "/etc/nginx/vhost.d/default") }}
|
||||
include /etc/nginx/vhost.d/default;
|
||||
{{- end }}
|
||||
@ -874,7 +896,8 @@ server {
|
||||
{{- range $path, $vpath := $vhost.paths }}
|
||||
{{- template "location" (dict
|
||||
"Path" $path
|
||||
"Host" $hostname
|
||||
"Host" $vhostFileName
|
||||
"HostIsRegexp" $vhost.is_regexp
|
||||
"VhostRoot" $vhost.vhost_root
|
||||
"VPath" $vpath
|
||||
) }}
|
||||
|
@ -5,7 +5,7 @@ services:
|
||||
image: nginxproxy/nginx-proxy:test
|
||||
volumes:
|
||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||
- ./my_custom_proxy_settings.conf:/etc/nginx/vhost.d/default_location:ro
|
||||
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/default_location:ro
|
||||
- ./my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/web3.nginx-proxy.example_location:ro
|
||||
|
||||
web1:
|
||||
|
@ -5,7 +5,7 @@ services:
|
||||
image: nginxproxy/nginx-proxy:test
|
||||
volumes:
|
||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||
- ./my_custom_proxy_settings.conf:/etc/nginx/proxy.conf:ro
|
||||
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/proxy.conf:ro
|
||||
|
||||
web1:
|
||||
image: web
|
||||
|
@ -12,6 +12,13 @@ def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
|
||||
assert "X-test" in r.headers
|
||||
assert "f00" == r.headers["X-test"]
|
||||
|
||||
def test_custom_conf_applies_to_regex(docker_compose, nginxproxy):
|
||||
r = nginxproxy.get("http://regex.foo.nginx-proxy.example/port")
|
||||
assert r.status_code == 200
|
||||
assert r.text == "answer from port 83\n"
|
||||
assert "X-test" in r.headers
|
||||
assert "bar" == r.headers["X-test"]
|
||||
|
||||
def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy):
|
||||
r = nginxproxy.get("http://web2.nginx-proxy.example/port")
|
||||
assert r.status_code == 200
|
||||
|
@ -5,7 +5,8 @@ services:
|
||||
image: nginxproxy/nginx-proxy:test
|
||||
volumes:
|
||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||
- ./my_custom_proxy_settings.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example_location:ro
|
||||
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example_location:ro
|
||||
- ./my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430_location:ro
|
||||
|
||||
web1:
|
||||
image: web
|
||||
@ -22,3 +23,11 @@ services:
|
||||
environment:
|
||||
WEB_PORTS: 82
|
||||
VIRTUAL_HOST: web2.nginx-proxy.example
|
||||
|
||||
regex:
|
||||
image: web
|
||||
expose:
|
||||
- "83"
|
||||
environment:
|
||||
WEB_PORTS: 83
|
||||
VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$
|
||||
|
@ -12,6 +12,13 @@ def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
|
||||
assert "X-test" in r.headers
|
||||
assert "f00" == r.headers["X-test"]
|
||||
|
||||
def test_custom_conf_applies_to_regex(docker_compose, nginxproxy):
|
||||
r = nginxproxy.get("http://regex.foo.nginx-proxy.example/port")
|
||||
assert r.status_code == 200
|
||||
assert r.text == "answer from port 83\n"
|
||||
assert "X-test" in r.headers
|
||||
assert "bar" == r.headers["X-test"]
|
||||
|
||||
def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy):
|
||||
r = nginxproxy.get("http://web2.nginx-proxy.example/port")
|
||||
assert r.status_code == 200
|
||||
|
@ -5,7 +5,8 @@ services:
|
||||
image: nginxproxy/nginx-proxy:test
|
||||
volumes:
|
||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||
- ./my_custom_proxy_settings.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example:ro
|
||||
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example:ro
|
||||
- ./my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430:ro
|
||||
|
||||
web1:
|
||||
image: web
|
||||
@ -22,3 +23,11 @@ services:
|
||||
environment:
|
||||
WEB_PORTS: 82
|
||||
VIRTUAL_HOST: web2.nginx-proxy.example
|
||||
|
||||
regex:
|
||||
image: web
|
||||
expose:
|
||||
- "83"
|
||||
environment:
|
||||
WEB_PORTS: 83
|
||||
VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$
|
||||
|
@ -5,7 +5,7 @@ services:
|
||||
image: nginxproxy/nginx-proxy:test
|
||||
volumes:
|
||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||
- ./my_custom_proxy_settings.conf:/etc/nginx/conf.d/my_custom_proxy_settings.conf:ro
|
||||
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/conf.d/my_custom_proxy_settings_f00.conf:ro
|
||||
|
||||
web1:
|
||||
image: web
|
||||
|
@ -0,0 +1 @@
|
||||
vhost:$2a$13$/aPYmoK0mmgyAI4TpKdFY.6441Ugo39MdXjhpm.Pp6D15rbz9tvz.
|
13
test/test_htpasswd/test_htpasswd_regex_virtual_host.py
Normal file
13
test/test_htpasswd/test_htpasswd_regex_virtual_host.py
Normal file
@ -0,0 +1,13 @@
|
||||
import pytest
|
||||
|
||||
def test_htpasswd_regex_virtual_host_is_restricted(docker_compose, nginxproxy):
|
||||
r = nginxproxy.get("http://regex.htpasswd.nginx-proxy.example/port")
|
||||
assert r.status_code == 401
|
||||
assert "WWW-Authenticate" in r.headers
|
||||
assert r.headers["WWW-Authenticate"] == 'Basic realm="Restricted access"'
|
||||
|
||||
|
||||
def test_htpasswd_regex_virtual_host_basic_auth(docker_compose, nginxproxy):
|
||||
r = nginxproxy.get("http://regex.htpasswd.nginx-proxy.example/port", auth=("vhost", "password"))
|
||||
assert r.status_code == 200
|
||||
assert r.text == "answer from port 80\n"
|
17
test/test_htpasswd/test_htpasswd_regex_virtual_host.yml
Normal file
17
test/test_htpasswd/test_htpasswd_regex_virtual_host.yml
Normal file
@ -0,0 +1,17 @@
|
||||
version: "2"
|
||||
|
||||
services:
|
||||
regex:
|
||||
image: web
|
||||
expose:
|
||||
- "80"
|
||||
environment:
|
||||
WEB_PORTS: 80
|
||||
VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$
|
||||
|
||||
sut:
|
||||
container_name: sut
|
||||
image: nginxproxy/nginx-proxy:test
|
||||
volumes:
|
||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||
- ./htpasswd:/etc/nginx/htpasswd:ro
|
Loading…
x
Reference in New Issue
Block a user