diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index 9bd3eaf87..6aeb9f540 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -19,8 +19,11 @@ on: - "*.md" jobs: - multiarch-build-debian: - name: Build and publish Debian image + multiarch-build: + name: Build and publish image + strategy: + matrix: + base: [alpine, debian] runs-on: ubuntu-latest steps: - name: Checkout @@ -32,77 +35,12 @@ jobs: id: nginx-proxy_version run: echo "VERSION=$(git describe --tags)" >> "$GITHUB_OUTPUT" - - name: Get Docker tags for Debian based image - id: docker_meta_debian - uses: docker/metadata-action@v5 - with: - images: | - ghcr.io/nginx-proxy/nginx-proxy - nginxproxy/nginx-proxy - jwilder/nginx-proxy - tags: | - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=raw,value=latest,enable={{is_default_branch}} - labels: | - org.opencontainers.image.authors=Nicolas Duchon (@buchdag), Jason Wilder - org.opencontainers.image.version=${{ steps.nginx-proxy_version.outputs.VERSION }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Retrieve docker-gen version id: docker-gen_version - run: sed -n -e 's;^FROM nginxproxy/docker-gen:\([0-9.]*\).*;VERSION=\1;p' Dockerfile >> "$GITHUB_OUTPUT" - - - name: Build and push the Debian based image - id: docker_build_debian - uses: docker/build-push-action@v5 - with: - context: . - file: Dockerfile - build-args: | - NGINX_PROXY_VERSION=${{ steps.nginx-proxy_version.outputs.VERSION }} - DOCKER_GEN_VERSION=${{ steps.docker-gen_version.outputs.VERSION }} - platforms: linux/amd64,linux/arm64,linux/arm/v7 - push: true - tags: ${{ steps.docker_meta_debian.outputs.tags }} - labels: ${{ steps.docker_meta_debian.outputs.labels }} + run: sed -n -e 's;^FROM nginxproxy/docker-gen:\([0-9.]*\).*;VERSION=\1;p' Dockerfile.${{ matrix.base }} >> "$GITHUB_OUTPUT" - - name: Images digests - run: echo ${{ steps.docker_build_debian.outputs.digest }} - - multiarch-build-alpine: - name: Build and publish Alpine image - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Retrieve nginx-proxy version - id: nginx-proxy_version - run: echo "VERSION=$(git describe --tags)" >> "$GITHUB_OUTPUT" - - - name: Get Docker tags for Alpine based image - id: docker_meta_alpine + - name: Get Docker tags + id: docker_meta uses: docker/metadata-action@v5 with: images: | @@ -110,13 +48,17 @@ jobs: nginxproxy/nginx-proxy jwilder/nginx-proxy tags: | - type=semver,suffix=-alpine,pattern={{version}} - type=semver,suffix=-alpine,pattern={{major}}.{{minor}} - type=raw,value=alpine,enable={{is_default_branch}} + type=semver,pattern={{version}},enable=${{ matrix.base == 'debian' }} + type=semver,pattern={{major}}.{{minor}},enable=${{ matrix.base == 'debian' }} + type=semver,suffix=-alpine,pattern={{version}},enable=${{ matrix.base == 'alpine' }} + type=semver,suffix=-alpine,pattern={{major}}.{{minor}},enable=${{ matrix.base == 'alpine' }} + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' && matrix.base == 'debian' }} + type=raw,value=alpine,enable=${{ github.ref == 'refs/heads/main' && matrix.base == 'alpine' }} labels: | org.opencontainers.image.authors=Nicolas Duchon (@buchdag), Jason Wilder org.opencontainers.image.version=${{ steps.nginx-proxy_version.outputs.VERSION }} - flavor: latest=false + flavor: | + latest=false - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -137,23 +79,23 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Retrieve docker-gen version - id: docker-gen_version - run: sed -n -e 's;^FROM nginxproxy/docker-gen:\([0-9.]*\).*;VERSION=\1;p' Dockerfile >> "$GITHUB_OUTPUT" - - - name: Build and push the Alpine based image - id: docker_build_alpine + - name: Build and push the image + id: docker_build uses: docker/build-push-action@v5 with: context: . - file: Dockerfile.alpine + file: Dockerfile.${{ matrix.base }} build-args: | NGINX_PROXY_VERSION=${{ steps.nginx-proxy_version.outputs.VERSION }} DOCKER_GEN_VERSION=${{ steps.docker-gen_version.outputs.VERSION }} - platforms: linux/amd64,linux/arm64,linux/arm/v7 + platforms: linux/amd64,linux/arm64,linux/s390x,linux/arm/v7 + sbom: true push: true - tags: ${{ steps.docker_meta_alpine.outputs.tags }} - labels: ${{ steps.docker_meta_alpine.outputs.labels }} + provenance: mode=max + tags: ${{ steps.docker_meta.outputs.tags }} + labels: ${{ steps.docker_meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max - name: Images digests - run: echo ${{ steps.docker_build_alpine.outputs.digest }} + run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/.github/workflows/dockerhub-description.yml b/.github/workflows/dockerhub-description.yml new file mode 100644 index 000000000..4be8cc29f --- /dev/null +++ b/.github/workflows/dockerhub-description.yml @@ -0,0 +1,27 @@ +name: Update Docker Hub Description + +on: + push: + branches: + - main + paths: + - README.md + - .github/workflows/dockerhub-description.yml + +jobs: + dockerHubDescription: + name: Update Docker Hub Description + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Docker Hub Description + uses: peter-evans/dockerhub-description@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN_RWD }} + repository: nginxproxy/nginx-proxy + short-description: ${{ github.event.repository.description }} + enable-url-completion: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2d8db9236..36e6273e6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python 3.9 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.9 diff --git a/Dockerfile.alpine b/Dockerfile.alpine index ce2f7a615..1a1c8bf7f 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -1,6 +1,6 @@ -FROM nginxproxy/docker-gen:0.10.7 AS docker-gen +FROM nginxproxy/docker-gen:0.11.2 AS docker-gen -FROM nginxproxy/forego:0.17.2 AS forego +FROM nginxproxy/forego:0.18.1 AS forego # Build the final image FROM nginx:1.25.3-alpine @@ -14,17 +14,13 @@ ENV NGINX_PROXY_VERSION=${NGINX_PROXY_VERSION} \ DOCKER_HOST=unix:///tmp/docker.sock # Install dependencies -RUN apk add --no-cache --virtual .run-deps \ - bash \ - ca-certificates \ - openssl \ - && update-ca-certificates +RUN apk add --no-cache --virtual .run-deps bash openssl # Configure Nginx -RUN echo "daemon off;" >> /etc/nginx/nginx.conf \ - && sed -i 's/worker_processes 1/worker_processes auto/' /etc/nginx/nginx.conf \ - && sed -i 's/worker_connections 1024/worker_connections 10240/' /etc/nginx/nginx.conf \ - && mkdir -p '/etc/nginx/dhparam' +RUN sed -i 's/worker_connections.*;$/worker_connections 10240;/' /etc/nginx/nginx.conf \ + && sed -i -e '/^\}$/{s//\}\nworker_rlimit_nofile 20480;/;:a' -e '$!N;$!ba' -e '}' /etc/nginx/nginx.conf \ + && mkdir -p '/etc/nginx/dhparam' \ + && mkdir -p '/etc/nginx/certs' # Install Forego + docker-gen COPY --from=forego /usr/local/bin/forego /usr/local/bin/forego diff --git a/Dockerfile b/Dockerfile.debian similarity index 56% rename from Dockerfile rename to Dockerfile.debian index 5c44047af..a8c26bc30 100644 --- a/Dockerfile +++ b/Dockerfile.debian @@ -1,6 +1,6 @@ -FROM nginxproxy/docker-gen:0.10.7-debian AS docker-gen +FROM nginxproxy/docker-gen:0.11.2-debian AS docker-gen -FROM nginxproxy/forego:0.17.2-debian AS forego +FROM nginxproxy/forego:0.18.1-debian AS forego # Build the final image FROM nginx:1.25.3 @@ -13,17 +13,11 @@ ENV NGINX_PROXY_VERSION=${NGINX_PROXY_VERSION} \ DOCKER_GEN_VERSION=${DOCKER_GEN_VERSION} \ DOCKER_HOST=unix:///tmp/docker.sock -# Install/update certificates -RUN apt-get update \ - && apt-get install -y -q --no-install-recommends ca-certificates \ - && apt-get clean \ - && rm -r /var/lib/apt/lists/* - # Configure Nginx -RUN echo "daemon off;" >> /etc/nginx/nginx.conf \ - && sed -i 's/worker_processes 1/worker_processes auto/' /etc/nginx/nginx.conf \ - && sed -i 's/worker_connections 1024/worker_connections 10240/' /etc/nginx/nginx.conf \ - && mkdir -p '/etc/nginx/dhparam' +RUN sed -i 's/worker_connections.*;$/worker_connections 10240;/' /etc/nginx/nginx.conf \ + && sed -i -e '/^\}$/{s//\}\nworker_rlimit_nofile 20480;/;:a' -e '$!N;$!ba' -e '}' /etc/nginx/nginx.conf \ + && mkdir -p '/etc/nginx/dhparam' \ + && mkdir -p '/etc/nginx/certs' # Install Forego + docker-gen COPY --from=forego /usr/local/bin/forego /usr/local/bin/forego diff --git a/Makefile b/Makefile index 5e53e3636..e735e6aa1 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ build-webserver: docker build --pull -t web test/requirements/web build-nginx-proxy-test-debian: - docker build --pull --build-arg NGINX_PROXY_VERSION="test" -t nginxproxy/nginx-proxy:test . + docker build --pull --build-arg NGINX_PROXY_VERSION="test" -f Dockerfile.debian -t nginxproxy/nginx-proxy:test . build-nginx-proxy-test-alpine: docker build --pull --build-arg NGINX_PROXY_VERSION="test" -f Dockerfile.alpine -t nginxproxy/nginx-proxy:test . diff --git a/README.md b/README.md index 30bf5914a..edb3bb280 100644 --- a/README.md +++ b/README.md @@ -15,667 +15,56 @@ See [Automated Nginx Reverse Proxy for Docker](http://jasonwilder.com/blog/2014/ To run it: ```console -docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy +docker run --detach \ + --name nginx-proxy \ + --publish 80:80 \ + --volume /var/run/docker.sock:/tmp/docker.sock:ro \ + nginxproxy/nginx-proxy:1.4 ``` -Then start any containers you want proxied with an env var `VIRTUAL_HOST=subdomain.youdomain.com` +Then start any containers (here an nginx container) you want proxied with an env var `VIRTUAL_HOST=subdomain.yourdomain.com` ```console -docker run -e VIRTUAL_HOST=foo.bar.com ... +docker run --detach \ + --name your-proxied-app \ + --env VIRTUAL_HOST=foo.bar.com \ + nginx ``` -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 resolve `foo.bar.com` to the host running nginx-proxy, a request to `http://foo.bar.com` will then be routed to a container with the `VIRTUAL_HOST` env var set to `foo.bar.com` (in this case, the **your-proxied-app** container). -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. +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`. +- share at least one Docker network with the nginx-proxy container: 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. -Note: providing a port number in `VIRTUAL_HOST` isn't suported, please see [virtual ports](https://github.com/nginx-proxy/nginx-proxy#virtual-ports) or [custom external HTTP/HTTPS ports](https://github.com/nginx-proxy/nginx-proxy#custom-external-httphttps-ports) depending on what you want to achieve. +Note: providing a port number in `VIRTUAL_HOST` isn't suported, please see [virtual ports](https://github.com/nginx-proxy/nginx-proxy/tree/main/docs#virtual-ports) or [custom external HTTP/HTTPS ports](https://github.com/nginx-proxy/nginx-proxy/tree/main/docs#custom-external-httphttps-ports) depending on what you want to achieve. ### Image variants The nginx-proxy images are available in two flavors. -#### nginxproxy/nginx-proxy:latest +#### Debian based version -This image uses the debian:buster based nginx image. +This image is based on the nginx:mainline image, itself based on the debian slim image. ```console -docker pull nginxproxy/nginx-proxy:latest +docker pull nginxproxy/nginx-proxy:1.4 ``` -#### nginxproxy/nginx-proxy:alpine +#### Alpine based version (`-alpine` suffix) -This image is based on the nginx:alpine image. Use this image to fully support HTTP/2 (including ALPN required by recent Chrome versions). A valid certificate is required as well (see eg. below "SSL Support using an ACME CA" for more info). +This image is based on the nginx:alpine image. ```console -docker pull nginxproxy/nginx-proxy:alpine +docker pull nginxproxy/nginx-proxy:1.4-alpine ``` -### Docker Compose +#### :warning: a note on `latest` and `alpine`: -```yaml -version: '2' +It is not recommended to use the `latest` (`nginxproxy/nginx-proxy`, `nginxproxy/nginx-proxy:latest`) or `alpine` (`nginxproxy/nginx-proxy:alpine`) tag for production setups. -services: - nginx-proxy: - image: nginxproxy/nginx-proxy - ports: - - "80:80" - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro +Those tags points to the latest commit in the `main` branch. They do not carry any promise of stability, and using them will probably put your nginx-proxy setup at risk of experiencing uncontrolled updates to non backward compatible versions (or versions with breaking changes). You should always specify the version you want to use explicitly to ensure your setup doesn't break when the image is updated. - whoami: - image: jwilder/whoami - expose: - - "8000" - environment: - - VIRTUAL_HOST=whoami.example - - VIRTUAL_PORT=8000 -``` - -```console -docker-compose up -curl -H "Host: whoami.example" localhost -``` - -Example output: -```console -I'm 5b129ab83266 -``` - -### IPv6 support - -You can activate the IPv6 support for the nginx-proxy container by passing the value `true` to the `ENABLE_IPV6` environment variable: - -```console -docker run -d -p 80:80 -e ENABLE_IPV6=true -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy -``` - -#### Scoped IPv6 Resolvers - -NginX does not support scoped IPv6 resolvers. In [docker-entrypoint.sh](./docker-entrypoint.sh) the resolvers are parsed from resolv.conf, but any scoped IPv6 addreses will be removed. - -#### IPv6 NAT - -By default, docker uses IPv6-to-IPv4 NAT. This means all client connections from IPv6 addresses will show docker's internal IPv4 host address. To see true IPv6 client IP addresses, you must [enable IPv6](https://docs.docker.com/config/daemon/ipv6/) and use [ipv6nat](https://github.com/robbertkl/docker-ipv6nat). You must also disable the userland proxy by adding `"userland-proxy": false` to `/etc/docker/daemon.json` and restarting the daemon. - -### Multiple Hosts - -If you need to support multiple virtual hosts for a container, you can separate each entry with commas. For example, `foo.bar.com,baz.bar.com,bar.com` and each host will be setup the same. - -### Virtual Ports - -When your container exposes only one port, nginx-proxy will default to this port, else to port 80. - -If you need to specify a different port, you can set a `VIRTUAL_PORT` env var to select a different one. This variable cannot be set to more than one port. - -For each host defined into `VIRTUAL_HOST`, the associated virtual port is retrieved by order of precedence: -1. From the `VIRTUAL_PORT` environment variable -1. From the container's exposed port if there is only one -1. From the default port 80 when none of the above methods apply - -### Wildcard Hosts - -You can also use wildcards at the beginning and the end of host name, like `*.bar.com` or `foo.bar.*`. Or even a regular expression, which can be very useful in conjunction with a wildcard DNS service like [nip.io](https://nip.io) or [sslip.io](https://sslip.io), using `~^foo\.bar\..*\.nip\.io` will match `foo.bar.127.0.0.1.nip.io`, `foo.bar.10.0.2.2.nip.io` and all other given IPs. More information about this topic can be found in the nginx documentation about [`server_names`](http://nginx.org/en/docs/http/server_names.html). - -### Path-based Routing - -You can have multiple containers proxied by the same `VIRTUAL_HOST` by adding a `VIRTUAL_PATH` environment variable containing the absolute path to where the container should be mounted. For example with `VIRTUAL_HOST=foo.example.com` and `VIRTUAL_PATH=/api/v2/service`, then requests to http://foo.example.com/api/v2/service will be routed to the container. If you wish to have a container serve the root while other containers serve other paths, give the root container a `VIRTUAL_PATH` of `/`. Unmatched paths will be served by the container at `/` or will return the default nginx error page if no container has been assigned `/`. -It is also possible to specify multiple paths with regex locations like `VIRTUAL_PATH=~^/(app1|alternative1)/`. For further details see the nginx documentation on location blocks. This is not compatible with `VIRTUAL_DEST`. - -The full request URI will be forwarded to the serving container in the `X-Original-URI` header. - -**NOTE**: Your application needs to be able to generate links starting with `VIRTUAL_PATH`. This can be achieved by it being natively on this path or having an option to prepend this path. The application does not need to expect this path in the request. - -#### VIRTUAL_DEST - -This environment variable can be used to rewrite the `VIRTUAL_PATH` part of the requested URL to proxied application. The default value is empty (off). -Make sure that your settings won't result in the slash missing or being doubled. Both these versions can cause troubles. - -If the application runs natively on this sub-path or has a setting to do so, `VIRTUAL_DEST` should not be set or empty. -If the requests are expected to not contain a sub-path and the generated links contain the sub-path, `VIRTUAL_DEST=/` should be used. - -```console -$ docker run -d -e VIRTUAL_HOST=example.tld -e VIRTUAL_PATH=/app1/ -e VIRTUAL_DEST=/ --name app1 app -``` - -In this example, the incoming request `http://example.tld/app1/foo` will be proxied as `http://app1/foo` instead of `http://app1/app1/foo`. - -#### 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 filename of the previous example would be `example.tld_8610f6c344b4096614eab6e09d58885349f42faf_location`. - -#### DEFAULT_ROOT - -This environment variable of the nginx proxy container can be used to customize the return error page if no matching path is found. Furthermore it is possible to use anything which is compatible with the `return` statement of nginx. - -Exception: If this is set to the string `none`, no default `location /` directive will be generated. This makes it possible for you to provide your own `location /` directive in your [`/etc/nginx/vhost.d/VIRTUAL_HOST`](#per-virtual_host) or [`/etc/nginx/vhost.d/default`](#per-virtual_host-default-configuration) files. - -If unspecified, `DEFAULT_ROOT` defaults to `404`. - -Examples (YAML syntax): - - * `DEFAULT_ROOT: "none"` prevents `nginx-proxy` from generating a default `location /` directive. - * `DEFAULT_ROOT: "418"` returns a 418 error page instead of the normal 404 one. - * `DEFAULT_ROOT: "301 https://github.com/nginx-proxy/nginx-proxy/blob/main/README.md"` redirects the client to this documentation. - -Nginx variables such as `$scheme`, `$host`, and `$request_uri` can be used. However, care must be taken to make sure the `$` signs are escaped properly. For example, if you want to use `301 $scheme://$host/myapp1$request_uri` you should use: - -* Bash: `DEFAULT_ROOT='301 $scheme://$host/myapp1$request_uri'` -* Docker Compose yaml: `- DEFAULT_ROOT: 301 $$scheme://$$host/myapp1$$request_uri` - - -### Multiple Networks - -With the addition of [overlay networking](https://docs.docker.com/engine/userguide/networking/get-started-overlay/) in Docker 1.9, your `nginx-proxy` container may need to connect to backend containers on multiple networks. 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`. - -If you want your `nginx-proxy` container to be attached to a different network, you must pass the `--net=my-network` option in your `docker create` or `docker run` command. At the time of this writing, only a single network can be specified at container creation time. To attach to other networks, you can use the `docker network connect` command after your container is created: - -```console -docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro \ - --name my-nginx-proxy --net my-network nginxproxy/nginx-proxy -docker network connect my-other-network my-nginx-proxy -``` - -In this example, the `my-nginx-proxy` container will be connected to `my-network` and `my-other-network` and will be able to proxy to other containers attached to those networks. - -### Host networking - -`nginx-proxy` is compatible with containers using Docker's [host networking](https://docs.docker.com/network/host/), both with the proxy connected to one or more [bridge network](https://docs.docker.com/network/bridge/) (default or user created) or running in host network mode itself. - -Proxyed containers running in host network mode **must** use the [`VIRTUAL_PORT`](#virtual-ports) environment variable, as this is the only way for `nginx-proxy` to get the correct port (or a port at all) for those containers. - -### Custom external HTTP/HTTPS ports - -If you want to use `nginx-proxy` with different external ports that the default ones of `80` for `HTTP` traffic and `443` for `HTTPS` traffic, you'll have to use the environment variable(s) `HTTP_PORT` and/or `HTTPS_PORT` in addition to the changes to the Docker port mapping. If you change the `HTTPS` port, the redirect for `HTTPS` traffic will also be configured to redirect to the custom port. Typical usage, here with the custom ports `1080` and `10443`: - -```console -docker run -d -p 1080:1080 -p 10443:10443 -e HTTP_PORT=1080 -e HTTPS_PORT=10443 -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy -``` - -### Internet vs. Local Network Access - -If you allow traffic from the public internet to access your `nginx-proxy` container, you may want to restrict some containers to the internal network only, so they cannot be accessed from the public internet. On containers that should be restricted to the internal network, you should set the environment variable `NETWORK_ACCESS=internal`. By default, the *internal* network is defined as `127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16`. To change the list of networks considered internal, mount a file on the `nginx-proxy` at `/etc/nginx/network_internal.conf` with these contents, edited to suit your needs: - -```Nginx -# These networks are considered "internal" -allow 127.0.0.0/8; -allow 10.0.0.0/8; -allow 192.168.0.0/16; -allow 172.16.0.0/12; - -# Traffic from all other networks will be rejected -deny all; -``` - -When internal-only access is enabled, external clients will be denied with an `HTTP 403 Forbidden` - -> If there is a load-balancer / reverse proxy in front of `nginx-proxy` that hides the client IP (example: AWS Application/Elastic Load Balancer), you will need to use the nginx `realip` module (already installed) to extract the client's IP from the HTTP request headers. Please see the [nginx realip module configuration](http://nginx.org/en/docs/http/ngx_http_realip_module.html) for more details. This configuration can be added to a new config file and mounted in `/etc/nginx/conf.d/`. - -### SSL Backends - -If you would like the reverse proxy to connect to your backend using HTTPS instead of HTTP, set `VIRTUAL_PROTO=https` on the backend container. - -> Note: If you use `VIRTUAL_PROTO=https` and your backend container exposes port 80 and 443, `nginx-proxy` will use HTTPS on port 80. This is almost certainly not what you want, so you should also include `VIRTUAL_PORT=443`. - -### uWSGI Backends - -If you would like to connect to uWSGI backend, set `VIRTUAL_PROTO=uwsgi` on the backend container. Your backend container should then listen on a port rather than a socket and expose that port. - -### FastCGI Backends - -If you would like to connect to FastCGI backend, set `VIRTUAL_PROTO=fastcgi` on the backend container. Your backend container should then listen on a port rather than a socket and expose that port. - -### FastCGI File Root Directory - -If you use fastcgi,you can set `VIRTUAL_ROOT=xxx` for your root directory - -### Custom log format - -If you want to use a custom log format, you can set `LOG_FORMAT=xxx` on the proxy container. - -With docker compose take care to escape the `$` character with `$$` to avoid variable interpolation. Example: `$remote_addr` becomes `$$remote_addr`. - -### Default Host - -To set the default host for nginx use the env var `DEFAULT_HOST=foo.bar.com` for example - -```console -docker run -d -p 80:80 -e DEFAULT_HOST=foo.bar.com -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy -``` - -nginx-proxy will then redirect all requests to a container where `VIRTUAL_HOST` is set to `DEFAULT_HOST`, if they don't match any (other) `VIRTUAL_HOST`. Using the example above requests without matching `VIRTUAL_HOST` will be redirected to a plain nginx instance after running the following command: - -```console -docker run -d -e VIRTUAL_HOST=foo.bar.com nginx -``` - -### Separate Containers - -nginx-proxy can also be run as two separate containers using the [nginxproxy/docker-gen](https://hub.docker.com/r/nginxproxy/docker-gen) image and the official [nginx](https://registry.hub.docker.com/_/nginx/) image. - -You may want to do this to prevent having the docker socket bound to a publicly exposed container service. - -You can demo this pattern with docker-compose: - -```console -docker-compose --file docker-compose-separate-containers.yml up -curl -H "Host: whoami.example" localhost -``` - -Example output: -```console -I'm 5b129ab83266 -``` - -To run nginx proxy as a separate container you'll need to have [nginx.tmpl](https://github.com/nginx-proxy/nginx-proxy/blob/main/nginx.tmpl) on your host system. - -First start nginx with a volume: - - -```console -docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx -``` - -Then start the docker-gen container with the shared volume and template: - -```console -docker run --volumes-from nginx \ - -v /var/run/docker.sock:/tmp/docker.sock:ro \ - -v $(pwd):/etc/docker-gen/templates \ - -t nginxproxy/docker-gen -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf -``` - -Finally, start your containers with `VIRTUAL_HOST` environment variables. - -```console -docker run -e VIRTUAL_HOST=foo.bar.com ... -``` - -### SSL Support using an ACME CA - -[acme-companion](https://github.com/nginx-proxy/acme-companion) is a lightweight companion container for the nginx-proxy. It allows the automated creation/renewal of SSL certificates using the ACME protocol. - -### SSL Support - -SSL is supported using single host, wildcard and SNI certificates using naming conventions for certificates or optionally specifying a cert name (for SNI) as an environment variable. - -To enable SSL: - -```console -docker run -d -p 80:80 -p 443:443 -v /path/to/certs:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy -``` - -The contents of `/path/to/certs` should contain the certificates and private keys for any virtual hosts in use. The certificate and keys should be named after the virtual host with a `.crt` and `.key` extension. For example, a container with `VIRTUAL_HOST=foo.bar.com` should have a `foo.bar.com.crt` and `foo.bar.com.key` file in the certs directory. - -If you are running the container in a virtualized environment (Hyper-V, VirtualBox, etc...), /path/to/certs must exist in that environment or be made accessible to that environment. By default, Docker is not able to mount directories on the host machine to containers running in a virtual machine. - -#### 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. - -To use custom `dhparam.pem` files per-virtual-host, the files should be named after the virtual host with a `dhparam` suffix and `.pem` extension. For example, a container with `VIRTUAL_HOST=foo.bar.com` should have a `foo.bar.com.dhparam.pem` file in the `/etc/nginx/certs` directory. - -> COMPATIBILITY WARNING: The default generated `dhparam.pem` key is 4096 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 clients, you must provide your own `dhparam.pem`. - -In the separate container setup, no pre-generated key will be available and neither the [nginxproxy/docker-gen](https://hub.docker.com/r/nginxproxy/docker-gen) image, nor the offical [nginx](https://registry.hub.docker.com/_/nginx/) image will provide one. If you still want A+ security in a separate container setup, you should mount an RFC7919 DH key file to the nginx container at `/etc/nginx/dhparam/dhparam.pem`. - -Set `DHPARAM_SKIP` environment variable to `true` to disable using default Diffie-Hellman parameters. The default value is `false`. - -```console -docker run -e DHPARAM_SKIP=true .... -``` - -#### Wildcard Certificates - -Wildcard certificates and keys should be named after the domain name with a `.crt` and `.key` extension. For example `VIRTUAL_HOST=foo.bar.com` would use cert name `bar.com.crt` and `bar.com.key`. - -#### SNI - -If your certificate(s) supports multiple domain names, you can start a container with `CERT_NAME=` to identify the certificate to be used. For example, a certificate for `*.foo.com` and `*.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. - -#### 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/.chain.pem`, where `` 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 - -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 27, Android 4.4.2, Chrome 31, Edge, IE 11 on Windows 7, 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.2 and 1.3 are supported. - -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 the nginx-proxy container or to your container. This profile is compatible with clients back to Firefox 63, Android 10.0, Chrome 70, Edge 75, Java 11, 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) and the [AWS ELB Security Policies](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html) `AWS-TLS-1-2-2017-01`, `AWS-TLS-1-1-2017-01`, `AWS-2016-08`, `AWS-2015-05`, `AWS-2015-03` and `AWS-2015-02`. - -Note that the `Mozilla-Old` policy should use a 1024 bits DH key for compatibility but this container provides a 4096 bits key. The [Diffie-Hellman Groups](#diffie-hellman-groups) section details different methods of bypassing this, either globally or per virtual-host. - -The default behavior for the proxy when port 80 and 443 are exposed is as follows: - -* If a virtual host has a usable cert, port 80 will redirect to 443 for that virtual host so that HTTPS is always preferred when available. -* If the virtual host does not have a usable cert, but `default.crt` and `default.key` exist, those will be used as the virtual host's certificate and the client browser will receive a 500 error. -* If the virtual host does not have a usable cert, and `default.crt` and `default.key` do not exist, TLS negotiation will fail (see [Missing Certificate](#missing-certificate) below). - -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 disable the non-SSL site entirely with `HTTPS_METHOD=nohttp`, or disable the HTTPS site with `HTTPS_METHOD=nohttps`. `HTTPS_METHOD` can be specified on each container for which you want to override the default behavior or on the proxy container to set it globally. 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 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 window / different browser. - -By default, [HTTP Strict Transport Security (HSTS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) is enabled with `max-age=31536000` for HTTPS sites. You can disable HSTS with the environment variable `HSTS=off` or use a custom HSTS configuration like `HSTS=max-age=31536000; includeSubDomains; preload`. - -*WARNING*: HSTS will force your users to visit the HTTPS version of your site for the `max-age` time - even if they type in `http://` manually. The only way to get to an HTTP site after receiving an HSTS response is to clear your browser's HSTS cache. - -#### Missing Certificate - -If HTTPS is enabled for a virtual host but its certificate is missing, nginx-proxy will configure nginx to use the default certificate (`default.crt` with `default.key`) and return a 500 error. - -If the default certificate is also missing, nginx-proxy will configure nginx to accept HTTPS connections but fail the TLS negotiation. Client browsers will render a TLS error page. As of March 2023, web browsers display the following error messages: - - * Chrome: - - > This site can't provide a secure connection - > - > example.test sent an invalid response. - > - > Try running Connectivity Diagnostics. - > - > `ERR_SSL_PROTOCOL_ERROR` - - * Firefox: - - > Secure Connection Failed - > - > An error occurred during a connection to example.test. - > Peer reports it experienced an internal error. - > - > Error code: `SSL_ERROR_INTERNAL_ERROR_ALERT` "TLS error". - -### HTTP/2 support - -HTTP/2 is enabled by default and can be disabled if necessary either per-proxied container or globally: - -To disable HTTP/2 for a single proxied container, set the `com.github.nginx-proxy.nginx-proxy.http2.enable` label to `false` on this container. - -To disable HTTP/2 globally set the environment variable `ENABLE_HTTP2` to `false` on the nginx-proxy container. - -More reading on the potential TCP head-of-line blocking issue with HTTP/2: [HTTP/2 Issues](https://www.twilio.com/blog/2017/10/http2-issues.html), [Comparing HTTP/3 vs HTTP/2](https://blog.cloudflare.com/http-3-vs-http-2/) - -### HTTP/3 support - -> **Warning** -> HTTP/3 support [is still considered experimental in nginx](https://www.nginx.com/blog/binary-packages-for-preview-nginx-quic-http3-implementation/) and as such is considered experimental in nginx-proxy too and is disabled by default. [Feedbacks for the HTTP/3 support are welcome in #2271.](https://github.com/nginx-proxy/nginx-proxy/discussions/2271) - -HTTP/3 use the QUIC protocol over UDP (unlike HTTP/1.1 and HTTP/2 which work over TCP), so if you want to use HTTP/3 you'll have to explicitely publish the 443/udp port of the proxy in addition to the 443/tcp port: - -```console -docker run -d -p 80:80 -p 443:443/tcp -p 443:443/udp \ - -v /var/run/docker.sock:/tmp/docker.sock:ro \ - nginxproxy/nginx-proxy -``` - -HTTP/3 can be enabled either per-proxied container or globally: - -To enable HTTP/3 for a single proxied container, set the `com.github.nginx-proxy.nginx-proxy.http3.enable` label to `true` on this container. - -To enable HTTP/3 globally set the environment variable `ENABLE_HTTP3` to `true` on the nginx-proxy container. - -### 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 on directory -/etc/nginx/htpasswd/$VIRTUAL_HOST - -```console -docker run -d -p 80:80 -p 443:443 \ - -v /path/to/htpasswd:/etc/nginx/htpasswd \ - -v /path/to/certs:/etc/nginx/certs \ - -v /var/run/docker.sock:/tmp/docker.sock:ro \ - nginxproxy/nginx-proxy -``` - -You'll need apache2-utils on the machine where you plan to create the htpasswd file. Follow these [instructions](http://httpd.apache.org/docs/2.2/programs/htpasswd.html) - -### Upstream (Backend) Server HTTP Load Balancing Support - -> **Warning** -> This feature is experimental. The behavior may change (or the feature may be removed entirely) without warning in a future release, even if the release is not a new major version. If you use this feature, or if you would like to use this feature but you require changes to it first, please [provide feedback in #2195](https://github.com/nginx-proxy/nginx-proxy/discussions/2195). Once we have collected enough feedback we will promote this feature to officially supported. - -If you have multiple containers with the same `VIRTUAL_HOST` and `VIRTUAL_PATH` settings, nginx will spread the load across all of them. To change the load balancing algorithm from nginx's default (round-robin), set the `com.github.nginx-proxy.nginx-proxy.loadbalance` label on one or more of your application containers to the desired load balancing directive. See the [`ngx_http_upstream_module` documentation](https://nginx.org/en/docs/http/ngx_http_upstream_module.html) for available directives. - -> **Note** -> * Don't forget the terminating semicolon (`;`). -> * If you are using Docker Compose, remember to escape any dollar sign (`$`) characters (`$` becomes `$$`). - -Docker Compose example: - -```yaml -services: - nginx-proxy: - image: nginxproxy/nginx-proxy - ports: - - "80:80" - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - environment: - HTTPS_METHOD: nohttps - myapp: - image: jwilder/whoami - expose: - - "8000" - environment: - VIRTUAL_HOST: myapp.example - VIRTUAL_PORT: "8000" - labels: - com.github.nginx-proxy.nginx-proxy.loadbalance: "hash $$remote_addr;" - deploy: - replicas: 4 -``` - -### Upstream (Backend) Server HTTP Keep-Alive Support - -> **Warning** -> This feature is experimental. The behavior may change (or the feature may be removed entirely) without warning in a future release, even if the release is not a new major version. If you use this feature, or if you would like to use this feature but you require changes to it first, please [provide feedback in #2194](https://github.com/nginx-proxy/nginx-proxy/discussions/2194). Once we have collected enough feedback we will promote this feature to officially supported. - -To enable HTTP keep-alive between `nginx-proxy` and a backend server, set the `com.github.nginx-proxy.nginx-proxy.keepalive` label on the server's container to the desired maximum number of idle connections. See the [nginx keepalive documentation](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) and the [Docker label documentation](https://docs.docker.com/config/labels-custom-metadata/) for details. - -### Headers - -By default, `nginx-proxy` forwards all incoming request headers from the client to the backend server unmodified, with the following exceptions: - - * `Connection`: Set to `upgrade` if the client sets the `Upgrade` header, otherwise set to `close`. (Keep-alive between `nginx-proxy` and the backend server is not supported.) - * `Proxy`: Always removed if present. This prevents attackers from using the so-called [httpoxy attack](http://httpoxy.org). There is no legitimate reason for a client to send this header, and there are many vulnerable languages / platforms (`CVE-2016-5385`, `CVE-2016-5386`, `CVE-2016-5387`, `CVE-2016-5388`, `CVE-2016-1000109`, `CVE-2016-1000110`, `CERT-VU#797896`). - * `X-Real-IP`: Set to the client's IP address. - * `X-Forwarded-For`: The client's IP address is appended to the value provided by the client. (If the client did not provide this header, it is set to the client's IP address.) - * `X-Forwarded-Host`: If the client did not provide this header or if the `TRUST_DOWNSTREAM_PROXY` environment variable is set to `false` (see below), this is set to the value of the `Host` header provided by the client. Otherwise, the header is forwarded to the backend server unmodified. - * `X-Forwarded-Proto`: If the client did not provide this header or if the `TRUST_DOWNSTREAM_PROXY` environment variable is set to `false` (see below), this is set to `http` for plain HTTP connections and `https` for TLS connections. Otherwise, the header is forwarded to the backend server unmodified. - * `X-Forwarded-Ssl`: Set to `on` if the `X-Forwarded-Proto` header sent to the backend server is `https`, otherwise set to `off`. - * `X-Forwarded-Port`: If the client did not provide this header or if the `TRUST_DOWNSTREAM_PROXY` environment variable is set to `false` (see below), this is set to the port of the server that accepted the client's request. Otherwise, the header is forwarded to the backend server unmodified. - * `X-Original-URI`: Set to the original request URI. - -#### Trusting Downstream Proxy Headers - -For legacy compatibility reasons, `nginx-proxy` forwards any client-supplied `X-Forwarded-Proto` (which affects the value of `X-Forwarded-Ssl`), `X-Forwarded-Host`, and `X-Forwarded-Port` headers unchecked and unmodified. To prevent malicious clients from spoofing the protocol, hostname, or port that is perceived by your backend server, you are encouraged to set the `TRUST_DOWNSTREAM_PROXY` value to `false` if: - - * you do not operate a second reverse proxy downstream of `nginx-proxy`, or - * you do operate a second reverse proxy downstream of `nginx-proxy` but that proxy forwards those headers unchecked from untrusted clients. - -The default for `TRUST_DOWNSTREAM_PROXY` may change to `false` in a future version of `nginx-proxy`. If you require it to be enabled, you are encouraged to explicitly set it to `true` to avoid compatibility problems when upgrading. - -### Custom Nginx Configuration - -If you need to configure Nginx beyond what is possible using environment variables, you can provide custom configuration files on either a proxy-wide or per-`VIRTUAL_HOST` basis. - -#### Replacing default proxy settings - -If you want to replace the default proxy settings for the nginx container, add a configuration file at `/etc/nginx/proxy.conf`. A file with the default settings would look like this: - -```Nginx -# HTTP 1.1 support -proxy_http_version 1.1; -proxy_buffering off; -proxy_set_header Host $http_host; -proxy_set_header Upgrade $http_upgrade; -proxy_set_header Connection $proxy_connection; -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host; -proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; -proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl; -proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port; -proxy_set_header X-Original-URI $request_uri; - -# Mitigate httpoxy attack (see README for details) -proxy_set_header Proxy ""; -``` - -***NOTE***: If you provide this file it will replace the defaults; you may want to check the .tmpl file to make sure you have all of the needed options. - -#### Proxy-wide - -To add settings on a proxy-wide basis, add your configuration file under `/etc/nginx/conf.d` using a name ending in `.conf`. - -This can be done in a derived image by creating the file in a `RUN` command or by `COPY`ing the file into `conf.d`: - -```Dockerfile -FROM nginxproxy/nginx-proxy -RUN { \ - echo 'server_tokens off;'; \ - echo 'client_max_body_size 100m;'; \ - } > /etc/nginx/conf.d/my_proxy.conf -``` - -Or it can be done by mounting in your custom configuration in your `docker run` command: - -```console -docker run -d -p 80:80 -p 443:443 -v /path/to/my_proxy.conf:/etc/nginx/conf.d/my_proxy.conf:ro -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy -``` - -#### 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`. - -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. - -For example, if you have a virtual host named `app.example.com`, you could provide a custom configuration for that host as follows: - -```console -docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy -{ echo 'server_tokens off;'; echo 'client_max_body_size 100m;'; } > /path/to/vhost.d/app.example.com -``` - -If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink: - -```console -{ echo 'server_tokens off;'; echo 'client_max_body_size 100m;'; } > /path/to/vhost.d/www.example.com -ln -s /path/to/vhost.d/www.example.com /path/to/vhost.d/example.com -``` - -#### Per-VIRTUAL_HOST default configuration - -If you want most of your virtual hosts to use a default single configuration and then override on a few specific ones, add those settings to the `/etc/nginx/vhost.d/default` file. This file will be used on any virtual host which does not have a `/etc/nginx/vhost.d/{VIRTUAL_HOST}` file associated with it. - -#### 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`. - -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: - -```console -docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy -{ echo 'proxy_cache my-cache;'; echo 'proxy_cache_valid 200 302 60m;'; echo 'proxy_cache_valid 404 1m;' } > /path/to/vhost.d/app.example.com_location -``` - -If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink: - -```console -{ echo 'proxy_cache my-cache;'; echo 'proxy_cache_valid 200 302 60m;'; echo 'proxy_cache_valid 404 1m;' } > /path/to/vhost.d/app.example.com_location -ln -s /path/to/vhost.d/www.example.com /path/to/vhost.d/example.com -``` - -#### Per-VIRTUAL_HOST location default configuration - -If you want most of your virtual hosts to use a default single `location` block configuration and then override on a few specific ones, add those settings to the `/etc/nginx/vhost.d/default_location` file. This file will be used on any virtual host which does not have a `/etc/nginx/vhost.d/{VIRTUAL_HOST}_location` file associated with it. - -#### Overriding `location` blocks - -The `${VIRTUAL_HOST}_${PATH_HASH}_location`, `${VIRTUAL_HOST}_location`, and `default_location` files documented above make it possible to *augment* the generated [`location` block(s)](https://nginx.org/en/docs/http/ngx_http_core_module.html#location) in a virtual host. In some circumstances, you may need to *completely override* the `location` block for a particular combination of virtual host and path. To do this, create a file whose name follows this pattern: - -``` -/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). - -For convenience, the `_${PATH_HASH}` part can be omitted if the path is `/`: - -``` -/etc/nginx/vhost.d/${VIRTUAL_HOST}_location_override -``` - -When an override file exists, the `location` block that is normally created by `nginx-proxy` is not generated. Instead, the override file is included via the [nginx `include` directive](https://nginx.org/en/docs/ngx_core_module.html#include). - -You are responsible for providing a suitable `location` block in your override file as required for your service. By default, `nginx-proxy` uses the `VIRTUAL_HOST` name as the upstream name for your application's Docker container; see [here](#unhashed-vs-sha1-upstream-names) for details. As an example, if your container has a `VIRTUAL_HOST` value of `app.example.com`, then to override the location block for `/` you would create a file named `/etc/nginx/vhost.d/app.example.com_location_override` that contains something like this: - -``` -location / { - proxy_pass http://app.example.com; -} -``` - -#### Per-VIRTUAL_HOST `server_tokens` configuration -Per virtual-host `servers_tokens` directive can be configured by passing appropriate value to the `SERVER_TOKENS` environment variable. Please see the [nginx http_core module configuration](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens) for more details. - -### Unhashed vs SHA1 upstream names - -By default the nginx configuration `upstream` blocks will use this block's corresponding hostname as a predictable name. However, this can cause issues in some setups (see [this issue](https://github.com/nginx-proxy/nginx-proxy/issues/1162)). In those cases you might want to switch to SHA1 names for the `upstream` blocks by setting the `SHA1_UPSTREAM_NAME` environment variable to `true` on the nginx-proxy container. - -Please note that using regular expressions in `VIRTUAL_HOST` will always result in a corresponding `upstream` block with an SHA1 name. - -### Troubleshooting - -If you can't access your `VIRTUAL_HOST`, inspect the generated nginx configuration: - -```console -docker exec nginx -T -``` - -Pay attention to the `upstream` definition blocks, which should look like this: - -```Nginx -# foo.example.com -upstream foo.example.com { - ## Can be connected with "my_network" network - # Exposed ports: [{ tcp } { tcp } ...] - # Default virtual port: - # VIRTUAL_PORT: - # foo - server 172.18.0.9:; - # Fallback entry - server 127.0.0.1 down; -} -``` - -The effective `Port` is retrieved by order of precedence: -1. From the `VIRTUAL_PORT` environment variable -1. From the container's exposed port if there is only one -1. From the default port 80 when none of the above methods apply - -### Contributing - -Before submitting pull requests or issues, please check github to make sure an existing issue or pull request is not already open. - -#### Running Tests Locally - -To run tests, you just need to run the command below: - -```console -make test -``` - -This commands run tests on two variants of the nginx-proxy docker image: Debian and Alpine. - -You can run the tests for each of these images with their respective commands: - -```console -make test-debian -make test-alpine -``` +### Additional documentation -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. +Please check the [docs section](https://github.com/nginx-proxy/nginx-proxy/tree/main/docs). diff --git a/app/Procfile b/app/Procfile index 29fe16627..f23e0f4fd 100644 --- a/app/Procfile +++ b/app/Procfile @@ -1,2 +1,2 @@ dockergen: docker-gen -watch -notify "nginx -s reload" /app/nginx.tmpl /etc/nginx/conf.d/default.conf -nginx: nginx +nginx: nginx -g "daemon off;" diff --git a/docker-compose-separate-containers.yml b/docker-compose-separate-containers.yml index 427763282..5a6489596 100644 --- a/docker-compose-separate-containers.yml +++ b/docker-compose-separate-containers.yml @@ -1,4 +1,5 @@ -version: '2' +version: "2" + services: nginx: image: nginx diff --git a/docker-compose.yml b/docker-compose.yml index 931c364bb..809d6fa80 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,5 @@ -version: '2' +version: "2" + services: nginx-proxy: image: nginxproxy/nginx-proxy diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..e381b7f19 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,781 @@ +### Docker Compose + +```yaml +version: '2' + +services: + nginx-proxy: + image: nginxproxy/nginx-proxy + ports: + - "80:80" + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + + whoami: + image: jwilder/whoami + expose: + - "8000" + environment: + - VIRTUAL_HOST=whoami.example + - VIRTUAL_PORT=8000 +``` + +```console +docker compose up +curl -H "Host: whoami.example" localhost +``` + +Example output: +```console +I'm 5b129ab83266 +``` + +### IPv6 support + +You can activate the IPv6 support for the nginx-proxy container by passing the value `true` to the `ENABLE_IPV6` environment variable: + +```console +docker run -d -p 80:80 -e ENABLE_IPV6=true -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy +``` + +#### Scoped IPv6 Resolvers + +NginX does not support scoped IPv6 resolvers. In [docker-entrypoint.sh](https://github.com/nginx-proxy/nginx-proxy/tree/main/docker-entrypoint.sh) the resolvers are parsed from resolv.conf, but any scoped IPv6 addreses will be removed. + +#### IPv6 NAT + +By default, docker uses IPv6-to-IPv4 NAT. This means all client connections from IPv6 addresses will show docker's internal IPv4 host address. To see true IPv6 client IP addresses, you must [enable IPv6](https://docs.docker.com/config/daemon/ipv6/) and use [ipv6nat](https://github.com/robbertkl/docker-ipv6nat). You must also disable the userland proxy by adding `"userland-proxy": false` to `/etc/docker/daemon.json` and restarting the daemon. + +### Multiple Hosts + +If you need to support multiple virtual hosts for a container, you can separate each entry with commas. For example, `foo.bar.com,baz.bar.com,bar.com` and each host will be setup the same. + +### Virtual Ports + +When your container exposes only one port, nginx-proxy will default to this port, else to port 80. + +If you need to specify a different port, you can set a `VIRTUAL_PORT` env var to select a different one. This variable cannot be set to more than one port. + +For each host defined into `VIRTUAL_HOST`, the associated virtual port is retrieved by order of precedence: +1. From the `VIRTUAL_PORT` environment variable +1. From the container's exposed port if there is only one +1. From the default port 80 when none of the above methods apply + +### Wildcard Hosts + +You can also use wildcards at the beginning and the end of host name, like `*.bar.com` or `foo.bar.*`. Or even a regular expression, which can be very useful in conjunction with a wildcard DNS service like [nip.io](https://nip.io) or [sslip.io](https://sslip.io), using `~^foo\.bar\..*\.nip\.io` will match `foo.bar.127.0.0.1.nip.io`, `foo.bar.10.0.2.2.nip.io` and all other given IPs. More information about this topic can be found in the nginx documentation about [`server_names`](http://nginx.org/en/docs/http/server_names.html). + +### Path-based Routing + +You can have multiple containers proxied by the same `VIRTUAL_HOST` by adding a `VIRTUAL_PATH` environment variable containing the absolute path to where the container should be mounted. For example with `VIRTUAL_HOST=foo.example.com` and `VIRTUAL_PATH=/api/v2/service`, then requests to http://foo.example.com/api/v2/service will be routed to the container. If you wish to have a container serve the root while other containers serve other paths, give the root container a `VIRTUAL_PATH` of `/`. Unmatched paths will be served by the container at `/` or will return the default nginx error page if no container has been assigned `/`. +It is also possible to specify multiple paths with regex locations like `VIRTUAL_PATH=~^/(app1|alternative1)/`. For further details see the nginx documentation on location blocks. This is not compatible with `VIRTUAL_DEST`. + +The full request URI will be forwarded to the serving container in the `X-Original-URI` header. + +**NOTE**: Your application needs to be able to generate links starting with `VIRTUAL_PATH`. This can be achieved by it being natively on this path or having an option to prepend this path. The application does not need to expect this path in the request. + +#### VIRTUAL_DEST + +This environment variable can be used to rewrite the `VIRTUAL_PATH` part of the requested URL to proxied application. The default value is empty (off). +Make sure that your settings won't result in the slash missing or being doubled. Both these versions can cause troubles. + +If the application runs natively on this sub-path or has a setting to do so, `VIRTUAL_DEST` should not be set or empty. +If the requests are expected to not contain a sub-path and the generated links contain the sub-path, `VIRTUAL_DEST=/` should be used. + +```console +$ docker run -d -e VIRTUAL_HOST=example.tld -e VIRTUAL_PATH=/app1/ -e VIRTUAL_DEST=/ --name app1 app +``` + +In this example, the incoming request `http://example.tld/app1/foo` will be proxied as `http://app1/foo` instead of `http://app1/app1/foo`. + +#### 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 filename of the previous example would be `example.tld_8610f6c344b4096614eab6e09d58885349f42faf_location`. + +#### DEFAULT_ROOT + +This environment variable of the nginx proxy container can be used to customize the return error page if no matching path is found. Furthermore it is possible to use anything which is compatible with the `return` statement of nginx. + +Exception: If this is set to the string `none`, no default `location /` directive will be generated. This makes it possible for you to provide your own `location /` directive in your [`/etc/nginx/vhost.d/VIRTUAL_HOST`](#per-virtual_host) or [`/etc/nginx/vhost.d/default`](#per-virtual_host-default-configuration) files. + +If unspecified, `DEFAULT_ROOT` defaults to `404`. + +Examples (YAML syntax): + + * `DEFAULT_ROOT: "none"` prevents `nginx-proxy` from generating a default `location /` directive. + * `DEFAULT_ROOT: "418"` returns a 418 error page instead of the normal 404 one. + * `DEFAULT_ROOT: "301 https://github.com/nginx-proxy/nginx-proxy/blob/main/README.md"` redirects the client to this documentation. + +Nginx variables such as `$scheme`, `$host`, and `$request_uri` can be used. However, care must be taken to make sure the `$` signs are escaped properly. For example, if you want to use `301 $scheme://$host/myapp1$request_uri` you should use: + +* Bash: `DEFAULT_ROOT='301 $scheme://$host/myapp1$request_uri'` +* Docker Compose yaml: `- DEFAULT_ROOT: 301 $$scheme://$$host/myapp1$$request_uri` + + +### Multiple Networks + +With the addition of [overlay networking](https://docs.docker.com/engine/userguide/networking/get-started-overlay/) in Docker 1.9, your `nginx-proxy` container may need to connect to backend containers on multiple networks. 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`. + +If you want your `nginx-proxy` container to be attached to a different network, you must pass the `--net=my-network` option in your `docker create` or `docker run` command. At the time of this writing, only a single network can be specified at container creation time. To attach to other networks, you can use the `docker network connect` command after your container is created: + +```console +docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro \ + --name my-nginx-proxy --net my-network nginxproxy/nginx-proxy +docker network connect my-other-network my-nginx-proxy +``` + +In this example, the `my-nginx-proxy` container will be connected to `my-network` and `my-other-network` and will be able to proxy to other containers attached to those networks. + +### Host networking + +`nginx-proxy` is compatible with containers using Docker's [host networking](https://docs.docker.com/network/host/), both with the proxy connected to one or more [bridge network](https://docs.docker.com/network/bridge/) (default or user created) or running in host network mode itself. + +Proxyed containers running in host network mode **must** use the [`VIRTUAL_PORT`](#virtual-ports) environment variable, as this is the only way for `nginx-proxy` to get the correct port (or a port at all) for those containers. + +### Custom external HTTP/HTTPS ports + +If you want to use `nginx-proxy` with different external ports that the default ones of `80` for `HTTP` traffic and `443` for `HTTPS` traffic, you'll have to use the environment variable(s) `HTTP_PORT` and/or `HTTPS_PORT` in addition to the changes to the Docker port mapping. If you change the `HTTPS` port, the redirect for `HTTPS` traffic will also be configured to redirect to the custom port. Typical usage, here with the custom ports `1080` and `10443`: + +```console +docker run -d -p 1080:1080 -p 10443:10443 -e HTTP_PORT=1080 -e HTTPS_PORT=10443 -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy +``` + +### Internet vs. Local Network Access + +If you allow traffic from the public internet to access your `nginx-proxy` container, you may want to restrict some containers to the internal network only, so they cannot be accessed from the public internet. On containers that should be restricted to the internal network, you should set the environment variable `NETWORK_ACCESS=internal`. By default, the *internal* network is defined as `127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16`. To change the list of networks considered internal, mount a file on the `nginx-proxy` at `/etc/nginx/network_internal.conf` with these contents, edited to suit your needs: + +```Nginx +# These networks are considered "internal" +allow 127.0.0.0/8; +allow 10.0.0.0/8; +allow 192.168.0.0/16; +allow 172.16.0.0/12; + +# Traffic from all other networks will be rejected +deny all; +``` + +When internal-only access is enabled, external clients will be denied with an `HTTP 403 Forbidden` + +> If there is a load-balancer / reverse proxy in front of `nginx-proxy` that hides the client IP (example: AWS Application/Elastic Load Balancer), you will need to use the nginx `realip` module (already installed) to extract the client's IP from the HTTP request headers. Please see the [nginx realip module configuration](http://nginx.org/en/docs/http/ngx_http_realip_module.html) for more details. This configuration can be added to a new config file and mounted in `/etc/nginx/conf.d/`. + +### SSL Backends + +If you would like the reverse proxy to connect to your backend using HTTPS instead of HTTP, set `VIRTUAL_PROTO=https` on the backend container. + +> Note: If you use `VIRTUAL_PROTO=https` and your backend container exposes port 80 and 443, `nginx-proxy` will use HTTPS on port 80. This is almost certainly not what you want, so you should also include `VIRTUAL_PORT=443`. + +### uWSGI Backends + +If you would like to connect to uWSGI backend, set `VIRTUAL_PROTO=uwsgi` on the backend container. Your backend container should then listen on a port rather than a socket and expose that port. + +### FastCGI Backends + +If you would like to connect to FastCGI backend, set `VIRTUAL_PROTO=fastcgi` on the backend container. Your backend container should then listen on a port rather than a socket and expose that port. + +### FastCGI File Root Directory + +If you use fastcgi,you can set `VIRTUAL_ROOT=xxx` for your root directory + +### Logging + +The default nginx access log format is + +``` +$host $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$upstream_addr" +``` + +#### Custom log format + +If you want to use a custom access log format, you can set `LOG_FORMAT=xxx` on the proxy container. + +With docker compose take care to escape the `$` character with `$$` to avoid variable interpolation. Example: `$remote_addr` becomes `$$remote_addr`. + +#### JSON log format + +If you want access logs in JSON format, you can set `LOG_JSON=true`. This will correctly set the escape character to `json` and the log format to : + +```json +{ + "time_local": "$time_iso8601", + "client_ip": "$http_x_forwarded_for", + "remote_addr": "$remote_addr", + "request": "$request", + "status": "$status", + "body_bytes_sent": "$body_bytes_sent", + "request_time": "$request_time", + "upstream_response_time": "$upstream_response_time", + "upstream_addr": "$upstream_addr", + "http_referrer": "$http_referer", + "http_user_agent": "$http_user_agent", + "request_id": "$request_id" +} +``` + +#### Log format escaping + +If you want to manually set nginx `log_format`'s `escape`, set the `LOG_FORMAT_ESCAPE` variable to [a value supported by nginx](https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format). + +#### Disable access logs + +To disable nginx access logs entirely, set the `DISABLE_ACCESS_LOGS` environment variable to any value. + +#### Disabling colors in the container log output + +To remove colors from the container log output, set the [`NO_COLOR` environment variable to any value other than an empty string](https://no-color.org/) on the nginx-proxy container. + +```console +docker run --detach \ + --publish 80:80 \ + --env NO_COLOR=1 \ + --volume /var/run/docker.sock:/tmp/docker.sock:ro \ + nginxproxy/nginx-proxy +``` + +### Default Host + +To set the default host for nginx use the env var `DEFAULT_HOST=foo.bar.com` for example + +```console +docker run -d -p 80:80 -e DEFAULT_HOST=foo.bar.com -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy +``` + +nginx-proxy will then redirect all requests to a container where `VIRTUAL_HOST` is set to `DEFAULT_HOST`, if they don't match any (other) `VIRTUAL_HOST`. Using the example above requests without matching `VIRTUAL_HOST` will be redirected to a plain nginx instance after running the following command: + +```console +docker run -d -e VIRTUAL_HOST=foo.bar.com nginx +``` + +### Separate Containers + +nginx-proxy can also be run as two separate containers using the [nginxproxy/docker-gen](https://hub.docker.com/r/nginxproxy/docker-gen) image and the official [nginx](https://registry.hub.docker.com/_/nginx/) image. + +You may want to do this to prevent having the docker socket bound to a publicly exposed container service. + +You can demo this pattern with docker compose: + +```console +docker compose --file docker-compose-separate-containers.yml up +curl -H "Host: whoami.example" localhost +``` + +Example output: +```console +I'm 5b129ab83266 +``` + +To run nginx proxy as a separate container you'll need to have [nginx.tmpl](https://github.com/nginx-proxy/nginx-proxy/blob/main/nginx.tmpl) on your host system. + +First start nginx with a volume: + + +```console +docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx +``` + +Then start the docker-gen container with the shared volume and template: + +```console +docker run --volumes-from nginx \ + -v /var/run/docker.sock:/tmp/docker.sock:ro \ + -v $(pwd):/etc/docker-gen/templates \ + -t nginxproxy/docker-gen -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf +``` + +Finally, start your containers with `VIRTUAL_HOST` environment variables. + +```console +docker run -e VIRTUAL_HOST=foo.bar.com ... +``` + +### SSL Support using an ACME CA + +[acme-companion](https://github.com/nginx-proxy/acme-companion) is a lightweight companion container for the nginx-proxy. It allows the automated creation/renewal of SSL certificates using the ACME protocol. + +### SSL Support + +SSL is supported using single host, wildcard and SNI certificates using naming conventions for certificates or optionally specifying a cert name (for SNI) as an environment variable. + +To enable SSL: + +```console +docker run -d -p 80:80 -p 443:443 -v /path/to/certs:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy +``` + +The contents of `/path/to/certs` should contain the certificates and private keys for any virtual hosts in use. The certificate and keys should be named after the virtual host with a `.crt` and `.key` extension. For example, a container with `VIRTUAL_HOST=foo.bar.com` should have a `foo.bar.com.crt` and `foo.bar.com.key` file in the certs directory. + +If you are running the container in a virtualized environment (Hyper-V, VirtualBox, etc...), /path/to/certs must exist in that environment or be made accessible to that environment. By default, Docker is not able to mount directories on the host machine to containers running in a virtual machine. + +#### 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. + +To use custom `dhparam.pem` files per-virtual-host, the files should be named after the virtual host with a `dhparam` suffix and `.pem` extension. For example, a container with `VIRTUAL_HOST=foo.bar.com` should have a `foo.bar.com.dhparam.pem` file in the `/etc/nginx/certs` directory. + +> COMPATIBILITY WARNING: The default generated `dhparam.pem` key is 4096 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 clients, you must provide your own `dhparam.pem`. + +In the separate container setup, no pre-generated key will be available and neither the [nginxproxy/docker-gen](https://hub.docker.com/r/nginxproxy/docker-gen) image, nor the offical [nginx](https://registry.hub.docker.com/_/nginx/) image will provide one. If you still want A+ security in a separate container setup, you should mount an RFC7919 DH key file to the nginx container at `/etc/nginx/dhparam/dhparam.pem`. + +Set `DHPARAM_SKIP` environment variable to `true` to disable using default Diffie-Hellman parameters. The default value is `false`. + +```console +docker run -e DHPARAM_SKIP=true .... +``` + +#### Wildcard Certificates + +Wildcard certificates and keys should be named after the domain name with a `.crt` and `.key` extension. For example `VIRTUAL_HOST=foo.bar.com` would use cert name `bar.com.crt` and `bar.com.key`. + +#### SNI + +If your certificate(s) supports multiple domain names, you can start a container with `CERT_NAME=` to identify the certificate to be used. For example, a certificate for `*.foo.com` and `*.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. + +#### 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/.chain.pem`, where `` 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 + +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 27, Android 4.4.2, Chrome 31, Edge, IE 11 on Windows 7, 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.2 and 1.3 are supported. + +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 the nginx-proxy container or to your container. This profile is compatible with clients back to Firefox 63, Android 10.0, Chrome 70, Edge 75, Java 11, OpenSSL 1.1.1, Opera 57, and Safari 12.1. Note that this profile is **not** compatible with any version of Internet Explorer. + +Complete list of policies available through the `SSL_POLICY` environment variable, including the [AWS ELB Security Policies](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies) and [AWS Classic ELB security policies](https://docs.aws.amazon.com/fr_fr/elasticloadbalancing/latest/classic/elb-security-policy-table.html): + +
+ Mozilla policies + +
+
+ AWS ELB TLS 1.3 security policies +
    +
  • + AWS-TLS13-1-3-2021-06 +
  • +
  • + AWS-TLS13-1-2-2021-06 +
  • +
  • + AWS-TLS13-1-2-Res-2021-06 +
  • +
  • + AWS-TLS13-1-2-Ext1-2021-06 +
  • +
  • + AWS-TLS13-1-2-Ext2-2021-06 +
  • +
  • + AWS-TLS13-1-1-2021-06 +
  • +
  • + AWS-TLS13-1-0-2021-06 +
  • +
+
+
+ AWS ELB FS supported policies +
    +
  • + AWS-FS-1-2-Res-2020-10 +
  • +
  • + AWS-FS-1-2-Res-2019-08 +
  • +
  • + AWS-FS-1-2-2019-08 +
  • +
  • + AWS-FS-1-1-2019-08 +
  • +
  • + AWS-FS-2018-06 +
  • +
+
+
+ AWS ELB TLS 1.0 - 1.2 security policies +
    +
  • + AWS-TLS-1-2-Ext-2018-06 +
  • +
  • + AWS-TLS-1-2-2017-01 +
  • +
  • + AWS-TLS-1-1-2017-01 +
  • +
  • + AWS-2016-08 +
  • +
+
+
+ AWS Classic ELB security policies +
    +
  • + AWS-2015-05 +
  • +
  • + AWS-2015-03 +
  • +
  • + AWS-2015-02 +
  • +
+
+
+ +Note that the `Mozilla-Old` policy should use a 1024 bits DH key for compatibility but this container provides a 4096 bits key. The [Diffie-Hellman Groups](#diffie-hellman-groups) section details different methods of bypassing this, either globally or per virtual-host. + +The default behavior for the proxy when port 80 and 443 are exposed is as follows: + +* If a virtual host has a usable cert, port 80 will redirect to 443 for that virtual host so that HTTPS is always preferred when available. +* If the virtual host does not have a usable cert, but `default.crt` and `default.key` exist, those will be used as the virtual host's certificate and the client browser will receive a 500 error. +* If the virtual host does not have a usable cert, and `default.crt` and `default.key` do not exist, TLS negotiation will fail (see [Missing Certificate](#missing-certificate) below). + +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 disable the non-SSL site entirely with `HTTPS_METHOD=nohttp`, or disable the HTTPS site with `HTTPS_METHOD=nohttps`. `HTTPS_METHOD` can be specified on each container for which you want to override the default behavior or on the proxy container to set it globally. 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 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 window / different browser. + +By default, [HTTP Strict Transport Security (HSTS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) is enabled with `max-age=31536000` for HTTPS sites. You can disable HSTS with the environment variable `HSTS=off` or use a custom HSTS configuration like `HSTS=max-age=31536000; includeSubDomains; preload`. + +*WARNING*: HSTS will force your users to visit the HTTPS version of your site for the `max-age` time - even if they type in `http://` manually. The only way to get to an HTTP site after receiving an HSTS response is to clear your browser's HSTS cache. + +#### Missing Certificate + +If HTTPS is enabled for a virtual host but its certificate is missing, nginx-proxy will configure nginx to use the default certificate (`default.crt` with `default.key`) and return a 500 error. + +If the default certificate is also missing, nginx-proxy will configure nginx to accept HTTPS connections but fail the TLS negotiation. Client browsers will render a TLS error page. As of March 2023, web browsers display the following error messages: + + * Chrome: + + > This site can't provide a secure connection + > + > example.test sent an invalid response. + > + > Try running Connectivity Diagnostics. + > + > `ERR_SSL_PROTOCOL_ERROR` + + * Firefox: + + > Secure Connection Failed + > + > An error occurred during a connection to example.test. + > Peer reports it experienced an internal error. + > + > Error code: `SSL_ERROR_INTERNAL_ERROR_ALERT` "TLS error". + +### HTTP/2 support + +HTTP/2 is enabled by default and can be disabled if necessary either per-proxied container or globally: + +To disable HTTP/2 for a single proxied container, set the `com.github.nginx-proxy.nginx-proxy.http2.enable` label to `false` on this container. + +To disable HTTP/2 globally set the environment variable `ENABLE_HTTP2` to `false` on the nginx-proxy container. + +More reading on the potential TCP head-of-line blocking issue with HTTP/2: [HTTP/2 Issues](https://www.twilio.com/blog/2017/10/http2-issues.html), [Comparing HTTP/3 vs HTTP/2](https://blog.cloudflare.com/http-3-vs-http-2/) + +### HTTP/3 support + +> **Warning** +> HTTP/3 support [is still considered experimental in nginx](https://www.nginx.com/blog/binary-packages-for-preview-nginx-quic-http3-implementation/) and as such is considered experimental in nginx-proxy too and is disabled by default. [Feedbacks for the HTTP/3 support are welcome in #2271.](https://github.com/nginx-proxy/nginx-proxy/discussions/2271) + +HTTP/3 use the QUIC protocol over UDP (unlike HTTP/1.1 and HTTP/2 which work over TCP), so if you want to use HTTP/3 you'll have to explicitely publish the 443/udp port of the proxy in addition to the 443/tcp port: + +```console +docker run -d -p 80:80 -p 443:443/tcp -p 443:443/udp \ + -v /var/run/docker.sock:/tmp/docker.sock:ro \ + nginxproxy/nginx-proxy +``` + +HTTP/3 can be enabled either per-proxied container or globally: + +To enable HTTP/3 for a single proxied container, set the `com.github.nginx-proxy.nginx-proxy.http3.enable` label to `true` on this container. + +To enable HTTP/3 globally set the environment variable `ENABLE_HTTP3` to `true` on the nginx-proxy container. + +### 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 on directory +/etc/nginx/htpasswd/$VIRTUAL_HOST + +```console +docker run -d -p 80:80 -p 443:443 \ + -v /path/to/htpasswd:/etc/nginx/htpasswd \ + -v /path/to/certs:/etc/nginx/certs \ + -v /var/run/docker.sock:/tmp/docker.sock:ro \ + nginxproxy/nginx-proxy +``` + +You'll need apache2-utils on the machine where you plan to create the htpasswd file. Follow these [instructions](http://httpd.apache.org/docs/2.2/programs/htpasswd.html) + +If you want to define basic authentication for a `VIRTUAL_PATH`, you have to create a file named as /etc/ngingx/htpasswd/${VIRTUAL_HOST}_${VIRTUAL_PATH_SHA1} +(where $VIRTUAL_PATH_SHA1 is the SHA1 hash for the virtual path, you can use any SHA1 online generator to calculate it). + +### Upstream (Backend) Server HTTP Load Balancing Support + +> **Warning** +> This feature is experimental. The behavior may change (or the feature may be removed entirely) without warning in a future release, even if the release is not a new major version. If you use this feature, or if you would like to use this feature but you require changes to it first, please [provide feedback in #2195](https://github.com/nginx-proxy/nginx-proxy/discussions/2195). Once we have collected enough feedback we will promote this feature to officially supported. + +If you have multiple containers with the same `VIRTUAL_HOST` and `VIRTUAL_PATH` settings, nginx will spread the load across all of them. To change the load balancing algorithm from nginx's default (round-robin), set the `com.github.nginx-proxy.nginx-proxy.loadbalance` label on one or more of your application containers to the desired load balancing directive. See the [`ngx_http_upstream_module` documentation](https://nginx.org/en/docs/http/ngx_http_upstream_module.html) for available directives. + +> **Note** +> * Don't forget the terminating semicolon (`;`). +> * If you are using Docker Compose, remember to escape any dollar sign (`$`) characters (`$` becomes `$$`). + +Docker Compose example: + +```yaml +services: + nginx-proxy: + image: nginxproxy/nginx-proxy + ports: + - "80:80" + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + environment: + HTTPS_METHOD: nohttps + myapp: + image: jwilder/whoami + expose: + - "8000" + environment: + VIRTUAL_HOST: myapp.example + VIRTUAL_PORT: "8000" + labels: + com.github.nginx-proxy.nginx-proxy.loadbalance: "hash $$remote_addr;" + deploy: + replicas: 4 +``` + +### Upstream (Backend) Server HTTP Keep-Alive Support + +> **Warning** +> This feature is experimental. The behavior may change (or the feature may be removed entirely) without warning in a future release, even if the release is not a new major version. If you use this feature, or if you would like to use this feature but you require changes to it first, please [provide feedback in #2194](https://github.com/nginx-proxy/nginx-proxy/discussions/2194). Once we have collected enough feedback we will promote this feature to officially supported. + +To enable HTTP keep-alive between `nginx-proxy` and backend server(s), set the `com.github.nginx-proxy.nginx-proxy.keepalive` label on the server's container either to `auto` or to the desired maximum number of idle connections. The `auto` setting will dynamically set the maximum number of idle connections to twice the number of servers listed in the corresponding `upstream{}` block, [per nginx recommendation](https://www.nginx.com/blog/avoiding-top-10-nginx-configuration-mistakes/#no-keepalives). + +See the [nginx keepalive documentation](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) and the [Docker label documentation](https://docs.docker.com/config/labels-custom-metadata/) for details. + +### Headers + +By default, `nginx-proxy` forwards all incoming request headers from the client to the backend server unmodified, with the following exceptions: + + * `Connection`: Set to `upgrade` if the client sets the `Upgrade` header, otherwise set to `close`. (Keep-alive between `nginx-proxy` and the backend server is not supported.) + * `Proxy`: Always removed if present. This prevents attackers from using the so-called [httpoxy attack](http://httpoxy.org). There is no legitimate reason for a client to send this header, and there are many vulnerable languages / platforms (`CVE-2016-5385`, `CVE-2016-5386`, `CVE-2016-5387`, `CVE-2016-5388`, `CVE-2016-1000109`, `CVE-2016-1000110`, `CERT-VU#797896`). + * `X-Real-IP`: Set to the client's IP address. + * `X-Forwarded-For`: The client's IP address is appended to the value provided by the client. (If the client did not provide this header, it is set to the client's IP address.) + * `X-Forwarded-Host`: If the client did not provide this header or if the `TRUST_DOWNSTREAM_PROXY` environment variable is set to `false` (see below), this is set to the value of the `Host` header provided by the client. Otherwise, the header is forwarded to the backend server unmodified. + * `X-Forwarded-Proto`: If the client did not provide this header or if the `TRUST_DOWNSTREAM_PROXY` environment variable is set to `false` (see below), this is set to `http` for plain HTTP connections and `https` for TLS connections. Otherwise, the header is forwarded to the backend server unmodified. + * `X-Forwarded-Ssl`: Set to `on` if the `X-Forwarded-Proto` header sent to the backend server is `https`, otherwise set to `off`. + * `X-Forwarded-Port`: If the client did not provide this header or if the `TRUST_DOWNSTREAM_PROXY` environment variable is set to `false` (see below), this is set to the port of the server that accepted the client's request. Otherwise, the header is forwarded to the backend server unmodified. + * `X-Original-URI`: Set to the original request URI. + +#### Trusting Downstream Proxy Headers + +For legacy compatibility reasons, `nginx-proxy` forwards any client-supplied `X-Forwarded-Proto` (which affects the value of `X-Forwarded-Ssl`), `X-Forwarded-Host`, and `X-Forwarded-Port` headers unchecked and unmodified. To prevent malicious clients from spoofing the protocol, hostname, or port that is perceived by your backend server, you are encouraged to set the `TRUST_DOWNSTREAM_PROXY` value to `false` if: + + * you do not operate a second reverse proxy downstream of `nginx-proxy`, or + * you do operate a second reverse proxy downstream of `nginx-proxy` but that proxy forwards those headers unchecked from untrusted clients. + +The default for `TRUST_DOWNSTREAM_PROXY` may change to `false` in a future version of `nginx-proxy`. If you require it to be enabled, you are encouraged to explicitly set it to `true` to avoid compatibility problems when upgrading. + +### Custom Nginx Configuration + +If you need to configure Nginx beyond what is possible using environment variables, you can provide custom configuration files on either a proxy-wide or per-`VIRTUAL_HOST` basis. + +#### Replacing default proxy settings + +If you want to replace the default proxy settings for the nginx container, add a configuration file at `/etc/nginx/proxy.conf`. A file with the default settings would look like this: + +```Nginx +# HTTP 1.1 support +proxy_http_version 1.1; +proxy_set_header Host $http_host; +proxy_set_header Upgrade $http_upgrade; +proxy_set_header Connection $proxy_connection; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host; +proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; +proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl; +proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port; +proxy_set_header X-Original-URI $request_uri; + +# Mitigate httpoxy attack (see README for details) +proxy_set_header Proxy ""; +``` + +***NOTE***: If you provide this file it will replace the defaults; you may want to check the .tmpl file to make sure you have all of the needed options. + +#### Proxy-wide + +To add settings on a proxy-wide basis, add your configuration file under `/etc/nginx/conf.d` using a name ending in `.conf`. + +This can be done in a derived image by creating the file in a `RUN` command or by `COPY`ing the file into `conf.d`: + +```Dockerfile +FROM nginxproxy/nginx-proxy +RUN { \ + echo 'server_tokens off;'; \ + echo 'client_max_body_size 100m;'; \ + } > /etc/nginx/conf.d/my_proxy.conf +``` + +Or it can be done by mounting in your custom configuration in your `docker run` command: + +```console +docker run -d -p 80:80 -p 443:443 -v /path/to/my_proxy.conf:/etc/nginx/conf.d/my_proxy.conf:ro -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy +``` + +#### 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`. + +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. + +For example, if you have a virtual host named `app.example.com`, you could provide a custom configuration for that host as follows: + +```console +docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy +{ echo 'server_tokens off;'; echo 'client_max_body_size 100m;'; } > /path/to/vhost.d/app.example.com +``` + +If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink: + +```console +{ echo 'server_tokens off;'; echo 'client_max_body_size 100m;'; } > /path/to/vhost.d/www.example.com +ln -s /path/to/vhost.d/www.example.com /path/to/vhost.d/example.com +``` + +#### Per-VIRTUAL_HOST default configuration + +If you want most of your virtual hosts to use a default single configuration and then override on a few specific ones, add those settings to the `/etc/nginx/vhost.d/default` file. This file will be used on any virtual host which does not have a `/etc/nginx/vhost.d/{VIRTUAL_HOST}` file associated with it. + +#### 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`. + +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: + +```console +docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy +{ echo 'proxy_cache my-cache;'; echo 'proxy_cache_valid 200 302 60m;'; echo 'proxy_cache_valid 404 1m;' } > /path/to/vhost.d/app.example.com_location +``` + +If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink: + +```console +{ echo 'proxy_cache my-cache;'; echo 'proxy_cache_valid 200 302 60m;'; echo 'proxy_cache_valid 404 1m;' } > /path/to/vhost.d/app.example.com_location +ln -s /path/to/vhost.d/www.example.com /path/to/vhost.d/example.com +``` + +#### Per-VIRTUAL_HOST location default configuration + +If you want most of your virtual hosts to use a default single `location` block configuration and then override on a few specific ones, add those settings to the `/etc/nginx/vhost.d/default_location` file. This file will be used on any virtual host which does not have a `/etc/nginx/vhost.d/{VIRTUAL_HOST}_location` file associated with it. + +#### Overriding `location` blocks + +The `${VIRTUAL_HOST}_${PATH_HASH}_location`, `${VIRTUAL_HOST}_location`, and `default_location` files documented above make it possible to *augment* the generated [`location` block(s)](https://nginx.org/en/docs/http/ngx_http_core_module.html#location) in a virtual host. In some circumstances, you may need to *completely override* the `location` block for a particular combination of virtual host and path. To do this, create a file whose name follows this pattern: + +``` +/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). + +For convenience, the `_${PATH_HASH}` part can be omitted if the path is `/`: + +``` +/etc/nginx/vhost.d/${VIRTUAL_HOST}_location_override +``` + +When an override file exists, the `location` block that is normally created by `nginx-proxy` is not generated. Instead, the override file is included via the [nginx `include` directive](https://nginx.org/en/docs/ngx_core_module.html#include). + +You are responsible for providing a suitable `location` block in your override file as required for your service. By default, `nginx-proxy` uses the `VIRTUAL_HOST` name as the upstream name for your application's Docker container; see [here](#unhashed-vs-sha1-upstream-names) for details. As an example, if your container has a `VIRTUAL_HOST` value of `app.example.com`, then to override the location block for `/` you would create a file named `/etc/nginx/vhost.d/app.example.com_location_override` that contains something like this: + +``` +location / { + proxy_pass http://app.example.com; +} +``` + +#### Per-VIRTUAL_HOST `server_tokens` configuration +Per virtual-host `servers_tokens` directive can be configured by passing appropriate value to the `SERVER_TOKENS` environment variable. Please see the [nginx http_core module configuration](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens) for more details. + +### Unhashed vs SHA1 upstream names + +By default the nginx configuration `upstream` blocks will use this block's corresponding hostname as a predictable name. However, this can cause issues in some setups (see [this issue](https://github.com/nginx-proxy/nginx-proxy/issues/1162)). In those cases you might want to switch to SHA1 names for the `upstream` blocks by setting the `SHA1_UPSTREAM_NAME` environment variable to `true` on the nginx-proxy container. + +Please note that using regular expressions in `VIRTUAL_HOST` will always result in a corresponding `upstream` block with an SHA1 name. + +### Troubleshooting + +If you can't access your `VIRTUAL_HOST`, inspect the generated nginx configuration: + +```console +docker exec nginx -T +``` + +Pay attention to the `upstream` definition blocks, which should look like this: + +```Nginx +# foo.example.com +upstream foo.example.com { + ## Can be connected with "my_network" network + # Exposed ports: [{ tcp } { tcp } ...] + # Default virtual port: + # VIRTUAL_PORT: + # foo + server 172.18.0.9:; + # Fallback entry + server 127.0.0.1 down; +} +``` + +The effective `Port` is retrieved by order of precedence: +1. From the `VIRTUAL_PORT` environment variable +1. From the container's exposed port if there is only one +1. From the default port 80 when none of the above methods apply + +### Contributing + +Before submitting pull requests or issues, please check github to make sure an existing issue or pull request is not already open. + +#### Running Tests Locally + +To run tests, you just need to run the command below: + +```console +make test +``` + +This commands run tests on two variants of the nginx-proxy docker image: Debian and Alpine. + +You can run the tests for each of these images with their respective commands: + +```console +make test-debian +make test-alpine +``` + +You can learn more about how the test suite works and how to write new tests in the [test/README.md](https://github.com/nginx-proxy/nginx-proxy/tree/main/test/README.md) file. diff --git a/nginx.tmpl b/nginx.tmpl index db2d54b6d..c72c1c7a4 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -75,7 +75,7 @@ {{- continue }} {{- end }} {{- range sortObjectsByKeysAsc $.globals.CurrentContainer.Networks "Name" }} - {{- if and . .Gateway }} + {{- if and . .Gateway (not .Internal) }} # container is in host network mode, using {{ .Name }} gateway IP {{- $ip = .Gateway }} {{- break }} @@ -142,16 +142,12 @@ {{- 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; + {{- /* + * This ssl_ciphers directive is not used but necessary to get TLSv1.3 only. + * see https://serverfault.com/questions/1023766/nginx-with-only-tls1-3-cipher-suites + */}} + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384; + ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256; ssl_prefer_server_ciphers off; {{- else if eq .ssl_policy "Mozilla-Intermediate" }} ssl_protocols TLSv1.2 TLSv1.3; @@ -161,28 +157,85 @@ 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" }} + {{- else if eq .ssl_policy "AWS-TLS13-1-3-2021-06" }} + ssl_protocols TLSv1.3; + {{- /* + * This ssl_ciphers directive is not used but necessary to get TLSv1.3 only. + * see https://serverfault.com/questions/1023766/nginx-with-only-tls1-3-cipher-suites + */}} + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384; + ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256; + ssl_prefer_server_ciphers on; + {{- else if eq .ssl_policy "AWS-TLS13-1-2-2021-06" }} + 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'; + ssl_prefer_server_ciphers on; + {{- else if eq .ssl_policy "AWS-TLS13-1-2-Res-2021-06" }} + 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'; + ssl_prefer_server_ciphers on; + {{- else if eq .ssl_policy "AWS-TLS13-1-2-Ext1-2021-06" }} 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" }} + {{- else if eq .ssl_policy "AWS-TLS13-1-2-Ext2-2021-06" }} + 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-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-TLS13-1-1-2021-06" }} 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" }} + {{- else if eq .ssl_policy "AWS-TLS13-1-0-2021-06" }} 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-FS-1-2-Res-2020-10" }} + ssl_protocols TLSv1.2; + ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384'; + ssl_prefer_server_ciphers on; + {{- else if eq .ssl_policy "AWS-FS-1-2-Res-2019-08" }} + 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'; + ssl_prefer_server_ciphers on; + {{- else if eq .ssl_policy "AWS-FS-1-2-2019-08" }} + 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-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'; + ssl_prefer_server_ciphers on; + {{- else if eq .ssl_policy "AWS-FS-1-1-2019-08" }} + 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'; + ssl_prefer_server_ciphers on; + {{- else if eq .ssl_policy "AWS-FS-2018-06" }} + 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'; + ssl_prefer_server_ciphers on; + {{- else if eq .ssl_policy "AWS-TLS-1-2-Ext-2018-06" }} + 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-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-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'; + ssl_prefer_server_ciphers on; + {{- 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'; + ssl_prefer_server_ciphers on; + {{- 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'; + ssl_prefer_server_ciphers on; {{- else if eq .ssl_policy "AWS-2015-05" }} - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + 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'; ssl_prefer_server_ciphers on; {{- else if eq .ssl_policy "AWS-2015-03" }} - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + 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'; ssl_prefer_server_ciphers on; {{- else if eq .ssl_policy "AWS-2015-02" }} - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + 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'; ssl_prefer_server_ciphers on; {{- end }} @@ -196,7 +249,7 @@ {{- if exists $override }} include {{ $override }}; {{- else }} - {{- $keepalive := first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.keepalive")) }} + {{- $keepalive := coalesce (first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.keepalive"))) "disabled" }} location {{ .Path }} { {{- if eq .NetworkTag "internal" }} # Only allow traffic from internal clients @@ -210,17 +263,22 @@ root {{ trim .VhostRoot }}; include fastcgi_params; fastcgi_pass {{ trim .Upstream }}; - {{- if $keepalive }} + {{- if ne $keepalive "disabled" }} fastcgi_keep_conn on; {{- end }} {{- else if eq .Proto "grpc" }} grpc_pass {{ trim .Proto }}://{{ trim .Upstream }}; + {{- else if eq .Proto "grpcs" }} + grpc_pass {{ trim .Proto }}://{{ trim .Upstream }}; {{- else }} proxy_pass {{ trim .Proto }}://{{ trim .Upstream }}{{ trim .Dest }}; - set $upstream_keepalive {{ if $keepalive }}true{{ else }}false{{ end }}; + set $upstream_keepalive {{ if ne $keepalive "disabled" }}true{{ else }}false{{ end }}; {{- end }} - {{- if (exists (printf "/etc/nginx/htpasswd/%s" .Host)) }} + {{- if (exists (printf "/etc/nginx/htpasswd/%s_%s" .Host (sha1 .Path) )) }} + 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_user_file {{ (printf "/etc/nginx/htpasswd/%s" .Host) }}; {{- end }} @@ -238,7 +296,7 @@ {{- define "upstream" }} upstream {{ .Upstream }} { - {{- $server_found := false }} + {{- $servers := 0 }} {{- $loadbalance := first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.loadbalance")) }} {{- if $loadbalance }} # From the container's loadbalance label: @@ -253,18 +311,22 @@ upstream {{ .Upstream }} { {{- template "container_port" $args }} {{- $port := $args.port }} {{- if $ip }} - {{- $server_found = true }} + {{- $servers = add1 $servers }} server {{ $ip }}:{{ $port }}; {{- end }} {{- end }} {{- /* nginx-proxy/nginx-proxy#1105 */}} - {{- if not $server_found }} + {{- if lt $servers 1 }} # Fallback entry server 127.0.0.1 down; {{- end }} - {{- $keepalive := first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.keepalive")) }} - {{- if $keepalive }} + {{- $keepalive := coalesce (first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.keepalive"))) "disabled" }} + {{- if and (ne $keepalive "disabled") (gt $servers 0) }} + {{- if eq $keepalive "auto" }} + keepalive {{ mul $servers 2 }}; + {{- else }} keepalive {{ $keepalive }}; + {{- end }} {{- end }} } {{- end }} @@ -288,6 +350,13 @@ map $http_x_forwarded_port $proxy_x_forwarded_port { '' $server_port; } +# Include the port in the Host header sent to the container if it is non-standard +map $server_port $host_port { + default :$server_port; + 80 ''; + 443 ''; +} + # If the request from the downstream client has an "Upgrade:" header (set to any # non-empty value), pass "Connection: upgrade" to the upstream (backend) server. # Otherwise, the value for the "Connection" header depends on whether the user @@ -333,7 +402,24 @@ map $proxy_x_forwarded_proto $proxy_x_forwarded_ssl { gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; -log_format vhost '{{ or $globals.Env.LOG_FORMAT "$host $remote_addr - $remote_user [$time_local] \"$request\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\" \"$upstream_addr\"" }}'; + +{{- /* See https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format for details and variables + * LOG_FORMAT_ESCAPE sets the escape part of the log format + * LOG_FORMAT sets the log format + */}} +{{- $logEscape := printf "escape=%s" (or $globals.Env.LOG_FORMAT_ESCAPE "default") }} +{{- $logFormat := or $globals.Env.LOG_FORMAT `$host $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$upstream_addr"` }} + +{{- if parseBool (or $globals.Env.LOG_JSON "false") }} + {{- /* LOG_JSON is a shorthand + * that sets logging defaults to JSON format + */}} +# JSON Logging enabled (via LOG_JSON env variable) + {{- $logEscape = printf "escape=%s" (or $globals.Env.LOG_FORMAT_ESCAPE "json") }} + {{- $logFormat = or $globals.Env.LOG_FORMAT `{"time_local":"$time_iso8601","client_ip":"$http_x_forwarded_for","remote_addr":"$remote_addr","request":"$request","status":"$status","body_bytes_sent":"$body_bytes_sent","request_time":"$request_time","upstream_response_time":"$upstream_response_time","upstream_addr":"$upstream_addr","http_referrer":"$http_referer","http_user_agent":"$http_user_agent","request_id":"$request_id"}` }} +{{- end }} + +log_format vhost {{ $logEscape }} '{{ or $globals.Env.LOG_FORMAT $logFormat }}'; access_log off; @@ -349,8 +435,7 @@ include /etc/nginx/proxy.conf; {{- else }} # HTTP 1.1 support proxy_http_version 1.1; -proxy_buffering off; -proxy_set_header Host $host; +proxy_set_header Host $host$host_port; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $proxy_connection; proxy_set_header X-Real-IP $remote_addr; diff --git a/test/README.md b/test/README.md index 99d16dbc9..07a29d28b 100644 --- a/test/README.md +++ b/test/README.md @@ -4,12 +4,10 @@ Nginx proxy test suite Install requirements -------------------- -You need [python 3.9](https://www.python.org/) and [pip](https://pip.pypa.io/en/stable/installing/) installed. Then run the commands: +You need [Docker Compose v2](https://docs.docker.com/compose/install/linux/), [python 3.9](https://www.python.org/) and [pip](https://pip.pypa.io/en/stable/installation/) installed. Then run the commands: pip install -r requirements/python-requirements.txt - - Prepare the nginx-proxy test image ---------------------------------- @@ -28,12 +26,25 @@ need more verbosity ? pytest -s +Note: By default this test suite relies on Docker Compose v2 with the command `docker compose`. It still supports Docker Compose v1 via the `DOCKER_COMPOSE` environment variable: + + DOCKER_COMPOSE=docker-compose pytest Run one single test module -------------------------- pytest test_nominal.py +Run the test suite from a Docker container +------------------------------------------ + +If you cannot (or don't want to) install pytest and its requirements on your computer. You can use the nginx-proxy-tester docker image to run the test suite from a Docker container. + + make test-debian + +or if you want to test the alpine flavor: + + make test-alpine Write a test module ------------------- @@ -48,11 +59,11 @@ This test suite uses [pytest](http://doc.pytest.org/en/latest/). The [conftest.p When using the `docker_compose` fixture in a test, pytest will try to find a yml file named after your test module filename. For instance, if your test module is `test_example.py`, then the `docker_compose` fixture will try to load a `test_example.yml` [docker compose file](https://docs.docker.com/compose/compose-file/). -Once the docker compose file found, the fixture will remove all containers, run `docker-compose up`, and finally your test will be executed. +Once the docker compose file found, the fixture will remove all containers, run `docker compose up`, and finally your test will be executed. -The fixture will run the _docker-compose_ command with the `-f` option to load the given compose file. So you can test your docker compose file syntax by running it yourself with: +The fixture will run the _docker compose_ command with the `-f` option to load the given compose file. So you can test your docker compose file syntax by running it yourself with: - docker-compose -f test_example.yml up -d + docker compose -f test_example.yml up -d In the case you are running pytest from within a docker container, the `docker_compose` fixture will make sure the container running pytest is attached to all docker networks. That way, your test will be able to reach any of them. diff --git a/test/conftest.py b/test/conftest.py index f73b7c0a2..7fa269a61 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -26,6 +26,7 @@ PYTEST_RUNNING_IN_CONTAINER = os.environ.get('PYTEST_RUNNING_IN_CONTAINER') == "1" FORCE_CONTAINER_IPV6 = False # ugly global state to consider containers' IPv6 address instead of IPv4 +DOCKER_COMPOSE = os.environ.get('DOCKER_COMPOSE', 'docker compose') docker_client = docker.from_env() @@ -301,19 +302,19 @@ def get_nginx_conf_from_container(container): def docker_compose_up(compose_file='docker-compose.yml'): - logging.info(f'docker-compose -f {compose_file} up -d') + logging.info(f'{DOCKER_COMPOSE} -f {compose_file} up -d') try: - subprocess.check_output(shlex.split(f'docker-compose -f {compose_file} up -d'), stderr=subprocess.STDOUT) + subprocess.check_output(shlex.split(f'{DOCKER_COMPOSE} -f {compose_file} up -d'), stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: - pytest.fail(f"Error while runninng 'docker-compose -f {compose_file} up -d':\n{e.output}", pytrace=False) + pytest.fail(f"Error while runninng '{DOCKER_COMPOSE} -f {compose_file} up -d':\n{e.output}", pytrace=False) def docker_compose_down(compose_file='docker-compose.yml'): - logging.info(f'docker-compose -f {compose_file} down -v') + logging.info(f'{DOCKER_COMPOSE} -f {compose_file} down -v') try: - subprocess.check_output(shlex.split(f'docker-compose -f {compose_file} down -v'), stderr=subprocess.STDOUT) + subprocess.check_output(shlex.split(f'{DOCKER_COMPOSE} -f {compose_file} down -v'), stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: - pytest.fail(f"Error while runninng 'docker-compose -f {compose_file} down -v':\n{e.output}", pytrace=False) + pytest.fail(f"Error while runninng '{DOCKER_COMPOSE} -f {compose_file} down -v':\n{e.output}", pytrace=False) def wait_for_nginxproxy_to_be_ready(): @@ -333,7 +334,7 @@ def wait_for_nginxproxy_to_be_ready(): @pytest.fixture def docker_compose_file(request): - """Fixture naming the docker-compose file to consider. + """Fixture naming the docker compose file to consider. If a YAML file exists with the same name as the test module (with the `.py` extension replaced with `.yml` or `.yaml`), use that. Otherwise, use `docker-compose.yml` in the same directory @@ -354,7 +355,7 @@ def docker_compose_file(request): docker_compose_file = default_file if not os.path.isfile(docker_compose_file): - logging.error("Could not find any docker-compose file named either '{0}.yml', '{0}.yaml' or 'docker-compose.yml'".format(request.module.__name__)) + logging.error("Could not find any docker compose file named either '{0}.yml', '{0}.yaml' or 'docker-compose.yml'".format(request.module.__name__)) logging.debug(f"using docker compose file {docker_compose_file}") return docker_compose_file diff --git a/test/pytest.ini b/test/pytest.ini index 9ca76672c..10ef47813 100644 --- a/test/pytest.ini +++ b/test/pytest.ini @@ -1,5 +1,5 @@ [pytest] # disable the creation of the `.cache` folders -addopts = -p no:cacheprovider --ignore=requirements --ignore=certs -r s -v +addopts = -p no:cacheprovider --ignore=requirements --ignore=certs --color=yes -v markers = - incremental: mark a test as incremental. \ No newline at end of file + incremental: mark a test as incremental. diff --git a/test/pytest.sh b/test/pytest.sh index 19a81881f..9cbe75017 100755 --- a/test/pytest.sh +++ b/test/pytest.sh @@ -19,8 +19,8 @@ docker build --pull -t nginx-proxy-tester \ "${TESTDIR}/requirements" \ || exit 1 -# run the nginx-proxy-tester container setting the correct value for the working dir in order for -# docker-compose to work properly when run from within that container. +# run the nginx-proxy-tester container setting the correct value for the working dir +# in order for docker compose to work properly when run from within that container. exec docker run --rm -it --name "nginx-proxy-pytest" \ --volume "/var/run/docker.sock:/var/run/docker.sock" \ --volume "${DIR}:${DIR}" \ diff --git a/test/requirements/Dockerfile-nginx-proxy-tester b/test/requirements/Dockerfile-nginx-proxy-tester index 36984fe15..1af4a16b2 100644 --- a/test/requirements/Dockerfile-nginx-proxy-tester +++ b/test/requirements/Dockerfile-nginx-proxy-tester @@ -5,5 +5,32 @@ ENV PYTEST_RUNNING_IN_CONTAINER=1 COPY python-requirements.txt /requirements.txt RUN pip install -r /requirements.txt +# Add Docker's official GPG key +RUN apt-get update \ + && apt-get install -y \ + ca-certificates \ + curl \ + gnupg \ + && install -m 0755 -d /etc/apt/keyrings \ + && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \ + && chmod a+r /etc/apt/keyrings/docker.gpg + +# Add the Docker repository to Apt sources +RUN echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ + tee /etc/apt/sources.list.d/docker.list > /dev/null + +# Install docker-ce-cli and docker-compose-plugin requirements for Pytest docker_compose fixture +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + docker-ce-cli \ + docker-compose-plugin \ + && apt-get clean \ + && rm -r /var/lib/apt/lists/* + +# Check if docker compose is available +RUN docker compose version + WORKDIR /test ENTRYPOINT ["pytest"] diff --git a/test/requirements/python-requirements.txt b/test/requirements/python-requirements.txt index 15182fd2b..d5033424a 100644 --- a/test/requirements/python-requirements.txt +++ b/test/requirements/python-requirements.txt @@ -1,5 +1,4 @@ backoff==2.2.1 -docker-compose==1.29.2 -docker==6.1.3 -pytest==7.4.3 +docker==7.0.0 +pytest==7.4.4 requests==2.31.0 diff --git a/test/stress_tests/test_deleted_cert/docker-compose.yml b/test/stress_tests/test_deleted_cert/docker-compose.yml index a42abacad..a362e443d 100644 --- a/test/stress_tests/test_deleted_cert/docker-compose.yml +++ b/test/stress_tests/test_deleted_cert/docker-compose.yml @@ -1,15 +1,17 @@ -web: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: web.nginx-proxy +version: "2" +services: + web: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: web.nginx-proxy -reverseproxy: - image: nginxproxy/nginx-proxy:test - container_name: reverseproxy - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./tmp_certs:/etc/nginx/certs:ro + reverseproxy: + image: nginxproxy/nginx-proxy:test + container_name: reverseproxy + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./tmp_certs:/etc/nginx/certs:ro diff --git a/test/stress_tests/test_unreachable_network/docker-compose.yml b/test/stress_tests/test_unreachable_network/docker-compose.yml index 9666d2970..f90a441e7 100644 --- a/test/stress_tests/test_unreachable_network/docker-compose.yml +++ b/test/stress_tests/test_unreachable_network/docker-compose.yml @@ -32,4 +32,3 @@ services: environment: WEB_PORTS: 82 VIRTUAL_HOST: webB.nginx-proxy - diff --git a/test/test_DOCKER_HOST_unix_socket.yml b/test/test_DOCKER_HOST_unix_socket.yml index 15638725d..caeaa2a55 100644 --- a/test/test_DOCKER_HOST_unix_socket.yml +++ b/test/test_DOCKER_HOST_unix_socket.yml @@ -1,23 +1,25 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: web1.nginx-proxy.tld +version: "2" -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: 82 - VIRTUAL_HOST: web2.nginx-proxy.tld +services: + 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 -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/f00.sock:ro - environment: - DOCKER_HOST: unix:///f00.sock + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/f00.sock:ro + environment: + DOCKER_HOST: unix:///f00.sock diff --git a/test/test_composev2.yml b/test/test_composev2.yml index dff434c63..3c36022b5 100644 --- a/test/test_composev2.yml +++ b/test/test_composev2.yml @@ -1,4 +1,5 @@ -version: '2' +version: "2" + services: nginx-proxy: image: nginxproxy/nginx-proxy:test diff --git a/test/test_custom/test_defaults-location.yml b/test/test_custom/test_defaults-location.yml index 195d232fc..9a3ab44f3 100644 --- a/test/test_custom/test_defaults-location.yml +++ b/test/test_custom/test_defaults-location.yml @@ -1,30 +1,33 @@ -nginx-proxy: - 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_bar.conf:/etc/nginx/vhost.d/web3.nginx-proxy.example_location:ro +version: "2" -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: web1.nginx-proxy.example +services: + nginx-proxy: + 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_bar.conf:/etc/nginx/vhost.d/web3.nginx-proxy.example_location:ro -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: 82 - VIRTUAL_HOST: web2.nginx-proxy.example + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: web1.nginx-proxy.example -web3: - image: web - expose: - - "83" - environment: - WEB_PORTS: 83 - VIRTUAL_HOST: web3.nginx-proxy.example + web2: + image: web + expose: + - "82" + environment: + WEB_PORTS: 82 + VIRTUAL_HOST: web2.nginx-proxy.example + + web3: + image: web + expose: + - "83" + environment: + WEB_PORTS: 83 + VIRTUAL_HOST: web3.nginx-proxy.example diff --git a/test/test_custom/test_defaults.yml b/test/test_custom/test_defaults.yml index 2983e25f0..d6a959a48 100644 --- a/test/test_custom/test_defaults.yml +++ b/test/test_custom/test_defaults.yml @@ -1,4 +1,5 @@ -version: '2' +version: "2" + services: nginx-proxy: image: nginxproxy/nginx-proxy:test diff --git a/test/test_custom/test_location-per-vhost.yml b/test/test_custom/test_location-per-vhost.yml index 6bf69f9d0..52943086e 100644 --- a/test/test_custom/test_location-per-vhost.yml +++ b/test/test_custom/test_location-per-vhost.yml @@ -1,4 +1,5 @@ -version: '2' +version: "2" + services: nginx-proxy: image: nginxproxy/nginx-proxy:test diff --git a/test/test_custom/test_per-vhost.yml b/test/test_custom/test_per-vhost.yml index e7e50b49b..63d33b2b1 100644 --- a/test/test_custom/test_per-vhost.yml +++ b/test/test_custom/test_per-vhost.yml @@ -1,4 +1,5 @@ -version: '2' +version: "2" + services: nginx-proxy: image: nginxproxy/nginx-proxy:test diff --git a/test/test_custom/test_proxy-wide.yml b/test/test_custom/test_proxy-wide.yml index 0c4a2a0f5..1322bcde7 100644 --- a/test/test_custom/test_proxy-wide.yml +++ b/test/test_custom/test_proxy-wide.yml @@ -1,4 +1,5 @@ -version: '2' +version: "2" + services: nginx-proxy: image: nginxproxy/nginx-proxy:test diff --git a/test/test_default-host.yml b/test/test_default-host.yml index 2cb94d97c..405bb081a 100644 --- a/test/test_default-host.yml +++ b/test/test_default-host.yml @@ -1,17 +1,19 @@ -# GIVEN a webserver with VIRTUAL_HOST set to web1.tld -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: web1.tld +version: "2" +services: + # GIVEN a webserver with VIRTUAL_HOST set to web1.tld + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: web1.tld -# WHEN nginx-proxy runs with DEFAULT_HOST set to web1.tld -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - environment: - DEFAULT_HOST: web1.tld + # WHEN nginx-proxy runs with DEFAULT_HOST set to web1.tld + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + environment: + DEFAULT_HOST: web1.tld diff --git a/test/test_default-root-none.yml b/test/test_default-root-none.yml index 309d2ab3e..f0172e8f5 100644 --- a/test/test_default-root-none.yml +++ b/test/test_default-root-none.yml @@ -1,3 +1,5 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test @@ -5,6 +7,7 @@ services: - /var/run/docker.sock:/tmp/docker.sock:ro environment: DEFAULT_ROOT: none + web: image: web expose: diff --git a/test/test_dockergen/test_dockergen_v2.yml b/test/test_dockergen/test_dockergen_v2.yml index 36ee1c169..f98992f20 100644 --- a/test/test_dockergen/test_dockergen_v2.yml +++ b/test/test_dockergen/test_dockergen_v2.yml @@ -1,4 +1,4 @@ -version: '2' +version: "2" services: nginx: diff --git a/test/test_dockergen/test_dockergen_v3.yml b/test/test_dockergen/test_dockergen_v3.yml index 8b0411caa..7e4aef8c1 100644 --- a/test/test_dockergen/test_dockergen_v3.yml +++ b/test/test_dockergen/test_dockergen_v3.yml @@ -1,4 +1,5 @@ -version: '3' +version: "3" + services: nginx: image: nginx diff --git a/test/test_events.py b/test/test_events.py index b5da3dd4a..9b99e93b8 100644 --- a/test/test_events.py +++ b/test/test_events.py @@ -22,6 +22,7 @@ def web1(docker_compose): }, ports={"81/tcp": None} ) + docker_compose.networks.get("test_default").connect(container) sleep(2) # give it some time to initialize and for docker-gen to detect it yield container try: @@ -46,6 +47,7 @@ def web2(docker_compose): }, ports={"82/tcp": None} ) + docker_compose.networks.get("test_default").connect(container) sleep(2) # give it some time to initialize and for docker-gen to detect it yield container try: diff --git a/test/test_events.yml b/test/test_events.yml index 260529e72..ac27e1d0c 100644 --- a/test/test_events.yml +++ b/test/test_events.yml @@ -1,4 +1,7 @@ -nginxproxy: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro +version: "2" + +services: + nginxproxy: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_fallback.data/custom-fallback.yml b/test/test_fallback.data/custom-fallback.yml index bc44b1188..a15044181 100644 --- a/test/test_fallback.data/custom-fallback.yml +++ b/test/test_fallback.data/custom-fallback.yml @@ -1,9 +1,12 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./custom-fallback.conf:/etc/nginx/conf.d/zzz-custom-fallback.conf:ro + http-only: image: web expose: diff --git a/test/test_fallback.data/nodefault.yml b/test/test_fallback.data/nodefault.yml index ecd43591a..6397a0bc6 100644 --- a/test/test_fallback.data/nodefault.yml +++ b/test/test_fallback.data/nodefault.yml @@ -1,9 +1,12 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./nodefault.certs:/etc/nginx/certs:ro + https-and-http: image: web expose: @@ -11,6 +14,7 @@ services: environment: WEB_PORTS: "81" VIRTUAL_HOST: https-and-http.nginx-proxy.test + https-only: image: web expose: @@ -19,6 +23,7 @@ services: WEB_PORTS: "82" VIRTUAL_HOST: https-only.nginx-proxy.test HTTPS_METHOD: nohttp + http-only: image: web expose: @@ -27,6 +32,7 @@ services: WEB_PORTS: "83" VIRTUAL_HOST: http-only.nginx-proxy.test HTTPS_METHOD: nohttps + missing-cert: image: web expose: diff --git a/test/test_fallback.data/nohttp-on-app.yml b/test/test_fallback.data/nohttp-on-app.yml index d81c9ca64..b6ca82a19 100644 --- a/test/test_fallback.data/nohttp-on-app.yml +++ b/test/test_fallback.data/nohttp-on-app.yml @@ -1,3 +1,5 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test @@ -6,6 +8,7 @@ services: - ./withdefault.certs:/etc/nginx/certs:ro environment: HTTPS_METHOD: redirect + https-only: image: web expose: diff --git a/test/test_fallback.data/nohttp-with-missing-cert.yml b/test/test_fallback.data/nohttp-with-missing-cert.yml index 3593a32c1..70ece7b77 100644 --- a/test/test_fallback.data/nohttp-with-missing-cert.yml +++ b/test/test_fallback.data/nohttp-with-missing-cert.yml @@ -1,3 +1,5 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test @@ -6,6 +8,7 @@ services: - ./withdefault.certs:/etc/nginx/certs:ro environment: HTTPS_METHOD: nohttp + https-only: image: web expose: @@ -13,6 +16,7 @@ services: environment: WEB_PORTS: "82" VIRTUAL_HOST: https-only.nginx-proxy.test + missing-cert: image: web expose: diff --git a/test/test_fallback.data/nohttp.yml b/test/test_fallback.data/nohttp.yml index 3ed0c0e96..9d47d51a3 100644 --- a/test/test_fallback.data/nohttp.yml +++ b/test/test_fallback.data/nohttp.yml @@ -1,3 +1,5 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test @@ -6,6 +8,7 @@ services: - ./withdefault.certs:/etc/nginx/certs:ro environment: HTTPS_METHOD: nohttp + https-only: image: web expose: diff --git a/test/test_fallback.data/nohttps-on-app.yml b/test/test_fallback.data/nohttps-on-app.yml index 690d6562e..966154cf9 100644 --- a/test/test_fallback.data/nohttps-on-app.yml +++ b/test/test_fallback.data/nohttps-on-app.yml @@ -1,3 +1,5 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test @@ -5,6 +7,7 @@ services: - /var/run/docker.sock:/tmp/docker.sock:ro environment: HTTPS_METHOD: redirect + http-only: image: web expose: diff --git a/test/test_fallback.data/nohttps.yml b/test/test_fallback.data/nohttps.yml index f07ddf946..c73349247 100644 --- a/test/test_fallback.data/nohttps.yml +++ b/test/test_fallback.data/nohttps.yml @@ -1,3 +1,5 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test @@ -5,6 +7,7 @@ services: - /var/run/docker.sock:/tmp/docker.sock:ro environment: HTTPS_METHOD: nohttps + http-only: image: web expose: diff --git a/test/test_fallback.data/withdefault.yml b/test/test_fallback.data/withdefault.yml index 00f7ee7a0..46ab1267a 100644 --- a/test/test_fallback.data/withdefault.yml +++ b/test/test_fallback.data/withdefault.yml @@ -1,9 +1,12 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./withdefault.certs:/etc/nginx/certs:ro + https-and-http: image: web expose: @@ -11,6 +14,7 @@ services: environment: WEB_PORTS: "81" VIRTUAL_HOST: https-and-http.nginx-proxy.test + https-only: image: web expose: @@ -19,6 +23,7 @@ services: WEB_PORTS: "82" VIRTUAL_HOST: https-only.nginx-proxy.test HTTPS_METHOD: nohttp + http-only: image: web expose: @@ -27,6 +32,7 @@ services: WEB_PORTS: "83" VIRTUAL_HOST: http-only.nginx-proxy.test HTTPS_METHOD: nohttps + missing-cert: image: web expose: diff --git a/test/test_headers/test_http.yml b/test/test_headers/test_http.yml index 93795dc60..fa5984028 100644 --- a/test/test_headers/test_http.yml +++ b/test/test_headers/test_http.yml @@ -1,22 +1,24 @@ -web: - image: web - expose: - - "80" - environment: - WEB_PORTS: 80 - VIRTUAL_HOST: web.nginx-proxy.tld +version: "2" -web-server-tokens-off: - image: web - expose: - - "80" - environment: - WEB_PORTS: 80 - VIRTUAL_HOST: web-server-tokens-off.nginx-proxy.tld - SERVER_TOKENS: "off" +services: + web: + image: web + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: web.nginx-proxy.tld + web-server-tokens-off: + image: web + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: web-server-tokens-off.nginx-proxy.tld + SERVER_TOKENS: "off" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_headers/test_https.yml b/test/test_headers/test_https.yml index 49dcec456..0300d4386 100644 --- a/test/test_headers/test_https.yml +++ b/test/test_headers/test_https.yml @@ -1,28 +1,30 @@ -web: - image: web - expose: - - "80" - environment: - WEB_PORTS: 80 - VIRTUAL_HOST: web.nginx-proxy.tld +version: "2" -web-server-tokens-off: - image: web - expose: - - "80" - environment: - WEB_PORTS: 80 - VIRTUAL_HOST: web-server-tokens-off.nginx-proxy.tld - SERVER_TOKENS: "off" +services: + web: + image: web + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: web.nginx-proxy.tld + web-server-tokens-off: + image: web + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: web-server-tokens-off.nginx-proxy.tld + SERVER_TOKENS: "off" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/default.crt:ro - - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/default.key:ro - - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro - - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro - - ./certs/web-server-tokens-off.nginx-proxy.tld.crt:/etc/nginx/certs/web-server-tokens-off.nginx-proxy.tld.crt:ro - - ./certs/web-server-tokens-off.nginx-proxy.tld.key:/etc/nginx/certs/web-server-tokens-off.nginx-proxy.tld.key:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/default.crt:ro + - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/default.key:ro + - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro + - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro + - ./certs/web-server-tokens-off.nginx-proxy.tld.crt:/etc/nginx/certs/web-server-tokens-off.nginx-proxy.tld.crt:ro + - ./certs/web-server-tokens-off.nginx-proxy.tld.key:/etc/nginx/certs/web-server-tokens-off.nginx-proxy.tld.key:ro diff --git a/test/test_http2/test_http2_global_disabled.yml b/test/test_http2/test_http2_global_disabled.yml index 5dffa1972..8fd3cde63 100644 --- a/test/test_http2/test_http2_global_disabled.yml +++ b/test/test_http2/test_http2_global_disabled.yml @@ -1,3 +1,5 @@ +version: "2" + services: http2-global-disabled: image: web diff --git a/test/test_http3/test_http3_global_disabled.yml b/test/test_http3/test_http3_global_disabled.yml index 66530a4bc..482a5eaea 100644 --- a/test/test_http3/test_http3_global_disabled.yml +++ b/test/test_http3/test_http3_global_disabled.yml @@ -1,3 +1,5 @@ +version: "2" + services: http3-global-disabled: image: web @@ -12,4 +14,4 @@ services: volumes: - /var/run/docker.sock:/tmp/docker.sock:ro #environment: - #ENABLE_HTTP3: "false" #Disabled by default + #ENABLE_HTTP3: "false" #Disabled by default diff --git a/test/test_http3/test_http3_global_enabled.yml b/test/test_http3/test_http3_global_enabled.yml index 082546929..1cd40e0a0 100644 --- a/test/test_http3/test_http3_global_enabled.yml +++ b/test/test_http3/test_http3_global_enabled.yml @@ -1,3 +1,5 @@ +version: "2" + services: http3-global-enabled: image: web diff --git a/test/test_http3/test_http3_vhost.yml b/test/test_http3/test_http3_vhost.yml index 1d5cdf26e..345bb30e5 100644 --- a/test/test_http3/test_http3_vhost.yml +++ b/test/test_http3/test_http3_vhost.yml @@ -1,3 +1,5 @@ +version: "2" + services: http3-vhost-enabled: image: web diff --git a/test/test_http_port.yml b/test/test_http_port.yml index 72f142fae..a346982c3 100644 --- a/test/test_http_port.yml +++ b/test/test_http_port.yml @@ -1,14 +1,17 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "*.nginx-proxy.tld" +version: "2" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - environment: - HTTP_PORT: 8080 \ No newline at end of file +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "*.nginx-proxy.tld" + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + environment: + HTTP_PORT: 8080 diff --git a/test/test_internal/test_internal-per-vhost.yml b/test/test_internal/test_internal-per-vhost.yml index 3763723a0..cc67c2240 100644 --- a/test/test_internal/test_internal-per-vhost.yml +++ b/test/test_internal/test_internal-per-vhost.yml @@ -1,23 +1,25 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: web1.nginx-proxy.example - NETWORK_ACCESS: internal +version: "2" -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: 82 - VIRTUAL_HOST: web2.nginx-proxy.example +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: web1.nginx-proxy.example + NETWORK_ACCESS: internal -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./network_internal.conf:/etc/nginx/network_internal.conf:ro + web2: + image: web + expose: + - "82" + environment: + WEB_PORTS: 82 + VIRTUAL_HOST: web2.nginx-proxy.example + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./network_internal.conf:/etc/nginx/network_internal.conf:ro diff --git a/test/test_internal/test_internal-per-vpath.yml b/test/test_internal/test_internal-per-vpath.yml index 3cc4a05af..35e92f051 100644 --- a/test/test_internal/test_internal-per-vpath.yml +++ b/test/test_internal/test_internal-per-vpath.yml @@ -1,27 +1,29 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: nginx-proxy.example - VIRTUAL_PATH: /web1/ - VIRTUAL_DEST: / - NETWORK_ACCESS: internal +version: "2" -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: 82 - VIRTUAL_HOST: nginx-proxy.example - VIRTUAL_PATH: /web2/ - VIRTUAL_DEST: / +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: nginx-proxy.example + VIRTUAL_PATH: /web1/ + VIRTUAL_DEST: / + NETWORK_ACCESS: internal -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./network_internal.conf:/etc/nginx/network_internal.conf:ro + web2: + image: web + expose: + - "82" + environment: + WEB_PORTS: 82 + VIRTUAL_HOST: nginx-proxy.example + VIRTUAL_PATH: /web2/ + VIRTUAL_DEST: / + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./network_internal.conf:/etc/nginx/network_internal.conf:ro diff --git a/test/test_ipv6.yml b/test/test_ipv6.yml index 4dce515d3..d5fec9b40 100644 --- a/test/test_ipv6.yml +++ b/test/test_ipv6.yml @@ -1,4 +1,4 @@ -version: '2' +version: "2" networks: net1: @@ -28,7 +28,6 @@ services: networks: - net1 - sut: image: nginxproxy/nginx-proxy:test volumes: diff --git a/test/test_keepalive.py b/test/test_keepalive.py index b5b83539c..c007cf1cb 100644 --- a/test/test_keepalive.py +++ b/test/test_keepalive.py @@ -20,10 +20,21 @@ def test_keepalive_disabled_other_headers_ok(docker_compose, nginxproxy): assert re.search(fr'(?m)^(?i:X-Real-IP): ', r.text) def test_keepalive_enabled(docker_compose, nginxproxy): + conf = nginxproxy.get_conf().decode('ASCII') + assert re.search(r"keepalive 64\;", conf) + r = nginxproxy.get("http://keepalive-enabled.nginx-proxy.test/headers") assert r.status_code == 200 assert not re.search(fr'(?m)^(?i:Connection):', r.text) +def test_keepalive_auto_enabled(docker_compose, nginxproxy): + conf = nginxproxy.get_conf().decode('ASCII') + assert re.search(r"keepalive 8\;", conf) + + r = nginxproxy.get("http://keepalive-auto.nginx-proxy.test/headers") + assert r.status_code == 200 + assert not re.search(fr'(?m)^(?i:Connection):', r.text) + def test_keepalive_enabled_other_headers_ok(docker_compose, nginxproxy): """See the docstring for the disabled case above.""" r = nginxproxy.get("http://keepalive-enabled.nginx-proxy.test/headers") diff --git a/test/test_keepalive.yml b/test/test_keepalive.yml index 541b69dec..6da66f0b3 100644 --- a/test/test_keepalive.yml +++ b/test/test_keepalive.yml @@ -1,25 +1,40 @@ -keepalive-disabled: - image: web - expose: - - "80" - environment: - WEB_PORTS: 80 - VIRTUAL_HOST: keepalive-disabled.nginx-proxy.test +version: "2" -keepalive-enabled: - image: web - expose: - - "80" - environment: - WEB_PORTS: 80 - VIRTUAL_HOST: keepalive-enabled.nginx-proxy.test - labels: - com.github.nginx-proxy.nginx-proxy.keepalive: "64" +services: + keepalive-disabled: + image: web + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: keepalive-disabled.nginx-proxy.test + keepalive-enabled: + image: web + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: keepalive-enabled.nginx-proxy.test + labels: + com.github.nginx-proxy.nginx-proxy.keepalive: "64" + + keepalive-auto: + image: web + deploy: + mode: replicated + replicas: 4 + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: keepalive-auto.nginx-proxy.test + labels: + com.github.nginx-proxy.nginx-proxy.keepalive: "auto" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - environment: - HTTPS_METHOD: nohttps + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + environment: + HTTPS_METHOD: nohttps diff --git a/test/test_loadbalancing.yml b/test/test_loadbalancing.yml index b8f42eb67..72155fb11 100644 --- a/test/test_loadbalancing.yml +++ b/test/test_loadbalancing.yml @@ -1,3 +1,5 @@ +version: "2" + services: loadbalance-hash: image: web diff --git a/test/test_location-override.yml b/test/test_location-override.yml index f36b206a7..9ba4eb82b 100644 --- a/test/test_location-override.yml +++ b/test/test_location-override.yml @@ -1,3 +1,5 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test diff --git a/test/test_log_format.yml b/test/test_log_format.yml index ef3bbf624..2a32e3d00 100644 --- a/test/test_log_format.yml +++ b/test/test_log_format.yml @@ -1,15 +1,18 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: nginx-proxy.test +version: "2" -sut: - container_name: sut - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - environment: - LOG_FORMAT: "$$remote_addr - $$remote_user [$$time_local] \"$$request\" $$status $$body_bytes_sent \"$$http_referer\" \"$$http_user_agent\" request_time=$$request_time $$upstream_response_time" +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: nginx-proxy.test + + sut: + container_name: sut + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + environment: + LOG_FORMAT: '$$remote_addr - $$remote_user [$$time_local] "$$request" $$status $$body_bytes_sent "$$http_referer" "$$http_user_agent" request_time=$$request_time $$upstream_response_time' diff --git a/test/test_log_json.py b/test/test_log_json.py new file mode 100644 index 000000000..1a04b228c --- /dev/null +++ b/test/test_log_json.py @@ -0,0 +1,14 @@ +import pytest + +def test_log_json(docker_compose, nginxproxy): + log_conf = [line for line in nginxproxy.get_conf().decode('ASCII').splitlines() if "log_format vhost escape=" in line] + assert "{\"time_local\":\"$time_iso8601\"," in log_conf[0] + + r = nginxproxy.get("http://nginx-proxy.test/port") + assert r.status_code == 200 + assert r.text == "answer from port 81\n" + sut_container = docker_compose.containers.get("sut") + docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False) + docker_logs = docker_logs.decode("utf-8").splitlines() + docker_logs = [line for line in docker_logs if "{\"time_local\":" in line] + assert "GET /port" in docker_logs[0] diff --git a/test/test_log_json.yml b/test/test_log_json.yml new file mode 100644 index 000000000..2e6fefdba --- /dev/null +++ b/test/test_log_json.yml @@ -0,0 +1,18 @@ +version: "2" + +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: nginx-proxy.test + + sut: + container_name: sut + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + environment: + LOG_JSON: 1 diff --git a/test/test_log_json_format.py b/test/test_log_json_format.py new file mode 100644 index 000000000..2d158cb7c --- /dev/null +++ b/test/test_log_json_format.py @@ -0,0 +1,14 @@ +import pytest + +def test_log_json_format(docker_compose, nginxproxy): + log_conf = [line for line in nginxproxy.get_conf().decode('ASCII').splitlines() if "log_format vhost escape=" in line] + assert "{\"time_local\":\"$time_iso8601\"," in log_conf[0] + + r = nginxproxy.get("http://nginx-proxy.test/port") + assert r.status_code == 200 + assert r.text == "answer from port 81\n" + sut_container = docker_compose.containers.get("sut") + docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False) + docker_logs = docker_logs.decode("utf-8").splitlines() + docker_logs = [line for line in docker_logs if "{\"time_local\":" in line] + assert "GET /port" in docker_logs[0] diff --git a/test/test_log_json_format.yml b/test/test_log_json_format.yml new file mode 100644 index 000000000..5e01e924f --- /dev/null +++ b/test/test_log_json_format.yml @@ -0,0 +1,18 @@ +version: "2" + +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: nginx-proxy.test + + sut: + container_name: sut + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + environment: + LOG_FORMAT: '{"time_local":"$$time_iso8601","remote_addr":"$$remote_addr","request":"$$request","upstream_addr":"$$upstream_addr"}' diff --git a/test/test_multiple-hosts.yml b/test/test_multiple-hosts.yml index b72da83d7..832aac4cf 100644 --- a/test/test_multiple-hosts.yml +++ b/test/test_multiple-hosts.yml @@ -1,13 +1,15 @@ -web: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: webA.nginx-proxy.tld,webB.nginx-proxy.tld +version: "2" +services: + web: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: webA.nginx-proxy.tld,webB.nginx-proxy.tld -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_multiple-networks.yml b/test/test_multiple-networks.yml index 1247cb314..3e34b481e 100644 --- a/test/test_multiple-networks.yml +++ b/test/test_multiple-networks.yml @@ -1,4 +1,4 @@ -version: '2' +version: "2" networks: net1: {} diff --git a/test/test_multiple-ports/test_VIRTUAL_PORT-single-different-from-single-port.yml b/test/test_multiple-ports/test_VIRTUAL_PORT-single-different-from-single-port.yml index dff62128d..ba58d4ec1 100644 --- a/test/test_multiple-ports/test_VIRTUAL_PORT-single-different-from-single-port.yml +++ b/test/test_multiple-ports/test_VIRTUAL_PORT-single-different-from-single-port.yml @@ -1,14 +1,16 @@ -web: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "web.nginx-proxy.tld" - VIRTUAL_PORT: "90" +version: "2" +services: + web: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "web.nginx-proxy.tld" + VIRTUAL_PORT: "90" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_multiple-ports/test_VIRTUAL_PORT.yml b/test/test_multiple-ports/test_VIRTUAL_PORT.yml index 1a3ecaa4e..ab1af4664 100644 --- a/test/test_multiple-ports/test_VIRTUAL_PORT.yml +++ b/test/test_multiple-ports/test_VIRTUAL_PORT.yml @@ -1,14 +1,17 @@ -web: - image: web - expose: - - "80" - - "90" - environment: - WEB_PORTS: "80 90" - VIRTUAL_HOST: "web.nginx-proxy.tld" - VIRTUAL_PORT: 90 +version: "2" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro +services: + web: + image: web + expose: + - "80" + - "90" + environment: + WEB_PORTS: "80 90" + VIRTUAL_HOST: "web.nginx-proxy.tld" + VIRTUAL_PORT: 90 + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_multiple-ports/test_default-80.yml b/test/test_multiple-ports/test_default-80.yml index 10047dc51..0cfdd7e62 100644 --- a/test/test_multiple-ports/test_default-80.yml +++ b/test/test_multiple-ports/test_default-80.yml @@ -1,13 +1,16 @@ -web: - image: web - expose: - - "80" - - "81" - environment: - WEB_PORTS: "80 81" - VIRTUAL_HOST: "web.nginx-proxy.tld" +version: "2" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro +services: + web: + image: web + expose: + - "80" + - "81" + environment: + WEB_PORTS: "80 81" + VIRTUAL_HOST: "web.nginx-proxy.tld" + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_multiple-ports/test_single-port-not-80.yml b/test/test_multiple-ports/test_single-port-not-80.yml index 18b365507..eef4e0899 100644 --- a/test/test_multiple-ports/test_single-port-not-80.yml +++ b/test/test_multiple-ports/test_single-port-not-80.yml @@ -1,13 +1,15 @@ -web: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "web.nginx-proxy.tld" +version: "2" +services: + web: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "web.nginx-proxy.tld" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_nominal.yml b/test/test_nominal.yml index fe0203405..60678951b 100644 --- a/test/test_nominal.yml +++ b/test/test_nominal.yml @@ -1,4 +1,4 @@ -version: '2' +version: "2" networks: net1: @@ -28,7 +28,6 @@ services: networks: - net1 - sut: image: nginxproxy/nginx-proxy:test volumes: diff --git a/test/test_raw-ip-vhost.yml b/test/test_raw-ip-vhost.yml index 066dade1d..f034bdb87 100644 --- a/test/test_raw-ip-vhost.yml +++ b/test/test_raw-ip-vhost.yml @@ -1,4 +1,4 @@ -version: '2' +version: "2" networks: net1: @@ -6,7 +6,7 @@ networks: ipam: config: - subnet: 172.20.0.0/16 - - subnet: fd00::/80 + - subnet: fd00::/80 services: web1: diff --git a/test/test_server-down/test_load-balancing.yml b/test/test_server-down/test_load-balancing.yml index d420072b3..232259020 100644 --- a/test/test_server-down/test_load-balancing.yml +++ b/test/test_server-down/test_load-balancing.yml @@ -1,29 +1,32 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: web.nginx-proxy.tld +version: "2" -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: 83 - VIRTUAL_HOST: web.nginx-proxy.tld +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: web.nginx-proxy.tld -web3: - image: web - expose: - - "83" - environment: - WEB_PORTS: 83 - VIRTUAL_HOST: web.nginx-proxy.tld - net: "none" + web2: + image: web + expose: + - "82" + environment: + WEB_PORTS: 83 + VIRTUAL_HOST: web.nginx-proxy.tld -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro + web3: + image: web + expose: + - "83" + environment: + WEB_PORTS: 83 + VIRTUAL_HOST: web.nginx-proxy.tld + network_mode: "none" + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_server-down/test_no-server-down.yml b/test/test_server-down/test_no-server-down.yml index b3d46291f..cd7e5acf5 100644 --- a/test/test_server-down/test_no-server-down.yml +++ b/test/test_server-down/test_no-server-down.yml @@ -1,12 +1,15 @@ -web: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: web.nginx-proxy.tld +version: "2" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro +services: + web: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: web.nginx-proxy.tld + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_server-down/test_server-down.yml b/test/test_server-down/test_server-down.yml index 938d26a14..98fd30f28 100644 --- a/test/test_server-down/test_server-down.yml +++ b/test/test_server-down/test_server-down.yml @@ -1,13 +1,16 @@ -web: - image: web - expose: - - "81" - environment: - WEB_PORTS: 81 - VIRTUAL_HOST: web.nginx-proxy.tld - net: "none" +version: "2" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro +services: + web: + image: web + expose: + - "81" + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: web.nginx-proxy.tld + network_mode: "none" + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_ssl/test_dhparam.py b/test/test_ssl/test_dhparam.py index d4d64a34c..1cbc0ac9a 100644 --- a/test/test_ssl/test_dhparam.py +++ b/test/test_ssl/test_dhparam.py @@ -60,7 +60,8 @@ def versiontuple(v): @require_openssl("1.0.2") def negotiate_cipher(sut_container, additional_params='', grep='Cipher is'): - host = f"{sut_container.attrs['NetworkSettings']['IPAddress']}:443" + sut_container.reload() + host = f"{sut_container.attrs['NetworkSettings']['Networks']['test_ssl_default']['IPAddress']}:443" try: # Enforce TLS 1.2 as newer versions don't support custom dhparam or ciphersuite preference. @@ -77,7 +78,7 @@ def negotiate_cipher(sut_container, additional_params='', grep='Cipher is'): except subprocess.CalledProcessError as e: # Output a more helpful error, the original exception in this case isn't that helpful. # `from None` to ignore undesired output from exception chaining. - raise Exception("Failed to process CLI request:\n" + e.stderr) from None + raise Exception(f"Failed to process CLI request openssl s_client -connect {host} -tls1_2 {additional_params}:\n" + e.stderr) from None # The default `dh_bits` can vary due to configuration. diff --git a/test/test_ssl/test_dhparam.yml b/test/test_ssl/test_dhparam.yml index 505ac4cb6..456b1b3f8 100644 --- a/test/test_ssl/test_dhparam.yml +++ b/test/test_ssl/test_dhparam.yml @@ -1,73 +1,75 @@ -web5: - image: web - expose: - - "85" - environment: - WEB_PORTS: "85" - VIRTUAL_HOST: "web5.nginx-proxy.tld" +version: "2" -# Intended for testing with `dh-file` container. -# VIRTUAL_HOST is paired with site-specific DH param file. -# DEFAULT_HOST is required to avoid defaulting to web2, -# if not specifying FQDN (`-servername`) in openssl queries. -web2: - image: web - expose: - - "85" - environment: - WEB_PORTS: "85" - VIRTUAL_HOST: "web2.nginx-proxy.tld" +services: + web5: + image: web + expose: + - "85" + environment: + WEB_PORTS: "85" + VIRTUAL_HOST: "web5.nginx-proxy.tld" + # Intended for testing with `dh-file` container. + # VIRTUAL_HOST is paired with site-specific DH param file. + # DEFAULT_HOST is required to avoid defaulting to web2, + # if not specifying FQDN (`-servername`) in openssl queries. + web2: + image: web + expose: + - "85" + environment: + WEB_PORTS: "85" + VIRTUAL_HOST: "web2.nginx-proxy.tld" -# sut - System Under Test -# `docker.sock` required for functionality -# `certs` required to enable HTTPS via template -with_default_group: - container_name: dh-default - image: &img-nginxproxy nginxproxy/nginx-proxy:test - environment: &env-common - - &default-host DEFAULT_HOST=web5.nginx-proxy.tld - volumes: &vols-common - - &docker-sock /var/run/docker.sock:/tmp/docker.sock:ro - - &nginx-certs ./certs:/etc/nginx/certs:ro + # sut - System Under Test + # `docker.sock` required for functionality + # `certs` required to enable HTTPS via template + with_default_group: + container_name: dh-default + image: &img-nginxproxy nginxproxy/nginx-proxy:test + environment: &env-common + - &default-host DEFAULT_HOST=web5.nginx-proxy.tld + volumes: &vols-common + - &docker-sock /var/run/docker.sock:/tmp/docker.sock:ro + - &nginx-certs ./certs:/etc/nginx/certs:ro -with_alternative_group: - container_name: dh-env - environment: - - DHPARAM_BITS=3072 - - *default-host - image: *img-nginxproxy - volumes: *vols-common + with_alternative_group: + container_name: dh-env + environment: + - DHPARAM_BITS=3072 + - *default-host + image: *img-nginxproxy + volumes: *vols-common -with_invalid_group: - container_name: invalid-group-1024 - environment: - - DHPARAM_BITS=1024 - - *default-host - image: *img-nginxproxy - volumes: *vols-common + with_invalid_group: + container_name: invalid-group-1024 + environment: + - DHPARAM_BITS=1024 + - *default-host + image: *img-nginxproxy + volumes: *vols-common -with_custom_file: - container_name: dh-file - image: *img-nginxproxy - environment: *env-common - volumes: - - *docker-sock - - *nginx-certs - - ../../app/dhparam/ffdhe3072.pem:/etc/nginx/dhparam/dhparam.pem:ro + with_custom_file: + container_name: dh-file + image: *img-nginxproxy + environment: *env-common + volumes: + - *docker-sock + - *nginx-certs + - ../../app/dhparam/ffdhe3072.pem:/etc/nginx/dhparam/dhparam.pem:ro -with_skip: - container_name: dh-skip - environment: - - DHPARAM_SKIP=true - - *default-host - image: *img-nginxproxy - volumes: *vols-common + with_skip: + container_name: dh-skip + environment: + - DHPARAM_SKIP=true + - *default-host + image: *img-nginxproxy + volumes: *vols-common -with_skip_backward: - container_name: dh-skip-backward - environment: - - DHPARAM_GENERATION=false - - *default-host - image: *img-nginxproxy - volumes: *vols-common + with_skip_backward: + container_name: dh-skip-backward + environment: + - DHPARAM_GENERATION=false + - *default-host + image: *img-nginxproxy + volumes: *vols-common diff --git a/test/test_ssl/test_hsts.yml b/test/test_ssl/test_hsts.yml index da3b62962..b84fb8009 100644 --- a/test/test_ssl/test_hsts.yml +++ b/test/test_ssl/test_hsts.yml @@ -1,51 +1,54 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "web1.nginx-proxy.tld" +version: "2" -web2: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "web2.nginx-proxy.tld" - HSTS: "off" +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "web1.nginx-proxy.tld" -web3: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "web3.nginx-proxy.tld" - HSTS: "max-age=86400; includeSubDomains; preload" + web2: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "web2.nginx-proxy.tld" + HSTS: "off" -web4: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "web4.nginx-proxy.tld" - HSTS: "off" - HTTPS_METHOD: "noredirect" + web3: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "web3.nginx-proxy.tld" + HSTS: "max-age=86400; includeSubDomains; preload" -web5: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: http3-vhost-enabled.nginx-proxy.tld - labels: - com.github.nginx-proxy.nginx-proxy.http3.enable: "true" + web4: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "web4.nginx-proxy.tld" + HSTS: "off" + HTTPS_METHOD: "noredirect" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs:/etc/nginx/certs:ro + web5: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: http3-vhost-enabled.nginx-proxy.tld + labels: + com.github.nginx-proxy.nginx-proxy.http3.enable: "true" + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs:/etc/nginx/certs:ro diff --git a/test/test_ssl/test_https_port.yml b/test/test_ssl/test_https_port.yml index 7b674d76a..047054a39 100644 --- a/test/test_ssl/test_https_port.yml +++ b/test/test_ssl/test_https_port.yml @@ -1,16 +1,19 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "*.nginx-proxy.tld" +version: "2" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs:/etc/nginx/certs:ro - environment: - HTTP_PORT: 8080 - HTTPS_PORT: 8443 \ No newline at end of file +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "*.nginx-proxy.tld" + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs:/etc/nginx/certs:ro + environment: + HTTP_PORT: 8080 + HTTPS_PORT: 8443 diff --git a/test/test_ssl/test_nohttp.yml b/test/test_ssl/test_nohttp.yml index 48a7aa3c6..40b393ad6 100644 --- a/test/test_ssl/test_nohttp.yml +++ b/test/test_ssl/test_nohttp.yml @@ -1,15 +1,17 @@ -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: "82" - VIRTUAL_HOST: "web2.nginx-proxy.tld" - HTTPS_METHOD: nohttp +version: "2" +services: + web2: + image: web + expose: + - "82" + environment: + WEB_PORTS: "82" + VIRTUAL_HOST: "web2.nginx-proxy.tld" + HTTPS_METHOD: nohttp -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs:/etc/nginx/certs:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs:/etc/nginx/certs:ro diff --git a/test/test_ssl/test_nohttps.yml b/test/test_ssl/test_nohttps.yml index 3f3df1957..f2b07574b 100644 --- a/test/test_ssl/test_nohttps.yml +++ b/test/test_ssl/test_nohttps.yml @@ -1,14 +1,16 @@ -web: - image: web - expose: - - "83" - environment: - WEB_PORTS: "83" - VIRTUAL_HOST: "web.nginx-proxy.tld" - HTTPS_METHOD: nohttps +version: "2" +services: + web: + image: web + expose: + - "83" + environment: + WEB_PORTS: "83" + VIRTUAL_HOST: "web.nginx-proxy.tld" + HTTPS_METHOD: nohttps -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_ssl/test_noredirect.yml b/test/test_ssl/test_noredirect.yml index ecd93f6a6..8ee845525 100644 --- a/test/test_ssl/test_noredirect.yml +++ b/test/test_ssl/test_noredirect.yml @@ -1,15 +1,17 @@ -web3: - image: web - expose: - - "83" - environment: - WEB_PORTS: "83" - VIRTUAL_HOST: "web3.nginx-proxy.tld" - HTTPS_METHOD: noredirect +version: "2" +services: + web3: + image: web + expose: + - "83" + environment: + WEB_PORTS: "83" + VIRTUAL_HOST: "web3.nginx-proxy.tld" + HTTPS_METHOD: noredirect -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs:/etc/nginx/certs:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs:/etc/nginx/certs:ro diff --git a/test/test_ssl/test_virtual_path.yml b/test/test_ssl/test_virtual_path.yml index 22603217e..2494d35d8 100644 --- a/test/test_ssl/test_virtual_path.yml +++ b/test/test_ssl/test_virtual_path.yml @@ -1,26 +1,28 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "www.nginx-proxy.tld" - VIRTUAL_PATH: "/web1/" - VIRTUAL_DEST: "/" +version: "2" -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: "82" - VIRTUAL_HOST: "www.nginx-proxy.tld" - VIRTUAL_PATH: "/web2/" - VIRTUAL_DEST: "/" +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "www.nginx-proxy.tld" + VIRTUAL_PATH: "/web1/" + VIRTUAL_DEST: "/" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs:/etc/nginx/certs:ro + web2: + image: web + expose: + - "82" + environment: + WEB_PORTS: "82" + VIRTUAL_HOST: "www.nginx-proxy.tld" + VIRTUAL_PATH: "/web2/" + VIRTUAL_DEST: "/" + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs:/etc/nginx/certs:ro diff --git a/test/test_ssl/test_wildcard.yml b/test/test_ssl/test_wildcard.yml index e1504edeb..ea8c596cc 100644 --- a/test/test_ssl/test_wildcard.yml +++ b/test/test_ssl/test_wildcard.yml @@ -1,13 +1,16 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "*.nginx-proxy.tld" +version: "2" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs:/etc/nginx/certs:ro +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "*.nginx-proxy.tld" + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs:/etc/nginx/certs:ro diff --git a/test/test_ssl/wildcard_cert_and_nohttps/test_wildcard_cert_nohttps.py b/test/test_ssl/wildcard_cert_and_nohttps/test_wildcard_cert_nohttps.py index 590eafc2f..445377912 100644 --- a/test/test_ssl/wildcard_cert_and_nohttps/test_wildcard_cert_nohttps.py +++ b/test/test_ssl/wildcard_cert_and_nohttps/test_wildcard_cert_nohttps.py @@ -27,7 +27,8 @@ def test_https_get_served(docker_compose, nginxproxy, subdomain): def test_https_request_to_nohttps_vhost_goes_to_fallback_server(docker_compose, nginxproxy): with pytest.raises( (CertificateError, SSLError) ) as excinfo: nginxproxy.get("https://3.web.nginx-proxy.tld/port") - assert """certificate is not valid for '3.web.nginx-proxy.tld'""" in str(excinfo.value) + assert """certificate is not valid for '3.web.nginx-proxy.tld'""" in str(excinfo.value) or \ + """hostname '3.web.nginx-proxy.tld' doesn't match 'nginx-proxy.tld'""" in str(excinfo.value) r = nginxproxy.get("https://3.web.nginx-proxy.tld/port", verify=False) assert r.status_code == 503 diff --git a/test/test_trust-downstream-proxy/test_default.yml b/test/test_trust-downstream-proxy/test_default.yml index c420d806b..936dbad53 100644 --- a/test/test_trust-downstream-proxy/test_default.yml +++ b/test/test_trust-downstream-proxy/test_default.yml @@ -1,16 +1,18 @@ -web: - image: web - expose: - - "80" - environment: - WEB_PORTS: 80 - VIRTUAL_HOST: web.nginx-proxy.tld - HTTPS_METHOD: noredirect +version: "2" +services: + web: + image: web + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: web.nginx-proxy.tld + HTTPS_METHOD: noredirect -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro - - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro + - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro diff --git a/test/test_trust-downstream-proxy/test_disabled.yml b/test/test_trust-downstream-proxy/test_disabled.yml index 860e5f95e..9318d6381 100644 --- a/test/test_trust-downstream-proxy/test_disabled.yml +++ b/test/test_trust-downstream-proxy/test_disabled.yml @@ -1,18 +1,20 @@ -web: - image: web - expose: - - "80" - environment: - WEB_PORTS: 80 - VIRTUAL_HOST: web.nginx-proxy.tld - HTTPS_METHOD: noredirect +version: "2" +services: + web: + image: web + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: web.nginx-proxy.tld + HTTPS_METHOD: noredirect -sut: - image: nginxproxy/nginx-proxy:test - environment: - TRUST_DOWNSTREAM_PROXY: "false" - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro - - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro + sut: + image: nginxproxy/nginx-proxy:test + environment: + TRUST_DOWNSTREAM_PROXY: "false" + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro + - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro diff --git a/test/test_trust-downstream-proxy/test_enabled.yml b/test/test_trust-downstream-proxy/test_enabled.yml index 7b2a8de95..9a3e97554 100644 --- a/test/test_trust-downstream-proxy/test_enabled.yml +++ b/test/test_trust-downstream-proxy/test_enabled.yml @@ -1,18 +1,20 @@ -web: - image: web - expose: - - "80" - environment: - WEB_PORTS: 80 - VIRTUAL_HOST: web.nginx-proxy.tld - HTTPS_METHOD: noredirect +version: "2" +services: + web: + image: web + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: web.nginx-proxy.tld + HTTPS_METHOD: noredirect -sut: - image: nginxproxy/nginx-proxy:test - environment: - TRUST_DOWNSTREAM_PROXY: "true" - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro - - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro + sut: + image: nginxproxy/nginx-proxy:test + environment: + TRUST_DOWNSTREAM_PROXY: "true" + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro + - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro diff --git a/test/test_upstream-name/test_predictable-name.yml b/test/test_upstream-name/test_predictable-name.yml index cd8d25080..b5caad0fb 100644 --- a/test/test_upstream-name/test_predictable-name.yml +++ b/test/test_upstream-name/test_predictable-name.yml @@ -1,4 +1,4 @@ -version: '2' +version: "2" services: web: diff --git a/test/test_upstream-name/test_sha1-name.yml b/test/test_upstream-name/test_sha1-name.yml index 54989ae44..b52a5c946 100644 --- a/test/test_upstream-name/test_sha1-name.yml +++ b/test/test_upstream-name/test_sha1-name.yml @@ -1,4 +1,4 @@ -version: '2' +version: "2" services: web: diff --git a/test/test_vhost-empty-string.yml b/test/test_vhost-empty-string.yml index 83dd55457..9d2ff529e 100644 --- a/test/test_vhost-empty-string.yml +++ b/test/test_vhost-empty-string.yml @@ -1,8 +1,11 @@ +version: "2" + services: sut: image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro + web1: image: web expose: @@ -11,6 +14,7 @@ services: WEB_PORTS: "81" # The space is intentional (should be trimmed). VIRTUAL_HOST: " " + web2: image: web expose: @@ -19,6 +23,7 @@ services: WEB_PORTS: "82" # The space is intentional (should be trimmed). VIRTUAL_HOST: "web2.nginx-proxy.test ," + web3: image: web expose: @@ -27,6 +32,7 @@ services: WEB_PORTS: "83" # The space is intentional (should be trimmed). VIRTUAL_HOST: " ,web3.nginx-proxy.test" + web4: image: web expose: diff --git a/test/test_vhost-in-multiple-networks.yml b/test/test_vhost-in-multiple-networks.yml index 280af0401..4e9bb3e9e 100644 --- a/test/test_vhost-in-multiple-networks.yml +++ b/test/test_vhost-in-multiple-networks.yml @@ -1,4 +1,4 @@ -version: '2' +version: "2" networks: net1: {} diff --git a/test/test_virtual-path/test_custom_conf.yml b/test/test_virtual-path/test_custom_conf.yml index 40ab51244..2c4d6b9e8 100644 --- a/test/test_virtual-path/test_custom_conf.yml +++ b/test/test_virtual-path/test_custom_conf.yml @@ -1,48 +1,49 @@ +version: "2" -foo: - image: web - expose: - - "42" - environment: - WEB_PORTS: "42" - VIRTUAL_HOST: "foo.nginx-proxy.test" +services: + foo: + image: web + expose: + - "42" + environment: + WEB_PORTS: "42" + VIRTUAL_HOST: "foo.nginx-proxy.test" -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "nginx-proxy.test" - VIRTUAL_PATH: "/web1/" - VIRTUAL_DEST: "/" + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "nginx-proxy.test" + VIRTUAL_PATH: "/web1/" + VIRTUAL_DEST: "/" -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: "82" - VIRTUAL_HOST: "nginx-proxy.test" - VIRTUAL_PATH: "/web2/" - VIRTUAL_DEST: "/" + web2: + image: web + expose: + - "82" + environment: + WEB_PORTS: "82" + VIRTUAL_HOST: "nginx-proxy.test" + VIRTUAL_PATH: "/web2/" + VIRTUAL_DEST: "/" -web3: - image: web - expose: - - "83" - environment: - WEB_PORTS: "83" - VIRTUAL_HOST: "nginx-proxy.test" - VIRTUAL_PATH: "~ ^/(web3|alt)/" - -sut: - image: nginxproxy/nginx-proxy:test - environment: - DEFAULT_ROOT: 418 - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./foo.conf:/etc/nginx/vhost.d/foo.nginx-proxy.test:ro - - ./bar.conf:/etc/nginx/vhost.d/nginx-proxy.test_918d687a929083edd0c7224ee2293e0e7c062ab4_location:ro - - ./alternate.conf:/etc/nginx/vhost.d/nginx-proxy.test_7fb22b74bbdf907425dbbad18e4462565cada230_location:ro + web3: + image: web + expose: + - "83" + environment: + WEB_PORTS: "83" + VIRTUAL_HOST: "nginx-proxy.test" + VIRTUAL_PATH: "~ ^/(web3|alt)/" + sut: + image: nginxproxy/nginx-proxy:test + environment: + DEFAULT_ROOT: 418 + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./foo.conf:/etc/nginx/vhost.d/foo.nginx-proxy.test:ro + - ./bar.conf:/etc/nginx/vhost.d/nginx-proxy.test_918d687a929083edd0c7224ee2293e0e7c062ab4_location:ro + - ./alternate.conf:/etc/nginx/vhost.d/nginx-proxy.test_7fb22b74bbdf907425dbbad18e4462565cada230_location:ro diff --git a/test/test_virtual-path/test_forwarding.yml b/test/test_virtual-path/test_forwarding.yml index ee87e8d61..9b15c7416 100644 --- a/test/test_virtual-path/test_forwarding.yml +++ b/test/test_virtual-path/test_forwarding.yml @@ -1,17 +1,20 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "www.nginx-proxy.tld" - VIRTUAL_PATH: "/web1/" - VIRTUAL_DEST: "/" +version: "2" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./certs:/etc/nginx/certs:ro - environment: - - DEFAULT_ROOT=301 http://$$host/web1$$request_uri +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "www.nginx-proxy.tld" + VIRTUAL_PATH: "/web1/" + VIRTUAL_DEST: "/" + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./certs:/etc/nginx/certs:ro + environment: + - DEFAULT_ROOT=301 http://$$host/web1$$request_uri diff --git a/test/test_virtual-path/test_location_precedence.yml b/test/test_virtual-path/test_location_precedence.yml index be3248c7f..a250a1d27 100644 --- a/test/test_virtual-path/test_location_precedence.yml +++ b/test/test_virtual-path/test_location_precedence.yml @@ -1,37 +1,40 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "foo.nginx-proxy.test" - VIRTUAL_PATH: "/web1/" - VIRTUAL_DEST: "/" +version: "2" -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: "82" - VIRTUAL_HOST: "bar.nginx-proxy.test" - VIRTUAL_PATH: "/web2/" - VIRTUAL_DEST: "/" +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "foo.nginx-proxy.test" + VIRTUAL_PATH: "/web1/" + VIRTUAL_DEST: "/" -web3: - image: web - expose: - - "83" - environment: - WEB_PORTS: "83" - VIRTUAL_HOST: "bar.nginx-proxy.test" - VIRTUAL_PATH: "/web3/" - VIRTUAL_DEST: "/" + web2: + image: web + expose: + - "82" + environment: + WEB_PORTS: "82" + VIRTUAL_HOST: "bar.nginx-proxy.test" + VIRTUAL_PATH: "/web2/" + VIRTUAL_DEST: "/" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./default.conf:/etc/nginx/vhost.d/default_location:ro - - ./host.conf:/etc/nginx/vhost.d/bar.nginx-proxy.test_location:ro - - ./path.conf:/etc/nginx/vhost.d/bar.nginx-proxy.test_99f2db0ed8aa95dbb5b87fca79c7eff2ff6bb8bd_location:ro + web3: + image: web + expose: + - "83" + environment: + WEB_PORTS: "83" + VIRTUAL_HOST: "bar.nginx-proxy.test" + VIRTUAL_PATH: "/web3/" + VIRTUAL_DEST: "/" + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./default.conf:/etc/nginx/vhost.d/default_location:ro + - ./host.conf:/etc/nginx/vhost.d/bar.nginx-proxy.test_location:ro + - ./path.conf:/etc/nginx/vhost.d/bar.nginx-proxy.test_99f2db0ed8aa95dbb5b87fca79c7eff2ff6bb8bd_location:ro diff --git a/test/test_virtual-path/test_virtual_paths.py b/test/test_virtual-path/test_virtual_paths.py index 115d47fee..a91a8dd42 100644 --- a/test/test_virtual-path/test_virtual_paths.py +++ b/test/test_virtual-path/test_virtual_paths.py @@ -39,6 +39,7 @@ def web4(docker_compose): }, ports={"84/tcp": None} ) + docker_compose.networks.get("test_virtual-path_default").connect(container) sleep(2) # give it some time to initialize and for docker-gen to detect it yield container try: diff --git a/test/test_virtual-path/test_virtual_paths.yml b/test/test_virtual-path/test_virtual_paths.yml index 9f6a54f51..ac70297ec 100644 --- a/test/test_virtual-path/test_virtual_paths.yml +++ b/test/test_virtual-path/test_virtual_paths.yml @@ -1,42 +1,44 @@ +version: "2" -foo: - image: web - expose: - - "42" - environment: - WEB_PORTS: "42" - VIRTUAL_HOST: "foo.nginx-proxy.test" +services: + foo: + image: web + expose: + - "42" + environment: + WEB_PORTS: "42" + VIRTUAL_HOST: "foo.nginx-proxy.test" -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "nginx-proxy.test" - VIRTUAL_PATH: "/web1/" - VIRTUAL_DEST: "/" + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "nginx-proxy.test" + VIRTUAL_PATH: "/web1/" + VIRTUAL_DEST: "/" -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: "82" - VIRTUAL_HOST: "nginx-proxy.test" - VIRTUAL_PATH: "/web2/" - VIRTUAL_DEST: "/" + web2: + image: web + expose: + - "82" + environment: + WEB_PORTS: "82" + VIRTUAL_HOST: "nginx-proxy.test" + VIRTUAL_PATH: "/web2/" + VIRTUAL_DEST: "/" -web3: - image: web - expose: - - "83" - environment: - WEB_PORTS: "83" - VIRTUAL_HOST: "nginx-proxy.test" - VIRTUAL_PATH: "/" + web3: + image: web + expose: + - "83" + environment: + WEB_PORTS: "83" + VIRTUAL_HOST: "nginx-proxy.test" + VIRTUAL_PATH: "/" -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_wildcard_host.yml b/test/test_wildcard_host.yml index b745e3103..47e75e447 100644 --- a/test/test_wildcard_host.yml +++ b/test/test_wildcard_host.yml @@ -1,37 +1,39 @@ -web1: - image: web - expose: - - "81" - environment: - WEB_PORTS: "81" - VIRTUAL_HOST: "*.nginx-proxy.test" +version: "2" -web2: - image: web - expose: - - "82" - environment: - WEB_PORTS: "82" - VIRTUAL_HOST: "test.nginx-proxy.*" +services: + web1: + image: web + expose: + - "81" + environment: + WEB_PORTS: "81" + VIRTUAL_HOST: "*.nginx-proxy.test" -web3: - image: web - expose: - - "83" - environment: - WEB_PORTS: "83" - VIRTUAL_HOST: ~^web3\..*\.nginx-proxy\.regexp + web2: + image: web + expose: + - "82" + environment: + WEB_PORTS: "82" + VIRTUAL_HOST: "test.nginx-proxy.*" -web4: - image: web - expose: - - "84" - environment: - WEB_PORTS: "84" - VIRTUAL_HOST: ~^web4\..*\.nginx-proxy\.regexp$$ # we need to double the `$` because of docker-compose variable interpolation + web3: + image: web + expose: + - "83" + environment: + WEB_PORTS: "83" + VIRTUAL_HOST: ~^web3\..*\.nginx-proxy\.regexp + web4: + image: web + expose: + - "84" + environment: + WEB_PORTS: "84" + VIRTUAL_HOST: ~^web4\..*\.nginx-proxy\.regexp$$ # we need to double the `$` because of docker compose variable interpolation -sut: - image: nginxproxy/nginx-proxy:test - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro