mirror of
https://github.com/thib8956/nginx-proxy
synced 2024-11-21 19:36:30 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
8219788df6
@ -7,7 +7,8 @@ env:
|
|||||||
- TEST_TARGET: test-alpine
|
- TEST_TARGET: test-alpine
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get remove docker docker-engine
|
- sudo apt-get -y remove docker docker-engine docker-ce
|
||||||
|
- sudo rm /etc/apt/sources.list.d/docker.list
|
||||||
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
||||||
- sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
- sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
||||||
- sudo apt-get update
|
- sudo apt-get update
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM nginx:1.13
|
FROM nginx:1.17.8
|
||||||
LABEL maintainer="Jason Wilder mail@jasonwilder.com"
|
LABEL maintainer="Jason Wilder mail@jasonwilder.com"
|
||||||
|
|
||||||
# Install wget and install/updates certificates
|
# Install wget and install/updates certificates
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM nginx:1.13-alpine
|
FROM nginx:1.17.8-alpine
|
||||||
LABEL maintainer="Jason Wilder mail@jasonwilder.com"
|
LABEL maintainer="Jason Wilder mail@jasonwilder.com"
|
||||||
|
|
||||||
# Install wget and install/updates certificates
|
# Install wget and install/updates certificates
|
||||||
|
57
README.md
57
README.md
@ -1,5 +1,5 @@
|
|||||||
![latest 0.7.0](https://img.shields.io/badge/latest-0.7.0-green.svg?style=flat)
|
![latest 0.7.0](https://img.shields.io/badge/latest-0.7.0-green.svg?style=flat)
|
||||||
![nginx 1.13](https://img.shields.io/badge/nginx-1.13-brightgreen.svg) ![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/jwilder/nginx-proxy.svg?branch=master)](https://travis-ci.org/jwilder/nginx-proxy) [![](https://img.shields.io/docker/stars/jwilder/nginx-proxy.svg)](https://hub.docker.com/r/jwilder/nginx-proxy 'DockerHub') [![](https://img.shields.io/docker/pulls/jwilder/nginx-proxy.svg)](https://hub.docker.com/r/jwilder/nginx-proxy 'DockerHub')
|
![nginx 1.17.8](https://img.shields.io/badge/nginx-1.17.8-brightgreen.svg) ![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/jwilder/nginx-proxy.svg?branch=master)](https://travis-ci.org/jwilder/nginx-proxy) [![](https://img.shields.io/docker/stars/jwilder/nginx-proxy.svg)](https://hub.docker.com/r/jwilder/nginx-proxy 'DockerHub') [![](https://img.shields.io/docker/pulls/jwilder/nginx-proxy.svg)](https://hub.docker.com/r/jwilder/nginx-proxy 'DockerHub')
|
||||||
|
|
||||||
|
|
||||||
nginx-proxy sets up a container running nginx and [docker-gen][1]. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped.
|
nginx-proxy sets up a container running nginx and [docker-gen][1]. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped.
|
||||||
@ -16,7 +16,7 @@ Then start any containers you want proxied with an env var `VIRTUAL_HOST=subdoma
|
|||||||
|
|
||||||
$ docker run -e VIRTUAL_HOST=foo.bar.com ...
|
$ docker run -e VIRTUAL_HOST=foo.bar.com ...
|
||||||
|
|
||||||
The containers being proxied must [expose](https://docs.docker.com/engine/reference/run/#expose-incoming-ports) the port to be proxied, either by using the `EXPOSE` directive in their `Dockerfile` or by using the `--expose` flag to `docker run` or `docker create`.
|
The containers being proxied must [expose](https://docs.docker.com/engine/reference/run/#expose-incoming-ports) the port to be proxied, either by using the `EXPOSE` directive in their `Dockerfile` or by using the `--expose` flag to `docker run` or `docker create` and be in the same network. By default, if you don't pass the --net flag when your nginx-proxy container is created, it will only be attached to the default bridge network. This means that it will not be able to connect to containers on networks other than bridge.
|
||||||
|
|
||||||
Provided your DNS is setup to forward foo.bar.com to the host running nginx-proxy, the request will be routed to a container with the VIRTUAL_HOST env var set.
|
Provided your DNS is setup to forward foo.bar.com to the host running nginx-proxy, the request will be routed to a container with the VIRTUAL_HOST env var set.
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ If you would like to connect to FastCGI backend, set `VIRTUAL_PROTO=fastcgi` on
|
|||||||
backend container. Your backend container should then listen on a port rather
|
backend container. Your backend container should then listen on a port rather
|
||||||
than a socket and expose that port.
|
than a socket and expose that port.
|
||||||
|
|
||||||
### FastCGI Filr Root Directory
|
### FastCGI File Root Directory
|
||||||
|
|
||||||
If you use fastcgi,you can set `VIRTUAL_ROOT=xxx` for your root directory
|
If you use fastcgi,you can set `VIRTUAL_ROOT=xxx` for your root directory
|
||||||
|
|
||||||
@ -181,8 +181,12 @@ Finally, start your containers with `VIRTUAL_HOST` environment variables.
|
|||||||
$ docker run -e VIRTUAL_HOST=foo.bar.com ...
|
$ docker run -e VIRTUAL_HOST=foo.bar.com ...
|
||||||
### SSL Support using letsencrypt
|
### SSL Support using letsencrypt
|
||||||
|
|
||||||
[letsencrypt-nginx-proxy-companion](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion) is a lightweight companion container for the nginx-proxy. It allow the creation/renewal of Let's Encrypt certificates automatically.
|
[letsencrypt-nginx-proxy-companion](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion) is a lightweight companion container for the nginx-proxy. It allows the creation/renewal of Let's Encrypt certificates automatically.
|
||||||
|
|
||||||
|
Set `DHPARAM_GENERATION` environment variable to `false` to disabled Diffie-Hellman parameters completely. This will also ignore auto-generation made by `nginx-proxy`.
|
||||||
|
The default value is `true`
|
||||||
|
|
||||||
|
$ docker run -e DHPARAM_GENERATION=false ....
|
||||||
### SSL Support
|
### SSL Support
|
||||||
|
|
||||||
SSL is supported using single host, wildcard and SNI certificates using naming conventions for
|
SSL is supported using single host, wildcard and SNI certificates using naming conventions for
|
||||||
@ -214,7 +218,7 @@ at startup. Since it can take minutes to generate a new `dhparam.pem`, it is do
|
|||||||
background. Once generation is complete, the `dhparam.pem` is saved on a persistent volume and nginx
|
background. Once generation is complete, the `dhparam.pem` is saved on a persistent volume and nginx
|
||||||
is reloaded. This generation process only occurs the first time you start `nginx-proxy`.
|
is reloaded. This generation process only occurs the first time you start `nginx-proxy`.
|
||||||
|
|
||||||
> COMPATIBILITY WARNING: The default generated `dhparam.pem` key is 2048 bits for A+ security. Some
|
> COMPATIBILITY WARNING: The default generated `dhparam.pem` key is 2048 bits for A+ security. Some
|
||||||
> older clients (like Java 6 and 7) do not support DH keys with over 1024 bits. In order to support these
|
> older clients (like Java 6 and 7) do not support DH keys with over 1024 bits. In order to support these
|
||||||
> clients, you must either provide your own `dhparam.pem`, or tell `nginx-proxy` to generate a 1024-bit
|
> clients, you must either provide your own `dhparam.pem`, or tell `nginx-proxy` to generate a 1024-bit
|
||||||
> key on startup by passing `-e DHPARAM_BITS=1024`.
|
> key on startup by passing `-e DHPARAM_BITS=1024`.
|
||||||
@ -237,20 +241,27 @@ to identify the certificate to be used. For example, a certificate for `*.foo.c
|
|||||||
could be named `shared.crt` and `shared.key`. A container running with `VIRTUAL_HOST=foo.bar.com`
|
could be named `shared.crt` and `shared.key`. A container running with `VIRTUAL_HOST=foo.bar.com`
|
||||||
and `CERT_NAME=shared` will then use this shared cert.
|
and `CERT_NAME=shared` will then use this shared cert.
|
||||||
|
|
||||||
|
#### OCSP Stapling
|
||||||
|
To enable OCSP Stapling for a domain, `nginx-proxy` looks for a PEM certificate containing the trusted
|
||||||
|
CA certificate chain at `/etc/nginx/certs/<domain>.chain.pem`, where `<domain>` is the domain name in
|
||||||
|
the `VIRTUAL_HOST` directive. The format of this file is a concatenation of the public PEM CA
|
||||||
|
certificates starting with the intermediate CA most near the SSL certificate, down to the root CA. This is
|
||||||
|
often referred to as the "SSL Certificate Chain". If found, this filename is passed to the NGINX
|
||||||
|
[`ssl_trusted_certificate` directive](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_trusted_certificate)
|
||||||
|
and OCSP Stapling is enabled.
|
||||||
|
|
||||||
#### How SSL Support Works
|
#### How SSL Support Works
|
||||||
|
|
||||||
The default SSL cipher configuration is based on the [Mozilla intermediate profile](https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29) which
|
The default SSL cipher configuration is based on the [Mozilla intermediate profile](https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29) version 5.0 which
|
||||||
should provide compatibility with clients back to Firefox 1, Chrome 1, IE 7, Opera 5, Safari 1,
|
should provide compatibility with clients back to Firefox 27, Android 4.4.2, Chrome 31, Edge, IE 11 on Windows 7,
|
||||||
Windows XP IE8, Android 2.3, Java 7. Note that the DES-based TLS ciphers were removed for security.
|
Java 8u31, OpenSSL 1.0.1, Opera 20, and Safari 9. Note that the DES-based TLS ciphers were removed for security.
|
||||||
The configuration also enables HSTS, PFS, OCSP stapling and SSL session caches. Currently TLS 1.0, 1.1 and 1.2
|
The configuration also enables HSTS, PFS, OCSP stapling and SSL session caches. Currently TLS 1.2 and 1.3
|
||||||
are supported. TLS 1.0 is deprecated but its end of life is not until June 30, 2018. It is being
|
are supported.
|
||||||
included because the following browsers will stop working when it is removed: Chrome < 22, Firefox < 27,
|
|
||||||
IE < 11, Safari < 7, iOS < 5, Android Browser < 5.
|
|
||||||
|
|
||||||
If you don't require backward compatibility, you can use the [Mozilla modern profile](https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility)
|
If you don't require backward compatibility, you can use the [Mozilla modern profile](https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility)
|
||||||
profile instead by including the environment variable `SSL_POLICY=Mozilla-Modern` to your container.
|
profile instead by including the environment variable `SSL_POLICY=Mozilla-Modern` to the nginx-proxy container or to your container.
|
||||||
This profile is compatible with clients back to Firefox 27, Chrome 30, IE 11 on Windows 7,
|
This profile is compatible with clients back to Firefox 63, Android 10.0, Chrome 70, Edge 75, Java 11,
|
||||||
Edge, Opera 17, Safari 9, Android 5.0, and Java 8.
|
OpenSSL 1.1.1, Opera 57, and Safari 12.1. Note that this profile is **not** compatible with any version of Internet Explorer.
|
||||||
|
|
||||||
Other policies available through the `SSL_POLICY` environment variable are [`Mozilla-Old`](https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility)
|
Other policies available through the `SSL_POLICY` environment variable are [`Mozilla-Old`](https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility)
|
||||||
and the [AWS ELB Security Policies](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html)
|
and the [AWS ELB Security Policies](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html)
|
||||||
@ -273,12 +284,12 @@ a 500.
|
|||||||
|
|
||||||
To serve traffic in both SSL and non-SSL modes without redirecting to SSL, you can include the
|
To serve traffic in both SSL and non-SSL modes without redirecting to SSL, you can include the
|
||||||
environment variable `HTTPS_METHOD=noredirect` (the default is `HTTPS_METHOD=redirect`). You can also
|
environment variable `HTTPS_METHOD=noredirect` (the default is `HTTPS_METHOD=redirect`). You can also
|
||||||
disable the non-SSL site entirely with `HTTPS_METHOD=nohttp`, or disable the HTTPS site with
|
disable the non-SSL site entirely with `HTTPS_METHOD=nohttp`, or disable the HTTPS site with
|
||||||
`HTTPS_METHOD=nohttps`. `HTTPS_METHOD` must be specified on each container for which you want to
|
`HTTPS_METHOD=nohttps`. `HTTPS_METHOD` must be specified on each container for which you want to
|
||||||
override the default behavior. If `HTTPS_METHOD=noredirect` is used, Strict Transport Security (HSTS)
|
override the default behavior. If `HTTPS_METHOD=noredirect` is used, Strict Transport Security (HSTS)
|
||||||
is disabled to prevent HTTPS users from being redirected by the client. If you cannot get to the HTTP
|
is disabled to prevent HTTPS users from being redirected by the client. If you cannot get to the HTTP
|
||||||
site after changing this setting, your browser has probably cached the HSTS policy and is automatically
|
site after changing this setting, your browser has probably cached the HSTS policy and is automatically
|
||||||
redirecting you back to HTTPS. You will need to clear your browser's HSTS cache or use an incognito
|
redirecting you back to HTTPS. You will need to clear your browser's HSTS cache or use an incognito
|
||||||
window / different browser.
|
window / different browser.
|
||||||
|
|
||||||
By default, [HTTP Strict Transport Security (HSTS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security)
|
By default, [HTTP Strict Transport Security (HSTS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security)
|
||||||
@ -401,7 +412,7 @@ Before submitting pull requests or issues, please check github to make sure an e
|
|||||||
To run tests, you need to prepare the docker image to test which must be tagged `jwilder/nginx-proxy:test`:
|
To run tests, you need to prepare the docker image to test which must be tagged `jwilder/nginx-proxy:test`:
|
||||||
|
|
||||||
docker build -t jwilder/nginx-proxy:test . # build the Debian variant image
|
docker build -t jwilder/nginx-proxy:test . # build the Debian variant image
|
||||||
|
|
||||||
and call the [test/pytest.sh](test/pytest.sh) script.
|
and call the [test/pytest.sh](test/pytest.sh) script.
|
||||||
|
|
||||||
Then build the Alpine variant of the image:
|
Then build the Alpine variant of the image:
|
||||||
@ -414,7 +425,7 @@ and call the [test/pytest.sh](test/pytest.sh) script again.
|
|||||||
If your system has the `make` command, you can automate those tasks by calling:
|
If your system has the `make` command, you can automate those tasks by calling:
|
||||||
|
|
||||||
make test
|
make test
|
||||||
|
|
||||||
|
|
||||||
You can learn more about how the test suite works and how to write new tests in the [test/README.md](test/README.md) file.
|
You can learn more about how the test suite works and how to write new tests in the [test/README.md](test/README.md) file.
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ fi
|
|||||||
|
|
||||||
# Generate dhparam file if required
|
# Generate dhparam file if required
|
||||||
# Note: if $DHPARAM_BITS is not defined, generate-dhparam.sh will use 2048 as a default
|
# Note: if $DHPARAM_BITS is not defined, generate-dhparam.sh will use 2048 as a default
|
||||||
/app/generate-dhparam.sh $DHPARAM_BITS
|
# Note2: if $DHPARAM_GENERATION is set to false in environment variable, dh param generator will skip completely
|
||||||
|
/app/generate-dhparam.sh $DHPARAM_BITS $DHPARAM_GENERATION
|
||||||
|
|
||||||
# Compute the DNS resolvers for use in the templates - if the IP contains ":", it's IPv6 and must be enclosed in []
|
# Compute the DNS resolvers for use in the templates - if the IP contains ":", it's IPv6 and must be enclosed in []
|
||||||
export RESOLVERS=$(awk '$1 == "nameserver" {print ($2 ~ ":")? "["$2"]": $2}' ORS=' ' /etc/resolv.conf | sed 's/ *$//g')
|
export RESOLVERS=$(awk '$1 == "nameserver" {print ($2 ~ ":")? "["$2"]": $2}' ORS=' ' /etc/resolv.conf | sed 's/ *$//g')
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
# The first argument is the bit depth of the dhparam, or 2048 if unspecified
|
# The first argument is the bit depth of the dhparam, or 2048 if unspecified
|
||||||
DHPARAM_BITS=${1:-2048}
|
DHPARAM_BITS=${1:-2048}
|
||||||
|
GENERATE_DHPARAM=${2:-true}
|
||||||
|
|
||||||
# If a dhparam file is not available, use the pre-generated one and generate a new one in the background.
|
# If a dhparam file is not available, use the pre-generated one and generate a new one in the background.
|
||||||
# Note that /etc/nginx/dhparam is a volume, so this dhparam will persist restarts.
|
# Note that /etc/nginx/dhparam is a volume, so this dhparam will persist restarts.
|
||||||
@ -25,6 +26,11 @@ if [[ -f $DHPARAM_FILE ]]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ $GENERATE_DHPARAM =~ ^[Ff][Aa][Ll][Ss][Ee]$ ]]; then
|
||||||
|
echo "Skipping Diffie-Hellman parameters generation and Ignoring pre-generated dhparam.pem"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
cat >&2 <<-EOT
|
cat >&2 <<-EOT
|
||||||
WARNING: $DHPARAM_FILE was not found. A pre-generated dhparam.pem will be used for now while a new one
|
WARNING: $DHPARAM_FILE was not found. A pre-generated dhparam.pem will be used for now while a new one
|
||||||
is being generated in the background. Once the new dhparam.pem is in place, nginx will be reloaded.
|
is being generated in the background. Once the new dhparam.pem is in place, nginx will be reloaded.
|
||||||
@ -37,7 +43,8 @@ touch $GEN_LOCKFILE
|
|||||||
# Generate a new dhparam in the background in a low priority and reload nginx when finished (grep removes the progress indicator).
|
# Generate a new dhparam in the background in a low priority and reload nginx when finished (grep removes the progress indicator).
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
nice -n +5 openssl dhparam -out $DHPARAM_FILE $DHPARAM_BITS 2>&1 \
|
nice -n +5 openssl dhparam -out $DHPARAM_FILE.tmp $DHPARAM_BITS 2>&1 \
|
||||||
|
&& mv $DHPARAM_FILE.tmp $DHPARAM_FILE \
|
||||||
&& echo "dhparam generation complete, reloading nginx" \
|
&& echo "dhparam generation complete, reloading nginx" \
|
||||||
&& nginx -s reload
|
&& nginx -s reload
|
||||||
) | grep -vE '^[\.+]+'
|
) | grep -vE '^[\.+]+'
|
||||||
|
135
nginx.tmpl
135
nginx.tmpl
@ -1,5 +1,8 @@
|
|||||||
{{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }}
|
{{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }}
|
||||||
|
|
||||||
|
{{ $external_http_port := coalesce $.Env.HTTP_PORT "80" }}
|
||||||
|
{{ $external_https_port := coalesce $.Env.HTTPS_PORT "443" }}
|
||||||
|
|
||||||
{{ define "upstream" }}
|
{{ define "upstream" }}
|
||||||
{{ if .Address }}
|
{{ if .Address }}
|
||||||
{{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}}
|
{{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}}
|
||||||
@ -19,7 +22,50 @@
|
|||||||
server 127.0.0.1 down;
|
server 127.0.0.1 down;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "ssl_policy" }}
|
||||||
|
{{ if eq .ssl_policy "Mozilla-Modern" }}
|
||||||
|
ssl_protocols TLSv1.3;
|
||||||
|
{{/* nginx currently lacks ability to choose ciphers in TLS 1.3 in configuration, see https://trac.nginx.org/nginx/ticket/1529 /*}}
|
||||||
|
{{/* a possible workaround can be modify /etc/ssl/openssl.cnf to change it globally (see https://trac.nginx.org/nginx/ticket/1529#comment:12 ) /*}}
|
||||||
|
{{/* explicitly set ngnix default value in order to allow single servers to override the global http value */}}
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
ssl_prefer_server_ciphers off;
|
||||||
|
{{ else if eq .ssl_policy "Mozilla-Intermediate" }}
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
|
||||||
|
ssl_prefer_server_ciphers off;
|
||||||
|
{{ else if eq .ssl_policy "Mozilla-Old" }}
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA';
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
{{ else if eq .ssl_policy "AWS-TLS-1-2-2017-01" }}
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES128-SHA256:AES256-GCM-SHA384:AES256-SHA256';
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
{{ else if eq .ssl_policy "AWS-TLS-1-1-2017-01" }}
|
||||||
|
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
{{ else if eq .ssl_policy "AWS-2016-08" }}
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
{{ else if eq .ssl_policy "AWS-2015-05" }}
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DES-CBC3-SHA';
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
{{ else if eq .ssl_policy "AWS-2015-03" }}
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA';
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
{{ else if eq .ssl_policy "AWS-2015-02" }}
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA';
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
|
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
|
||||||
@ -65,6 +111,10 @@ log_format vhost '$host $remote_addr - $remote_user [$time_local] '
|
|||||||
|
|
||||||
access_log off;
|
access_log off;
|
||||||
|
|
||||||
|
{{/* Get the SSL_POLICY defined by this container, falling back to "Mozilla-Intermediate" */}}
|
||||||
|
{{ $ssl_policy := or ($.Env.SSL_POLICY) "Mozilla-Intermediate" }}
|
||||||
|
{{ template "ssl_policy" (dict "ssl_policy" $ssl_policy) }}
|
||||||
|
|
||||||
{{ if $.Env.RESOLVERS }}
|
{{ if $.Env.RESOLVERS }}
|
||||||
resolver {{ $.Env.RESOLVERS }};
|
resolver {{ $.Env.RESOLVERS }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
@ -93,9 +143,9 @@ proxy_set_header Proxy "";
|
|||||||
{{ $enable_ipv6 := eq (or ($.Env.ENABLE_IPV6) "") "true" }}
|
{{ $enable_ipv6 := eq (or ($.Env.ENABLE_IPV6) "") "true" }}
|
||||||
server {
|
server {
|
||||||
server_name _; # This is just an invalid value which will never trigger on a real hostname.
|
server_name _; # This is just an invalid value which will never trigger on a real hostname.
|
||||||
listen 80;
|
listen {{ $external_http_port }};
|
||||||
{{ if $enable_ipv6 }}
|
{{ if $enable_ipv6 }}
|
||||||
listen [::]:80;
|
listen [::]:{{ $external_http_port }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ $access_log }}
|
{{ $access_log }}
|
||||||
return 503;
|
return 503;
|
||||||
@ -104,13 +154,14 @@ server {
|
|||||||
{{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
|
{{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
|
||||||
server {
|
server {
|
||||||
server_name _; # This is just an invalid value which will never trigger on a real hostname.
|
server_name _; # This is just an invalid value which will never trigger on a real hostname.
|
||||||
listen 443 ssl http2;
|
listen {{ $external_https_port }} ssl http2;
|
||||||
{{ if $enable_ipv6 }}
|
{{ if $enable_ipv6 }}
|
||||||
listen [::]:443 ssl http2;
|
listen [::]:{{ $external_https_port }} ssl http2;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ $access_log }}
|
{{ $access_log }}
|
||||||
return 503;
|
return 503;
|
||||||
|
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
ssl_session_tickets off;
|
ssl_session_tickets off;
|
||||||
ssl_certificate /etc/nginx/certs/default.crt;
|
ssl_certificate /etc/nginx/certs/default.crt;
|
||||||
ssl_certificate_key /etc/nginx/certs/default.key;
|
ssl_certificate_key /etc/nginx/certs/default.key;
|
||||||
@ -165,8 +216,8 @@ upstream {{ $upstream_name }} {
|
|||||||
{{/* Get the HTTPS_METHOD defined by containers w/ the same vhost, falling back to "redirect" */}}
|
{{/* Get the HTTPS_METHOD defined by containers w/ the same vhost, falling back to "redirect" */}}
|
||||||
{{ $https_method := or (first (groupByKeys $containers "Env.HTTPS_METHOD")) "redirect" }}
|
{{ $https_method := or (first (groupByKeys $containers "Env.HTTPS_METHOD")) "redirect" }}
|
||||||
|
|
||||||
{{/* Get the SSL_POLICY defined by containers w/ the same vhost, falling back to "Mozilla-Intermediate" */}}
|
{{/* Get the SSL_POLICY defined by containers w/ the same vhost, falling back to empty string (use default) */}}
|
||||||
{{ $ssl_policy := or (first (groupByKeys $containers "Env.SSL_POLICY")) "Mozilla-Intermediate" }}
|
{{ $ssl_policy := or (first (groupByKeys $containers "Env.SSL_POLICY")) "" }}
|
||||||
|
|
||||||
{{/* Get the HSTS defined by containers w/ the same vhost, falling back to "max-age=31536000" */}}
|
{{/* Get the HSTS defined by containers w/ the same vhost, falling back to "max-age=31536000" */}}
|
||||||
{{ $hsts := or (first (groupByKeys $containers "Env.HSTS")) "max-age=31536000" }}
|
{{ $hsts := or (first (groupByKeys $containers "Env.HSTS")) "max-age=31536000" }}
|
||||||
@ -195,20 +246,32 @@ upstream {{ $upstream_name }} {
|
|||||||
{{ if eq $https_method "redirect" }}
|
{{ if eq $https_method "redirect" }}
|
||||||
server {
|
server {
|
||||||
server_name {{ $host }};
|
server_name {{ $host }};
|
||||||
listen 80 {{ $default_server }};
|
listen {{ $external_http_port }} {{ $default_server }};
|
||||||
{{ if $enable_ipv6 }}
|
{{ if $enable_ipv6 }}
|
||||||
listen [::]:80 {{ $default_server }};
|
listen [::]:{{ $external_http_port }} {{ $default_server }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ $access_log }}
|
{{ $access_log }}
|
||||||
return 301 https://$host$request_uri;
|
|
||||||
|
# Do not HTTPS redirect Let'sEncrypt ACME challenge
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
auth_basic off;
|
||||||
|
allow all;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
try_files $uri =404;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
server_name {{ $host }};
|
server_name {{ $host }};
|
||||||
listen 443 ssl http2 {{ $default_server }};
|
listen {{ $external_https_port }} ssl http2 {{ $default_server }};
|
||||||
{{ if $enable_ipv6 }}
|
{{ if $enable_ipv6 }}
|
||||||
listen [::]:443 ssl http2 {{ $default_server }};
|
listen [::]:{{ $external_https_port }} ssl http2 {{ $default_server }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ $access_log }}
|
{{ $access_log }}
|
||||||
|
|
||||||
@ -217,36 +280,8 @@ server {
|
|||||||
include /etc/nginx/network_internal.conf;
|
include /etc/nginx/network_internal.conf;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ if eq $ssl_policy "Mozilla-Modern" }}
|
{{ template "ssl_policy" (dict "ssl_policy" $ssl_policy) }}
|
||||||
ssl_protocols TLSv1.2;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
|
|
||||||
{{ else if eq $ssl_policy "Mozilla-Intermediate" }}
|
|
||||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS';
|
|
||||||
{{ else if eq $ssl_policy "Mozilla-Old" }}
|
|
||||||
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP';
|
|
||||||
{{ else if eq $ssl_policy "AWS-TLS-1-2-2017-01" }}
|
|
||||||
ssl_protocols TLSv1.2;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES128-SHA256:AES256-GCM-SHA384:AES256-SHA256';
|
|
||||||
{{ else if eq $ssl_policy "AWS-TLS-1-1-2017-01" }}
|
|
||||||
ssl_protocols TLSv1.1 TLSv1.2;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
|
|
||||||
{{ else if eq $ssl_policy "AWS-2016-08" }}
|
|
||||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
|
|
||||||
{{ else if eq $ssl_policy "AWS-2015-05" }}
|
|
||||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DES-CBC3-SHA';
|
|
||||||
{{ else if eq $ssl_policy "AWS-2015-03" }}
|
|
||||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA';
|
|
||||||
{{ else if eq $ssl_policy "AWS-2015-02" }}
|
|
||||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA';
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
ssl_prefer_server_ciphers on;
|
|
||||||
ssl_session_timeout 5m;
|
ssl_session_timeout 5m;
|
||||||
ssl_session_cache shared:SSL:50m;
|
ssl_session_cache shared:SSL:50m;
|
||||||
ssl_session_tickets off;
|
ssl_session_tickets off;
|
||||||
@ -264,8 +299,8 @@ server {
|
|||||||
ssl_trusted_certificate {{ printf "/etc/nginx/certs/%s.chain.pem" $cert }};
|
ssl_trusted_certificate {{ printf "/etc/nginx/certs/%s.chain.pem" $cert }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ if (and (ne $https_method "noredirect") (ne $hsts "off")) }}
|
{{ if (not (or (eq $https_method "noredirect") (eq $hsts "off"))) }}
|
||||||
add_header Strict-Transport-Security "{{ trim $hsts }}";
|
add_header Strict-Transport-Security "{{ trim $hsts }}" always;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
|
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
|
||||||
@ -280,8 +315,10 @@ server {
|
|||||||
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||||
{{ else if eq $proto "fastcgi" }}
|
{{ else if eq $proto "fastcgi" }}
|
||||||
root {{ trim $vhost_root }};
|
root {{ trim $vhost_root }};
|
||||||
include fastcgi.conf;
|
include fastcgi_params;
|
||||||
fastcgi_pass {{ trim $upstream_name }};
|
fastcgi_pass {{ trim $upstream_name }};
|
||||||
|
{{ else if eq $proto "grpc" }}
|
||||||
|
grpc_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||||
{{ else }}
|
{{ else }}
|
||||||
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
@ -304,7 +341,7 @@ server {
|
|||||||
|
|
||||||
server {
|
server {
|
||||||
server_name {{ $host }};
|
server_name {{ $host }};
|
||||||
listen 80 {{ $default_server }};
|
listen {{ $external_http_port }} {{ $default_server }};
|
||||||
{{ if $enable_ipv6 }}
|
{{ if $enable_ipv6 }}
|
||||||
listen [::]:80 {{ $default_server }};
|
listen [::]:80 {{ $default_server }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
@ -327,8 +364,10 @@ server {
|
|||||||
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||||
{{ else if eq $proto "fastcgi" }}
|
{{ else if eq $proto "fastcgi" }}
|
||||||
root {{ trim $vhost_root }};
|
root {{ trim $vhost_root }};
|
||||||
include fastcgi.conf;
|
include fastcgi_params;
|
||||||
fastcgi_pass {{ trim $upstream_name }};
|
fastcgi_pass {{ trim $upstream_name }};
|
||||||
|
{{ else if eq $proto "grpc" }}
|
||||||
|
grpc_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||||
{{ else }}
|
{{ else }}
|
||||||
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
@ -347,9 +386,9 @@ server {
|
|||||||
{{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
|
{{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
|
||||||
server {
|
server {
|
||||||
server_name {{ $host }};
|
server_name {{ $host }};
|
||||||
listen 443 ssl http2 {{ $default_server }};
|
listen {{ $external_https_port }} ssl http2 {{ $default_server }};
|
||||||
{{ if $enable_ipv6 }}
|
{{ if $enable_ipv6 }}
|
||||||
listen [::]:443 ssl http2 {{ $default_server }};
|
listen [::]:{{ $external_https_port }} ssl http2 {{ $default_server }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ $access_log }}
|
{{ $access_log }}
|
||||||
return 500;
|
return 500;
|
||||||
|
@ -24,7 +24,7 @@ fi
|
|||||||
# Create a nginx container (which conveniently provides the `openssl` command)
|
# Create a nginx container (which conveniently provides the `openssl` command)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
CONTAINER=$(docker run -d -v $DIR:/work -w /work -e SAN="$ALTERNATE_DOMAINS" nginx:1.13)
|
CONTAINER=$(docker run -d -v $DIR:/work -w /work -e SAN="$ALTERNATE_DOMAINS" nginx:1.14.1)
|
||||||
# Configure openssl
|
# Configure openssl
|
||||||
docker exec $CONTAINER bash -c '
|
docker exec $CONTAINER bash -c '
|
||||||
mkdir -p /ca/{certs,crl,private,newcerts} 2>/dev/null
|
mkdir -p /ca/{certs,crl,private,newcerts} 2>/dev/null
|
||||||
|
@ -257,7 +257,7 @@ def get_nginx_conf_from_container(container):
|
|||||||
strm, stat = container.get_archive('/etc/nginx/conf.d/default.conf')
|
strm, stat = container.get_archive('/etc/nginx/conf.d/default.conf')
|
||||||
with tarfile.open(fileobj=StringIO(strm.read())) as tf:
|
with tarfile.open(fileobj=StringIO(strm.read())) as tf:
|
||||||
conffile = tf.extractfile('default.conf')
|
conffile = tf.extractfile('default.conf')
|
||||||
return conffile.read()
|
return conffile.read()
|
||||||
|
|
||||||
|
|
||||||
def docker_compose_up(compose_file='docker-compose.yml'):
|
def docker_compose_up(compose_file='docker-compose.yml'):
|
||||||
@ -469,5 +469,5 @@ try:
|
|||||||
except docker.errors.ImageNotFound:
|
except docker.errors.ImageNotFound:
|
||||||
pytest.exit("The docker image 'jwilder/nginx-proxy:test' is missing")
|
pytest.exit("The docker image 'jwilder/nginx-proxy:test' is missing")
|
||||||
|
|
||||||
if docker.__version__ != "2.0.2":
|
if docker.__version__ != "2.1.0":
|
||||||
pytest.exit("This test suite is meant to work with the python docker module v2.0.2")
|
pytest.exit("This test suite is meant to work with the python docker module v2.1.0")
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
backoff==1.3.2
|
backoff==1.3.2
|
||||||
docker-compose==1.11.1
|
docker-compose==1.11.2
|
||||||
docker==2.0.2
|
docker==2.1.0
|
||||||
pytest==3.0.5
|
pytest==3.0.5
|
||||||
requests==2.11.1
|
requests==2.11.1
|
||||||
|
@ -1,28 +1,35 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import os, sys
|
import os, sys, re
|
||||||
import http.server
|
import http.server
|
||||||
import socketserver
|
import socketserver
|
||||||
|
|
||||||
|
|
||||||
class Handler(http.server.SimpleHTTPRequestHandler):
|
class Handler(http.server.SimpleHTTPRequestHandler):
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
|
|
||||||
self.send_response(200)
|
response_body = ""
|
||||||
|
response_code = 200
|
||||||
|
|
||||||
|
if self.path == "/headers":
|
||||||
|
response_body += self.headers.as_string()
|
||||||
|
elif self.path == "/port":
|
||||||
|
response_body += "answer from port %s\n" % PORT
|
||||||
|
elif re.match("/status/(\d+)", self.path):
|
||||||
|
result = re.match("/status/(\d+)", self.path)
|
||||||
|
response_code = int(result.group(1))
|
||||||
|
response_body += "answer with response code %s\n" % response_code
|
||||||
|
elif self.path == "/":
|
||||||
|
response_body += "I'm %s\n" % os.environ['HOSTNAME']
|
||||||
|
else:
|
||||||
|
response_body += "No route for this path!\n"
|
||||||
|
response_code = 404
|
||||||
|
|
||||||
|
self.send_response(response_code)
|
||||||
self.send_header("Content-Type", "text/plain")
|
self.send_header("Content-Type", "text/plain")
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
|
||||||
if self.path == "/headers":
|
if (len(response_body)):
|
||||||
self.wfile.write(self.headers.as_string().encode())
|
self.wfile.write(response_body.encode())
|
||||||
elif self.path == "/port":
|
|
||||||
response = "answer from port %s\n" % PORT
|
|
||||||
self.wfile.write(response.encode())
|
|
||||||
elif self.path == "/":
|
|
||||||
response = "I'm %s\n" % os.environ['HOSTNAME']
|
|
||||||
self.wfile.write(response.encode())
|
|
||||||
else:
|
|
||||||
self.wfile.write("No route for this path!\n".encode())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
PORT = int(sys.argv[1])
|
PORT = int(sys.argv[1])
|
||||||
|
@ -90,4 +90,4 @@ def test_web5_dhparam_is_used(docker_compose):
|
|||||||
host = "%s:443" % sut_container.attrs["NetworkSettings"]["IPAddress"]
|
host = "%s:443" % sut_container.attrs["NetworkSettings"]["IPAddress"]
|
||||||
r = subprocess.check_output(
|
r = subprocess.check_output(
|
||||||
"echo '' | openssl s_client -connect %s -cipher 'EDH' | grep 'Server Temp Key'" % host, shell=True)
|
"echo '' | openssl s_client -connect %s -cipher 'EDH' | grep 'Server Temp Key'" % host, shell=True)
|
||||||
assert "Server Temp Key: DH, 2048 bits\n" == r
|
assert "Server Temp Key: X25519, 253 bits\n" == r
|
||||||
|
@ -7,6 +7,13 @@ def test_web1_HSTS_default(docker_compose, nginxproxy):
|
|||||||
assert "Strict-Transport-Security" in r.headers
|
assert "Strict-Transport-Security" in r.headers
|
||||||
assert "max-age=31536000" == r.headers["Strict-Transport-Security"]
|
assert "max-age=31536000" == r.headers["Strict-Transport-Security"]
|
||||||
|
|
||||||
|
# Regression test to ensure HSTS is enabled even when the upstream sends an error in response
|
||||||
|
# Issue #1073 https://github.com/jwilder/nginx-proxy/pull/1073
|
||||||
|
def test_web1_HSTS_error(docker_compose, nginxproxy):
|
||||||
|
r = nginxproxy.get("https://web1.nginx-proxy.tld/status/500", allow_redirects=False)
|
||||||
|
assert "Strict-Transport-Security" in r.headers
|
||||||
|
assert "max-age=31536000" == r.headers["Strict-Transport-Security"]
|
||||||
|
|
||||||
def test_web2_HSTS_off(docker_compose, nginxproxy):
|
def test_web2_HSTS_off(docker_compose, nginxproxy):
|
||||||
r = nginxproxy.get("https://web2.nginx-proxy.tld/port", allow_redirects=False)
|
r = nginxproxy.get("https://web2.nginx-proxy.tld/port", allow_redirects=False)
|
||||||
assert "answer from port 81\n" in r.text
|
assert "answer from port 81\n" in r.text
|
||||||
@ -17,3 +24,10 @@ def test_web3_HSTS_custom(docker_compose, nginxproxy):
|
|||||||
assert "answer from port 81\n" in r.text
|
assert "answer from port 81\n" in r.text
|
||||||
assert "Strict-Transport-Security" in r.headers
|
assert "Strict-Transport-Security" in r.headers
|
||||||
assert "max-age=86400; includeSubDomains; preload" == r.headers["Strict-Transport-Security"]
|
assert "max-age=86400; includeSubDomains; preload" == r.headers["Strict-Transport-Security"]
|
||||||
|
|
||||||
|
# Regression test for issue 1080
|
||||||
|
# https://github.com/jwilder/nginx-proxy/issues/1080
|
||||||
|
def test_web4_HSTS_off_noredirect(docker_compose, nginxproxy):
|
||||||
|
r = nginxproxy.get("https://web4.nginx-proxy.tld/port", allow_redirects=False)
|
||||||
|
assert "answer from port 81\n" in r.text
|
||||||
|
assert "Strict-Transport-Security" not in r.headers
|
||||||
|
@ -24,6 +24,16 @@ web3:
|
|||||||
VIRTUAL_HOST: "web3.nginx-proxy.tld"
|
VIRTUAL_HOST: "web3.nginx-proxy.tld"
|
||||||
HSTS: "max-age=86400; includeSubDomains; preload"
|
HSTS: "max-age=86400; includeSubDomains; preload"
|
||||||
|
|
||||||
|
web4:
|
||||||
|
image: web
|
||||||
|
expose:
|
||||||
|
- "81"
|
||||||
|
environment:
|
||||||
|
WEB_PORTS: "81"
|
||||||
|
VIRTUAL_HOST: "web4.nginx-proxy.tld"
|
||||||
|
HSTS: "off"
|
||||||
|
HTTPS_METHOD: "noredirect"
|
||||||
|
|
||||||
sut:
|
sut:
|
||||||
image: jwilder/nginx-proxy:test
|
image: jwilder/nginx-proxy:test
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -7,6 +7,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||||
- ./certs:/etc/nginx/certs:ro
|
- ./certs:/etc/nginx/certs:ro
|
||||||
|
- ../../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro
|
||||||
|
|
||||||
web1:
|
web1:
|
||||||
image: web
|
image: web
|
||||||
@ -30,4 +31,4 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
WEB_PORTS: "83"
|
WEB_PORTS: "83"
|
||||||
VIRTUAL_HOST: "3.web.nginx-proxy.tld"
|
VIRTUAL_HOST: "3.web.nginx-proxy.tld"
|
||||||
HTTPS_METHOD: nohttps
|
HTTPS_METHOD: nohttps
|
||||||
|
@ -11,6 +11,7 @@ from requests.exceptions import SSLError
|
|||||||
def test_http_redirects_to_https(docker_compose, nginxproxy, subdomain, should_redirect_to_https):
|
def test_http_redirects_to_https(docker_compose, nginxproxy, subdomain, should_redirect_to_https):
|
||||||
r = nginxproxy.get("http://%s.web.nginx-proxy.tld/port" % subdomain)
|
r = nginxproxy.get("http://%s.web.nginx-proxy.tld/port" % subdomain)
|
||||||
if should_redirect_to_https:
|
if should_redirect_to_https:
|
||||||
|
assert len(r.history) > 0
|
||||||
assert r.history[0].is_redirect
|
assert r.history[0].is_redirect
|
||||||
assert r.history[0].headers.get("Location") == "https://%s.web.nginx-proxy.tld/port" % subdomain
|
assert r.history[0].headers.get("Location") == "https://%s.web.nginx-proxy.tld/port" % subdomain
|
||||||
assert "answer from port 8%s\n" % subdomain == r.text
|
assert "answer from port 8%s\n" % subdomain == r.text
|
||||||
|
Loading…
Reference in New Issue
Block a user