first commit
This commit is contained in:
commit
5e3dcd47ca
95
.env.sample
Normal file
95
.env.sample
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#
|
||||||
|
# docker-compose-letsencrypt-nginx-proxy-companion
|
||||||
|
#
|
||||||
|
# A Web Proxy using docker with NGINX and Let's Encrypt
|
||||||
|
# Using the great community docker-gen, nginx-proxy and docker-letsencrypt-nginx-proxy-companion
|
||||||
|
#
|
||||||
|
# This is the .env file to set up your webproxy enviornment
|
||||||
|
|
||||||
|
#
|
||||||
|
# Your local containers NAME
|
||||||
|
#
|
||||||
|
NGINX_WEB=nginx-web
|
||||||
|
DOCKER_GEN=nginx-gen
|
||||||
|
LETS_ENCRYPT=nginx-letsencrypt
|
||||||
|
|
||||||
|
#
|
||||||
|
# Set the IP address of the external access Interface
|
||||||
|
#
|
||||||
|
IP=0.0.0.0
|
||||||
|
|
||||||
|
#
|
||||||
|
# Default Network
|
||||||
|
#
|
||||||
|
NETWORK=webproxy
|
||||||
|
|
||||||
|
# If you want to customize the created network, use the following variable
|
||||||
|
#NETWORK_OPTIONS="--opt encrypted=true"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Service Network (Optional)
|
||||||
|
#
|
||||||
|
# In case you decide to add a new network to your services containers you can set this
|
||||||
|
# network as a SERVICE_NETWORK
|
||||||
|
#
|
||||||
|
# [WARNING] This setting was built to use our `start.sh` script or in that special case
|
||||||
|
# you could use the docker-composer with our multiple network option, as of:
|
||||||
|
# `docker-compose -f docker-compose-multiple-networks.yml up -d`
|
||||||
|
#
|
||||||
|
#SERVICE_NETWORK=webservices
|
||||||
|
|
||||||
|
# If you want to customize the created network, use the following variable
|
||||||
|
#SERVICE_NETWORK_OPTIONS="--opt encrypted=true"
|
||||||
|
|
||||||
|
#
|
||||||
|
## NGINX file path (mount into the host)
|
||||||
|
# Here you can configure the path where nginx stores all the configurations and certificates.
|
||||||
|
# With the value ./nginx-data it creates a new sub-folder into your current path.
|
||||||
|
|
||||||
|
NGINX_FILES_PATH=./nginx-data
|
||||||
|
|
||||||
|
#
|
||||||
|
# NGINX use special conf files
|
||||||
|
#
|
||||||
|
# In case you want to add some special configuration to your NGINX Web Proxy you could
|
||||||
|
# add your files to ./conf.d/ folder as of sample file 'uploadsize.conf'
|
||||||
|
#
|
||||||
|
# [WARNING] This setting was built to use our `start.sh`.
|
||||||
|
#
|
||||||
|
# [WARNING] Once you set this options to true all your files will be copied to data
|
||||||
|
# folder (./data/conf.d). If you decide to remove this special configuration
|
||||||
|
# you must delete your files from data folder ./data/conf.d.
|
||||||
|
#
|
||||||
|
#USE_NGINX_CONF_FILES=true
|
||||||
|
|
||||||
|
#
|
||||||
|
# Docker Logging Config
|
||||||
|
#
|
||||||
|
# This section offers two options max-size and max-file, which follow the docker documentation
|
||||||
|
# as follow:
|
||||||
|
#
|
||||||
|
# logging:
|
||||||
|
# driver: "json-file"
|
||||||
|
# options:
|
||||||
|
# max-size: "200k"
|
||||||
|
# max-file: "10"
|
||||||
|
#
|
||||||
|
#NGINX_WEB_LOG_DRIVER=json-file
|
||||||
|
#NGINX_WEB_LOG_MAX_SIZE=4m
|
||||||
|
#NGINX_WEB_LOG_MAX_FILE=10
|
||||||
|
|
||||||
|
#NGINX_GEN_LOG_DRIVER=json-file
|
||||||
|
#NGINX_GEN_LOG_MAX_SIZE=2m
|
||||||
|
#NGINX_GEN_LOG_MAX_FILE=10
|
||||||
|
|
||||||
|
#NGINX_LETSENCRYPT_LOG_DRIVER=json-file
|
||||||
|
#NGINX_LETSENCRYPT_LOG_MAX_SIZE=2m
|
||||||
|
#NGINX_LETSENCRYPT_LOG_MAX_FILE=10
|
||||||
|
|
||||||
|
#
|
||||||
|
# Set the local exposed ports for http and https on the Host
|
||||||
|
#
|
||||||
|
# NOTE: The default values are 80 and 443, only change this options if you really know what you are doing
|
||||||
|
#
|
||||||
|
#DOCKER_HTTP=80
|
||||||
|
#DOCKER_HTTPS=443
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
data
|
||||||
|
.env*
|
||||||
|
!.env.sample
|
||||||
|
.DS_Store
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 Evert Ramos
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
261
README.md
Normal file
261
README.md
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
# Web Proxy using Docker, NGINX and Let's Encrypt
|
||||||
|
|
||||||
|
With this repo you will be able to set up your server with multiple sites using a single NGINX proxy to manage your connections, automating your apps container (port 80 and 443) to auto renew your ssl certificates with Let´s Encrypt.
|
||||||
|
|
||||||
|
Something like:
|
||||||
|
|
||||||
|
![Web Proxy environment](https://github.com/evertramos/images/raw/master/webproxy.jpg)
|
||||||
|
|
||||||
|
|
||||||
|
## Why use it?
|
||||||
|
|
||||||
|
Using this set up you will be able start a production environment in a few seconds. For each new web project simply start the containers with the option `-e VIRTUAL_HOST=your.domain.com` and you will be ready to go. If you want to use SSL (Let's Encrypt) just add the tag `-e LETSENCRYPT_HOST=your.domain.com`. Done!
|
||||||
|
|
||||||
|
Easy and trustworthy!
|
||||||
|
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
In order to use this compose file (docker-compose.yml) you must have:
|
||||||
|
|
||||||
|
1. docker (https://docs.docker.com/engine/installation/)
|
||||||
|
2. docker-compose (https://docs.docker.com/compose/install/)
|
||||||
|
|
||||||
|
|
||||||
|
## How to use it
|
||||||
|
|
||||||
|
1. Clone this repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion.git
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Make a copy of our `.env.sample` and rename it to `.env`:
|
||||||
|
|
||||||
|
Update this file with your preferences.
|
||||||
|
|
||||||
|
```
|
||||||
|
#
|
||||||
|
# docker-compose-letsencrypt-nginx-proxy-companion
|
||||||
|
#
|
||||||
|
# A Web Proxy using docker with NGINX and Let's Encrypt
|
||||||
|
# Using the great community docker-gen, nginx-proxy and docker-letsencrypt-nginx-proxy-companion
|
||||||
|
#
|
||||||
|
# This is the .env file to set up your webproxy enviornment
|
||||||
|
|
||||||
|
#
|
||||||
|
# Your local containers NAME
|
||||||
|
#
|
||||||
|
NGINX_WEB=nginx-web
|
||||||
|
DOCKER_GEN=nginx-gen
|
||||||
|
LETS_ENCRYPT=nginx-letsencrypt
|
||||||
|
|
||||||
|
#
|
||||||
|
# Set the IP address of the external access Interface
|
||||||
|
#
|
||||||
|
IP=0.0.0.0
|
||||||
|
|
||||||
|
#
|
||||||
|
# Default Network
|
||||||
|
#
|
||||||
|
NETWORK=webproxy
|
||||||
|
|
||||||
|
# If you want to customize the created network, use the following variable
|
||||||
|
#NETWORK_OPTIONS="--opt encrypted=true"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Service Network (Optional)
|
||||||
|
#
|
||||||
|
# In case you decide to add a new network to your services containers you can set this
|
||||||
|
# network as a SERVICE_NETWORK
|
||||||
|
#
|
||||||
|
# [WARNING] This setting was built to use our `start.sh` script or in that special case
|
||||||
|
# you could use the docker-composer with our multiple network option, as of:
|
||||||
|
# `docker-compose -f docker-compose-multiple-networks.yml up -d`
|
||||||
|
#
|
||||||
|
#SERVICE_NETWORK=webservices
|
||||||
|
|
||||||
|
# If you want to customize the created network, use the following variable
|
||||||
|
#SERVICE_NETWORK_OPTIONS="--opt encrypted=true"
|
||||||
|
|
||||||
|
#
|
||||||
|
## NGINX file path (mount into the host)
|
||||||
|
# Here you can configure the path where nginx stores all the configurations and certificates.
|
||||||
|
# With the value ./nginx-data it creates a new sub-folder into your current path.
|
||||||
|
|
||||||
|
NGINX_FILES_PATH=./nginx-data
|
||||||
|
|
||||||
|
#
|
||||||
|
# NGINX use special conf files
|
||||||
|
#
|
||||||
|
# In case you want to add some special configuration to your NGINX Web Proxy you could
|
||||||
|
# add your files to ./conf.d/ folder as of sample file 'uploadsize.conf'
|
||||||
|
#
|
||||||
|
# [WARNING] This setting was built to use our `start.sh`.
|
||||||
|
#
|
||||||
|
# [WARNING] Once you set this options to true all your files will be copied to data
|
||||||
|
# folder (./data/conf.d). If you decide to remove this special configuration
|
||||||
|
# you must delete your files from data folder ./data/conf.d.
|
||||||
|
#
|
||||||
|
#USE_NGINX_CONF_FILES=true
|
||||||
|
|
||||||
|
#
|
||||||
|
# Docker Logging Config
|
||||||
|
#
|
||||||
|
# This section offers two options max-size and max-file, which follow the docker documentation
|
||||||
|
# as follow:
|
||||||
|
#
|
||||||
|
# logging:
|
||||||
|
# driver: "json-file"
|
||||||
|
# options:
|
||||||
|
# max-size: "200k"
|
||||||
|
# max-file: "10"
|
||||||
|
#
|
||||||
|
#NGINX_WEB_LOG_DRIVER=json-file
|
||||||
|
#NGINX_WEB_LOG_MAX_SIZE=4m
|
||||||
|
#NGINX_WEB_LOG_MAX_FILE=10
|
||||||
|
|
||||||
|
#NGINX_GEN_LOG_DRIVER=json-file
|
||||||
|
#NGINX_GEN_LOG_MAX_SIZE=2m
|
||||||
|
#NGINX_GEN_LOG_MAX_FILE=10
|
||||||
|
|
||||||
|
#NGINX_LETSENCRYPT_LOG_DRIVER=json-file
|
||||||
|
#NGINX_LETSENCRYPT_LOG_MAX_SIZE=2m
|
||||||
|
#NGINX_LETSENCRYPT_LOG_MAX_FILE=10
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run our start script
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./start.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Your proxy is ready to go!
|
||||||
|
|
||||||
|
## Starting your web containers
|
||||||
|
|
||||||
|
After following the steps above you can start new web containers with port 80 open and add the option `-e VIRTUAL_HOST=your.domain.com` so proxy will automatically generate the reverse script in NGINX Proxy to forward new connections to your web/app container, as of:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d -e VIRTUAL_HOST=your.domain.com \
|
||||||
|
--network=webproxy \
|
||||||
|
--name my_app \
|
||||||
|
httpd:alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
To have SSL in your web/app you just add the option `-e LETSENCRYPT_HOST=your.domain.com`, as follow:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d -e VIRTUAL_HOST=your.domain.com \
|
||||||
|
-e LETSENCRYPT_HOST=your.domain.com \
|
||||||
|
-e LETSENCRYPT_EMAIL=your.email@your.domain.com \
|
||||||
|
--network=webproxy \
|
||||||
|
--name my_app \
|
||||||
|
httpd:alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
> You don´t need to open port *443* in your container, the certificate validation is managed by the web proxy.
|
||||||
|
|
||||||
|
|
||||||
|
> Please note that when running a new container to generate certificates with LetsEncrypt (`-e LETSENCRYPT_HOST=your.domain.com`), it may take a few minutes, depending on multiples circumstances.
|
||||||
|
|
||||||
|
## Further Options
|
||||||
|
|
||||||
|
1. Basic Authentication Support
|
||||||
|
|
||||||
|
In order to be able to secure your virtual host with basic authentication, you must create a htpasswd file within `${NGINX_FILES_PATH}/htpasswd/${VIRTUAL_HOST}` via:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo sh -c "echo -n '[username]:' >> ${NGINX_FILES_PATH}/htpasswd/${VIRTUAL_HOST}"
|
||||||
|
sudo sh -c "openssl passwd -apr1 >> ${NGINX_FILES_PATH}/htpasswd/${VIRTUAL_HOST}"
|
||||||
|
```
|
||||||
|
|
||||||
|
> Please substitute the `${NGINX_FILES_PATH}` with your path information, replace `[username]` with your username and `${VIRTUAL_HOST}` with your host's domain. You will be prompted for a password.
|
||||||
|
|
||||||
|
2. Using multiple networks
|
||||||
|
|
||||||
|
If you want to use more than one network to better organize your environment you could set the option `SERVICE_NETWORK` in our `.env.sample` or you can just create your own network and attach all your containers as of:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker network create myownnetwork
|
||||||
|
docker network connect myownnetwork nginx-web
|
||||||
|
docker network connect myownnetwork nginx-gen
|
||||||
|
docker network connect myownnetwork nginx-letsencrypt
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Using different ports to be proxied
|
||||||
|
|
||||||
|
If your service container runs on port 8545 you probably will need to add the `VIRTUAL_PORT` environment variable to your container, in the `docker-compose.yml`, as of:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
parity
|
||||||
|
image: parity/parity:v1.8.9
|
||||||
|
[...]
|
||||||
|
environment:
|
||||||
|
[...]
|
||||||
|
VIRTUAL_PORT: 8545
|
||||||
|
```
|
||||||
|
|
||||||
|
Or as of below:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run [...] -e VIRTUAL_PORT=8545 [...]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing your proxy with scripts preconfigured
|
||||||
|
|
||||||
|
1. Run the script `test.sh` informing your domain already configured in your DNS to point out to your server as follow:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./test_start_ssl.sh your.domain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
or simply run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -dit -e VIRTUAL_HOST=your.domain.com --network=webproxy --name test-web httpd:alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
Access your browser with your domain!
|
||||||
|
|
||||||
|
To stop and remove your test container run our `stop_test.sh` script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./test_stop.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Or simply run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker stop test-web && docker rm test-web
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running this Proxy on a Synology NAS
|
||||||
|
|
||||||
|
Please checkout this [howto](https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion/blob/master/docs/HOWTO-Synlogy.md).
|
||||||
|
|
||||||
|
|
||||||
|
## Production Environment using Web Proxy and Wordpress
|
||||||
|
|
||||||
|
1. [docker-wordpress-letsencrypt](https://github.com/evertramos/docker-wordpress-letsencrypt)
|
||||||
|
2. [docker-portainer-letsencrypt](https://github.com/evertramos/docker-portainer-letsencrypt)
|
||||||
|
3. [docker-nextcloud-letsencrypt](https://github.com/evertramos/docker-nextcloud-letsencrypt)
|
||||||
|
|
||||||
|
In this repo you will find a docker-compose file to start a production environment for a new wordpress site.
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
Without the repositories below this webproxy wouldn´t be possible.
|
||||||
|
|
||||||
|
Credits goes to:
|
||||||
|
- nginx-proxy [@jwilder](https://github.com/jwilder/nginx-proxy)
|
||||||
|
- docker-gen [@jwilder](https://github.com/jwilder/docker-gen)
|
||||||
|
- docker-letsencrypt-nginx-proxy-companion [@JrCs](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion)
|
||||||
|
|
||||||
|
|
||||||
|
### Special thanks to:
|
||||||
|
|
||||||
|
- [@j7an](https://github.com/j7an) - Many contributions and the ipv6 branch!
|
||||||
|
- [@buchdag](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/pull/226#event-1145800062)
|
||||||
|
- [@fracz](https://github.com/fracz) - Many contributions!
|
||||||
|
|
50
conf.d/realip.conf
Normal file
50
conf.d/realip.conf
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#
|
||||||
|
# [WARNING] To enable this files you need to uncomment USE_NGINX_CONF_FILES=true in .env file
|
||||||
|
#
|
||||||
|
# [WARNING] Also, read all the comments in .env about NGINX use special conf files
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Real IP Settings
|
||||||
|
#
|
||||||
|
# This option get user's real ip address
|
||||||
|
# to be fowared to your service container
|
||||||
|
|
||||||
|
#
|
||||||
|
# Basic settings
|
||||||
|
#
|
||||||
|
# The option 'set_real_ip_from'
|
||||||
|
# must correspont to your docker network address
|
||||||
|
set_real_ip_from 172.18.0.0/32;
|
||||||
|
real_ip_header X-Real-IP;
|
||||||
|
real_ip_recursive on;
|
||||||
|
|
||||||
|
#
|
||||||
|
# CloudFlare settings
|
||||||
|
#
|
||||||
|
# If you CloudFlare and want to forward the
|
||||||
|
# user's real IP to your app services you
|
||||||
|
# must uncomment all lines below and be sure
|
||||||
|
# to comment the lines of the "Basic settings"
|
||||||
|
#set_real_ip_from 103.21.244.0/22;
|
||||||
|
#set_real_ip_from 103.22.200.0/22;
|
||||||
|
#set_real_ip_from 103.31.4.0/22;
|
||||||
|
#set_real_ip_from 104.16.0.0/12;
|
||||||
|
#set_real_ip_from 108.162.192.0/18;
|
||||||
|
#set_real_ip_from 131.0.72.0/22;
|
||||||
|
#set_real_ip_from 141.101.64.0/18;
|
||||||
|
#set_real_ip_from 162.158.0.0/15;
|
||||||
|
#set_real_ip_from 172.64.0.0/13;
|
||||||
|
#set_real_ip_from 173.245.48.0/20;
|
||||||
|
#set_real_ip_from 188.114.96.0/20;
|
||||||
|
#set_real_ip_from 190.93.240.0/20;
|
||||||
|
#set_real_ip_from 197.234.240.0/22;
|
||||||
|
#set_real_ip_from 198.41.128.0/17;
|
||||||
|
#set_real_ip_from 2400:cb00::/32;
|
||||||
|
#set_real_ip_from 2606:4700::/32;
|
||||||
|
#set_real_ip_from 2803:f800::/32;
|
||||||
|
#set_real_ip_from 2405:b500::/32;
|
||||||
|
#set_real_ip_from 2405:8100::/32;
|
||||||
|
#set_real_ip_from 2c0f:f248::/32;
|
||||||
|
#set_real_ip_from 2a06:98c0::/29;
|
||||||
|
#real_ip_header X-Forwarded-For;
|
7
conf.d/servertokens.conf
Normal file
7
conf.d/servertokens.conf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
# [WARNING] To enable this files you need to uncomment USE_NGINX_CONF_FILES=true in .env file
|
||||||
|
#
|
||||||
|
# [WARNING] Also, read all the comments in .env about NGINX use special conf files
|
||||||
|
#
|
||||||
|
|
||||||
|
server_tokens off;
|
7
conf.d/uploadsize.conf
Normal file
7
conf.d/uploadsize.conf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
# [WARNING] To enable this files you need to uncomment USE_NGINX_CONF_FILES=true in .env file
|
||||||
|
#
|
||||||
|
# [WARNING] Also, read all the comments in .env about NGINX use special conf files
|
||||||
|
#
|
||||||
|
|
||||||
|
client_max_body_size 100m;
|
77
docker-compose-multiple-networks.yml
Normal file
77
docker-compose-multiple-networks.yml
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
nginx-web:
|
||||||
|
image: nginx
|
||||||
|
labels:
|
||||||
|
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
|
||||||
|
container_name: ${NGINX_WEB:-nginx-web}
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "${IP:-0.0.0.0}:${DOCKER_HTTP:-80}:80"
|
||||||
|
- "${IP:-0.0.0.0}:${DOCKER_HTTPS:-443}:443"
|
||||||
|
volumes:
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/conf.d:/etc/nginx/conf.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/vhost.d:/etc/nginx/vhost.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/html:/usr/share/nginx/html
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/certs:/etc/nginx/certs:ro
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/htpasswd:/etc/nginx/htpasswd:ro
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
- outside
|
||||||
|
logging:
|
||||||
|
driver: ${NGINX_WEB_LOG_DRIVER:-json-file}
|
||||||
|
options:
|
||||||
|
max-size: ${NGINX_WEB_LOG_MAX_SIZE:-4m}
|
||||||
|
max-file: ${NGINX_WEB_LOG_MAX_FILE:-10}
|
||||||
|
|
||||||
|
nginx-gen:
|
||||||
|
image: jwilder/docker-gen
|
||||||
|
command: -notify-sighup ${NGINX_WEB:-nginx-web} -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
|
||||||
|
container_name: ${DOCKER_GEN:-nginx-gen}
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/conf.d:/etc/nginx/conf.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/vhost.d:/etc/nginx/vhost.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/html:/usr/share/nginx/html
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/certs:/etc/nginx/certs:ro
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/htpasswd:/etc/nginx/htpasswd:ro
|
||||||
|
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||||
|
- ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
- outside
|
||||||
|
logging:
|
||||||
|
driver: ${NGINX_GEN_LOG_DRIVER:-json-file}
|
||||||
|
options:
|
||||||
|
max-size: ${NGINX_GEN_LOG_MAX_SIZE:-2m}
|
||||||
|
max-file: ${NGINX_GEN_LOG_MAX_FILE:-10}
|
||||||
|
|
||||||
|
nginx-letsencrypt:
|
||||||
|
image: jrcs/letsencrypt-nginx-proxy-companion
|
||||||
|
container_name: ${LETS_ENCRYPT:-nginx-letsencrypt}
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/conf.d:/etc/nginx/conf.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/vhost.d:/etc/nginx/vhost.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/html:/usr/share/nginx/html
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/certs:/etc/nginx/certs:rw
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
environment:
|
||||||
|
NGINX_DOCKER_GEN_CONTAINER: ${DOCKER_GEN:-nginx-gen}
|
||||||
|
NGINX_PROXY_CONTAINER: ${NGINX_WEB:-nginx-web}
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
- outside
|
||||||
|
logging:
|
||||||
|
driver: ${NGINX_LETSENCRYPT_LOG_DRIVER:-json-file}
|
||||||
|
options:
|
||||||
|
max-size: ${NGINX_LETSENCRYPT_LOG_MAX_SIZE:-2m}
|
||||||
|
max-file: ${NGINX_LETSENCRYPT_LOG_MAX_FILE:-10}
|
||||||
|
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
external:
|
||||||
|
name: ${NETWORK:-webproxy}
|
||||||
|
outside:
|
||||||
|
external:
|
||||||
|
name: ${SERVICE_NETWORK:-webservices}
|
65
docker-compose.yml
Normal file
65
docker-compose.yml
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
nginx-web:
|
||||||
|
image: nginx
|
||||||
|
labels:
|
||||||
|
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
|
||||||
|
container_name: ${NGINX_WEB:-nginx-web}
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "${IP:-0.0.0.0}:${DOCKER_HTTP:-80}:80"
|
||||||
|
- "${IP:-0.0.0.0}:${DOCKER_HTTPS:-443}:443"
|
||||||
|
volumes:
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/conf.d:/etc/nginx/conf.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/vhost.d:/etc/nginx/vhost.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/html:/usr/share/nginx/html
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/certs:/etc/nginx/certs:ro
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/htpasswd:/etc/nginx/htpasswd:ro
|
||||||
|
logging:
|
||||||
|
driver: ${NGINX_WEB_LOG_DRIVER:-json-file}
|
||||||
|
options:
|
||||||
|
max-size: ${NGINX_WEB_LOG_MAX_SIZE:-4m}
|
||||||
|
max-file: ${NGINX_WEB_LOG_MAX_FILE:-10}
|
||||||
|
|
||||||
|
nginx-gen:
|
||||||
|
image: jwilder/docker-gen
|
||||||
|
command: -notify-sighup ${NGINX_WEB:-nginx-web} -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
|
||||||
|
container_name: ${DOCKER_GEN:-nginx-gen}
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/conf.d:/etc/nginx/conf.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/vhost.d:/etc/nginx/vhost.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/html:/usr/share/nginx/html
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/certs:/etc/nginx/certs:ro
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/htpasswd:/etc/nginx/htpasswd:ro
|
||||||
|
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||||
|
- ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
|
||||||
|
logging:
|
||||||
|
driver: ${NGINX_GEN_LOG_DRIVER:-json-file}
|
||||||
|
options:
|
||||||
|
max-size: ${NGINX_GEN_LOG_MAX_SIZE:-2m}
|
||||||
|
max-file: ${NGINX_GEN_LOG_MAX_FILE:-10}
|
||||||
|
|
||||||
|
nginx-letsencrypt:
|
||||||
|
image: jrcs/letsencrypt-nginx-proxy-companion
|
||||||
|
container_name: ${LETS_ENCRYPT:-nginx-letsencrypt}
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/conf.d:/etc/nginx/conf.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/vhost.d:/etc/nginx/vhost.d
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/html:/usr/share/nginx/html
|
||||||
|
- ${NGINX_FILES_PATH:-./data}/certs:/etc/nginx/certs:rw
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
environment:
|
||||||
|
NGINX_DOCKER_GEN_CONTAINER: ${DOCKER_GEN:-nginx-gen}
|
||||||
|
NGINX_PROXY_CONTAINER: ${NGINX_WEB:-nginx-web}
|
||||||
|
logging:
|
||||||
|
driver: ${NGINX_LETSENCRYPT_LOG_DRIVER:-json-file}
|
||||||
|
options:
|
||||||
|
max-size: ${NGINX_LETSENCRYPT_LOG_MAX_SIZE:-2m}
|
||||||
|
max-file: ${NGINX_LETSENCRYPT_LOG_MAX_FILE:-10}
|
||||||
|
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
external:
|
||||||
|
name: ${NETWORK:-webproxy}
|
27
docs/HOWTO-Synlogy.md
Executable file
27
docs/HOWTO-Synlogy.md
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
## Port mapping
|
||||||
|
Synology default installs a web server on port 80 blocking certificate generation.
|
||||||
|
|
||||||
|
To circumvent this - if you do not need external access to the default web server (and you should not expose it anyway) configure your .env to use alternative ports and your router to forward the external official port to the alternative internal ports:
|
||||||
|
|
||||||
|
#
|
||||||
|
# Set the local exposed ports for http and https - this will allow you to run with a legacy web
|
||||||
|
# server already installed for local use
|
||||||
|
#
|
||||||
|
# NOTE: For this to function your internet router must forward the official ports to the mapped ports -
|
||||||
|
# in this example external port 80 to docker host 81 and external port 443 to docker host 444
|
||||||
|
#
|
||||||
|
DOCKER_HTTP=81
|
||||||
|
DOCKER_HTTPS=444
|
||||||
|
|
||||||
|
## File permissions
|
||||||
|
To setup the needed configuration directoties and proper permissions run the below commands (assuming default ./data is where you have your catalog for persistent files)
|
||||||
|
|
||||||
|
mkdir -p data/certs
|
||||||
|
mkdir data/htpasswd
|
||||||
|
mkdir data/conf.d
|
||||||
|
mkdir data/vhost.d
|
||||||
|
mkdir data/html
|
||||||
|
chgrp -R 101 data
|
||||||
|
chmod -R g+rwx data
|
||||||
|
|
||||||
|
Contributed by https://github.com/nicolailang/
|
361
nginx.tmpl
Normal file
361
nginx.tmpl
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
{{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }}
|
||||||
|
|
||||||
|
{{ define "upstream" }}
|
||||||
|
{{ if .Address }}
|
||||||
|
{{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}}
|
||||||
|
{{ if and .Container.Node.ID .Address.HostPort }}
|
||||||
|
# {{ .Container.Node.Name }}/{{ .Container.Name }}
|
||||||
|
server {{ .Container.Node.Address.IP }}:{{ .Address.HostPort }};
|
||||||
|
{{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}}
|
||||||
|
{{ else if .Network }}
|
||||||
|
# {{ .Container.Name }}
|
||||||
|
server {{ .Network.IP }}:{{ .Address.Port }};
|
||||||
|
{{ end }}
|
||||||
|
{{ else if .Network }}
|
||||||
|
# {{ .Container.Name }}
|
||||||
|
{{ if .Network.IP }}
|
||||||
|
server {{ .Network.IP }} down;
|
||||||
|
{{ else }}
|
||||||
|
server 127.0.0.1 down;
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
|
||||||
|
# scheme used to connect to this server
|
||||||
|
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
|
||||||
|
default $http_x_forwarded_proto;
|
||||||
|
'' $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
|
||||||
|
# server port the client connected to
|
||||||
|
map $http_x_forwarded_port $proxy_x_forwarded_port {
|
||||||
|
default $http_x_forwarded_port;
|
||||||
|
'' $server_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
|
||||||
|
# Connection header that may have been passed to this server
|
||||||
|
map $http_upgrade $proxy_connection {
|
||||||
|
default upgrade;
|
||||||
|
'' close;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Apply fix for very long server names
|
||||||
|
server_names_hash_bucket_size 128;
|
||||||
|
|
||||||
|
# Default dhparam
|
||||||
|
{{ if (exists "/etc/nginx/dhparam/dhparam.pem") }}
|
||||||
|
ssl_dhparam /etc/nginx/dhparam/dhparam.pem;
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
# Set appropriate X-Forwarded-Ssl header
|
||||||
|
map $scheme $proxy_x_forwarded_ssl {
|
||||||
|
default off;
|
||||||
|
https on;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 '$host $remote_addr - $remote_user [$time_local] '
|
||||||
|
'"$request" $status $body_bytes_sent '
|
||||||
|
'"$http_referer" "$http_user_agent"';
|
||||||
|
|
||||||
|
access_log off;
|
||||||
|
|
||||||
|
{{ if $.Env.RESOLVERS }}
|
||||||
|
resolver {{ $.Env.RESOLVERS }};
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if (exists "/etc/nginx/proxy.conf") }}
|
||||||
|
include /etc/nginx/proxy.conf;
|
||||||
|
{{ else }}
|
||||||
|
# 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-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;
|
||||||
|
|
||||||
|
# Mitigate httpoxy attack (see README for details)
|
||||||
|
proxy_set_header Proxy "";
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ $enable_ipv6 := eq (or ($.Env.ENABLE_IPV6) "") "true" }}
|
||||||
|
server {
|
||||||
|
server_name _; # This is just an invalid value which will never trigger on a real hostname.
|
||||||
|
listen 80;
|
||||||
|
{{ if $enable_ipv6 }}
|
||||||
|
listen [::]:80;
|
||||||
|
{{ end }}
|
||||||
|
access_log /var/log/nginx/access.log vhost;
|
||||||
|
return 503;
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
|
||||||
|
server {
|
||||||
|
server_name _; # This is just an invalid value which will never trigger on a real hostname.
|
||||||
|
listen 443 ssl http2;
|
||||||
|
{{ if $enable_ipv6 }}
|
||||||
|
listen [::]:443 ssl http2;
|
||||||
|
{{ end }}
|
||||||
|
access_log /var/log/nginx/access.log vhost;
|
||||||
|
return 503;
|
||||||
|
|
||||||
|
ssl_session_tickets off;
|
||||||
|
ssl_certificate /etc/nginx/certs/default.crt;
|
||||||
|
ssl_certificate_key /etc/nginx/certs/default.key;
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
|
||||||
|
|
||||||
|
{{ $host := trim $host }}
|
||||||
|
{{ $is_regexp := hasPrefix "~" $host }}
|
||||||
|
{{ $upstream_name := when $is_regexp (sha1 $host) $host }}
|
||||||
|
|
||||||
|
# {{ $host }}
|
||||||
|
upstream {{ $upstream_name }} {
|
||||||
|
|
||||||
|
{{ range $container := $containers }}
|
||||||
|
{{ $addrLen := len $container.Addresses }}
|
||||||
|
|
||||||
|
{{ range $knownNetwork := $CurrentContainer.Networks }}
|
||||||
|
{{ range $containerNetwork := $container.Networks }}
|
||||||
|
{{ if (and (ne $containerNetwork.Name "ingress") (or (eq $knownNetwork.Name $containerNetwork.Name) (eq $knownNetwork.Name "host"))) }}
|
||||||
|
## Can be connected with "{{ $containerNetwork.Name }}" network
|
||||||
|
|
||||||
|
{{/* If only 1 port exposed, use that */}}
|
||||||
|
{{ if eq $addrLen 1 }}
|
||||||
|
{{ $address := index $container.Addresses 0 }}
|
||||||
|
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
|
||||||
|
{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}}
|
||||||
|
{{ else }}
|
||||||
|
{{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }}
|
||||||
|
{{ $address := where $container.Addresses "Port" $port | first }}
|
||||||
|
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
# Cannot connect to network of this container
|
||||||
|
server 127.0.0.1 down;
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ $default_host := or ($.Env.DEFAULT_HOST) "" }}
|
||||||
|
{{ $default_server := index (dict $host "" $default_host "default_server") $host }}
|
||||||
|
|
||||||
|
{{/* Get the VIRTUAL_PROTO defined by containers w/ the same vhost, falling back to "http" */}}
|
||||||
|
{{ $proto := trim (or (first (groupByKeys $containers "Env.VIRTUAL_PROTO")) "http") }}
|
||||||
|
|
||||||
|
{{/* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external" */}}
|
||||||
|
{{ $network_tag := or (first (groupByKeys $containers "Env.NETWORK_ACCESS")) "external" }}
|
||||||
|
|
||||||
|
{{/* Get the HTTPS_METHOD defined by containers w/ the same vhost, falling back to "redirect" */}}
|
||||||
|
{{ $https_method := or (first (groupByKeys $containers "Env.HTTPS_METHOD")) "redirect" }}
|
||||||
|
|
||||||
|
{{/* Get the SSL_POLICY defined by containers w/ the same vhost, falling back to "Mozilla-Intermediate" */}}
|
||||||
|
{{ $ssl_policy := or (first (groupByKeys $containers "Env.SSL_POLICY")) "Mozilla-Intermediate" }}
|
||||||
|
|
||||||
|
{{/* Get the HSTS defined by containers w/ the same vhost, falling back to "max-age=31536000" */}}
|
||||||
|
{{ $hsts := or (first (groupByKeys $containers "Env.HSTS")) "max-age=31536000" }}
|
||||||
|
|
||||||
|
{{/* Get the VIRTUAL_ROOT By containers w/ use fastcgi root */}}
|
||||||
|
{{ $vhost_root := or (first (groupByKeys $containers "Env.VIRTUAL_ROOT")) "/var/www/public" }}
|
||||||
|
|
||||||
|
|
||||||
|
{{/* Get the first cert name defined by containers w/ the same vhost */}}
|
||||||
|
{{ $certName := (first (groupByKeys $containers "Env.CERT_NAME")) }}
|
||||||
|
|
||||||
|
{{/* Get the best matching cert by name for the vhost. */}}
|
||||||
|
{{ $vhostCert := (closest (dir "/etc/nginx/certs") (printf "%s.crt" $host))}}
|
||||||
|
|
||||||
|
{{/* vhostCert is actually a filename so remove any suffixes since they are added later */}}
|
||||||
|
{{ $vhostCert := trimSuffix ".crt" $vhostCert }}
|
||||||
|
{{ $vhostCert := trimSuffix ".key" $vhostCert }}
|
||||||
|
|
||||||
|
{{/* Use the cert specified on the container or fallback to the best vhost match */}}
|
||||||
|
{{ $cert := (coalesce $certName $vhostCert) }}
|
||||||
|
|
||||||
|
{{ $is_https := (and (ne $https_method "nohttps") (ne $cert "") (exists (printf "/etc/nginx/certs/%s.crt" $cert)) (exists (printf "/etc/nginx/certs/%s.key" $cert))) }}
|
||||||
|
|
||||||
|
{{ if $is_https }}
|
||||||
|
|
||||||
|
{{ if eq $https_method "redirect" }}
|
||||||
|
server {
|
||||||
|
server_name {{ $host }};
|
||||||
|
listen 80 {{ $default_server }};
|
||||||
|
{{ if $enable_ipv6 }}
|
||||||
|
listen [::]:80 {{ $default_server }};
|
||||||
|
{{ end }}
|
||||||
|
access_log /var/log/nginx/access.log vhost;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
server {
|
||||||
|
server_name {{ $host }};
|
||||||
|
listen 443 ssl http2 {{ $default_server }};
|
||||||
|
{{ if $enable_ipv6 }}
|
||||||
|
listen [::]:443 ssl http2 {{ $default_server }};
|
||||||
|
{{ end }}
|
||||||
|
access_log /var/log/nginx/access.log vhost;
|
||||||
|
|
||||||
|
{{ if eq $network_tag "internal" }}
|
||||||
|
# Only allow traffic from internal clients
|
||||||
|
include /etc/nginx/network_internal.conf;
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $ssl_policy "Mozilla-Modern" }}
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
|
||||||
|
{{ else if eq $ssl_policy "Mozilla-Intermediate" }}
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS';
|
||||||
|
{{ else if eq $ssl_policy "Mozilla-Old" }}
|
||||||
|
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP';
|
||||||
|
{{ else if eq $ssl_policy "AWS-TLS-1-2-2017-01" }}
|
||||||
|
ssl_protocols TLSv1.2 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';
|
||||||
|
{{ else if eq $ssl_policy "AWS-TLS-1-1-2017-01" }}
|
||||||
|
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
|
||||||
|
{{ else if eq $ssl_policy "AWS-2016-08" }}
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
|
||||||
|
{{ else if eq $ssl_policy "AWS-2015-05" }}
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DES-CBC3-SHA';
|
||||||
|
{{ else if eq $ssl_policy "AWS-2015-03" }}
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA';
|
||||||
|
{{ else if eq $ssl_policy "AWS-2015-02" }}
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA';
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
ssl_session_timeout 5m;
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_session_tickets off;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/certs/{{ (printf "%s.crt" $cert) }};
|
||||||
|
ssl_certificate_key /etc/nginx/certs/{{ (printf "%s.key" $cert) }};
|
||||||
|
|
||||||
|
{{ if (exists (printf "/etc/nginx/certs/%s.dhparam.pem" $cert)) }}
|
||||||
|
ssl_dhparam {{ printf "/etc/nginx/certs/%s.dhparam.pem" $cert }};
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if (exists (printf "/etc/nginx/certs/%s.chain.pem" $cert)) }}
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
ssl_trusted_certificate {{ printf "/etc/nginx/certs/%s.chain.pem" $cert }};
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if (and (ne $https_method "noredirect") (ne $hsts "off")) }}
|
||||||
|
add_header Strict-Transport-Security "{{ trim $hsts }}" always;
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
|
||||||
|
include {{ printf "/etc/nginx/vhost.d/%s" $host }};
|
||||||
|
{{ else if (exists "/etc/nginx/vhost.d/default") }}
|
||||||
|
include /etc/nginx/vhost.d/default;
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
{{ if eq $proto "uwsgi" }}
|
||||||
|
include uwsgi_params;
|
||||||
|
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||||
|
{{ else if eq $proto "fastcgi" }}
|
||||||
|
root {{ trim $vhost_root }};
|
||||||
|
include fastcgi.conf;
|
||||||
|
fastcgi_pass {{ trim $upstream_name }};
|
||||||
|
{{ else }}
|
||||||
|
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
|
||||||
|
auth_basic "Restricted {{ $host }}";
|
||||||
|
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }};
|
||||||
|
{{ end }}
|
||||||
|
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
|
||||||
|
include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
|
||||||
|
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
|
||||||
|
include /etc/nginx/vhost.d/default_location;
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if or (not $is_https) (eq $https_method "noredirect") }}
|
||||||
|
|
||||||
|
server {
|
||||||
|
server_name {{ $host }};
|
||||||
|
listen 80 {{ $default_server }};
|
||||||
|
{{ if $enable_ipv6 }}
|
||||||
|
listen [::]:80 {{ $default_server }};
|
||||||
|
{{ end }}
|
||||||
|
access_log /var/log/nginx/access.log vhost;
|
||||||
|
|
||||||
|
{{ if eq $network_tag "internal" }}
|
||||||
|
# Only allow traffic from internal clients
|
||||||
|
include /etc/nginx/network_internal.conf;
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
|
||||||
|
include {{ printf "/etc/nginx/vhost.d/%s" $host }};
|
||||||
|
{{ else if (exists "/etc/nginx/vhost.d/default") }}
|
||||||
|
include /etc/nginx/vhost.d/default;
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
{{ if eq $proto "uwsgi" }}
|
||||||
|
include uwsgi_params;
|
||||||
|
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||||
|
{{ else if eq $proto "fastcgi" }}
|
||||||
|
root {{ trim $vhost_root }};
|
||||||
|
include fastcgi.conf;
|
||||||
|
fastcgi_pass {{ trim $upstream_name }};
|
||||||
|
{{ else }}
|
||||||
|
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||||
|
{{ end }}
|
||||||
|
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
|
||||||
|
auth_basic "Restricted {{ $host }}";
|
||||||
|
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }};
|
||||||
|
{{ end }}
|
||||||
|
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
|
||||||
|
include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
|
||||||
|
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
|
||||||
|
include /etc/nginx/vhost.d/default_location;
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
|
||||||
|
server {
|
||||||
|
server_name {{ $host }};
|
||||||
|
listen 443 ssl http2 {{ $default_server }};
|
||||||
|
{{ if $enable_ipv6 }}
|
||||||
|
listen [::]:443 ssl http2 {{ $default_server }};
|
||||||
|
{{ end }}
|
||||||
|
access_log /var/log/nginx/access.log vhost;
|
||||||
|
return 500;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/certs/default.crt;
|
||||||
|
ssl_certificate_key /etc/nginx/certs/default.key;
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
18
scripts/base.sh
Normal file
18
scripts/base.sh
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Basic scripts
|
||||||
|
#
|
||||||
|
|
||||||
|
# 1. Check if .env file exists
|
||||||
|
check_env_file() {
|
||||||
|
if [ -e .env ]; then
|
||||||
|
source .env
|
||||||
|
else
|
||||||
|
echo
|
||||||
|
echo "Please set up your .env file before starting your enviornment."
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
42
scripts/update.sh
Executable file
42
scripts/update.sh
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# This scrip update the web proxy without downtime
|
||||||
|
#
|
||||||
|
# Source: https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion
|
||||||
|
#
|
||||||
|
|
||||||
|
# 1. Check if .env file exists
|
||||||
|
if [ -e .env ]; then
|
||||||
|
source .env
|
||||||
|
else
|
||||||
|
echo
|
||||||
|
echo "Please set up your .env file before starting your enviornment."
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Update your repo
|
||||||
|
git pull
|
||||||
|
git checkout master
|
||||||
|
|
||||||
|
# 3. Check if your env files has the same line numbers
|
||||||
|
if [ "$(wc -l .env | cut -f1 -d' ')" != "$(wc -l .env.sample | cut -f1 -d' ')" ]; then
|
||||||
|
echo
|
||||||
|
echo "The sample .env are different from the your current .env file."
|
||||||
|
echo "Please update your .env file to continue."
|
||||||
|
echo "It must has the same lines of the sample env file."
|
||||||
|
echo
|
||||||
|
echo "If you keep receiving this message please check the number of line of both files"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Download the latest version of nginx.tmpl
|
||||||
|
curl https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl > nginx.tmpl
|
||||||
|
|
||||||
|
# 4. Update containers without downtime
|
||||||
|
docker-compose up -d --no-deps --build nginx-web
|
||||||
|
docker-compose up -d --no-deps --build nginx-gen
|
||||||
|
docker-compose up -d --no-deps --build nginx-letsencrypt
|
||||||
|
|
||||||
|
exit 0
|
68
start.sh
Executable file
68
start.sh
Executable file
@ -0,0 +1,68 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# This file should be used to prepare and run your WebProxy after set up your .env file
|
||||||
|
# Source: https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion
|
||||||
|
#
|
||||||
|
|
||||||
|
# 1. Check if .env file exists
|
||||||
|
if [ -e .env ]; then
|
||||||
|
source .env
|
||||||
|
else
|
||||||
|
echo "Please set up your .env file before starting your environment."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Create docker network
|
||||||
|
docker network create $NETWORK $NETWORK_OPTIONS
|
||||||
|
|
||||||
|
# 3. Verify if second network is configured
|
||||||
|
if [ ! -z ${SERVICE_NETWORK+X} ]; then
|
||||||
|
docker network create $SERVICE_NETWORK $SERVICE_NETWORK_OPTIONS
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Download the latest version of nginx.tmpl
|
||||||
|
curl https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl > nginx.tmpl
|
||||||
|
|
||||||
|
# 5. Update local images
|
||||||
|
docker-compose pull
|
||||||
|
|
||||||
|
# 6. Add any special configuration if it's set in .env file
|
||||||
|
|
||||||
|
# Check if user set to use Special Conf Files
|
||||||
|
if [ ! -z ${USE_NGINX_CONF_FILES+X} ] && [ "$USE_NGINX_CONF_FILES" = true ]; then
|
||||||
|
|
||||||
|
# Create the conf folder if it does not exists
|
||||||
|
mkdir -p $NGINX_FILES_PATH/conf.d
|
||||||
|
|
||||||
|
# Copy the special configurations to the nginx conf folder
|
||||||
|
cp -R ./conf.d/* $NGINX_FILES_PATH/conf.d
|
||||||
|
|
||||||
|
# Check if there was an error and try with sudo
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
sudo cp -R ./conf.d/* $NGINX_FILES_PATH/conf.d
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If there was any errors inform the user
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo
|
||||||
|
echo "#######################################################"
|
||||||
|
echo
|
||||||
|
echo "There was an error trying to copy the nginx conf files."
|
||||||
|
echo "The webproxy will still work, your custom configuration"
|
||||||
|
echo "will not be loaded."
|
||||||
|
echo
|
||||||
|
echo "#######################################################"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7. Start proxy
|
||||||
|
|
||||||
|
# Check if you have multiple network
|
||||||
|
if [ -z ${SERVICE_NETWORK+X} ]; then
|
||||||
|
docker-compose up -d
|
||||||
|
else
|
||||||
|
docker-compose -f docker-compose-multiple-networks.yml up -d
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
22
test_start.sh
Executable file
22
test_start.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Set up your DOMAIN
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo "Please inform your domain name to test your proxy."
|
||||||
|
echo "./test_start.sh $1"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
DOMAIN=$1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Read your .env file
|
||||||
|
source .env
|
||||||
|
|
||||||
|
# Testing your proxy
|
||||||
|
if [ -z ${SERVICE_NETWORK+X} ]; then
|
||||||
|
docker run -d -e VIRTUAL_HOST=$DOMAIN --network=$NETWORK --name test-web httpd:alpine
|
||||||
|
else
|
||||||
|
docker run -d -e VIRTUAL_HOST=$DOMAIN --network=$SERVICE_NETWORK --name test-web httpd:alpine
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
25
test_start_ssl.sh
Executable file
25
test_start_ssl.sh
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
NAME=test-web
|
||||||
|
|
||||||
|
|
||||||
|
# Set up your DOMAIN
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo "Please inform your domain name to test your proxy."
|
||||||
|
echo "./test_start_ssl.sh $1"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
DOMAIN=$1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Read your .env file
|
||||||
|
source .env
|
||||||
|
|
||||||
|
# Testing your proxy
|
||||||
|
if [ -z ${SERVICE_NETWORK+X} ]; then
|
||||||
|
docker run -d -e VIRTUAL_HOST=$DOMAIN -e LETSENCRYPT_HOST=$DOMAIN --network=$NETWORK --name $NAME httpd:alpine
|
||||||
|
else
|
||||||
|
docker run -d -e VIRTUAL_HOST=$DOMAIN -e LETSENCRYPT_HOST=$DOMAIN --network=$SERVICE_NETWORK --name $NAME httpd:alpine
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
6
test_stop.sh
Executable file
6
test_stop.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Stop and remove test enviornment
|
||||||
|
docker stop test-web && docker rm test-web
|
||||||
|
|
||||||
|
exit 0
|
Loading…
Reference in New Issue
Block a user