mirror of
https://github.com/thib8956/nginx-proxy
synced 2025-08-23 07:51:56 +00:00
Merge pull request #2602 from p12tic/acme-unknown-virtual-host
feat: support ACME challenges for unknown virtual hosts
This commit is contained in:
@@ -459,6 +459,8 @@ By default nginx-proxy generates location blocks to handle ACME HTTP Challenge.
|
|||||||
- `false`: do not handle ACME HTTP Challenge at all.
|
- `false`: do not handle ACME HTTP Challenge at all.
|
||||||
- `legacy`: legacy behavior for compatibility with older (<= `2.3`) versions of acme-companion, only handle ACME HTTP challenge when there is a certificate for the domain and `HTTPS_METHOD=redirect`.
|
- `legacy`: legacy behavior for compatibility with older (<= `2.3`) versions of acme-companion, only handle ACME HTTP challenge when there is a certificate for the domain and `HTTPS_METHOD=redirect`.
|
||||||
|
|
||||||
|
By default, nginx-proxy does not handle ACME HTTP Challenges for unknown virtual hosts. This may happen in cases when a container is not running at the time of the renewal. To enable handling of unknown virtual hosts, set `ACME_HTTP_CHALLENGE_ACCEPT_UNKNOWN_HOST` environment variable to `true` on the nginx-proxy container.
|
||||||
|
|
||||||
### Diffie-Hellman Groups
|
### Diffie-Hellman Groups
|
||||||
|
|
||||||
[RFC7919 groups](https://datatracker.ietf.org/doc/html/rfc7919#appendix-A) with key lengths of 2048, 3072, and 4096 bits are [provided by `nginx-proxy`](https://github.com/nginx-proxy/nginx-proxy/dhparam). The ENV `DHPARAM_BITS` can be set to `2048` or `3072` to change from the default 4096-bit key. The DH key file will be located in the container at `/etc/nginx/dhparam/dhparam.pem`. Mounting a different `dhparam.pem` file at that location will override the RFC7919 key.
|
[RFC7919 groups](https://datatracker.ietf.org/doc/html/rfc7919#appendix-A) with key lengths of 2048, 3072, and 4096 bits are [provided by `nginx-proxy`](https://github.com/nginx-proxy/nginx-proxy/dhparam). The ENV `DHPARAM_BITS` can be set to `2048` or `3072` to change from the default 4096-bit key. The DH key file will be located in the container at `/etc/nginx/dhparam/dhparam.pem`. Mounting a different `dhparam.pem` file at that location will override the RFC7919 key.
|
||||||
|
11
nginx.tmpl
11
nginx.tmpl
@@ -28,6 +28,7 @@
|
|||||||
{{- $_ := set $config "enable_debug_endpoint" ($globals.Env.DEBUG_ENDPOINT | default "false") }}
|
{{- $_ := set $config "enable_debug_endpoint" ($globals.Env.DEBUG_ENDPOINT | default "false") }}
|
||||||
{{- $_ := set $config "hsts" ($globals.Env.HSTS | default "max-age=31536000") }}
|
{{- $_ := set $config "hsts" ($globals.Env.HSTS | default "max-age=31536000") }}
|
||||||
{{- $_ := set $config "acme_http_challenge" ($globals.Env.ACME_HTTP_CHALLENGE_LOCATION | default "true") }}
|
{{- $_ := set $config "acme_http_challenge" ($globals.Env.ACME_HTTP_CHALLENGE_LOCATION | default "true") }}
|
||||||
|
{{- $_ := set $config "acme_http_challenge_accept_unknown_host" ($globals.Env.ACME_HTTP_CHALLENGE_ACCEPT_UNKNOWN_HOST | default "false" | parseBool) }}
|
||||||
{{- $_ := set $config "enable_http2" ($globals.Env.ENABLE_HTTP2 | default "true") }}
|
{{- $_ := set $config "enable_http2" ($globals.Env.ENABLE_HTTP2 | default "true") }}
|
||||||
{{- $_ := set $config "enable_http3" ($globals.Env.ENABLE_HTTP3 | default "false") }}
|
{{- $_ := set $config "enable_http3" ($globals.Env.ENABLE_HTTP3 | default "false") }}
|
||||||
{{- $_ := set $config "enable_http_on_missing_cert" ($globals.Env.ENABLE_HTTP_ON_MISSING_CERT | default "true") }}
|
{{- $_ := set $config "enable_http_on_missing_cert" ($globals.Env.ENABLE_HTTP_ON_MISSING_CERT | default "true") }}
|
||||||
@@ -861,6 +862,16 @@ server {
|
|||||||
ssl_reject_handshake on;
|
ssl_reject_handshake on;
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if $globals.config.acme_http_challenge_accept_unknown_host }}
|
||||||
|
location ^~ /.well-known/acme-challenge/ {
|
||||||
|
auth_basic off;
|
||||||
|
allow all;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
try_files $uri =404;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
{{- if (exists "/usr/share/nginx/html/errors/50x.html") }}
|
{{- if (exists "/usr/share/nginx/html/errors/50x.html") }}
|
||||||
error_page 500 502 503 504 /50x.html;
|
error_page 500 502 503 504 /50x.html;
|
||||||
location /50x.html {
|
location /50x.html {
|
||||||
|
@@ -0,0 +1,34 @@
|
|||||||
|
def test_redirect_acme_challenge_location_enabled(docker_compose, nginxproxy, acme_challenge_path):
|
||||||
|
r = nginxproxy.get(
|
||||||
|
f"http://web1.nginx-proxy.tld/{acme_challenge_path}",
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
def test_redirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
|
||||||
|
r = nginxproxy.get(
|
||||||
|
f"http://web2.nginx-proxy.tld/{acme_challenge_path}",
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
assert r.status_code == 301
|
||||||
|
|
||||||
|
def test_noredirect_acme_challenge_location_enabled(docker_compose, nginxproxy, acme_challenge_path):
|
||||||
|
r = nginxproxy.get(
|
||||||
|
f"http://web3.nginx-proxy.tld/{acme_challenge_path}",
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
def test_noredirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
|
||||||
|
r = nginxproxy.get(
|
||||||
|
f"http://web4.nginx-proxy.tld/{acme_challenge_path}",
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
def test_unknown_domain_acme_challenge_location_default_enabled(docker_compose, nginxproxy, acme_challenge_path):
|
||||||
|
r = nginxproxy.get(
|
||||||
|
f"http://web-unknown.nginx-proxy.tld/{acme_challenge_path}",
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
@@ -0,0 +1,40 @@
|
|||||||
|
services:
|
||||||
|
nginx-proxy:
|
||||||
|
environment:
|
||||||
|
ACME_HTTP_CHALLENGE_ACCEPT_UNKNOWN_HOST: "true"
|
||||||
|
|
||||||
|
web1:
|
||||||
|
image: web
|
||||||
|
expose:
|
||||||
|
- "81"
|
||||||
|
environment:
|
||||||
|
WEB_PORTS: "81"
|
||||||
|
VIRTUAL_HOST: "web1.nginx-proxy.tld"
|
||||||
|
|
||||||
|
web2:
|
||||||
|
image: web
|
||||||
|
expose:
|
||||||
|
- "82"
|
||||||
|
environment:
|
||||||
|
WEB_PORTS: "82"
|
||||||
|
VIRTUAL_HOST: "web2.nginx-proxy.tld"
|
||||||
|
ACME_HTTP_CHALLENGE_LOCATION: "false"
|
||||||
|
|
||||||
|
web3:
|
||||||
|
image: web
|
||||||
|
expose:
|
||||||
|
- "83"
|
||||||
|
environment:
|
||||||
|
WEB_PORTS: "83"
|
||||||
|
VIRTUAL_HOST: "web3.nginx-proxy.tld"
|
||||||
|
HTTPS_METHOD: noredirect
|
||||||
|
|
||||||
|
web4:
|
||||||
|
image: web
|
||||||
|
expose:
|
||||||
|
- "84"
|
||||||
|
environment:
|
||||||
|
WEB_PORTS: "84"
|
||||||
|
VIRTUAL_HOST: "web4.nginx-proxy.tld"
|
||||||
|
HTTPS_METHOD: noredirect
|
||||||
|
ACME_HTTP_CHALLENGE_LOCATION: "false"
|
@@ -25,3 +25,10 @@ def test_noredirect_acme_challenge_location_enabled(docker_compose, nginxproxy,
|
|||||||
allow_redirects=False
|
allow_redirects=False
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
def test_unknown_domain_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
|
||||||
|
r = nginxproxy.get(
|
||||||
|
f"http://web-unknown.nginx-proxy.tld/{acme_challenge_path}",
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
assert r.status_code == 503
|
||||||
|
@@ -25,3 +25,10 @@ def test_noredirect_acme_challenge_location_disabled(docker_compose, nginxproxy,
|
|||||||
allow_redirects=False
|
allow_redirects=False
|
||||||
)
|
)
|
||||||
assert r.status_code == 404
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
def test_unknown_domain_acme_challenge_location_default_enabled(docker_compose, nginxproxy, acme_challenge_path):
|
||||||
|
r = nginxproxy.get(
|
||||||
|
f"http://web-unknown.nginx-proxy.tld/{acme_challenge_path}",
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
assert r.status_code == 503
|
||||||
|
@@ -11,3 +11,10 @@ def test_noredirect_acme_challenge_location_legacy(docker_compose, nginxproxy, a
|
|||||||
allow_redirects=False
|
allow_redirects=False
|
||||||
)
|
)
|
||||||
assert r.status_code == 404
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
def test_unknown_domain_acme_challenge_location_legacy(docker_compose, nginxproxy, acme_challenge_path):
|
||||||
|
r = nginxproxy.get(
|
||||||
|
f"http://web-unknown.nginx-proxy.tld/{acme_challenge_path}",
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
assert r.status_code == 503
|
||||||
|
Reference in New Issue
Block a user