├── .env.sample
├── .github
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── README.md
└── workflows
│ └── testing.yml
├── .gitignore
├── .gitmodules
├── LICENSE
├── bin
├── .env
├── fix-git-submodule.sh
├── fresh-start.sh
├── install.sh
├── localscript
│ ├── bootstrap.sh
│ ├── check-docker-nginx-proxy-automation-env-file.sh
│ ├── check-local-env-file.sh
│ ├── update-docker-compose-file.sh
│ ├── update-env-new-site-variables.sh
│ └── usage-fresh-start.sh
├── revert.sh
├── ssl_test.sh
├── stop.sh
├── test.sh
├── update-branch-name.sh
├── update-checksum.sh
└── update-nginx-template.sh
├── conf.d
├── realip.conf
├── servertokens.conf
└── uploadsize.conf
├── docker-compose.yml
├── docs
├── HOWTO-Synology.md
├── HOWTO-server-at-home.md
├── README.md
├── cloudflare.md
├── requirements.md
└── upgrade-guide.md
└── nginx.tmpl
/.env.sample:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------
2 | #
3 | # https://github.com/evertramos/nginx-proxy-automation
4 | #
5 | # NGINX Proxy automation
6 | #
7 | # This is the .env file to set up nginx-proxy in your environment
8 | #
9 | #-----------------------------------------------------------------------
10 |
11 | #-----------------------------------------------------------------------
12 | #
13 | # Script requirements
14 | #
15 |
16 | # PID file the running script
17 | PID_FILE=.fresh_start.pid
18 |
19 | # Allow run commands with sudo if needed
20 | ALLOW_RUN_WITH_SUDO=false
21 |
22 | #-----------------------------------------------------------------------
23 | #
24 | # NGINX-Proxy containers/service
25 | #
26 | # The variables below is used to set the containers name for the nginx-proxy
27 | # and the image version for each service, please note that if you use our script
28 | # we will replace the service name in docker-compose file with the container name
29 | #
30 | NGINX_WEB_SEVICE_NAME=proxy-web
31 | NGINX_IMAGE_VERSION=stable-alpine
32 |
33 | DOCKER_GEN_SEVICE_NAME=docker-gen
34 | DOCKER_GEN_IMAGE_VERSION=latest
35 |
36 | LETS_ENCRYPT_SEVICE_NAME=acme-companion
37 | NGINX_PROXY_COMPANION_IMAGE_VERSION=latest
38 |
39 | #-----------------------------------------------------------------------
40 | #
41 | # IP address of the external interface
42 | #
43 | # The IP address below is used to bind your local services to the internet
44 | # please make sure you use the correct address otherwise your proxy will not
45 | # work properly, '0.0.0.0' will work, but we recommend to update this variable
46 | #
47 | IPv4=0.0.0.0
48 | IPv6=::0
49 |
50 | #-----------------------------------------------------------------------
51 | #
52 | # Default network name
53 | #
54 | # The network name set below is used by the proxy to forward internet requests
55 | # to the correct containers in your environment, so please make sure to add this
56 | # network in all docker containers, otherwise it will break the proxy redirection
57 | #
58 | NETWORK=proxy
59 |
60 | #-----------------------------------------------------------------------
61 | #
62 | # Data path for the nginx-proxy files
63 | #
64 | # The variable below will be used to place all files used by the nginx-proxy
65 | # please consider including this folder to your backup services, once all config
66 | # files, settings and certificates will be placed here in case you need to recover
67 | #
68 | NGINX_FILES_PATH=./data
69 |
70 | #-----------------------------------------------------------------------
71 | #
72 | # Docker logging settings
73 | #
74 | # Logs! Very important, right? But if you do not clean it up, it might causes you
75 | # issues on disk space over time, so keep in mind to set this log options making sure
76 | # you will have the least to audit, any further information on that please check the docs
77 | #
78 | # https://docs.docker.com/config/containers/logging/configure/
79 | #
80 | NGINX_WEB_LOG_DRIVER=json-file
81 | NGINX_WEB_LOG_MAX_SIZE=4m
82 | NGINX_WEB_LOG_MAX_FILE=10
83 |
84 | NGINX_GEN_LOG_DRIVER=json-file
85 | NGINX_GEN_LOG_MAX_SIZE=2m
86 | NGINX_GEN_LOG_MAX_FILE=10
87 |
88 | NGINX_LETSENCRYPT_LOG_DRIVER=json-file
89 | NGINX_LETSENCRYPT_LOG_MAX_SIZE=2m
90 | NGINX_LETSENCRYPT_LOG_MAX_FILE=10
91 |
92 | #-----------------------------------------------------------------------
93 | #
94 | # Docker ports that should be binded by the proxy
95 | #
96 | # This option were added by a contributor long ago, so might be a very specific case
97 | # where you might need to change http and https port number, keep in mind that changes
98 | # on that setting might will break the auto renewing Let's Encrypt certificate services
99 | #
100 | DOCKER_HTTP_=80
101 | DOCKER_HTTPS=443
102 |
103 | #-----------------------------------------------------------------------
104 | #
105 | # SSL policy (defaults to Mozilla-Intermediate)
106 | #
107 | # This also was added by a contributor which sets the default cipher configuration
108 | # to the nginx-proxy container, which has the 'Mozilla-Intermediate' as default value
109 | # plase make sure you take a good look at options in the url below before messing around
110 | #
111 | # https://github.com/nginx-proxy/nginx-proxy#how-ssl-support-works
112 | #
113 | #SSL_POLICY=Mozilla-Modern
114 |
115 | #-----------------------------------------------------------------------
116 | #
117 | # Let's Encrypt default email
118 | #
119 | # You might want to inform a default email to Let's Encrypt certificate once it is
120 | # a required parameter in order to issue the new certificate. This information will be
121 | # replaced by the LETSENCRYPT_EMAIL environment varibale present in your docker container
122 | #
123 | DEFAULT_EMAIL=mail@yourdomain.tld
124 |
125 | #-----------------------------------------------------------------------
126 | #
127 | # Default host
128 | #
129 | # Nginx-proxy will then redirect all requests to a container where you have set
130 | # "VIRTUAL HOST" set to "DEFAULT HOST", if they don't match any (other) container
131 | # You might want to check the link below for more information:
132 | # https://github.com/nginx-proxy/nginx-proxy#default-host
133 | #
134 | DEFAULT_HOST=
135 |
136 | #-----------------------------------------------------------------------
137 | #
138 | # Docker Rootless
139 | #
140 | # In case you want to use this proxy on Docker Rootless (DR) and you also have followed
141 | # the DR installation from the official documentation (https://docs.docker.com/engine/security/rootless/)
142 | # Set the following value of the DOCKER_HOST variable that you got in the final info messages after executing
143 | # the "$ dockerd-rootless-setuptool.sh install" command.
144 | # For example DOCKER_HOST_PATH=$XDG_RUNTIME_DIR/docker.sock
145 | # If you are not using Docker Rootless, leave this variable blank
146 | DOCKER_HOST_ROOTLESS_PATH=
147 |
148 | #-----------------------------------------------------------------------
149 | #
150 | # Cloudflare API Token
151 | #
152 | # Despite nginx-proxy suggest the usage of global API keys,
153 | # I rather use a more restrict API token which you can follow
154 | # the steps to create it with Zone DNS restriction as documented.
155 | #
156 | # https://github.com/evertramos/nginx-proxy-automation/blob/main/docs/cloudflare.md
157 | #
158 | CLOUDFLARE_DNS_TOKEN=
159 |
--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at evert.ramos@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributions
2 |
3 | ### NGINX template file (nginx.tmpl)
4 |
5 | All contributions regarding the `nginx.tmpl` should be suggested or implemented in the [nginx-proxy repository](https://github.com/nginx-proxy/nginx-proxy).
6 |
7 | We always use the latest version of this file:
8 |
9 | [https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl](https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl)
10 |
11 | ### Pull requests
12 |
13 | Sometimes it's better to start a discussion or an issue to find out the best solution of suggestion before sending a pull request... and if you do so, please test it with the automation script before sending new code.
14 |
15 |
16 | Thanks!
17 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: evertramos
5 | open_collective: # nginx-proxy-automation
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG]"
5 | labels: ''
6 | assignees: evertramos
7 |
8 | ---
9 |
10 | **Check [Discussions](https://github.com/evertramos/nginx-proxy-automation/discussions) to see if there is an answer might help you before opening an issue**
11 |
12 | **Describe the bug**
13 | A clear and concise description of what the bug is.
14 |
15 | **To Reproduce**
16 | Steps to reproduce the behavior:
17 | 1. Run the script....
18 | 2. ...
19 |
20 | **Server info (please complete the following information):**
21 | - Linux release:
22 | - Server type:
23 | - Docker version:
24 | - docker-compose version:
25 |
26 | **Logs:**
27 | - basescript.log (send only last execution log with an error) - This log is in ./bin folder
28 | - nginx container logs
29 | - letsencrypt/acme container (if related to ssl)
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: evertramos
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/README.md:
--------------------------------------------------------------------------------
1 |
2 | # NGINX Proxy Automation 🔥
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | ## How to start 🔰
18 | [](https://github.com/evertramos)
19 |
20 |
21 | 1. Clone this repository using the option **_--recurse-submodules_** ⚠️
22 |
23 | ```bash
24 | git clone --recurse-submodules https://github.com/evertramos/nginx-proxy-automation.git proxy
25 | ```
26 |
27 | We use submodule for [basescript](https://github.com/evertramos/basescript)
28 |
29 | 2. 🚀 Run the script 'fresh_start.sh' from the _./proxy/bin_ folder
30 |
31 | ```bash
32 | cd proxy/bin && ./fresh-start.sh --yes --skip-docker-image-check -e your_email@domain
33 | ```
34 |
35 | Update the email above with your real e-mail address
36 |
37 | 3. 🧪 Test the proxy
38 |
39 | ```bash
40 | docker run -dit -e VIRTUAL_HOST=your.domain.com --network=proxy --name test-web httpd:alpine
41 | ```
42 | or simply run:
43 | ```bash
44 | ./test.sh your.domain.com
45 | ```
46 |
47 | Use your own domain name when testing this proxy and make sure your DNS is correctly configured.
48 |
49 | ## Video Tutorial 🎥
50 |
51 | I made a tutorial video to walk you through this project:
52 |
53 | [](https://www.youtube.com/channel/UCN5wb0eA3ZLlvJNYo23qBRQ)
54 |
55 | ### AWS EC2
56 |
57 |
58 |
59 |
60 | ### Digital Ocean Droplet
61 |
62 |
63 |
64 |
65 | ### OVH
66 |
67 |
68 |
69 |
70 | ## Server Automation 🚀
71 |
72 | Make user you try our [Server Automation](https://github.com/evertramos/server-automation)
73 |
74 | [https://github.com/evertramos/server-automation](https://github.com/evertramos/server-automation)
75 |
76 | ## Further information 📓
77 |
78 | For more installation details please [click here](/docs/).
79 |
80 | ## Supporting ♥️
81 | [](https://www.patreon.com/evertramos)
82 | [](https://picpay.me/evert.ramos)
83 |
84 | [List of all supporters](https://github.com/evertramos/evertramos/blob/main/pages/supporters.md).
85 |
86 | ## Code Contributors
87 |
88 | [
](https://opencollective.com/nginx-proxy-automation)
89 |
--------------------------------------------------------------------------------
/.github/workflows/testing.yml:
--------------------------------------------------------------------------------
1 | name: Testing Proxy Automation
2 |
3 | on:
4 | push:
5 | branches: [ "main" ]
6 | pull_request:
7 | branches: [ "main" ]
8 |
9 | workflow_dispatch:
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - uses: actions/checkout@v3
17 | with:
18 | submodules: true
19 |
20 | #- name: Testing if has docker
21 | # run: docker ps -q -a
22 |
23 | # Runs a set of commands using the runners shell
24 | - name: Run a multi-line script
25 | run: |
26 | cd ./bin
27 | ./fresh-start.sh --yes -e evert.ramos@gmail.com --skip-docker-image-check
28 |
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | data
2 | .env*
3 | !.env.sample
4 | .DS_Store
5 | .idea/
6 | /bin/basescript.log
7 | /docker-compose.yml.*
8 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "basescript"]
2 | path = basescript
3 | url = https://github.com/evertramos/basescript.git
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Evert Ramos
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/bin/.env:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------
2 | #
3 | # https://github.com/evertramos/nginx-proxy-automation
4 | #
5 | # NGINX Proxy automation
6 | #
7 | # This is the .env file with default values for the nginx-proxy-automation script
8 | #
9 | #-----------------------------------------------------------------------
10 |
11 | #-----------------------------------------------------------------------
12 | #
13 | # NGINX-Proxy default image, version and service name
14 | #
15 | DEFAULT_NGINX_PROXY_SERVICE_NAME=proxy-web
16 | DEFAULT_NGINX_PROXY_IMAGE_NAME="nginx"
17 | DEFAULT_NGINX_PROXY_IMAGE_VERSION="stable-alpine"
18 |
19 | #-----------------------------------------------------------------------
20 | #
21 | # Docker-gen default image, version and service name
22 | #
23 | DEFAULT_DOCKER_GEN_SERVICE_NAME=docker-gen
24 | DEFAULT_DOCKER_GEN_IMAGE_NAME="nginxproxy/docker-gen"
25 | DEFAULT_DOCKER_GEN_IMAGE_VERSION="0.14"
26 |
27 | #-----------------------------------------------------------------------
28 | #
29 | # Letsencrypt acme-compantion default image, version and service name
30 | #
31 | DEFAULT_LETSENCRYPT_SERVICE_NAME=acme-companion
32 | DEFAULT_LETSENCRYPT_IMAGE_NAME="nginxproxy/acme-companion"
33 | DEFAULT_LETSENCRYPT_IMAGE_VERSION="2.5"
34 |
35 | #-----------------------------------------------------------------------
36 | #
37 | # Network default name for the nginx-proxy
38 | #
39 | DEFAULT_DOCKER_NETWORK_NAME=proxy
40 |
41 | #-----------------------------------------------------------------------
42 | #
43 | # Data path for the nginx-proxy files
44 | #
45 | #DEFAULT_DATA_LOCATION="./data"
46 |
47 | #-----------------------------------------------------------------------
48 | #
49 | # Default servies name in docker-compose.yml
50 | #
51 | REPLACE_NGINX_PROXY_SERVICE_NAME="nginx-proxy-automation-web"
52 | REPLACE_DOCKER_GEN_SERVICE_NAME="nginx-proxy-automation-gen"
53 | REPLACE_LETSENCRYPT_SERVICE_NAME="nginx-proxy-automation-letsencrypt"
54 |
55 | #-----------------------------------------------------------------------
56 | #
57 | # md5 checksum for .env and docker-compose.yml files
58 | #
59 | MD5_SUM_DOCKER_COMPOSE=54590c26c4f3d0ce52ef9ea4268d1408
60 | MD5_SUM_ENV_SAMPLE=eb0ca95b7f2d14d11e337863d8e47566
61 |
--------------------------------------------------------------------------------
/bin/fix-git-submodule.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # This script updates the branch name to 'main'
5 | #
6 | # Source: https://github.com/evertramos/nginx-proxy-automation
7 | #
8 |
9 | # Get the script name and its real file path
10 | SCRIPT_PATH="$(dirname "$(readlink -f "$0")")"
11 | SCRIPT_NAME="${0##*/}"
12 | CURRENT_PATH=$(pwd)
13 |
14 | cd "${SCRIPT_PATH}/../basescript"
15 |
16 | # Set submodules
17 | git submodule init
18 | git submodule update
19 |
20 | echo "Submodule is set"
21 |
22 | exit 0
23 |
24 |
--------------------------------------------------------------------------------
/bin/fresh-start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #-----------------------------------------------------------------------
4 | #
5 | # Fresh Start script - set up nginx-proxy in a fresh installed server
6 | #
7 | # https://github.com/evertramos/nginx-proxy-automation
8 | #
9 | # Script developed by
10 | # Evert Ramos
11 | #
12 | # Copyright Evert Ramos
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | # Bash settings (do not mess with it)
17 | shopt -s nullglob globstar
18 |
19 | # Get the script name and its file real path
20 | SCRIPT_PATH="$(dirname "$(readlink -f "$0")")"
21 | SCRIPT_NAME="${0##*/}"
22 |
23 | # Source basescript functions
24 | source $SCRIPT_PATH"/../basescript/bootstrap.sh"
25 |
26 | # Source localscripts
27 | source $SCRIPT_PATH"/localscript/bootstrap.sh"
28 |
29 | # Log
30 | printf "${energy} Start execution '${SCRIPT_PATH}/${SCRIPT_NAME} "
31 | log "Start execution"
32 | log "$@"
33 |
34 | #-----------------------------------------------------------------------
35 | # Process arguments
36 | #-----------------------------------------------------------------------
37 | while [[ $# -gt 0 ]]; do
38 | case "$1" in
39 | -d)
40 | ARG_DATA_LOCATION="${2}"
41 | if [[ $ARG_DATA_LOCATION == "" ]]; then
42 | echoerror "Invalid option for -d"
43 | break
44 | fi
45 | shift 2
46 | ;;
47 | --data-files-location=*)
48 | ARG_DATA_LOCATION="${1#*=}"
49 | if [[ $ARG_DATA_LOCATION == "" ]]; then
50 | echoerror "Invalid option for --data-files-location=''"
51 | break
52 | fi
53 | shift 1
54 | ;;
55 | -e)
56 | ARG_DEFAULT_EMAIL="${2}"
57 | if [[ $ARG_DEFAULT_EMAIL == "" ]]; then
58 | echoerror "Invalid option for -e"
59 | break
60 | fi
61 | shift 2
62 | ;;
63 | --default-email=*)
64 | ARG_DEFAULT_EMAIL="${1#*=}"
65 | if [[ $ARG_DEFAULT_EMAIL == "" ]]; then
66 | echoerror "Invalid option for --default-email=''"
67 | break
68 | fi
69 | shift 1
70 | ;;
71 | -pn)
72 | ARG_NGINX_PROXY_SERVICE_NAME="${2}"
73 | if [[ $ARG_NGINX_PROXY_SERVICE_NAME == "" ]]; then
74 | echoerror "Invalid option for -pn"
75 | break
76 | fi
77 | shift 2
78 | ;;
79 | --proxy-name=*)
80 | ARG_NGINX_PROXY_SERVICE_NAME="${1#*=}"
81 | if [[ $ARG_NGINX_PROXY_SERVICE_NAME == "" ]]; then
82 | echoerror "Invalid option for --proxy-name=''"
83 | break
84 | fi
85 | shift 1
86 | ;;
87 | -ln)
88 | ARG_LETSENCRYPT_SERVICE_NAME="${2}"
89 | if [[ $ARG_LETSENCRYPT_SERVICE_NAME == "" ]]; then
90 | echoerror "Invalid option for -ln"
91 | break
92 | fi
93 | shift 2
94 | ;;
95 | --letsencrypt-name=*)
96 | ARG_LETSENCRYPT_SERVICE_NAME="${1#*=}"
97 | if [[ $ARG_LETSENCRYPT_SERVICE_NAME == "" ]]; then
98 | echoerror "Invalid option for --letsencrypt-name=''"
99 | break
100 | fi
101 | shift 1
102 | ;;
103 | -gn)
104 | ARG_DOCKER_GEN_SERVICE_NAME="${2}"
105 | if [[ $ARG_DOCKER_GEN_SERVICE_NAME == "" ]]; then
106 | echoerror "Invalid option for -gn"
107 | break
108 | fi
109 | shift 2
110 | ;;
111 | --docker-gen-name=*)
112 | ARG_DOCKER_GEN_SERVICE_NAME="${1#*=}"
113 | if [[ $ARG_DOCKER_GEN_SERVICE_NAME == "" ]]; then
114 | echoerror "Invalid option for --docker-gen-name=''"
115 | break
116 | fi
117 | shift 1
118 | ;;
119 | -piv)
120 | ARG_NGINX_PROXY_IMAGE_VERSION="${2}"
121 | if [[ $ARG_NGINX_PROXY_IMAGE_VERSION == "" ]]; then
122 | echoerror "Invalid option for -pversion"
123 | break
124 | fi
125 | shift 2
126 | ;;
127 | --proxy-image-version=*)
128 | ARG_NGINX_PROXY_IMAGE_VERSION="${1#*=}"
129 | if [[ $ARG_NGINX_PROXY_IMAGE_VERSION == "" ]]; then
130 | echoerror "Invalid option for --proxy-image-version=''"
131 | break
132 | fi
133 | shift 1
134 | ;;
135 | -liv)
136 | ARG_LETSENCRYPT_IMAGE_VERSION="${2}"
137 | if [[ $ARG_LETSENCRYPT_IMAGE_VERSION == "" ]]; then
138 | echoerror "Invalid option for -liv"
139 | break
140 | fi
141 | shift 2
142 | ;;
143 | --letsencrypt-image-version=*)
144 | ARG_LETSENCRYPT_IMAGE_VERSION="${1#*=}"
145 | if [[ $ARG_LETSENCRYPT_IMAGE_VERSION == "" ]]; then
146 | echoerror "Invalid option for --letsencrypt-image-version=''"
147 | break
148 | fi
149 | shift 1
150 | ;;
151 | -giv)
152 | ARG_DOCKER_GEN_IMAGE_VERSION="${2}"
153 | if [[ $ARG_DOCKER_GEN_IMAGE_VERSION == "" ]]; then
154 | echoerror "Invalid option for -giv"
155 | break
156 | fi
157 | shift 2
158 | ;;
159 | --docker-gen-image-version=*)
160 | ARG_DOCKER_GEN_IMAGE_VERSION="${1#*=}"
161 | if [[ $ARG_DOCKER_GEN_IMAGE_VERSION == "" ]]; then
162 | echoerror "Invalid option for --docker-gen-image-version=''"
163 | break
164 | fi
165 | shift 1
166 | ;;
167 |
168 | # Network options
169 | -ip)
170 | ARG_IP_ADDRESS="${2}"
171 | if [[ $ARG_IP_ADDRESS == "" ]]; then
172 | echoerror "Invalid option for -ip"
173 | break
174 | fi
175 | shift 2
176 | ;;
177 | --ip-address=*)
178 | ARG_IP_ADDRESS="${1#*=}"
179 | if [[ $ARG_IP_ADDRESS == "" ]]; then
180 | echoerror "Invalid option for --ip-address"
181 | break
182 | fi
183 | shift 1
184 | ;;
185 | -ipv6)
186 | ARG_IPv6_ADDRESS="${2}"
187 | if [[ $ARG_IPv6_ADDRESS == "" ]]; then
188 | echoerror "Invalid option for -ipv6"
189 | break
190 | fi
191 | shift 2
192 | ;;
193 | --ipv6-address=*)
194 | ARG_IPv6_ADDRESS="${1#*=}"
195 | if [[ $ARG_IPv6_ADDRESS == "" ]]; then
196 | echoerror "Invalid option for --ipv6-address"
197 | break
198 | fi
199 | shift 1
200 | ;;
201 | -net)
202 | ARG_NETWORK_NAME="${2}"
203 | if [[ $ARG_NETWORK_NAME == "" ]]; then
204 | echoerror "Invalid option for -net"
205 | break
206 | fi
207 | shift 2
208 | ;;
209 | --network-name=*)
210 | ARG_NETWORK_NAME="${1#*=}"
211 | if [[ $ARG_NETWORK_NAME == "" ]]; then
212 | echoerror "Invalid option for --network-name"
213 | break
214 | fi
215 | shift 1
216 | ;;
217 | -netopt)
218 | NETWORK_OPTION="${2}"
219 | if [[ $NETWORK_OPTION == "" ]]; then
220 | echoerror "Invalid option for -netopt"
221 | break
222 | fi
223 | shift 2
224 | ;;
225 | --network-option=*)
226 | NETWORK_OPTION="${1#*=}"
227 | if [[ $NETWORK_OPTION == "" ]]; then
228 | echoerror "Invalid option for --network-option"
229 | break
230 | fi
231 | shift 1
232 | ;;
233 |
234 | # Log settings
235 | -lpd)
236 | ARG_NGINX_PROXY_LOG_DRIVER="${2}"
237 | if [[ $ARG_NGINX_PROXY_LOG_DRIVER == "" ]]; then
238 | echoerror "Invalid option for -lpd"
239 | break
240 | fi
241 | shift 2
242 | ;;
243 | --log-nginx-proxy-driver=*)
244 | ARG_NGINX_PROXY_LOG_DRIVER="${1#*=}"
245 | if [[ $ARG_NGINX_PROXY_LOG_DRIVER == "" ]]; then
246 | echoerror "Invalid option for --log-nginx-proxy-driver"
247 | break
248 | fi
249 | shift 1
250 | ;;
251 | -lpms)
252 | ARG_NGINX_PROXY_LOG_MAX_SIZE="${2}"
253 | if [[ $ARG_NGINX_PROXY_LOG_MAX_SIZE == "" ]]; then
254 | echoerror "Invalid option for -lpms"
255 | break
256 | fi
257 | shift 2
258 | ;;
259 | --log-nginx-proxy-max_size=*)
260 | ARG_NGINX_PROXY_LOG_MAX_SIZE="${1#*=}"
261 | if [[ $ARG_NGINX_PROXY_LOG_MAX_SIZE == "" ]]; then
262 | echoerror "Invalid option for --log-nginx-proxy-max_size"
263 | break
264 | fi
265 | shift 1
266 | ;;
267 | -lpmf)
268 | ARG_NGINX_PROXY_LOG_MAX_FILE="${2}"
269 | if [[ $ARG_NGINX_PROXY_LOG_MAX_FILE == "" ]]; then
270 | echoerror "Invalid option for -lpmf"
271 | break
272 | fi
273 | shift 2
274 | ;;
275 | --log-nginx-proxy-max_file=*)
276 | ARG_NGINX_PROXY_LOG_MAX_FILE="${1#*=}"
277 | if [[ $ARG_NGINX_PROXY_LOG_MAX_FILE == "" ]]; then
278 | echoerror "Invalid option for --log-nginx-proxy-max_file"
279 | break
280 | fi
281 | shift 1
282 | ;;
283 | -lgd)
284 | ARG_DOCKER_GEN_LOG_DRIVER="${2}"
285 | if [[ $ARG_DOCKER_GEN_LOG_DRIVER == "" ]]; then
286 | echoerror "Invalid option for -lgd"
287 | break
288 | fi
289 | shift 2
290 | ;;
291 | --log-docker-gen-driver=*)
292 | ARG_DOCKER_GEN_LOG_DRIVER="${1#*=}"
293 | if [[ $ARG_DOCKER_GEN_LOG_DRIVER == "" ]]; then
294 | echoerror "Invalid option for --log-docker-gen-driver"
295 | break
296 | fi
297 | shift 1
298 | ;;
299 | -lgms)
300 | ARG_DOCKER_GEN_LOG_MAX_SIZE="${2}"
301 | if [[ $ARG_DOCKER_GEN_LOG_MAX_SIZE == "" ]]; then
302 | echoerror "Invalid option for -lgms"
303 | break
304 | fi
305 | shift 2
306 | ;;
307 | --log-docker-gen-max_size=*)
308 | ARG_DOCKER_GEN_LOG_MAX_SIZE="${1#*=}"
309 | if [[ $ARG_DOCKER_GEN_LOG_MAX_SIZE == "" ]]; then
310 | echoerror "Invalid option for --log-docker-gen-max_size"
311 | break
312 | fi
313 | shift 1
314 | ;;
315 | -lgmf)
316 | ARG_DOCKER_GEN_LOG_MAX_FILE="${2}"
317 | if [[ $ARG_DOCKER_GEN_LOG_MAX_FILE == "" ]]; then
318 | echoerror "Invalid option for -lgmf"
319 | break
320 | fi
321 | shift 2
322 | ;;
323 | --log-docker-gen-max_file=*)
324 | ARG_DOCKER_GEN_LOG_MAX_FILE="${1#*=}"
325 | if [[ $ARG_DOCKER_GEN_LOG_MAX_FILE == "" ]]; then
326 | echoerror "Invalid option for --log-docker-gen-max_file"
327 | break
328 | fi
329 | shift 1
330 | ;;
331 | -lld)
332 | ARG_LETSENCRYPT_LOG_DRIVER="${2}"
333 | if [[ $ARG_LETSENCRYPT_LOG_DRIVER == "" ]]; then
334 | echoerror "Invalid option for -lld"
335 | break
336 | fi
337 | shift 2
338 | ;;
339 | --log-letsencrypt-driver=*)
340 | ARG_LETSENCRYPT_LOG_DRIVER="${1#*=}"
341 | if [[ $ARG_LETSENCRYPT_LOG_DRIVER == "" ]]; then
342 | echoerror "Invalid option for --log-letsencrypt-driver"
343 | break
344 | fi
345 | shift 1
346 | ;;
347 | -llms)
348 | ARG_LETSENCRYPT_LOG_MAX_SIZE="${2}"
349 | if [[ $ARG_LETSENCRYPT_LOG_MAX_SIZE == "" ]]; then
350 | echoerror "Invalid option for -llms"
351 | break
352 | fi
353 | shift 2
354 | ;;
355 | --log-letsencrypt-max_size=*)
356 | ARG_LETSENCRYPT_LOG_MAX_SIZE="${1#*=}"
357 | if [[ $ARG_LETSENCRYPT_LOG_MAX_SIZE == "" ]]; then
358 | echoerror "Invalid option for --log-letsencrypt-max_size"
359 | break
360 | fi
361 | shift 1
362 | ;;
363 | -llmf)
364 | ARG_LETSENCRYPT_LOG_MAX_FILE="${2}"
365 | if [[ $ARG_LETSENCRYPT_LOG_MAX_FILE == "" ]]; then
366 | echoerror "Invalid option for -llmf"
367 | break
368 | fi
369 | shift 2
370 | ;;
371 | --log-letsencrypt-max_file=*)
372 | ARG_LETSENCRYPT_LOG_MAX_FILE="${1#*=}"
373 | if [[ $ARG_LETSENCRYPT_LOG_MAX_FILE == "" ]]; then
374 | echoerror "Invalid option for --log-letsencrypt-max_file"
375 | break
376 | fi
377 | shift 1
378 | ;;
379 |
380 | # Port binginds
381 | -phttp)
382 | ARG_DOCKER_HTTP="${2}"
383 | if [[ $ARG_DOCKER_HTTP == "" ]]; then
384 | echoerror "Invalid option for -phttp"
385 | break
386 | fi
387 | shift 2
388 | ;;
389 | --port-http=*)
390 | ARG_DOCKER_HTTP="${1#*=}"
391 | if [[ $ARG_DOCKER_HTTP == "" ]]; then
392 | echoerror "Invalid option for --port-http"
393 | break
394 | fi
395 | shift 1
396 | ;;
397 | -phttps)
398 | ARG_DOCKER_HTTPS="${2}"
399 | if [[ $ARG_DOCKER_HTTPS == "" ]]; then
400 | echoerror "Invalid option for -phttps"
401 | break
402 | fi
403 | shift 2
404 | ;;
405 | --port-https=*)
406 | ARG_DOCKER_HTTPS="${1#*=}"
407 | if [[ $ARG_DOCKER_HTTPS == "" ]]; then
408 | echoerror "Invalid option for --port-https"
409 | break
410 | fi
411 | shift 1
412 | ;;
413 |
414 | # SSL Policy
415 | -sp)
416 | ARG_SSL_POLICY="${2}"
417 | if [[ $ARG_SSL_POLICY == "" ]]; then
418 | echoerror "Invalid option for -sp"
419 | break
420 | fi
421 | shift 2
422 | ;;
423 | --ssl-policy=*)
424 | ARG_SSL_POLICY="${1#*=}"
425 | if [[ $ARG_SSL_POLICY == "" ]]; then
426 | echoerror "Invalid option for --ssl-policy"
427 | break
428 | fi
429 | shift 1
430 | ;;
431 |
432 | # Docker rootless support
433 | -dr)
434 | USE_DOCKER_ROOTLESS=true
435 | shift 1
436 | ;;
437 | --docker-rootless)
438 | USE_DOCKER_ROOTLESS=true
439 | shift 1
440 | ;;
441 |
442 | # IPv4 options
443 | --ipv4-subnet=*)
444 | ARG_IPv4_SUBNET="${1#*=}"
445 | if [[ $ARG_IPv4_SUBNET == "" ]]; then
446 | echoerror "Invalid option for --ipv4-subnet"
447 | break
448 | fi
449 | shift 1
450 | ;;
451 | # IPv6 options
452 | --ipv6-subnet=*)
453 | ARG_IPv6_SUBNET="${1#*=}"
454 | if [[ $ARG_IPv6_SUBNET == "" ]]; then
455 | echoerror "Invalid option for --ipv6-subnet"
456 | break
457 | fi
458 | shift 1
459 | ;;
460 | --activate-ipv6)
461 | ACTIVATE_IPV6=true
462 | shift 1
463 | ;;
464 |
465 | # Default host
466 | -dh)
467 | ARG_DEFAULT_HOST="${2}"
468 | if [[ $ARG_DEFAULT_HOST == "" ]]; then
469 | echoerror "Invalid option for -dh"
470 | break
471 | fi
472 | shift 2
473 | ;;
474 | --default-host=*)
475 | ARG_DEFAULT_HOST="${1#*=}"
476 | if [[ $ARG_DEFAULT_HOST == "" ]]; then
477 | echoerror "Invalid option for --default-host"
478 | break
479 | fi
480 | shift 1
481 | ;;
482 |
483 | # Other options
484 | --update-nginx-template)
485 | UPDATE_NGINX_TEMPLATE=true
486 | shift 1
487 | ;;
488 | --skip-docker-image-check)
489 | SKIP_DOCKER_IMAGE_CHECK=true
490 | shift 1
491 | ;;
492 | --use-nginx-conf-files)
493 | USE_NGINX_CONF_FILES=true
494 | shift 1
495 | ;;
496 | --yes)
497 | REPLY_YES=true
498 | shift 1
499 | ;;
500 | --debug)
501 | DEBUG=true
502 | shift 1
503 | ;;
504 | --silent)
505 | SILENT=true
506 | shift 1
507 | ;;
508 | -h | --help)
509 | usage
510 | exit 0
511 | ;;
512 | *)
513 | echoerror "Unknown argument: $1" false
514 | usage
515 | exit 0
516 | ;;
517 | esac
518 | done
519 |
520 | #-----------------------------------------------------------------------
521 | # Initial check - DO NOT CHANGE SETTINGS BELOW
522 | #-----------------------------------------------------------------------
523 |
524 | # Check if there is an .env file in local folder
525 | run_function check_local_env_file
526 |
527 | # Specific PID File if needs to run multiple scripts
528 | NEW_PID_FILE=${PID_FILE_FRESH_INSTALL:-".fresh_start.pid"}
529 |
530 | # Run initial check function
531 | run_function starts_initial_check $NEW_PID_FILE
532 |
533 | # Save PID
534 | system_save_pid $NEW_PID_FILE
535 |
536 | # DO NOT CHANGE ANY OPTIONS ABOVE THIS LINE!
537 |
538 | #-----------------------------------------------------------------------
539 | # [function] Undo script actions
540 | #-----------------------------------------------------------------------
541 | local_undo_restore() {
542 | local LOCAL_KEEP_RESTORE_FILES
543 |
544 | LOCAL_KEEP_RESTORE_FILES=${1:-$KEEP_RESTORE_FILES}
545 |
546 | echoerror \
547 | "It seems something went wrong! \
548 | \nRunning '${FUNCNAME[0]} to try to UNDO all actions done by this script. \
549 | \nPlease make sure everything was put it back in place." false
550 |
551 | # If docker network was created
552 | if [[ "$ACTION_DOCKER_NETWORK_CREATED" == true ]]; then
553 | [[ "$SILENT" != true ]] && echowarning "[undo] Deleting created docker network '$DOCKER_NETWORK_NAME'."
554 | run_function docker_network_remove $DOCKER_NETWORK_NAME
555 | ACTION_DOCKER_NETWORK_CREATED=false
556 | fi
557 |
558 | # If docker-compose file was renamed (backup)
559 | if [[ "$ACTION_DOCKER_COMPOSE_FILE_RENAMED" == true ]]; then
560 | [[ "$SILENT" != true ]] && echowarning "[undo] Renaming docker-compose.yml file '$LOCAL_BACKUP_DOCKER_COMPOSE_FILE'."
561 | mv $LOCAL_BACKUP_DOCKER_COMPOSE_FILE "$SCRIPT_PATH/../docker-compose.yml"
562 | ACTION_DOCKER_COMPOSE_FILE_RENAMED=false
563 | fi
564 |
565 | # If .env file was renamed (backup)
566 | if [[ "$ACTION_ENV_FILE_RENAMED" == true ]]; then
567 | [[ "$SILENT" != true ]] && echowarning "[undo] Renaming .env file '$LOCAL_BACKUP_ENV_FILE'."
568 | mv $LOCAL_BACKUP_ENV_FILE "$SCRIPT_PATH/../.env"
569 | ACTION_ENV_FILE_RENAMED=false
570 | fi
571 |
572 | # If docker-compose file was renamed (backup)
573 | if [[ "$ACTION_DOCKER_COMPOSE_FILE_RENAMED" == true ]]; then
574 | [[ "$SILENT" != true ]] && echowarning "[undo] Renaming docker-compose file '$LOCAL_BACKUP_DOCKER_COMPOSE_FILE'."
575 | mv $LOCAL_BACKUP_DOCKER_COMPOSE_FILE "$SCRIPT_PATH/../docker-compose.yml"
576 | ACTION_DOCKER_COMPOSE_FILE_RENAMED=false
577 | fi
578 |
579 | # If the service was stopped try to restart it
580 | if [[ "$ACTION_DOCKER_COMPOSE_STOPPED" == true ]]; then
581 | [[ "$SILENT" != true ]] && echowarning "[undo] Stopping docker-compose service '$SCRIPT_PATH/../'."
582 | run_function docker_compose_start "$SCRIPT_PATH/../"
583 | ACTION_DOCKER_COMPOSE_STOPPED=false
584 | fi
585 |
586 | exit 0
587 | }
588 |
589 | #-----------------------------------------------------------------------
590 | # [function] Docker images and version check
591 | #-----------------------------------------------------------------------
592 | local_check_docker_hub_image_version() {
593 | local LOCAL_DOCKER_IMAGE_NAME LOCAL_DOCKER_IMAGE_VERSION
594 |
595 | LOCAL_DOCKER_IMAGE_NAME=${1:-null}
596 | LOCAL_DOCKER_IMAGE_VERSION=${2:-null}
597 |
598 | # Check image exists
599 | run_function dockerhub_check_image_exists $LOCAL_DOCKER_IMAGE_NAME
600 |
601 | if [[ "$DOCKERHUB_IMAGE_EXISTS" != true ]]; then
602 | echoerror "It seems the image '$LOCAL_DOCKER_IMAGE_NAME' does not exist in docker hub (https://hub.docker.com) or the site is down. Wait a few minutes and try again." false
603 | local_undo_restore
604 | fi
605 |
606 | # Check if image and version exists in docker hub
607 | run_function dockerhub_check_image_exists $LOCAL_DOCKER_IMAGE_NAME $LOCAL_DOCKER_IMAGE_VERSION
608 |
609 | if [[ "$DOCKERHUB_IMAGE_EXISTS" != true ]]; then
610 | echoerror "It seems the image '$LOCAL_DOCKER_IMAGE_NAME:$LOCAL_DOCKER_IMAGE_VERSION' does not exist in docker hub (https://hub.docker.com) or the site is down. Wait a few minutes and try again." false
611 | local_undo_restore
612 | fi
613 | }
614 |
615 | #-----------------------------------------------------------------------
616 | # Check if the docker compose is already running
617 | #-----------------------------------------------------------------------
618 | LOCAL_DOCKER_COMPOSE_FILE_FULL_PATH="$SCRIPT_PATH/../ "
619 | run_function docker_compose_check_service_exists $LOCAL_DOCKER_COMPOSE_FILE_FULL_PATH
620 |
621 | if [[ "$DOCKER_COMPOSE_SERVICE_EXISTS" == true ]]; then
622 | [[ "$SILENT" != true ]] && echowarning \
623 | "The services in the docker compose file below is already running: \
624 | \n'$LOCAL_DOCKER_COMPOSE_FILE_FULL_PATH' \
625 | \nIf you continue, the services will be stopped and all settings replaced \
626 | \nif you are uncertain, check your current files settings before continue."
627 |
628 | if [[ "$REPLY_YES" == true ]]; then
629 | LOCAL_STOP_CURRENT_NGINX_PROXY_SERVICES=true
630 | LOCAL_BACKUP_OLD_DOCKER_COMPOSE_FILE=true
631 | else
632 | run_function confirm_user_action "Your services for this project are already running, \
633 | \nare you sure you want to continue?"
634 |
635 | [[ "$USER_ACTION_RESPONSE" == true ]] && LOCAL_STOP_CURRENT_NGINX_PROXY_SERVICES=true && LOCAL_BACKUP_OLD_DOCKER_COMPOSE_FILE=true
636 | fi
637 | fi
638 |
639 | #-----------------------------------------------------------------------
640 | # Check if the .env file was already configured
641 | #-----------------------------------------------------------------------
642 | run_function check_docker_nginx_proxy_automation_env_file_exits
643 |
644 | # Result from function above
645 | if [[ "$DOCKER_NGINX_PROXY_AUTOMATION_ENV_FILE_EXISTS" == true ]]; then
646 | [[ "$SILENT" != true ]] && echowarning \
647 | "There is an '.env' file already set to your project, if you continue \
648 | \nall settings will be replaced, there is no turn back on that, ok?."
649 |
650 | if [[ "$REPLY_YES" == true ]]; then
651 | LOCAL_BACKUP_OLD_ENV_FILE=true
652 | LOCAL_BACKUP_OLD_DOCKER_COMPOSE_FILE=true
653 | else
654 | run_function confirm_user_action "There is an .env file at your proxy folder, \
655 | \nall settings at will be replaced with new values, \
656 | \nare you sure you want to continue?"
657 | [[ "$USER_ACTION_RESPONSE" == true ]] && LOCAL_BACKUP_OLD_ENV_FILE=true && LOCAL_BACKUP_OLD_DOCKER_COMPOSE_FILE=true
658 | fi
659 | fi
660 |
661 | #-----------------------------------------------------------------------
662 | # Arguments validation and variables fulfillment
663 | #-----------------------------------------------------------------------
664 |
665 | #-----------------------------------------------------------------------
666 | # NGINX-proxy service/container name
667 | #
668 | # Parameters: -pn | --proxy-name
669 | #
670 | # Final result:
671 | # - NGINX_PROXY_SERVICE_NAME
672 | #
673 | # Further action:
674 | # - LOCAL_STOP_AND_REMOVE_NGINX_PROXY_SERVICE_CONTAINER
675 | #-----------------------------------------------------------------------
676 | LOCAL_DEFAULT_NGINX_PROXY_SERVICE_NAME="proxy-web-auto"
677 | if [[ $ARG_NGINX_PROXY_SERVICE_NAME == "" ]] && [[ ! "$REPLY_YES" == true ]]; then
678 |
679 | # Get user's response
680 | run_function common_read_user_input "Please enter the nginx-proxy service name (default: $LOCAL_DEFAULT_NGINX_PROXY_SERVICE_NAME):"
681 |
682 | LOCAL_NGINX_PROXY_SERVICE_NAME=${USER_INPUT_RESPONSE:-$LOCAL_DEFAULT_NGINX_PROXY_SERVICE_NAME}
683 | else
684 | LOCAL_NGINX_PROXY_SERVICE_NAME=${ARG_NGINX_PROXY_SERVICE_NAME:-$LOCAL_DEFAULT_NGINX_PROXY_SERVICE_NAME}
685 | fi
686 |
687 | # Validate the name
688 | run_function string_remove_all_special_char_string $LOCAL_NGINX_PROXY_SERVICE_NAME "-_"
689 | NGINX_PROXY_SERVICE_NAME=${STRING_REMOVE_ALL_SPECIAL_CHAR_STRING_RESPONSE:-null}
690 | [[ $NGINX_PROXY_SERVICE_NAME == null ]] && echoerror "The service name can not contain special chars, neither be empty"
691 |
692 | # Check exists a container with this name
693 | run_function docker_check_container_exists $NGINX_PROXY_SERVICE_NAME
694 |
695 | if [[ "$DOCKER_CONTAINER_EXISTS" == true ]]; then
696 | # Check if there is a container running with this name
697 | run_function docker_check_container_is_running $NGINX_PROXY_SERVICE_NAME
698 |
699 | if [[ "$DOCKER_CONTAINER_IS_RUNNING" == true ]]; then
700 | [[ "$SILENT" != true ]] && echowarning \
701 | "The container '$NGINX_PROXY_SERVICE_NAME' is running in this server \
702 | \nmake sure you have unique names for each container. This script \
703 | \nmight stop and remove the container if you set '--yes' or reply \
704 | \n'yes' on the line below, but, there is no turn back on this action!"
705 |
706 | if [[ "$REPLY_YES" == true ]]; then
707 | LOCAL_STOP_AND_REMOVE_NGINX_PROXY_SERVICE_CONTAINER=true
708 | else
709 | run_function confirm_user_action \
710 | "The container '$NGINX_PROXY_SERVICE_NAME' is running in this server. We will \
711 | \nstop and REMOVE it, do you want to continue?"
712 |
713 | [[ "$USER_ACTION_RESPONSE" == true ]] && LOCAL_STOP_AND_REMOVE_NGINX_PROXY_SERVICE_CONTAINER=true
714 | fi
715 | else
716 | [[ "$SILENT" != true ]] && echowarning \
717 | "The container '$NGINX_PROXY_SERVICE_NAME' is exist in this server, but it is not running \
718 | \nmake sure you have unique names for each container. This script \
719 | \nmight stop and remove the container if you set '--yes' or reply \
720 | \n'yes' on the line below, but, there is no turn back on this action!"
721 |
722 | if [[ "$REPLY_YES" == true ]]; then
723 | LOCAL_STOP_AND_REMOVE_NGINX_PROXY_SERVICE_CONTAINER=true
724 | else
725 | run_function confirm_user_action \
726 | "The container '$NGINX_PROXY_SERVICE_NAME' exist in this server. We will \
727 | \nREMOVE it, do you want to continue?"
728 |
729 | [[ "$USER_ACTION_RESPONSE" == true ]] && LOCAL_STOP_AND_REMOVE_NGINX_PROXY_SERVICE_CONTAINER=true
730 | fi
731 | # We kept STOP and REMOVE because the stop function will not break the script even if the container isn't running
732 | fi
733 | fi
734 |
735 | #-----------------------------------------------------------------------
736 | # Let's Encrypt service/container name
737 | #
738 | # Parameters: -ln | --letsencrypt-name
739 | #
740 | # Final result:
741 | # - LETSENCRYPT_SERVICE_NAME
742 | #
743 | # Further action:
744 | # - LOCAL_STOP_AND_REMOVE_LETSENCRYPT_SERVICE_CONTAINER
745 | #-----------------------------------------------------------------------
746 | LOCAL_DEFAULT_LETSENCRYPT_SERVICE_NAME="letsencrypt-auto"
747 | if [[ $ARG_LETSENCRYPT_SERVICE_NAME == "" ]] && [[ ! "$REPLY_YES" == true ]]; then
748 |
749 | # Get user's response
750 | run_function common_read_user_input "Please enter the letsencrypt service name (default: $LOCAL_DEFAULT_LETSENCRYPT_SERVICE_NAME):"
751 |
752 | LOCAL_LETSENCRYPT_SERVICE_NAME=${USER_INPUT_RESPONSE:-$LOCAL_DEFAULT_LETSENCRYPT_SERVICE_NAME}
753 | else
754 | LOCAL_LETSENCRYPT_SERVICE_NAME=${ARG_LETSENCRYPT_SERVICE_NAME:-$LOCAL_DEFAULT_LETSENCRYPT_SERVICE_NAME}
755 | fi
756 |
757 | # Validate the name
758 | run_function string_remove_all_special_char_string $LOCAL_LETSENCRYPT_SERVICE_NAME "-_"
759 | LETSENCRYPT_SERVICE_NAME=${STRING_REMOVE_ALL_SPECIAL_CHAR_STRING_RESPONSE:-null}
760 | [[ $LETSENCRYPT_SERVICE_NAME == null ]] && echoerror "The service name can not contain special chars, neither be empty"
761 |
762 | # Check exists a container with this name
763 | run_function docker_check_container_exists $LETSENCRYPT_SERVICE_NAME
764 |
765 | if [[ "$DOCKER_CONTAINER_EXISTS" == true ]]; then
766 | # Check if there is a container running with this name
767 | run_function docker_check_container_is_running $LETSENCRYPT_SERVICE_NAME
768 |
769 | if [[ "$DOCKER_CONTAINER_IS_RUNNING" == true ]]; then
770 | [[ "$SILENT" != true ]] && echowarning \
771 | "The container '$LETSENCRYPT_SERVICE_NAME' is running in this server \
772 | \nmake sure you have unique names for each container. This script \
773 | \nmight stop and remove the container if you set '--yes' or reply \
774 | \n'yes' on the line below, but, there is no turn back on this action!"
775 |
776 | if [[ "$REPLY_YES" == true ]]; then
777 | LOCAL_STOP_AND_REMOVE_LETSENCRYPT_SERVICE_CONTAINER=true
778 | else
779 | run_function confirm_user_action \
780 | "The container '$LETSENCRYPT_SERVICE_NAME' is running in this server. We will \
781 | \nstop and REMOVE it, do you want to continue?"
782 |
783 | [[ "$USER_ACTION_RESPONSE" == true ]] && LOCAL_STOP_AND_REMOVE_LETSENCRYPT_SERVICE_CONTAINER=true
784 | fi
785 | else
786 | [[ "$SILENT" != true ]] && echowarning \
787 | "The container '$LETSENCRYPT_SERVICE_NAME' is exist in this server, but it is not running \
788 | \nmake sure you have unique names for each container. This script \
789 | \nmight stop and remove the container if you set '--yes' or reply \
790 | \n'yes' on the line below, but, there is no turn back on this action!"
791 |
792 | if [[ "$REPLY_YES" == true ]]; then
793 | LOCAL_STOP_AND_REMOVE_LETSENCRYPT_SERVICE_CONTAINER=true
794 | else
795 | run_function confirm_user_action \
796 | "The container '$LETSENCRYPT_SERVICE_NAME' exist in this server. We will \
797 | \nREMOVE it, do you want to continue?"
798 |
799 | [[ "$USER_ACTION_RESPONSE" == true ]] && LOCAL_STOP_AND_REMOVE_LETSENCRYPT_SERVICE_CONTAINER=true
800 | fi
801 | # We kept STOP and REMOVE because the stop function will not break the script even if the container isn't running
802 | fi
803 | fi
804 |
805 | #-----------------------------------------------------------------------
806 | # Docker-gen service/container name
807 | #
808 | # Parameters: -gn | --docker-gen-name
809 | #
810 | # Final result:
811 | # - DOCKER_GEN_SERVICE_NAME
812 | #
813 | # Further action:
814 | # - LOCAL_STOP_AND_REMOVE_DOCKER_GEN_SERVICE_CONTAINER
815 | #-----------------------------------------------------------------------
816 | LOCAL_DEFAULT_DOCKER_GEN_SERVICE_NAME="docker-gen-auto"
817 | if [[ $ARG_DOCKER_GEN_SERVICE_NAME == "" ]] && [[ ! "$REPLY_YES" == true ]]; then
818 |
819 | # Get user's response
820 | run_function common_read_user_input "Please enter the docker-gen service name (default: $LOCAL_DEFAULT_DOCKER_GEN_SERVICE_NAME):"
821 |
822 | LOCAL_DOCKER_GEN_SERVICE_NAME=${USER_INPUT_RESPONSE:-$LOCAL_DEFAULT_DOCKER_GEN_SERVICE_NAME}
823 | else
824 | LOCAL_DOCKER_GEN_SERVICE_NAME=${ARG_DOCKER_GEN_SERVICE_NAME:-$LOCAL_DEFAULT_DOCKER_GEN_SERVICE_NAME}
825 | fi
826 |
827 | # Validate the name
828 | run_function string_remove_all_special_char_string $LOCAL_DOCKER_GEN_SERVICE_NAME "-_"
829 | DOCKER_GEN_SERVICE_NAME=${STRING_REMOVE_ALL_SPECIAL_CHAR_STRING_RESPONSE:-null}
830 | [[ $DOCKER_GEN_SERVICE_NAME == null ]] && echoerror "The service name can not contain special chars, neither be empty"
831 |
832 | # Check exists a container with this name
833 | run_function docker_check_container_exists $DOCKER_GEN_SERVICE_NAME
834 |
835 | if [[ "$DOCKER_CONTAINER_EXISTS" == true ]]; then
836 | # Check if there is a container running with this name
837 | run_function docker_check_container_is_running $DOCKER_GEN_SERVICE_NAME
838 |
839 | if [[ "$DOCKER_CONTAINER_IS_RUNNING" == true ]]; then
840 | [[ "$SILENT" != true ]] && echowarning \
841 | "The container '$DOCKER_GEN_SERVICE_NAME' is running in this server \
842 | \nmake sure you have unique names for each container. This script \
843 | \nmight stop and remove the container if you set '--yes' or reply \
844 | \n'yes' on the line below, but, there is no turn back on this action!"
845 |
846 | if [[ "$REPLY_YES" == true ]]; then
847 | LOCAL_STOP_AND_REMOVE_DOCKER_GEN_SERVICE_CONTAINER=true
848 | else
849 | run_function confirm_user_action \
850 | "The container '$DOCKER_GEN_SERVICE_NAME' is running in this server. We will \
851 | \nstop and REMOVE it, do you want to continue?"
852 |
853 | [[ "$USER_ACTION_RESPONSE" == true ]] && LOCAL_STOP_AND_REMOVE_DOCKER_GEN_SERVICE_CONTAINER=true
854 | fi
855 | else
856 | [[ "$SILENT" != true ]] && echowarning \
857 | "The container '$DOCKER_GEN_SERVICE_NAME' is exist in this server, but it is not running \
858 | \nmake sure you have unique names for each container. This script \
859 | \nmight stop and remove the container if you set '--yes' or reply \
860 | \n'yes' on the line below, but, there is no turn back on this action!"
861 |
862 | if [[ "$REPLY_YES" == true ]]; then
863 | LOCAL_STOP_AND_REMOVE_DOCKER_GEN_SERVICE_CONTAINER=true
864 | else
865 | run_function confirm_user_action \
866 | "The container '$DOCKER_GEN_SERVICE_NAME' exist in this server. We will \
867 | \nREMOVE it, do you want to continue?"
868 |
869 | [[ "$USER_ACTION_RESPONSE" == true ]] && LOCAL_STOP_AND_REMOVE_DOCKER_GEN_SERVICE_CONTAINER=true
870 | fi
871 | # We kept STOP and REMOVE because the stop function will not break the script even if the container isn't running
872 | fi
873 | fi
874 |
875 | #-----------------------------------------------------------------------
876 | # nginx-proxy image version
877 | #
878 | # Parameters: -piv | --proxy-image-version
879 | #
880 | # Final result:
881 | # - NGINX_PROXY_IMAGE_VERSION
882 | #-----------------------------------------------------------------------
883 | LOCAL_DEFAULT_NGINX_PROXY_IMAGE_NAME=${DEFAULT_NGINX_PROXY_IMAGE_NAME:-nginx}
884 | LOCAL_DEFAULT_NGINX_PROXY_IMAGE_VERSION=${DEFAULT_NGINX_PROXY_IMAGE_VERSION:-latest}
885 | # We have commented the lines below once the proxy will use a regular nginx container and it's not optional today
886 | #if [[ $ARG_NGINX_PROXY_IMAGE_VERSION == "" ]] && [[ ! "$REPLY_YES" == true ]]; then
887 | # # Get user's response
888 | # run_function dockerhub_list_tags $LOCAL_DEFAULT_NGINX_PROXY_IMAGE_NAME
889 | # run_function select_one_option "${DOCKERHUB_LIST_TAGS[*]}" "Please select a tag for the image '$LOCAL_DEFAULT_NGINX_PROXY_IMAGE_NAME' (the list below comes from https://hub.docker.com):"
890 | #
891 | # [[ $SELECT_ONE_OPTION_NAME == "" ]] && echowarning "Once you did not select any option, '$LOCAL_DEFAULT_NGINX_PROXY_IMAGE_VERSION' will be used."
892 | # NGINX_PROXY_IMAGE_VERSION=${SELECT_ONE_OPTION_NAME:-$LOCAL_DEFAULT_NGINX_PROXY_IMAGE_VERSION}
893 | #else
894 | NGINX_PROXY_IMAGE_VERSION=${ARG_NGINX_PROXY_IMAGE_VERSION:-$LOCAL_DEFAULT_NGINX_PROXY_IMAGE_VERSION}
895 | #fi
896 | #
897 | #if [[ "$NGINX_PROXY_IMAGE_VERSION" == null ]] || [[ "$LOCAL_DEFAULT_NGINX_PROXY_IMAGE_NAME" == null ]]; then
898 | # echoerror "It seems there is no default image or version, please check the .env file at '$SCRIPT_PATH'"
899 | #fi
900 |
901 | # Final check image a version with dockerhub
902 | #[[ "$SKIP_DOCKER_IMAGE_CHECK" != true ]] && [[ ! "$REPLY_YES" == true ]] && local_check_docker_hub_image_version $LOCAL_DEFAULT_NGINX_PROXY_IMAGE_NAME $NGINX_PROXY_IMAGE_VERSION
903 |
904 | #-----------------------------------------------------------------------
905 | # Let's Encrypt image version
906 | #
907 | # Parameters: -liv | --letsencrypt-image-version
908 | #
909 | # Final result:
910 | # - LETSENCRYPT_IMAGE_VERSION
911 | #-----------------------------------------------------------------------
912 | LOCAL_DEFAULT_LETSENCRYPT_IMAGE_NAME=${DEFAULT_LETSENCRYPT_IMAGE_NAME:-null}
913 | LOCAL_DEFAULT_LETSENCRYPT_IMAGE_VERSION=${DEFAULT_LETSENCRYPT_IMAGE_VERSION:-null}
914 | if [[ $ARG_LETSENCRYPT_IMAGE_VERSION == "" ]] && [[ ! "$REPLY_YES" == true ]]; then
915 |
916 | # -------
917 | # docker hub api v2 does not allow to get tags from personal repos without login
918 | # @todo - fix this with user login
919 | # -------
920 |
921 | LETSENCRYPT_IMAGE_VERSION=${LOCAL_DEFAULT_LETSENCRYPT_IMAGE_VERSION}
922 |
923 |
924 | # Get user's response (COMMENTED - TO BE FIXED)
925 | # run_function dockerhub_list_tags $LOCAL_DEFAULT_LETSENCRYPT_IMAGE_NAME
926 | # run_function select_one_option "${DOCKERHUB_LIST_TAGS[*]}" "Please select a tag for the image '$LOCAL_DEFAULT_LETSENCRYPT_IMAGE_NAME' (the list below comes from https://hub.docker.com):"
927 | #
928 | # [[ $SELECT_ONE_OPTION_NAME == "" ]] && echowarning "Once you did not select any option, '$LOCAL_DEFAULT_LETSENCRYPT_IMAGE_VERSION' will be used."
929 | # LETSENCRYPT_IMAGE_VERSION=${SELECT_ONE_OPTION_NAME:-$LOCAL_DEFAULT_LETSENCRYPT_IMAGE_VERSION}
930 | else
931 | LETSENCRYPT_IMAGE_VERSION=${ARG_LETSENCRYPT_IMAGE_VERSION:-$LOCAL_DEFAULT_LETSENCRYPT_IMAGE_VERSION}
932 | fi
933 |
934 | if [[ "$LETSENCRYPT_IMAGE_VERSION" == null ]] || [[ "$LOCAL_DEFAULT_LETSENCRYPT_IMAGE_VERSION" == null ]]; then
935 | echoerror "It seems there is no default image or version, please check the .env file at '$SCRIPT_PATH'"
936 | fi
937 |
938 | # -------
939 | # docker hub api v2 does not allow to get tags from personal repos without login
940 | # @todo - fix this with user login
941 | # -------
942 |
943 | # Final check image a version with dockerhub (COMMENTED - TO BE FIXED)
944 | #[[ "$SKIP_DOCKER_IMAGE_CHECK" != true ]] && [[ ! "$REPLY_YES" == true ]] && local_check_docker_hub_image_version $LOCAL_DEFAULT_LETSENCRYPT_IMAGE_NAME $LETSENCRYPT_IMAGE_VERSION
945 |
946 | #-----------------------------------------------------------------------
947 | # docker-gen image version
948 | #
949 | # Parameters: -giv | --docker-gen-image-versio
950 | #
951 | # Final result:
952 | # - DOCKER_GEN_IMAGE_VERSION
953 | #-----------------------------------------------------------------------
954 | LOCAL_DEFAULT_DOCKER_GEN_IMAGE_NAME=${DEFAULT_DOCKER_GEN_IMAGE_NAME:-null}
955 | LOCAL_DEFAULT_DOCKER_GEN_IMAGE_VERSION=${DEFAULT_DOCKER_GEN_IMAGE_VERSION:-null}
956 | if [[ $ARG_DOCKER_GEN_IMAGE_VERSION == "" ]] && [[ ! "$REPLY_YES" == true ]]; then
957 | # -------
958 | # docker hub api v2 does not allow to get tags from personal repos without login
959 | # @todo - fix this with user login
960 | # -------
961 |
962 | # # Get user's response (COMMENTED - TO BE FIXED)
963 | # run_function dockerhub_list_tags $LOCAL_DEFAULT_DOCKER_GEN_IMAGE_NAME false
964 | # run_function select_one_option "${DOCKERHUB_LIST_TAGS[*]}" "Please select a tag for the image '$LOCAL_DEFAULT_DOCKER_GEN_IMAGE_NAME' (the list below comes from https://hub.docker.com):"
965 | #
966 | # [[ $SELECT_ONE_OPTION_NAME == "" ]] && echowarning "Once you did not select any option, '$LOCAL_DEFAULT_DOCKER_GEN_IMAGE_VERSION' will be used."
967 | # DOCKER_GEN_IMAGE_VERSION=${SELECT_ONE_OPTION_NAME:-$LOCAL_DEFAULT_DOCKER_GEN_IMAGE_VERSION}
968 | DOCKER_GEN_IMAGE_VERSION=${ARG_DOCKER_GEN_IMAGE_VERSION:-$LOCAL_DEFAULT_DOCKER_GEN_IMAGE_VERSION}
969 | else
970 | DOCKER_GEN_IMAGE_VERSION=${ARG_DOCKER_GEN_IMAGE_VERSION:-$LOCAL_DEFAULT_DOCKER_GEN_IMAGE_VERSION}
971 | fi
972 |
973 | if [[ "$DOCKER_GEN_IMAGE_VERSION" == null ]] || [[ "$LOCAL_DEFAULT_DOCKER_GEN_IMAGE_VERSION" == null ]]; then
974 | echoerror "It seems there is no default image or version, please check the .env file at '$SCRIPT_PATH'"
975 | fi
976 |
977 | # -------
978 | # docker hub api v2 does not allow to get tags from personal repos without login
979 | # @todo - fix this with user login
980 | # -------
981 |
982 | # Final check image a version with dockerhub (COMMENTED - TO BE FIXED)
983 | #[[ "$SKIP_DOCKER_IMAGE_CHECK" != true ]] && [[ ! "$REPLY_YES" == true ]] && local_check_docker_hub_image_version $LOCAL_DEFAULT_DOCKER_GEN_IMAGE_NAME $DOCKER_GEN_IMAGE_VERSION
984 |
985 | #-----------------------------------------------------------------------
986 | # IP address (IPv4)
987 | #
988 | # Parameters: -ip | --ip-address
989 | #
990 | # Final result:
991 | # - IP_ADDRESS
992 | #-----------------------------------------------------------------------
993 | if [[ $ARG_IP_ADDRESS == "" ]] && [[ ! "$REPLY_YES" == true ]]; then
994 |
995 | run_function ip_get_external_ipv4
996 |
997 | # Get user's response
998 | run_function common_read_user_input \
999 | "Please enter the IP address (ipv4) that your server uses to connect to the internet. \
1000 | \nYou might try the following '$IP_EXTERNAL_IPV4' (default: 0.0.0.0):"
1001 |
1002 | LOCAL_IP_ADDRESS=${USER_INPUT_RESPONSE:-"0.0.0.0"}
1003 | else
1004 | LOCAL_IP_ADDRESS=${ARG_IP_ADDRESS:-"0.0.0.0"}
1005 | fi
1006 |
1007 | # Check the IP address
1008 | run_function ip_check_ipv4 $LOCAL_IP_ADDRESS
1009 |
1010 | if [[ ! "$IP_IPV4" == true ]]; then
1011 | echoerror "The IP address '$LOCAL_IP_ADDRESS' seems to be in wrong format. Please try again or keep the default value."
1012 | local_undo_restore
1013 | else
1014 | IP_ADDRESS=${LOCAL_IP_ADDRESS:-"0.0.0.0"}
1015 | fi
1016 |
1017 | #-----------------------------------------------------------------------
1018 | # IP address (IPv6)
1019 | #
1020 | # Parameters: -ipv6 | --ipv6-address
1021 | #
1022 | # Final result:
1023 | # - IPv6_ADDRESS
1024 | #-----------------------------------------------------------------------
1025 | if [[ "$ACTIVATE_IPV6" == true ]]; then
1026 |
1027 | # Check the ipv6
1028 | if [[ $ARG_IPv6_ADDRESS == "" ]] && [[ ! "$REPLY_YES" == true ]]; then
1029 |
1030 | run_function ip_get_external_ipv6
1031 |
1032 | # Get user's response
1033 | run_function common_read_user_input \
1034 | "Please enter the IP address (ipv6) that your server uses to connect to the internet. \
1035 | \nYou might try the following '$IP_EXTERNAL_IPV6' (default: ::0):"
1036 |
1037 | LOCAL_IPv6_ADDRESS=${USER_INPUT_RESPONSE:-"::0"}
1038 | else
1039 | LOCAL_IPv6_ADDRESS=${ARG_IPv6_ADDRESS:-"::0"}
1040 | fi
1041 |
1042 | # Check the IP address
1043 | run_function ip_check_ipv6 $LOCAL_IPv6_ADDRESS
1044 |
1045 | if [[ ! "$IP_IPV6" == true ]]; then
1046 | echoerror "The IP address '$LOCAL_IPv6_ADDRESS' seems to be in wrong format. Please try again or keep the default value."
1047 | local_undo_restore
1048 | else
1049 | IPv6_ADDRESS=${LOCAL_IPv6_ADDRESS:-"::0"}
1050 | fi
1051 | fi
1052 |
1053 | #-----------------------------------------------------------------------
1054 | # Docker network for the nginx-proxy
1055 | #
1056 | # Parameters: -net | --network-name
1057 | #
1058 | # Final result:
1059 | # - DOCKER_NETWORK_NAME
1060 | #-----------------------------------------------------------------------
1061 | LOCAL_DEFAULT_DOCKER_NETWORK_NAME=${DEFAULT_DOCKER_NETWORK_NAME:-"proxy"}
1062 | if [[ $ARG_NETWORK_NAME == "" ]] && [[ ! "$REPLY_YES" == true ]]; then
1063 |
1064 | # Get user's response
1065 | run_function common_read_user_input "Please enter the network name for your nginx-proxy (default: $LOCAL_DEFAULT_DOCKER_NETWORK_NAME):"
1066 |
1067 | LOCAL_DOCKER_NETWORK_NAME=${USER_INPUT_RESPONSE:-$LOCAL_DEFAULT_DOCKER_NETWORK_NAME}
1068 | else
1069 | LOCAL_DOCKER_NETWORK_NAME=${ARG_NETWORK_NAME:-$LOCAL_DEFAULT_DOCKER_NETWORK_NAME}
1070 | fi
1071 |
1072 | # Validate the name
1073 | run_function string_remove_all_special_char_string $LOCAL_DOCKER_NETWORK_NAME "-_"
1074 | DOCKER_NETWORK_NAME=${STRING_REMOVE_ALL_SPECIAL_CHAR_STRING_RESPONSE:-null}
1075 | [[ $DOCKER_NETWORK_NAME == null ]] && echoerror "The network name can not contain special chars, neither be empty"
1076 |
1077 | #-----------------------------------------------------------------------
1078 | # Data location for nginx-proxy files
1079 | #
1080 | # Parameters: -d | --data-files-location
1081 | #
1082 | # Final result:
1083 | # - DATA_LOCATION
1084 | #-----------------------------------------------------------------------
1085 | LOCAL_DEFAULT_DATA_LOCATION=${DEFAULT_DATA_LOCATION:-"$SCRIPT_PATH/../data"}
1086 | if [[ $ARG_DATA_LOCATION == "" ]] && [[ ! "$REPLY_YES" == true ]]; then
1087 |
1088 | # Get user's response
1089 | run_function common_read_user_input "Please enter the path location where you wish to place your nginx-proxy files (default: $LOCAL_DEFAULT_DATA_LOCATION):"
1090 |
1091 | DATA_LOCATION=${USER_INPUT_RESPONSE:-$LOCAL_DEFAULT_DATA_LOCATION}
1092 | else
1093 | DATA_LOCATION=${ARG_DATA_LOCATION:-$LOCAL_DEFAULT_DATA_LOCATION}
1094 | fi
1095 |
1096 | # Create folder if it does not exist
1097 | run_function common_create_folder $DATA_LOCATION
1098 |
1099 | #-----------------------------------------------------------------------
1100 | # Default email address for the Lets Encrypt certificates
1101 | #
1102 | # Parameters: -e | --default-email
1103 | #
1104 | # Final result:
1105 | # - DEFAULT_EMAIL
1106 | #-----------------------------------------------------------------------
1107 | if [[ $ARG_DEFAULT_EMAIL == "" ]]; then
1108 |
1109 | # Get user's response
1110 | run_function common_read_user_input "You must inform a valid email address in order to continue. Please check the docs:"
1111 |
1112 | DEFAULT_EMAIL=${USER_INPUT_RESPONSE}
1113 | else
1114 | DEFAULT_EMAIL=${ARG_DEFAULT_EMAIL}
1115 | fi
1116 |
1117 | # Check if email is valid
1118 | run_function email_check_is_valid $DEFAULT_EMAIL
1119 |
1120 | [[ ! "$EMAIL_IS_VALID" == true ]] && echoerror "You must inform a valid email address in order to continue. Please try again."
1121 |
1122 | #-----------------------------------------------------------------------
1123 | # Log settings for nginx-proxy
1124 | #
1125 | # We would like to comment that this is a very specific configuration
1126 | # that, once we will not offer the available options we decided to
1127 | # simplify these options once was not a common issue setting up
1128 | #-----------------------------------------------------------------------
1129 | NGINX_PROXY_LOG_DRIVER=${ARG_NGINX_PROXY_LOG_DRIVER:-"json-file"}
1130 | NGINX_PROXY_LOG_MAX_SIZE=${ARG_NGINX_PROXY_LOG_MAX_SIZE:-"4m"}
1131 | NGINX_PROXY_LOG_MAX_FILE=${ARG_NGINX_PROXY_LOG_MAX_FILE:-"10"}
1132 |
1133 | DOCKER_GEN_LOG_DRIVER=${ARG_DOCKER_GEN_LOG_DRIVER:-"json-file"}
1134 | DOCKER_GEN_LOG_MAX_SIZE=${ARG_DOCKER_GEN_LOG_MAX_SIZE:-"2m"}
1135 | DOCKER_GEN_LOG_MAX_FILE=${ARG_DOCKER_GEN_LOG_MAX_FILE:-"10"}
1136 |
1137 | LETSENCRYPT_LOG_DRIVER=${ARG_LETSENCRYPT_LOG_DRIVER:-"json-file"}
1138 | LETSENCRYPT_LOG_MAX_SIZE=${ARG_LETSENCRYPT_LOG_MAX_SIZE:-"2m"}
1139 | LETSENCRYPT_LOG_MAX_FILE=${ARG_LETSENCRYPT_LOG_MAX_FILE:-"10"}
1140 |
1141 | #-----------------------------------------------------------------------
1142 | # Port binding
1143 | #
1144 | # We would like to comment out that the settings below seems to be
1145 | # rearly changes by the users, so we kept that pretty simple in
1146 | # this script, if that is all right with you! Thank you!
1147 | #-----------------------------------------------------------------------
1148 | DOCKER_HTTP=${ARG_DOCKER_HTTP:-"80"}
1149 | DOCKER_HTTPS=${ARG_DOCKER_HTTPS:-"443"}
1150 |
1151 | #-----------------------------------------------------------------------
1152 | # SSL policy (set to Mozilla-Intermediate)
1153 | #
1154 | # Please read the options at the url below:
1155 | # https://github.com/nginx-proxy/nginx-proxy#how-ssl-support-works
1156 | #-----------------------------------------------------------------------
1157 | SSL_POLICY=${ARG_SSL_POLICY:-"Mozilla-Intermediate"}
1158 |
1159 | #-----------------------------------------------------------------------
1160 | # Docker rootless support. Add the current user's docker.sock path (default: blank)
1161 | # Please read the official documentation of installing Docker Rootless:
1162 | # https://docs.docker.com/engine/security/rootless/
1163 | #-----------------------------------------------------------------------
1164 | if [[ "$USE_DOCKER_ROOTLESS" == true ]]; then
1165 | # Get the current user's $XDG_RUNTIME_DIR and concat with the '/docker.sock'
1166 | DOCKER_HOST_ROOTLESS_PATH=`echo ${XDG_RUNTIME_DIR}/docker.sock`
1167 | fi
1168 |
1169 | #-----------------------------------------------------------------------
1170 | # Start actions!
1171 | #-----------------------------------------------------------------------
1172 |
1173 | #-----------------------------------------------------------------------
1174 | # Verify checksum of docker-compose.yml and .env.sample files
1175 | #-----------------------------------------------------------------------
1176 | run_function md5_check_checksum "$SCRIPT_PATH/../" "docker-compose.yml" $MD5_SUM_DOCKER_COMPOSE
1177 | if [[ ! "$MD5_CHECKSUM" == true ]] && [[ ! "$REPLY_YES" == true ]]; then
1178 |
1179 | run_function confirm_user_action \
1180 | "We could not verify the checksum (md5) for the docker-compose.yml \
1181 | \n are you sure you want to continue?"
1182 | fi
1183 |
1184 | run_function md5_check_checksum "$SCRIPT_PATH/../" ".env.sample" $MD5_SUM_ENV_SAMPLE
1185 | if [[ ! "$MD5_CHECKSUM" == true ]] && [[ ! "$REPLY_YES" == true ]]; then
1186 |
1187 | run_function confirm_user_action \
1188 | "We could not verify the checksum (md5) for the .env \
1189 | \n are you sure you want to continue?"
1190 | fi
1191 |
1192 | #-----------------------------------------------------------------------
1193 | # Stop services (docker-compose) if they are running
1194 | #-----------------------------------------------------------------------
1195 | if [[ "$LOCAL_STOP_CURRENT_NGINX_PROXY_SERVICES" == true ]]; then
1196 | run_function docker_compose_stop "$SCRIPT_PATH/../"
1197 |
1198 | ACTION_DOCKER_COMPOSE_STOPPED=true
1199 |
1200 | [[ "$ERROR_DOCKER_COMPOSE_START" == true ]] && local_undo_restore
1201 |
1202 | # If there is no error when stopping container backup docker-compose file
1203 | run_function backup_file "$SCRIPT_PATH/../docker-compose.yml"
1204 | ACTION_DOCKER_COMPOSE_FILE_RENAMED=true
1205 | LOCAL_BACKUP_DOCKER_COMPOSE_FILE=$BACKUP_FILE
1206 | fi
1207 |
1208 | #-----------------------------------------------------------------------
1209 | # Add nginx config folder (conf.d)
1210 | #-----------------------------------------------------------------------
1211 | if [[ "$USE_NGINX_CONF_FILES" == true ]]; then
1212 | # Create the conf folder if it does not exists
1213 | run_function common_create_folder "$DATA_LOCATION/conf.d"
1214 |
1215 | # Copy the special configurations to the nginx conf folder
1216 | cp -R $SCRIPT_PATH/../conf.d/* $DATA_LOCATION/conf.d/
1217 |
1218 | # Check if there was an error and try with sudo
1219 | if [ $? -ne 0 ]; then
1220 | echo "sudo cp -R $SCRIPT_PATH/../conf.d/* $DATA_LOCATION/conf.d/"
1221 | exit 0
1222 | sudo cp -R $SCRIPT_PATH/../conf.d/* $DATA_LOCATION/conf.d/
1223 | fi
1224 |
1225 | # If there was any errors inform the user
1226 | if [ $? -ne 0 ]; then
1227 | echoerror "There was an error trying to copy the nginx conf files. \
1228 | \nThe proxy will still work with default options, but \
1229 | \nthe custom settings might not be loaded."
1230 | fi
1231 | fi
1232 |
1233 | #-----------------------------------------------------------------------
1234 | # Update the nginx.template with the latest version
1235 | #-----------------------------------------------------------------------
1236 | DEFAULT_NGINX_TEMPLATE_URL="https://raw.githubusercontent.com/nginx-proxy/nginx-proxy/master/nginx.tmpl"
1237 | if [[ "$UPDATE_NGINX_TEMPLATE" == true ]]; then
1238 | cd "$SCRIPT_PATH/../"
1239 | curl -L $DEFAULT_NGINX_TEMPLATE_URL -o nginx.tmpl
1240 | cd - > /dev/null 2>&1
1241 | fi
1242 |
1243 | #-----------------------------------------------------------------------
1244 | # Backup .env file if exists
1245 | #-----------------------------------------------------------------------
1246 | if [[ "$LOCAL_BACKUP_OLD_ENV_FILE" == true ]]; then
1247 | run_function backup_file "$SCRIPT_PATH/../.env"
1248 | ACTION_ENV_FILE_RENAMED=true
1249 | LOCAL_BACKUP_ENV_FILE=$BACKUP_FILE
1250 | fi
1251 |
1252 | #-----------------------------------------------------------------------
1253 | # Backup docker-compose.yml file if exists
1254 | #-----------------------------------------------------------------------
1255 | if [[ "$LOCAL_BACKUP_OLD_DOCKER_COMPOSE_FILE" == true ]]; then
1256 | run_function backup_file "$SCRIPT_PATH/../docker-compose.yml"
1257 | ACTION_DOCKER_COMPOSE_FILE_RENAMED=true
1258 | LOCAL_BACKUP_DOCKER_COMPOSE_FILE=$BACKUP_FILE
1259 | fi
1260 |
1261 | #-----------------------------------------------------------------------
1262 | # Create and update .env file for nginx-proxy
1263 | #-----------------------------------------------------------------------
1264 | cp "$SCRIPT_PATH/../.env.sample" "$SCRIPT_PATH/../.env"
1265 |
1266 | run_function local_update_env_new_site_variables "$SCRIPT_PATH/../"
1267 |
1268 | #-----------------------------------------------------------------------
1269 | # Create docker network if it does not exist
1270 | #-----------------------------------------------------------------------
1271 | run_function docker_check_network_exists $DOCKER_NETWORK_NAME
1272 |
1273 | if [[ ! "$DOCKER_NETWORK_EXISTS" == true ]]; then
1274 |
1275 | run_function docker_network_create $DOCKER_NETWORK_NAME ${ARG_IPv4_SUBNET:-null} $ACTIVATE_IPV6 $ARG_IPv6_SUBNET
1276 |
1277 | if [[ "$ERROR_DOCKER_NETWORK_CREATE" == true ]]; then
1278 | echoerror \
1279 | "There was an error when creating the docker network $DOCKER_NETWORK_NAME [IPv6 enabled: ${ACTIVATE_IPV6:-'false'} ] \
1280 | \nPlease try to create the network by yourself using the appropriate options described below and try again: \
1281 | \nhttps://docs.docker.com/engine/reference/commandline/network_create/" \
1282 | false
1283 | local_undo_restore
1284 | else
1285 | ACTION_DOCKER_NETWORK_CREATED=true
1286 | fi
1287 | fi
1288 |
1289 | #-----------------------------------------------------------------------
1290 | # Update docker-compose file
1291 | #-----------------------------------------------------------------------
1292 | run_function local_update_docker_compose_file "$SCRIPT_PATH/../"
1293 |
1294 | #-----------------------------------------------------------------------
1295 | # Start proxy
1296 | #-----------------------------------------------------------------------
1297 | run_function docker_compose_start "$SCRIPT_PATH/../"
1298 |
1299 | if [[ "$ERROR_DOCKER_COMPOSE_START" == true ]]; then
1300 | echoerror "There was an error starting the service at '$SCRIPT_PATH/../'"
1301 | local_undo_restore
1302 | fi
1303 |
1304 | #-----------------------------------------------------------------------
1305 | # Show data for the user to take notes
1306 | #-----------------------------------------------------------------------
1307 | echosuccess "Your proxy was started successfully!"
1308 |
1309 | # @todo - testing the proxy
1310 | #
1311 | # attention:
1312 | # 1. if yes don't ask for testing unless splicit
1313 | # 2. timeout optional yes|no as default?
1314 | # 3. url for testing - test dns first
1315 | # 4. option for ssl testing as well
1316 | #
1317 | # without ssl
1318 | # docker run -d -e VIRTUAL_HOST=$DOMAIN --network=$NETWORK --name test-web httpd:alpine
1319 | #
1320 | # with ss
1321 | # docker run -d -e VIRTUAL_HOST=$DOMAIN -e LETSENCRYPT_HOST=$DOMAIN --network=$NETWORK --name $NAME httpd:alpine
1322 | #
1323 | # stop testint - timeout?!
1324 | # docker stop test-web && docker rm test-web
1325 |
1326 | exit 0
1327 |
--------------------------------------------------------------------------------
/bin/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #-----------------------------------------------------------------------
4 | #
5 | # Install script - configure the requirements for this project
6 | #
7 | # https://github.com/evertramos/nginx-proxy-automation
8 | #
9 | # Script developed by
10 | # Evert Ramos
11 | #
12 | # Copyright Evert Ramos
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | # Bash settings (do not mess with it)
17 | shopt -s nullglob globstar
18 |
19 | # Get the script name and its file real path
20 | SCRIPT_PATH="$(dirname "$(readlink -f "$0")")"
21 | SCRIPT_NAME="${0##*/}"
22 |
23 | # basescript (remove and install)
24 | BASESCRIPT_VERSION=v0.6.2
25 | BASESCRIPT_BASE_PATH=${SCRIPT_PATH}/../src/scripts
26 | mkdir -p ${BASESCRIPT_BASE_PATH}
27 | cd ${BASESCRIPT_BASE_PATH}
28 | rm -rf "basescript"
29 | git clone https://github.com/evertramos/basescript.git &> /dev/null
30 | cd basescript
31 | git checkout ${BASESCRIPT_VERSION} &> /dev/null
32 | cd ${SCRIPT_PATH}
33 | source "${BASESCRIPT_BASE_PATH}/basescript/bootstrap.sh"
34 | BASESCRIPT_LOG_BASE_PATH=${BASESCRIPT_BASE_PATH}/logs
35 | mkdir -p ${BASESCRIPT_LOG_BASE_PATH}
36 | # Source localscripts
37 | #source ${BASESCRIPT_BASE_PATH}"/localscripts/bootstrap.sh"
38 |
39 | log "testing..."
40 |
--------------------------------------------------------------------------------
/bin/localscript/bootstrap.sh:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------
2 | #
3 | # Server Automation - https://github.com/evertramos/server-automation
4 | #
5 | # Developed by
6 | # Evert Ramos
7 | #
8 | # Copyright Evert Ramos
9 | #
10 | #-----------------------------------------------------------------------
11 | #
12 | # Be careful when editing this file, it is part of a bigger script!
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | #-----------------------------------------------------------------------
17 | # This script has one main objective:
18 | # 1. Load all functions in local folder
19 | #-----------------------------------------------------------------------
20 |
21 | #-----------------------------------------------------------------------
22 | # Fill out local variables
23 | #-----------------------------------------------------------------------
24 | # Get Current directory
25 | LOCAL_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
26 |
27 | # Bootstrap file name
28 | BOOTSTRAP_FILE_NAME="bootstrap.sh"
29 |
30 | #-----------------------------------------------------------------------
31 | # Debug message
32 | #-----------------------------------------------------------------------
33 | [[ "$DEBUG" == true ]] && "Reading base script files... [bootstrap.sh]"
34 |
35 | #-----------------------------------------------------------------------
36 | # Read files with extension '.sh'
37 | #-----------------------------------------------------------------------
38 | # Loop the base folder and source all files in root folder
39 | for file in $LOCAL_PATH/*.sh
40 | do
41 | [[ $file != $LOCAL_PATH/$BOOTSTRAP_FILE_NAME ]] && source $file
42 | done
43 |
44 | return 0
45 |
--------------------------------------------------------------------------------
/bin/localscript/check-docker-nginx-proxy-automation-env-file.sh:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------
2 | #
3 | # Server Automation - https://github.com/evertramos/server-automation
4 | #
5 | # Developed by
6 | # Evert Ramos
7 | #
8 | # Copyright Evert Ramos
9 | #
10 | #-----------------------------------------------------------------------
11 | #
12 | # Be careful when editing this file, it is part of a bigger script!
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | #-----------------------------------------------------------------------
17 | # This script has one main objective:
18 | # 1. Check if the .env file already exists for the
19 | # docker-nginx-proxy-automation
20 | #-----------------------------------------------------------------------
21 |
22 | check_docker_nginx_proxy_automation_env_file_exits()
23 | {
24 | [[ "$DEBUG" == true ]] && echo "Check if '.env' file exists for the nginx-proxy."
25 |
26 | if [[ -e ./../.env ]]; then
27 | DOCKER_NGINX_PROXY_AUTOMATION_ENV_FILE_EXISTS=true
28 | fi
29 | }
30 |
--------------------------------------------------------------------------------
/bin/localscript/check-local-env-file.sh:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------
2 | #
3 | # Server Automation - https://github.com/evertramos/server-automation
4 | #
5 | # Developed by
6 | # Evert Ramos
7 | #
8 | # Copyright Evert Ramos
9 | #
10 | #-----------------------------------------------------------------------
11 | #
12 | # Be careful when editing this file, it is part of a bigger script!
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | #-----------------------------------------------------------------------
17 | # This script has one main objective:
18 | # 1. Check if the .env file exists in the current folder
19 | #-----------------------------------------------------------------------
20 |
21 | check_local_env_file()
22 | {
23 | [[ "$DEBUG" == true ]] && echo "Check if local '.env' file is set."
24 |
25 | if [[ -e .env ]]; then
26 | source .env
27 | else
28 | MESSAGE="'.env' file not found! \n Cheers!"
29 | return 1
30 | fi
31 | }
32 |
--------------------------------------------------------------------------------
/bin/localscript/update-docker-compose-file.sh:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------
2 | #
3 | # Server Automation - https://github.com/evertramos/server-automation
4 | #
5 | # Developed by
6 | # Evert Ramos
7 | #
8 | # Copyright Evert Ramos
9 | #
10 | #-----------------------------------------------------------------------
11 | #
12 | # Be careful when editing this file, it is part of a bigger script!
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | # ----------------------------------------------------------------------
17 | # This function has one main objective:
18 | # 1. Update all variables in docker-compose file
19 | #
20 | # You must/might inform the parameters below:
21 | # 1. Path where docker-compose.yml file is located
22 | # 2. [optional] (default: )
23 | #
24 | # ----------------------------------------------------------------------
25 |
26 | local_update_docker_compose_file()
27 | {
28 | local LOCAL_FULL_PATH
29 |
30 | LOCAL_FULL_PATH=${1}
31 |
32 | [[ $LOCAL_FULL_PATH == "" || $LOCAL_FULL_PATH == null ]] && echoerror "You must inform the required argument(s) to the function: '${FUNCNAME[0]}'"
33 |
34 | [[ "$DEBUG" == true ]] && echo "Updating all variables in docker-compose.yml file for nginx-proxy (file: ${LOCAL_FULL_PATH})"
35 |
36 | # Services name
37 | run_function docker_compose_replace_string $LOCAL_FULL_PATH "$REPLACE_NGINX_PROXY_SERVICE_NAME" "$NGINX_PROXY_SERVICE_NAME"
38 | run_function docker_compose_replace_string $LOCAL_FULL_PATH "$REPLACE_DOCKER_GEN_SERVICE_NAME" "$DOCKER_GEN_SERVICE_NAME"
39 | run_function docker_compose_replace_string $LOCAL_FULL_PATH "$REPLACE_LETSENCRYPT_SERVICE_NAME" "$LETSENCRYPT_SERVICE_NAME"
40 |
41 | # Uncomment in case of IPv6 activation or comment
42 | [[ "$ACTIVATE_IPV6" == true ]] && run_function file_uncomment_line_with_string ${LOCAL_FULL_PATH%/}"/docker-compose.yml" "IPv6" && run_function file_uncomment_line_with_string ${LOCAL_FULL_PATH%/}"/docker-compose.yml" "IPV6"
43 | [[ ! "$ACTIVATE_IPV6" == true ]] && run_function file_comment_line_with_string ${LOCAL_FULL_PATH%/}"/docker-compose.yml" "IPv6" && run_function file_comment_line_with_string ${LOCAL_FULL_PATH%/}"/docker-compose.yml" "IPV6"
44 | # We are aware that it will set two '#' if the IPv6 is already commented
45 |
46 | # Uncomment in case of Default Host activation
47 | [[ ! $ARG_DEFAULT_HOST == "" ]] && run_function file_uncomment_line_with_string ${LOCAL_FULL_PATH%/}"/docker-compose.yml" "DEFAULT_HOST"
48 |
49 | return 0
50 | }
51 |
--------------------------------------------------------------------------------
/bin/localscript/update-env-new-site-variables.sh:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------
2 | #
3 | # Server Automation - https://github.com/evertramos/server-automation
4 | #
5 | # Developed by
6 | # Evert Ramos
7 | #
8 | # Copyright Evert Ramos
9 | #
10 | #-----------------------------------------------------------------------
11 | #
12 | # Be careful when editing this file, it is part of a bigger script!
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | #-----------------------------------------------------------------------
17 | # This function has one main objective:
18 | # 1. Update all variables in .env file for fresh start script
19 | #
20 | # You must/might inform the parameters below:
21 | # 1. Path where .env is located
22 | # 2. [optional] (default: ) n/a
23 | #
24 | #-----------------------------------------------------------------------
25 |
26 | local_update_env_new_site_variables()
27 | {
28 | local LOCAL_FILE_PATH
29 |
30 | LOCAL_FILE_PATH=${1:-null}
31 |
32 | [[ $LOCAL_FILE_PATH == "" || $LOCAL_FILE_PATH == null ]] && echoerror "You must inform the required argument(s) to the function: '${FUNCNAME[0]}'"
33 |
34 | [[ "$DEBUG" == true ]] && echo "Updating all variables in .env file for nginx-proxy (file: ${LOCAL_FILE_PATH})"
35 |
36 | # Docker servides and image versions
37 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_WEB_SEVICE_NAME" "$NGINX_PROXY_SERVICE_NAME"
38 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_IMAGE_VERSION" "$NGINX_PROXY_IMAGE_VERSION"
39 | run_function env_update_variable $LOCAL_FILE_PATH "DOCKER_GEN_SEVICE_NAME" "$DOCKER_GEN_SERVICE_NAME"
40 | run_function env_update_variable $LOCAL_FILE_PATH "DOCKER_GEN_IMAGE_VERSION" "$DOCKER_GEN_IMAGE_VERSION"
41 | run_function env_update_variable $LOCAL_FILE_PATH "LETS_ENCRYPT_SEVICE_NAME" "$LETSENCRYPT_SERVICE_NAME"
42 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_PROXY_COMPANION_IMAGE_VERSION" "$LETSENCRYPT_IMAGE_VERSION"
43 |
44 | # IPs
45 | run_function env_update_variable $LOCAL_FILE_PATH "IPv4" "$IP_ADDRESS"
46 | [[ "$ACTIVATE_IPV6" == true ]] && run_function env_update_variable $LOCAL_FILE_PATH "IPv6" "$IPv6_ADDRESS"
47 |
48 | # Network
49 | run_function env_update_variable $LOCAL_FILE_PATH "NETWORK" "$DOCKER_NETWORK_NAME"
50 |
51 | # Data files path
52 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_FILES_PATH" "$DATA_LOCATION"
53 |
54 | # Log variables
55 | # proxy
56 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_WEB_LOG_DRIVER" "$NGINX_PROXY_LOG_DRIVER"
57 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_WEB_LOG_MAX_SIZE" "$NGINX_PROXY_LOG_MAX_SIZE"
58 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_WEB_LOG_MAX_FILE" "$NGINX_PROXY_LOG_MAX_FILE"
59 | # docker-gen
60 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_GEN_LOG_DRIVER" "$DOCKER_GEN_LOG_DRIVER"
61 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_GEN_LOG_MAX_SIZE" "$DOCKER_GEN_LOG_MAX_SIZE"
62 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_GEN_LOG_MAX_FILE" "$DOCKER_GEN_LOG_MAX_FILE"
63 | # Lets Encrypt
64 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_LETSENCRYPT_LOG_DRIVER" "$LETSENCRYPT_LOG_DRIVER"
65 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_LETSENCRYPT_LOG_MAX_SIZE" "$LETSENCRYPT_LOG_MAX_SIZE"
66 | run_function env_update_variable $LOCAL_FILE_PATH "NGINX_LETSENCRYPT_LOG_MAX_FILE" "$LETSENCRYPT_LOG_MAX_FILE"
67 |
68 | # Port bindings
69 | run_function env_update_variable $LOCAL_FILE_PATH "DOCKER_HTTP_" "$DOCKER_HTTP"
70 | run_function env_update_variable $LOCAL_FILE_PATH "DOCKER_HTTPS" "$DOCKER_HTTPS"
71 |
72 | # SSL Policy
73 | run_function env_update_variable $LOCAL_FILE_PATH "SSL_POLICY" "$SSL_POLICY"
74 |
75 | # Default email address
76 | run_function env_update_variable $LOCAL_FILE_PATH "DEFAULT_EMAIL" "$DEFAULT_EMAIL"
77 |
78 | # Default host
79 | [[ ! $ARG_DEFAULT_HOST == "" ]] && run_function env_update_variable $LOCAL_FILE_PATH "DEFAULT_HOST" "${ARG_DEFAULT_HOST}"
80 |
81 | # Docker rootless support
82 | [[ "$USE_DOCKER_ROOTLESS" == true ]] && run_function env_update_variable $LOCAL_FILE_PATH "DOCKER_HOST_ROOTLESS_PATH" "$DOCKER_HOST_ROOTLESS_PATH"
83 |
84 | return 0
85 | }
86 |
--------------------------------------------------------------------------------
/bin/localscript/usage-fresh-start.sh:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------
2 | #
3 | # Server Automation - https://github.com/evertramos/server-automation
4 | #
5 | # Developed by
6 | # Evert Ramos
7 | #
8 | # Copyright Evert Ramos
9 | #
10 | #-----------------------------------------------------------------------
11 | #
12 | # Be careful when editing this file, it is part of a bigger script!
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | #-----------------------------------------------------------------------
17 | # This script has one main objective:
18 | # 1. Show the script usage (helper)
19 | #-----------------------------------------------------------------------
20 |
21 | #
22 | # NGINX use special conf files
23 | #
24 | # In case you want to add some special configuration to your NGINX Web Proxy you could
25 | # add your files to ./conf.d/ folder as of sample file 'uploadsize.conf'
26 | #
27 | # [WARNING] This setting was built to use our `start.sh`.
28 | #
29 | # [WARNING] Once you set this options to true all your files will be copied to data
30 | # folder (./data/conf.d). If you decide to remove this special configuration
31 | # you must delete your files from data folder ./data/conf.d.
32 | #
33 | # USE_NGINX_CONF_FILES=true
34 |
35 | #-----------------------------------------------------------------------
36 | #
37 | # Docker network options
38 | #
39 | # The docker network has many options when creating a new network, you can
40 | # check the url below for more information about the docker network creation
41 | # in our 'fresh_start.sh' script you can enable the network encryption option
42 | #
43 | # https://docs.docker.com/engine/reference/commandline/network_create/
44 | #
45 | # NETWORK_OPTIONS="--opt encrypted=true"
46 |
47 | usage()
48 | {
49 | cat << USAGE >&2
50 | ${purple}
51 | =============================================================================
52 | | _____ _____ _ _ _ |
53 | | | __|___ ___ _ _ ___ ___ ___| _ |_ _| |_ ___ _____ ___| |_|_|___ ___ |
54 | | |__ | -_| _| | | -_| _|___| | | | _| . | | .'| _| | . | | |
55 | | |_____|___|_| \_/|___|_| |__|__|___|_| |___|_|_|_|__,|_| |_|___|_|_| |
56 | | |
57 | =============================================================================
58 | ${reset}${blue}
59 | Usage:
60 | $SCRIPT_NAME -e "john.doe@example.com"
61 | [-d "/server/proxy/data"]
62 | [-pn "proxy"] [-ln "letsencrypt"] [-gn "docker-gen"]
63 | [-net "proxy"]
64 | [--use-nginx-conf-files] [--update-nginx-template]
65 | [--yes]
66 | [--debug]
67 | [--docker-rootless]
68 |
69 | Required
70 | -e | --default-email Default email address require to issue ssl
71 | certificates with Let's Encrypt service
72 |
73 | Basic options
74 | -d | --data-files-location Proxy files location
75 | -pn | --proxy-name Proxy service and container name
76 | -ln | --letsencrypt-name Let's Encrypt service & container name
77 | -gn | --docker-gen-name Docker-gen service and container name
78 | -net | --network-name Docker network name for proxy services
79 | -ip | --ip-address IP address for external connectivity
80 |
81 | Proxy config
82 | --use-nginx-conf-files Add basic config folder to the Proxy
83 | --update-nginx-template Download the latest nginx.tmpl
84 |
85 | Network
86 | -netopt | --network-option Network options please check the docs
87 | --ipv4-subnet You may inform IPv4 subnet to create
88 | a docker network
89 | (default: 172.17.0.0/16)
90 |
91 | Docker image
92 | -piv | --proxy-image-version Proxy image version
93 | -liv | --letsencrypt-image-version Let's Encrypt image version
94 | -giv | --docker-gen-image-version Docker-gen image version
95 |
96 | --skip-docker-image-check Use this option to skip docker image
97 | verification which might takes a few
98 | seconds to check if images exists in
99 | docker hub api
100 |
101 | Docker log
102 | -lpd | --log-nginx-proxy-driver Proxy service log driver
103 | -lpms | --log-nginx-proxy-max_size Proxy service log max file size
104 | -lpmf | --log-nginx-proxy-max_file Proxy service log max files
105 | -lgd | --log-docker-gen-driver Docker-gen service log driver
106 | -lgms | --log-docker-gen-max_size Docker-gen service log max file size
107 | -lgmf | --log-docker-gen-max_file Docker-gen service log max files
108 | -lld | --log-letsencrypt-driver Let's Encrypt service log driver
109 | -llms | --log-letsencrypt-max_size Let's Encrypt service log max size
110 | -llmf | --log-letsencrypt-max_file Let's Encrypt service log max files
111 |
112 | Proxy port binding
113 | -phttp | --port-http Proxy http port (default: 80)
114 | -phttps | --port-https Proxy https port (default: 443)
115 |
116 | Proxy SSL policy
117 | -sp | --ssl-policy Proxy SSL suport
118 | (default: Mozilla-Intermediate)
119 |
120 | Default Host
121 | -df | --default-host The default host where nginx-proxy will redirect all requests to
122 | the container that matches the VIRTUAL_HOST
123 |
124 | IPv6 support
125 | --activate-ipv6 Use to activate IPv6 support
126 | -ipv6 | --ipv6-address IPv6 address for external connectivity
127 | --ipv6-subnet You must inform IPv6 subnet to create
128 | a docker network
129 | (default: 2001:db8:1:1::/112)
130 |
131 | Other options
132 | --yes Set "yes" to all, use it with caution
133 | --debug Show script debug options
134 | --silent Hide all script message
135 | -dr | --docker-rootless Add Docker rootless support by adding the
136 | the current user's $XDG_RUNTIME_DIR and
137 | concat with the '/docker.sock' in the
138 | DOCKER_HOST_ROOTLESS_PATH .env file.
139 | -h | --help Display this help
140 |
141 | ${reset}
142 | USAGE
143 | exit 1
144 | }
145 |
--------------------------------------------------------------------------------
/bin/revert.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # This script revert the fresh start script to git branch
5 | #
6 | # Source: https://github.com/evertramos/nginx-proxy-automation
7 | #
8 |
9 | # Get the script name and its real file path
10 | SCRIPT_PATH="$(dirname "$(readlink -f "$0")")"
11 | SCRIPT_NAME="${0##*/}"
12 | CURRENT_PATH=$(pwd)
13 |
14 | # Go to script path if not there
15 | cd "${SCRIPT_PATH}/../"
16 |
17 | # Stop compose
18 | #export COMPOSE_INTERACTIVE_NO_CLI=1
19 | docker compose down || true
20 |
21 | # Remove newly created files/folder
22 | sudo rm -rf ./data .env docker-compose.yml.backup_* .env.backup_* .env
23 |
24 | # Restore docker-compose.yml
25 | git restore docker-compose.yml
26 |
27 | echo 'Repo restored!'
28 |
29 | exit 0
30 |
31 |
--------------------------------------------------------------------------------
/bin/ssl_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #-----------------------------------------------------------------------
4 | #
5 | # test-proxy script - testing nginx-proxy
6 | #
7 | # https://github.com/evertramos/nginx-proxy-automation
8 | #
9 | # Script developed by
10 | # Evert Ramos
11 | #
12 | # Copyright Evert Ramos
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | # Set up your DOMAIN
17 | if [ $# -eq 0 ]; then
18 | echo "Please inform your domain name to test your proxy."
19 | echo "./test.sh $1"
20 | exit 1
21 | else
22 | DOMAIN=$1
23 | fi
24 |
25 | # Read your .env file
26 | source ./../.env
27 |
28 | # Testing your proxy
29 | docker run -d -e VIRTUAL_HOST=$DOMAIN -e LETSENCRYPT_HOST=$DOMAIN --network=$NETWORK --rm --name test-web httpd:alpine
30 |
31 | exit 0
32 |
--------------------------------------------------------------------------------
/bin/stop.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #-----------------------------------------------------------------------
4 | #
5 | # test-proxy script - testing nginx-proxy
6 | #
7 | # https://github.com/evertramos/nginx-proxy-automation
8 | #
9 | # Script developed by
10 | # Evert Ramos
11 | #
12 | # Copyright Evert Ramos
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | # Stop if test is running
17 | docker stop test-web
18 |
19 | exit 0
20 |
--------------------------------------------------------------------------------
/bin/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #-----------------------------------------------------------------------
4 | #
5 | # test-proxy script - testing nginx-proxy
6 | #
7 | # https://github.com/evertramos/nginx-proxy-automation
8 | #
9 | # Script developed by
10 | # Evert Ramos
11 | #
12 | # Copyright Evert Ramos
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | # Set up your DOMAIN
17 | if [ $# -eq 0 ]; then
18 | echo "Please inform your domain name to test your proxy."
19 | echo "./test.sh $1"
20 | exit 1
21 | else
22 | DOMAIN=$1
23 | fi
24 |
25 | # Read your .env file
26 | source ./../.env
27 |
28 | # Testing your proxy
29 | docker run -d -e VIRTUAL_HOST=$DOMAIN --network=$NETWORK --rm --name test-web httpd:alpine
30 |
31 | exit 0
32 |
--------------------------------------------------------------------------------
/bin/update-branch-name.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # This script updates the branch name to 'main'
5 | #
6 | # Source: https://github.com/evertramos/nginx-proxy-automation
7 | #
8 |
9 | # Get the script name and its real file path
10 | SCRIPT_PATH="$(dirname "$(readlink -f "$0")")"
11 | SCRIPT_NAME="${0##*/}"
12 | CURRENT_PATH=$(pwd)
13 |
14 | # Go to script path if not there
15 | cd "${SCRIPT_PATH}/../"
16 |
17 | # Check branch name
18 | BRANCH_NAME="$(git symbolic-ref HEAD 2>/dev/null | awk -F'/' '{print $3}')"
19 | if [[ -z ${BRANCH_NAME} ]]; then
20 | echo "[ERROR] No branch was found at ${SCRIPT_PATH}."
21 | fi
22 |
23 | if [[ "${BRANCH_NAME}" == "master" ]]; then
24 | echo "Your local branch 'master' will be renamed to 'main'"
25 | git branch -m master main
26 | git fetch origin
27 | git branch -u origin/main main
28 | git remote set-head origin -a
29 | fi
30 |
31 | if [[ "${BRANCH_NAME}" == "main" ]]; then
32 | echo "Your local branch is already renamed to 'main'"
33 | fi
34 |
35 | if [[ ! "${SCRIPT_PATH}" == "${CURRENT_PATH}" ]]; then
36 | cd - 1>/dev/null 2>/dev/null
37 | fi
38 |
39 | exit 0
40 |
41 |
--------------------------------------------------------------------------------
/bin/update-checksum.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #-----------------------------------------------------------------------
4 | #
5 | # Update checksum in .env files
6 | #
7 | # Part of https://github.com/evertramos/nginx-proxy-automation
8 | #
9 | # Script written by
10 | # Evert Ramos
11 | #
12 | # Copyright Evert Ramos
13 | #
14 | #-----------------------------------------------------------------------
15 |
16 | # Bash settings (do not mess with it)
17 | shopt -s nullglob globstar
18 |
19 | # Get the script name and its file real path
20 | SCRIPT_PATH="$(dirname "$(readlink -f "$0")")"
21 | SCRIPT_NAME="${0##*/}"
22 |
23 | # Source basescript functions
24 | source $SCRIPT_PATH"/../basescript/bootstrap.sh"
25 |
26 | # Source localscripts
27 | source $SCRIPT_PATH"/localscript/bootstrap.sh"
28 |
29 | # Log
30 | printf "${energy} Start execution '${SCRIPT_PATH}/${SCRIPT_NAME} "
31 | log "Start execution"
32 | log "$@"
33 |
34 | #-----------------------------------------------------------------------
35 | # Initial check - DO NOT CHANGE SETTINGS BELOW
36 | #-----------------------------------------------------------------------
37 |
38 | # Check if there is an .env file in local folder
39 | run_function check_local_env_file
40 |
41 | # Specific PID File if needs to run multiple scripts
42 | NEW_PID_FILE=${PID_FILE_FRESH_INSTALL:-".update_checksum"}
43 |
44 | # Run initial check function
45 | run_function starts_initial_check $NEW_PID_FILE
46 |
47 | # Save PID
48 | system_save_pid $NEW_PID_FILE
49 |
50 | # DO NOT CHANGE ANY OPTIONS ABOVE THIS LINE!
51 |
52 | #-----------------------------------------------------------------------
53 | # [function] Undo script actions
54 | #-----------------------------------------------------------------------
55 | local_undo_restore() {
56 | # local LOCAL_KEEP_RESTORE_FILES
57 | #
58 | # LOCAL_KEEP_RESTORE_FILES=${1:-$KEEP_RESTORE_FILES}
59 |
60 | echoerror \
61 | "It seems something went wrong! \
62 | \nRunning '${FUNCNAME[0]} to try to UNDO all actions done by this script. \
63 | \nPlease make sure everything was put it back in place." false
64 |
65 | # If docker network was created
66 | # if [[ "$ACTION_DOCKER_NETWORK_CREATED" == true ]]; then
67 | # [[ "$SILENT" != true ]] && echowarning "[undo] Deleting created docker network '$DOCKER_NETWORK_NAME'."
68 | # run_function docker_network_remove $DOCKER_NETWORK_NAME
69 | # ACTION_DOCKER_NETWORK_CREATED=false
70 | # fi
71 |
72 | exit 0
73 | }
74 |
75 | #-----------------------------------------------------------------------
76 | # Verify checksum of docker-compose.yml and .env.sample files
77 | #-----------------------------------------------------------------------
78 | run_function md5_check_checksum "$SCRIPT_PATH/../" "docker-compose.yml" $MD5_SUM_DOCKER_COMPOSE
79 | if [[ ! "$MD5_CHECKSUM" == true ]]; then
80 | DOCKER_COMPOSE_CHECKSUM=$(md5sum "$SCRIPT_PATH/../docker-compose.yml" | awk '{print $1}')
81 | echowarning "Updating the checksum for 'MD5_SUM_DOCKER_COMPOSE'"
82 | run_function env_update_variable "$SCRIPT_PATH" "MD5_SUM_DOCKER_COMPOSE" "$DOCKER_COMPOSE_CHECKSUM"
83 | else
84 | echosuccess "Checksum for 'MD5_SUM_DOCKER_COMPOSE' is just fine!"
85 | fi
86 |
87 | run_function md5_check_checksum "$SCRIPT_PATH/../" ".env.sample" $MD5_SUM_ENV_SAMPLE
88 | if [[ ! "$MD5_CHECKSUM" == true ]]; then
89 | ENV_CHECKSUM=$(md5sum "$SCRIPT_PATH/../.env.sample" | awk '{print $1}')
90 | echowarning "Updating the checksum for 'MD5_SUM_ENV_SAMPLE'"
91 | run_function env_update_variable "$SCRIPT_PATH" "MD5_SUM_ENV_SAMPLE" "$ENV_CHECKSUM"
92 | else
93 | echosuccess "Checksum for 'MD5_SUM_ENV_SAMPLE' is just fine!"
94 | fi
95 |
96 | exit 0
97 |
--------------------------------------------------------------------------------
/bin/update-nginx-template.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # This script updates the branch name to 'main'
5 | #
6 | # Source: https://github.com/evertramos/nginx-proxy-automation
7 | #
8 |
9 | # Get the script name and its real file path
10 | SCRIPT_PATH="$(dirname "$(readlink -f "$0")")"
11 | SCRIPT_NAME="${0##*/}"
12 | CURRENT_PATH=$(pwd)
13 |
14 | cd "${SCRIPT_PATH}/../"
15 |
16 | # Update template with the latest version of nginx template
17 | curl https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl > nginx.tmpl
18 |
19 | cd - 1>/dev/null 2>/dev/null
20 |
21 | exit 0
22 |
23 |
--------------------------------------------------------------------------------
/conf.d/realip.conf:
--------------------------------------------------------------------------------
1 | #
2 | # [WARNING] To enable this files you need to uncomment USE_NGINX_CONF_FILES=true in .env file
3 | #
4 | # [WARNING] Also, read all the comments in .env about NGINX use special conf files
5 | #
6 |
7 | #
8 | # Real IP Settings
9 | #
10 | # This option get user's real ip address
11 | # to be fowared to your service container
12 |
13 | #
14 | # Basic settings
15 | #
16 | # The option 'set_real_ip_from'
17 | # must correspont to your docker network address
18 | set_real_ip_from 172.16.0.0/12;
19 | set_real_ip_from 10.0.0.0/8;
20 | set_real_ip_from 192.168.0.0/16;
21 |
22 | #
23 | # CloudFlare settings
24 | #
25 | # If you CloudFlare and want to forward the
26 | # user's real IP to your app services you
27 | # must uncomment all lines below and be sure
28 | # to comment the lines of the "Basic settings"
29 | set_real_ip_from 103.21.244.0/22;
30 | set_real_ip_from 103.22.200.0/22;
31 | set_real_ip_from 103.31.4.0/22;
32 | set_real_ip_from 104.16.0.0/12;
33 | set_real_ip_from 108.162.192.0/18;
34 | set_real_ip_from 131.0.72.0/22;
35 | set_real_ip_from 141.101.64.0/18;
36 | set_real_ip_from 162.158.0.0/15;
37 | set_real_ip_from 172.64.0.0/13;
38 | set_real_ip_from 173.245.48.0/20;
39 | set_real_ip_from 188.114.96.0/20;
40 | set_real_ip_from 190.93.240.0/20;
41 | set_real_ip_from 197.234.240.0/22;
42 | set_real_ip_from 198.41.128.0/17;
43 | set_real_ip_from 2400:cb00::/32;
44 | set_real_ip_from 2606:4700::/32;
45 | set_real_ip_from 2803:f800::/32;
46 | set_real_ip_from 2405:b500::/32;
47 | set_real_ip_from 2405:8100::/32;
48 | set_real_ip_from 2c0f:f248::/32;
49 | set_real_ip_from 2a06:98c0::/29;
50 |
51 | #
52 | # Header for Real IP Address
53 | #
54 | real_ip_header X-Forwarded-For;
55 | #real_ip_header X-Real-IP;
56 | real_ip_recursive on;
57 |
58 |
--------------------------------------------------------------------------------
/conf.d/servertokens.conf:
--------------------------------------------------------------------------------
1 | #
2 | # [WARNING] To enable this files you need to uncomment USE_NGINX_CONF_FILES=true in .env file
3 | #
4 | # [WARNING] Also, read all the comments in .env about NGINX use special conf files
5 | #
6 |
7 | server_tokens off;
8 |
--------------------------------------------------------------------------------
/conf.d/uploadsize.conf:
--------------------------------------------------------------------------------
1 | #
2 | # [WARNING] In order to enable this option in the proxy you must run the fresh start script with the option `--use-nginx-conf-files`
3 | #
4 |
5 | client_max_body_size 100m;
6 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | nginx-proxy-automation-web:
3 | image: nginx:${NGINX_IMAGE_VERSION:-stable-alpine}
4 | labels:
5 | com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
6 | container_name: ${NGINX_WEB_SEVICE_NAME:-nginx-proxy-automation-web}
7 | restart: always
8 | ports:
9 | - "${IPv4:-0.0.0.0}:${DOCKER_HTTP_:-80}:80"
10 | - "${IPv4:-0.0.0.0}:${DOCKER_HTTPS:-443}:443"
11 | # - "${IPv6:-::0}:${DOCKER_HTTP_:-80}:80"
12 | # - "${IPv6:-::0}:${DOCKER_HTTPS:-443}:443"
13 | environment:
14 | SSL_POLICY: ${SSL_POLICY:-Mozilla-Intermediate}
15 | # DEFAULT_HOST: ${DEFAULT_HOST}
16 | # ENABLE_IPV6: "true"
17 | volumes:
18 | - ${NGINX_FILES_PATH:-./data}/conf.d:/etc/nginx/conf.d
19 | - ${NGINX_FILES_PATH:-./data}/vhost.d:/etc/nginx/vhost.d
20 | - ${NGINX_FILES_PATH:-./data}/html:/usr/share/nginx/html
21 | - ${NGINX_FILES_PATH:-./data}/certs:/etc/nginx/certs:ro
22 | - ${NGINX_FILES_PATH:-./data}/htpasswd:/etc/nginx/htpasswd:ro
23 | logging:
24 | driver: ${NGINX_WEB_LOG_DRIVER:-json-file}
25 | options:
26 | max-size: ${NGINX_WEB_LOG_MAX_SIZE:-4m}
27 | max-file: ${NGINX_WEB_LOG_MAX_FILE:-10}
28 |
29 | nginx-proxy-automation-gen:
30 | image: nginxproxy/docker-gen:${DOCKER_GEN_IMAGE_VERSION:-0.7.7}
31 | command: -notify-sighup ${NGINX_WEB_SEVICE_NAME:-nginx-proxy-automation-web} -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
32 | container_name: ${DOCKER_GEN_SEVICE_NAME:-nginx-proxy-automation-gen}
33 | restart: always
34 | volumes:
35 | - ${NGINX_FILES_PATH:-./data}/conf.d:/etc/nginx/conf.d
36 | - ${NGINX_FILES_PATH:-./data}/vhost.d:/etc/nginx/vhost.d
37 | - ${NGINX_FILES_PATH:-./data}/html:/usr/share/nginx/html
38 | - ${NGINX_FILES_PATH:-./data}/certs:/etc/nginx/certs:ro
39 | - ${NGINX_FILES_PATH:-./data}/htpasswd:/etc/nginx/htpasswd:ro
40 | - ${DOCKER_HOST_ROOTLESS_PATH:-/var/run/docker.sock}:/tmp/docker.sock:ro
41 | - ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
42 | logging:
43 | driver: ${NGINX_GEN_LOG_DRIVER:-json-file}
44 | options:
45 | max-size: ${NGINX_GEN_LOG_MAX_SIZE:-2m}
46 | max-file: ${NGINX_GEN_LOG_MAX_FILE:-10}
47 |
48 | nginx-proxy-automation-letsencrypt:
49 | image: nginxproxy/acme-companion:${NGINX_PROXY_COMPANION_IMAGE_VERSION:-2.1}
50 | container_name: ${LETS_ENCRYPT_SEVICE_NAME:-nginx-proxy-automation-letsencrypt}
51 | restart: always
52 | volumes:
53 | - ${NGINX_FILES_PATH:-./data}/conf.d:/etc/nginx/conf.d
54 | - ${NGINX_FILES_PATH:-./data}/vhost.d:/etc/nginx/vhost.d
55 | - ${NGINX_FILES_PATH:-./data}/html:/usr/share/nginx/html
56 | - ${NGINX_FILES_PATH:-./data}/certs:/etc/nginx/certs:rw
57 | - ${NGINX_FILES_PATH:-./data}/acme.sh:/etc/acme.sh
58 | - ${DOCKER_HOST_ROOTLESS_PATH:-/var/run/docker.sock}:/var/run/docker.sock:ro
59 | environment:
60 | NGINX_DOCKER_GEN_CONTAINER: ${DOCKER_GEN_SEVICE_NAME:-nginx-proxy-automation-gen}
61 | NGINX_PROXY_CONTAINER: ${NGINX_WEB_SEVICE_NAME:-nginx-proxy-automation-web}
62 | DEFAULT_EMAIL: ${DEFAULT_EMAIL:-mail@yourdomain.tld}
63 | # ACME_CHALLENGE: "DNS-01"
64 | # ACMESH_DNS_API_CONFIG: |-
65 | # DNS_API: dns_cf
66 | # CF_Token: "${CLOUDFLARE_DNS_TOKEN}"
67 | logging:
68 | driver: ${NGINX_LETSENCRYPT_LOG_DRIVER:-json-file}
69 | options:
70 | max-size: ${NGINX_LETSENCRYPT_LOG_MAX_SIZE:-2m}
71 | max-file: ${NGINX_LETSENCRYPT_LOG_MAX_FILE:-10}
72 |
73 | networks:
74 | default:
75 | external: true
76 | name: ${NETWORK:-proxy}
77 |
78 |
--------------------------------------------------------------------------------
/docs/HOWTO-Synology.md:
--------------------------------------------------------------------------------
1 | ## Port mapping
2 | Synology default installs a web server on port 80 blocking certificate generation.
3 |
4 | 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:
5 |
6 | #
7 | # Set the local exposed ports for http and https - this will allow you to run with a legacy web
8 | # server already installed for local use
9 | #
10 | # NOTE: For this to function your internet router must forward the official ports to the mapped ports -
11 | # in this example external port 80 to docker host 81 and external port 443 to docker host 444
12 | #
13 | DOCKER_HTTP=81
14 | DOCKER_HTTPS=444
15 |
16 | ## File permissions
17 | 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)
18 |
19 | mkdir -p data/certs
20 | mkdir data/htpasswd
21 | mkdir data/conf.d
22 | mkdir data/vhost.d
23 | mkdir data/html
24 | chgrp -R 101 data
25 | chmod -R g+rwx data
26 |
27 | Contributed by https://github.com/nicolailang/
28 |
--------------------------------------------------------------------------------
/docs/HOWTO-server-at-home.md:
--------------------------------------------------------------------------------
1 | # Home Server Testing
2 | This document provides basic troubleshooting for setting up `nginx-proxy-automation` on a home server. This includes the most common issues, but does not include all possible issues.
3 |
4 | Before following these steps, be sure to understand and follow all instructions in the primary [README](https://github.com/evertramos/nginx-proxy-automation/blob/master/docs/README.md) documentation.
5 |
6 | ## Debugging Failed Connections
7 |
8 | Start diagnosing as close to the server as possible, then move outwards.
9 |
10 | For testing ports, here is a list of common network command line (cli) tools for use:
11 | - [nmap](https://nmap.org)
12 | - [netcat](https://sectools.org/tool/netcat/)
13 | - [telnet](https://manpages.org/telnet)
14 |
15 | 1. Without using `nginx-proxy-automation`, run the container on the server, open the port as you normally would (i.e. `-p 9000:9000`), and attempt to see if the port is available (on the server) after running. You can test if the port is open using one of the common network cli tools, or other possible tools (i.e. [netstat](https://linux.die.net/man/8/netstat)). For example if you have exposed port 9000, running `nmap -p 9000 localhost` on the same server as the running Docker container, and it should return an open port. This tests if you may have a general issue with your docker setup. On failure, double check if you have setup any custom firewall rules or have setup `ufw` with Docker.
16 | 2. Perform the same steps as 1, but try testing the port from a different machine on the same subnet / LAN if possible. For example, running `nmap -p 9000 {SERVER-IP-ADDRESS}` should show an open connection. This tests if the server is exposing ports at all. This tests if you may have a firewall issue on the server that needs diagnosed. On failure, double check if you have setup any custom firewall rules or have setup `ufw` with Docker.
17 | 3. If you are using port forwarding on a router: Without using `nginx-proxy-automation`, run the container on the server, assuming you have successfully tested connecting to the container on another computer in the same LAN, and forward the port from the router to server's open port. Then you can run `nmap -p 9000 {PUBLIC-ROUTER-IP-ADDRESS-OR-DOMAIN-NAME}`, and it will show an open connection. This will test if you have properly forwarded the port. On failure, you will need to diagnose your port forwarding rules, and may need to consult your router manual. Be sure you are **not** using the local IP address of your router (i.e. 192.168.1.1 is a common local IP address, and that will not work for this test).
18 |
19 | ## Port Forwarding
20 | If you are using port forwarding, it is highly recommended to connect via your own registered domain using [DDNS](https://en.wikipedia.org/wiki/Dynamic_DNS). There is a chance your ISP will change the public address of your router. Using DDNS will ensure that the domain pointing to your router is using the latest public IP address of your router.
21 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # NGINX Proxy Automation 🔥
2 |
3 | ## What this project does
4 |
5 | This script will _power up_ your new server with the [*nginx-proxy*](https://github.com/nginx-proxy/nginx-proxy), where you will be able to host multiple sites,
6 | auto renewing Let´s Encrypt certificates! ❤️
7 |
8 | We strongly recommend you (please do! 🙏) to read all documentation before starting in production as well as the [nginx-proxy docs](https://github.com/nginx-proxy/nginx-proxy).
9 |
10 | > To access the previous version of this project please access [version 0.4](https://github.com/evertramos/nginx-proxy-automation/tree/v0.4).
11 |
12 | ### Upgrading from previous version
13 |
14 | If you are upgrading from the previous version please follow the guide below carefully:
15 |
16 | https://github.com/evertramos/nginx-proxy-automation/blob/master/docs/upgrade-guide.md
17 |
18 | ## Prerequisites
19 |
20 | 1. 🐧 Linux! (just in case...)
21 |
22 | > Please check all requirements at [requirements](/docs/requirements.md).
23 |
24 | In order to use this compose file (docker-compose.yml) you must have:
25 |
26 | 2. 🐋 Docker installed (https://docs.docker.com/engine/installation/)
27 |
28 | 3. Docker-compose installed (https://docs.docker.com/compose/install/)
29 |
30 | > I have an [easy-server](https://github.com/evertramos/easy-server) for myself which I use to install
31 | > docker and docker-compose in new servers and some aliases and other stuff. Feel free to use it, **but**
32 | > it is not related to this repo and maintainance it's for my own use only. Check './install/docker' folder.
33 |
34 | Also, you will need to make sure you have:
35 |
36 | 4. Port 80 and 443 available for binding - which means apache/nginx or other web services should not be
37 | running in your server
38 |
39 | 5. Server must be accessible by a public IP address
40 |
41 | ## How to use it
42 |
43 | 1. Clone this repository **using the option _--recurse-submodules_**:
44 |
45 | ```bash
46 | git clone --recurse-submodules https://github.com/evertramos/nginx-proxy-automation.git proxy
47 | ```
48 |
49 | > Make sure you use the option '--recurse-submodules' once we use an external module in this project, please check
50 | > [basescript](https://github.com/evertramos/basescript)
51 |
52 | > Please note we use 'proxy' as folder at the end. But you can change it to whatever fits you better
53 |
54 | 2. 🚀 Run the script 'fresh_start.sh'
55 |
56 | ```bash
57 | cd proxy/bin
58 | ./fresh-start.sh
59 | ```
60 | This script will walk you through all config process.
61 |
62 | When it finishes you are good to go! :checkered_flag:
63 |
64 | > ✈️ If you are in a 'hurry' just run `$ ./fresh-start.sh --yes -e your_email@domain --skip-docker-image-check`
65 |
66 | > ⚠️ You can check all available options to run the script `$ ./fresh-start.sh --help`
67 |
68 | > 🗒️ From version _v0.3_ the script will output logs to _/var/log/basescript.log_
69 |
70 | 3. Fire your new site with the following options:
71 |
72 | ```yaml
73 | VIRTUAL_HOST=your.domain.com
74 | LETSENCRYPT_HOST=your.domain.com
75 | LETSENCRYPT_EMAIL=your.email@your.domain.com
76 | NETWORK=proxy
77 | ```
78 |
79 | The fresh start script asked you for the proxy network name if you changed set a name differente from
80 | the default please update the option *'NETWORK'* in the examples below before running it.
81 |
82 | - Simple site without Let's Encrypt certificate
83 | ```bash
84 | docker run -d -e VIRTUAL_HOST=your.domain.com \
85 | --network=proxy \
86 | --name my_app \
87 | httpd:alpine
88 | ```
89 |
90 | - To have SSL in your web/app you must add the option `-e LETSENCRYPT_HOST=your.domain.com`, as follow:
91 |
92 | ```bash
93 | docker run -d -e VIRTUAL_HOST=your.domain.com \
94 | -e LETSENCRYPT_HOST=your.domain.com \
95 | -e LETSENCRYPT_EMAIL=your.email@your.domain.com \
96 | --network=proxy \
97 | --name my_app \
98 | httpd:alpine
99 | ```
100 |
101 | > You don´t need to open port *443* in your container, the certificate validation is managed by the web proxy
102 |
103 | > Please note that when running a new container to generate certificates with Let's Encrypt
104 | > (`-e LETSENCRYPT_HOST=your.domain.com`), it may take a few minutes
105 |
106 |
107 | ## Further Options
108 |
109 | 1. Basic Authentication Support
110 |
111 | In order to be able to secure your virtual host with basic authentication, you must create a htpasswd file
112 | within `${NGINX_FILES_PATH}/htpasswd/${VIRTUAL_HOST}` via:
113 |
114 | ```bash
115 | sudo sh -c "echo -n '[username]:' >> ${NGINX_FILES_PATH}/htpasswd/${VIRTUAL_HOST}"
116 | sudo sh -c "openssl passwd -apr1 >> ${NGINX_FILES_PATH}/htpasswd/${VIRTUAL_HOST}"
117 | ```
118 |
119 | > Please replace the `${NGINX_FILES_PATH}` with real path to information, replace `[username]` with your username and `${VIRTUAL_HOST}` with your host's domain. You will be prompted for a password.
120 |
121 | 2. Using different networks
122 |
123 | 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:
124 |
125 | ```bash
126 | docker network create myownnetwork
127 | docker network connect myownnetwork nginx-web
128 | docker network connect myownnetwork nginx-gen
129 | docker network connect myownnetwork nginx-letsencrypt
130 | ```
131 |
132 | 3. Ports
133 |
134 | If your service container runs on port 8545 you probably will need to add the `VIRTUAL_PORT` environment variable to your container,
135 | in the `docker-compose.yml`, so it can be proxied, as of:
136 |
137 | ```bash
138 | parity
139 | image: parity/parity:v1.8.9
140 | [...]
141 | environment:
142 | [...]
143 | VIRTUAL_PORT: 8545
144 | ```
145 |
146 | Or as of below:
147 |
148 | ```bash
149 | docker run [...] -e VIRTUAL_PORT=8545 [...]
150 | ```
151 |
152 | 4. Restarting proxy container
153 |
154 | In some cases you will need to restart the proxy in order to read, as an example, the Basic Auth, if you set it after your service container is already up and running. So, the way I use to restart the proxy (NGINX) is as following, which has no downtime:
155 |
156 | ```bash
157 | docker exec -it ${NGINX_WEB} nginx -s reload
158 | ```
159 |
160 | Where *${NGINX_WEB}* is your proxy container name, which in the original `.env` file is set as *nginx-web*.
161 |
162 | 5. **sudo** options
163 |
164 | If you need to save the nginx-proxy data files in a folder which the user running 'fresh-start.sh' script does not have access, you might accomplish that using _sudo_. In order to allow the script to run some commands with _sudo_ you need to set _true_ to the variable ['ALLOW_RUN_WITH_SUDO'](https://github.com/evertramos/nginx-proxy-automation/blob/d48b2477ed28cbda37738046079e35df219ba3e9/.env.sample#L20) at '.env.sample' file **before** running fresh-start.sh script, as of:
165 |
166 | ```bash
167 | # Allow run commands with sudo if needed
168 | ALLOW_RUN_WITH_SUDO=true
169 | ```
170 |
171 | ## Testing nginx-proxy
172 |
173 | 1. Run the script `test.sh` informing your domain already configured in your DNS to point out to your server as follow:
174 |
175 | ```bash
176 | ./test.sh your.domain.com
177 | ```
178 |
179 | or simply run:
180 |
181 | ```bash
182 | docker run -dit -e VIRTUAL_HOST=your.domain.com --network=proxy --name test-web httpd:alpine
183 | ```
184 |
185 | > If you want to test the Let's Encrypt certificate as well use `ssl_test.sh your.domain.com`
186 |
187 | Access your browser with your domain!
188 |
189 | To stop and remove your test container run our `stop.sh` script:
190 |
191 | ```bash
192 | ./stop.sh
193 | ```
194 |
195 | Or simply run:
196 |
197 | ```bash
198 | docker stop test-web && docker rm test-web
199 | ```
200 |
201 | ## **PRODUCTION** ⚠️ [IMPORTANT]
202 |
203 | If you are using this project in production enviroment, check all license involved and consider the following recomendation:
204 |
205 | - [rootless docker](https://docs.docker.com/engine/security/rootless/)
206 | - [docker compose files](https://docs.docker.com/compose/production/)
207 |
208 | ## Other projects using nginx-proxy
209 | Following are links to docker containers using this web proxy:
210 | 1. [docker-wordpress-letsencrypt](https://github.com/evertramos/docker-wordpress-letsencrypt)
211 | 2. [docker-portainer-letsencrypt](https://github.com/evertramos/docker-portainer-letsencrypt)
212 | 3. [docker-nextcloud-letsencrypt](https://github.com/evertramos/docker-nextcloud-letsencrypt)
213 | 4. [docker-registry-letsencrypt](https://github.com/evertramos/docker-registry-letsencrypt)
214 | 5. [gitlab-docker-letsencrypt](https://github.com/steevepay/gitlab-docker-letsencrypt)
215 | 6. [docker-webtrees-letsencrypt](https://github.com/mstroppel/docker-webtrees-letsencrypt)
216 |
217 | ## Running this Proxy on a Synology NAS
218 | Please checkout this [howto](https://github.com/evertramos/nginx-proxy-automation/blob/master/docs/HOWTO-Synlogy.md).
219 |
220 |
--------------------------------------------------------------------------------
/docs/cloudflare.md:
--------------------------------------------------------------------------------
1 | # Cloudflare integration
2 |
3 | If using Cloudflare services, an API Token to allow your server to validate your domain with DNS-01 might be needed.
4 |
5 | > We recommend using Cloudflare for a couple of reasons...
6 |
7 | Follow the steps below to use DNS-01:
8 |
9 | ## 1. Generate an API Token for ACME DNS-01
10 |
11 | In Cloudflare go to your profile and find API Token option:
12 | 
13 |
14 | You can manually create one or use the _'Edit zone DNS'_ template. Remember to add your domains which you would like to allow this token to have access to it and the source IP address:
15 | 
16 |
17 | Save your token and place it in .env at CLOUDFLARE_DNS_TOKEN.
18 |
19 | ## 2. Activate in your nginx proxy
20 |
21 | Uncomment the following lines:
22 | https://github.com/evertramos/nginx-proxy-automation/blob/462b224ce4fd9dce4b2b796e2b4524d4ee36b084/docker-compose.yml#L63-L66
23 |
24 | And restart your service running `docker compose up &` at your root folder.
25 |
26 | ## Disclaimer
27 |
28 | As of [acme-compnation](https://github.com/nginx-proxy/acme-companion) if we can not comply to use HTTP-01, using DNS-01 could be used, as also per [acme.sh](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) as well.
29 | So, following [acme-compnation instruction ](https://github.com/nginx-proxy/acme-companion/blob/main/docs/Let's-Encrypt-and-ACME.md#dns-01-acme-challenge) a global API Key could be used, but we do not like this idea much due to security resons, reason why we suggest creating a more restrict API Token as indicated above.
30 |
31 |
--------------------------------------------------------------------------------
/docs/requirements.md:
--------------------------------------------------------------------------------
1 | # Requirements to run this automation script
2 |
3 |
4 | ## Environment
5 | - Linux
6 |
7 | ## Softwares
8 | - Bash
9 | - Docker
10 | - Docker Compose
11 | - Git
12 | - Curl
13 | - Dpkg
14 | - Md5sum
15 |
16 | ## Used functions
17 | - sudo
18 | - source
19 | - cd
20 | - cp
21 | - mv
22 | - dirname
23 | - type
24 | - command
25 | - systemctl
26 | - echo
27 | - printf
28 | - read
29 | - sed
30 | - awk
31 | - wget
32 | - cat
33 | - cut
34 | - head
35 | - tr
36 | - grep
37 | - rm
38 | - trap
39 | - dpkg
40 | - tput
41 | - md5sum
42 | - ip
43 | - git
44 | - docker
45 | - docker-compose
46 | - curl
47 |
--------------------------------------------------------------------------------
/docs/upgrade-guide.md:
--------------------------------------------------------------------------------
1 | # Upgrading guide
2 |
3 | Here we will try to cover all aspects we faced in a real production environment when migrating from the previous version of this project to the newst version.
4 |
5 | ## From v0.4 to v0.5
6 |
7 | The version v0.5 was a big step into automation. We 'conquer the world'!
8 |
9 | > I update one of the production server and got a _96 seconds_ of downtime, with no complaint from clients.
10 | > Some of them did not even notice, but all were advised about the update and the possible downtime in case of failure.
11 |
12 | > If you can not afford this downtime there is a couple way around on this but you will need
13 | a couple things... new server (temporary), set a dns rules to create the new certificates
14 | copy all files to the new server and do the following, after all is ready, redirect the dns
15 | to the new server and than copy the temp server to the production, fire all services, test
16 | and redirect the dns to the new server. Be aware that changes made during this proccess might
17 | need to be updated in the containers when syncing files from one server to another.
18 |
19 | So, let's go. First thing first!
20 |
21 | 1. Backup EVERYTHING! I would suggest backup in the server and somewhere else (not in the server)
22 |
23 | 2. Update the git repo with the new version (:warning:)
24 |
25 | 2.1 Copy _docker-compose.yml_ (or the _docker-compose-multiple-networks.yml_ if you used this option) and _.env_ file
26 |
27 | ```bash
28 | $ cp docker-compose.yml docker-compose-old.yml
29 | $ cp .env .env-old
30 | ```
31 |
32 | > We will use this do stop the current services
33 |
34 | 2.2 Reset all changes in the repo
35 |
36 | This is required to update to the latest version
37 |
38 | ```bash
39 | $ git reset --hard
40 | ```
41 |
42 | 2.3 Pull and Checkout master
43 |
44 | ```bash
45 | $ git pull origin master
46 | $ git checkout master
47 | ```
48 |
49 | 2.4 Set the **basescript** submodule
50 |
51 | If you notice the submodule folder used in this project ([basescript](https://github.com/evertramos/basescript/))
52 | is present in the master branch we just checkout, but it is empty, so we need to fix it (init and update).
53 |
54 | ```bash
55 | $ git submodule init
56 | $ git submodule update
57 | ```
58 |
59 | > The _basescript_ folder should not be empty after the commands above
60 |
61 | 3. Run the _fresh-start.sh_ script (:construction:)
62 |
63 | Here we will run the _fresh-start.sh_ script in order to create all new settings that we will use.
64 | Please do it carefully. You might use different names for proxy services.
65 |
66 | ```bash
67 | $ cd bin
68 | $ ./fresh-start.sh
69 | ```
70 |
71 | In most cases you will get the following _'error'_, which is expected:
72 |
73 | 
74 |
75 | The error above is related to port binding, once port 80 is already binded to the current nginx-proxy container.
76 |
77 | > [IMPORTANT] If you use the *same service name* for all containers and the same network name you might not receive the error above
78 | > and you should be ready to go at this point. Check the your running sites at the browser to see if everything is up and running.
79 |
80 | ⚠️ if you do not get the error above and your sites are NOT working, you might checkthe network name and go for the next item.
81 |
82 | 4. Adding the running containers to the new network
83 |
84 | If you keep the same network name you might skip this item, but if not, you must add all running containers to the new network
85 | created by the _fresh-start.sh_ script.
86 |
87 | ```bash
88 | $ docker network connect [YOUR_NEW_NETWORK_NAME] [CONTAINER_NAME]
89 | ```
90 |
91 | > Run the command above for all containers connected to the proxy and remember to update the network name in the docker-compose file
92 | > for the all sites
93 |
94 | 5. Restart proxy with new service
95 |
96 | At this point all sites should be still up and running, so keep it cool and let's see if all will work as expected.
97 |
98 | After all containers are connected to the new proxy network (if the case) you will stop the current proxy services and start the new one.
99 | We did it in one command line to reduce the downtime.
100 |
101 | ```bash
102 | $ docker-compose --file docker-compose-old.yml down && docker-compose up -d
103 | ```
104 |
105 | Check your sites to see if it is all running, if some of them are not working, you might check the letsencrypt container logs to see if
106 | there was a problem issuing new certificates.
107 |
108 | If something else happen and you must reverse it quickly just follow the next step. But try to check the logs first, it might take a few
109 | minutes to fire new certificates with Let's Encrypt so, depending on the quantity of sites you are running in your server it might take
110 | some time to issue it all.
111 |
112 | 6. Reverting to the old proxy
113 |
114 | You can retore backup files and start the same exact environmen you had previously this upgrade guide, but there is a quicker way to restore your sites.
115 | Just run the following:
116 |
117 | ```bash
118 | $ docker-compose down && docker-compose --file docker-compose-old.yml --env-file .env-old up -d
119 | ```
120 |
121 | > The command above will stop the new version and fire the previous version of your proxy, so, after this command evertyhing should 'be back to normal'
122 | > as it was before the update, but keep in mind to find the errors if they occured and update it.
123 |
124 | 7. Clean up
125 |
126 | After having all work done you might remove unused file such as:
127 |
128 |
129 | ```bash
130 | $ rm docker-compose-old.yml .env-old
131 | ```
132 |
133 | > If you get any erros when updating please post on the [**upgrade discussion**](https://github.com/evertramos/basescript/discussions/5) (avoid creating new issues).
134 |
--------------------------------------------------------------------------------
/nginx.tmpl:
--------------------------------------------------------------------------------
1 | # nginx-proxy{{ if $.Env.NGINX_PROXY_VERSION }} version : {{ $.Env.NGINX_PROXY_VERSION }}{{ end }}
2 |
3 | {{- /*
4 | * Global values. Values are stored in this map rather than in individual
5 | * global variables so that the values can be easily passed to embedded
6 | * templates (Go templates cannot access variables outside of their own
7 | * scope) and displayed in the debug endpoint output.
8 | */}}
9 | {{- $globals := dict }}
10 | {{- $_ := set $globals "containers" $ }}
11 | {{- $_ := set $globals "Env" $.Env }}
12 | {{- $_ := set $globals "Docker" $.Docker }}
13 | {{- $_ := set $globals "CurrentContainer" (where $globals.containers "ID" $globals.Docker.CurrentContainerID | first) }}
14 |
15 | {{- $config := dict }}
16 | {{- $_ := set $config "nginx_proxy_version" $.Env.NGINX_PROXY_VERSION }}
17 | {{- $_ := set $config "default_cert_ok" (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
18 | {{- $_ := set $config "external_http_port" ($globals.Env.HTTP_PORT | default "80") }}
19 | {{- $_ := set $config "external_https_port" ($globals.Env.HTTPS_PORT | default "443") }}
20 | {{- $_ := set $config "sha1_upstream_name" ($globals.Env.SHA1_UPSTREAM_NAME | default "false" | parseBool) }}
21 | {{- $_ := set $config "default_root_response" ($globals.Env.DEFAULT_ROOT | default "404") }}
22 | {{- $_ := set $config "trust_default_cert" ($globals.Env.TRUST_DEFAULT_CERT | default "true") }}
23 | {{- $_ := set $config "trust_downstream_proxy" ($globals.Env.TRUST_DOWNSTREAM_PROXY | default "true" | parseBool) }}
24 | {{- $_ := set $config "enable_access_log" ($globals.Env.DISABLE_ACCESS_LOGS | default "false" | parseBool | not) }}
25 | {{- $_ := set $config "enable_ipv6" ($globals.Env.ENABLE_IPV6 | default "false" | parseBool) }}
26 | {{- $_ := set $config "prefer_ipv6_network" ($globals.Env.PREFER_IPV6_NETWORK | default "false" | parseBool) }}
27 | {{- $_ := set $config "ssl_policy" ($globals.Env.SSL_POLICY | default "Mozilla-Intermediate") }}
28 | {{- $_ := set $config "enable_debug_endpoint" ($globals.Env.DEBUG_ENDPOINT | default "false") }}
29 | {{- $_ := set $config "hsts" ($globals.Env.HSTS | default "max-age=31536000") }}
30 | {{- $_ := set $config "acme_http_challenge" ($globals.Env.ACME_HTTP_CHALLENGE_LOCATION | default "true") }}
31 | {{- $_ := set $config "enable_http2" ($globals.Env.ENABLE_HTTP2 | default "true") }}
32 | {{- $_ := set $config "enable_http3" ($globals.Env.ENABLE_HTTP3 | default "false") }}
33 | {{- $_ := set $config "enable_http_on_missing_cert" ($globals.Env.ENABLE_HTTP_ON_MISSING_CERT | default "true") }}
34 | {{- $_ := set $config "https_method" ($globals.Env.HTTPS_METHOD | default "redirect") }}
35 | {{- $_ := set $config "non_get_redirect" ($globals.Env.NON_GET_REDIRECT | default "301") }}
36 | {{- $_ := set $config "default_host" $globals.Env.DEFAULT_HOST }}
37 | {{- $_ := set $config "resolvers" $globals.Env.RESOLVERS }}
38 | {{- /* LOG_JSON is a shorthand that sets logging defaults to JSON format */}}
39 | {{- $_ := set $config "enable_json_logs" ($globals.Env.LOG_JSON | default "false" | parseBool) }}
40 | {{- $_ := set $config "log_format" $globals.Env.LOG_FORMAT }}
41 | {{- $_ := set $config "log_format_escape" $globals.Env.LOG_FORMAT_ESCAPE }}
42 |
43 | {{- $_ := set $globals "config" $config }}
44 |
45 | {{- $_ := set $globals "vhosts" (dict) }}
46 | {{- $_ := set $globals "networks" (dict) }}
47 | # Networks available to the container running docker-gen (which are assumed to
48 | # match the networks available to the container running nginx):
49 | {{- /*
50 | * Note: $globals.CurrentContainer may be nil in some circumstances due to
51 | * . For more context
52 | * see .
53 | */}}
54 | {{- if $globals.CurrentContainer }}
55 | {{- range sortObjectsByKeysAsc $globals.CurrentContainer.Networks "Name" }}
56 | {{- $_ := set $globals.networks .Name . }}
57 | # {{ .Name }}
58 | {{- else }}
59 | # (none)
60 | {{- end }}
61 | {{- else }}
62 | # /!\ WARNING: Failed to find the Docker container running docker-gen. All
63 | # upstream (backend) application containers will appear to be
64 | # unreachable. Try removing the -only-exposed and -only-published
65 | # arguments to docker-gen if you pass either of those. See
66 | # .
67 | {{- end }}
68 |
69 | {{- /*
70 | * Template used as a function to get a container's IP address. This
71 | * template only outputs debug comments; the IP address is "returned" by
72 | * storing the value in the provided dot dict.
73 | *
74 | * The provided dot dict is expected to have the following entries:
75 | * - "globals": Global values.
76 | * - "container": The container's RuntimeContainer struct.
77 | *
78 | * The return value will be added to the dot dict with key "ip".
79 | */}}
80 | {{- define "container_ip" }}
81 | {{- $ipv4 := "" }}
82 | {{- $ipv6 := "" }}
83 | # networks:
84 | {{- range sortObjectsByKeysAsc $.container.Networks "Name" }}
85 | {{- /*
86 | * TODO: Only ignore the "ingress" network for Swarm tasks (in case
87 | * the user is not using Swarm mode and names a network "ingress").
88 | */}}
89 | {{- if eq .Name "ingress" }}
90 | # {{ .Name }} (ignored)
91 | {{- continue }}
92 | {{- end }}
93 | {{- if eq .Name "host" }}
94 | {{- /* Handle containers in host nework mode */}}
95 | {{- if (index $.globals.networks "host") }}
96 | # both container and proxy are in host network mode, using localhost IP
97 | {{- $ipv4 = "127.0.0.1" }}
98 | {{- continue }}
99 | {{- end }}
100 | {{- range sortObjectsByKeysAsc $.globals.CurrentContainer.Networks "Name" }}
101 | {{- if and . .Gateway (not .Internal) }}
102 | # container is in host network mode, using {{ .Name }} gateway IP
103 | {{- $ipv4 = .Gateway }}
104 | {{- break }}
105 | {{- end }}
106 | {{- end }}
107 | {{- if $ipv4 }}
108 | {{- continue }}
109 | {{- end }}
110 | {{- end }}
111 | {{- if and (not (index $.globals.networks .Name)) (not $.globals.networks.host) }}
112 | # {{ .Name }} (unreachable)
113 | {{- continue }}
114 | {{- end }}
115 | {{- /*
116 | * Do not emit multiple `server` directives for this container if it
117 | * is reachable over multiple networks or multiple IP stacks. This avoids
118 | * accidentally inflating the effective round-robin weight of a server due
119 | * to the redundant upstream addresses that nginx sees as belonging to
120 | * distinct servers.
121 | */}}
122 | {{- if or $ipv4 $ipv6 }}
123 | # {{ .Name }} (ignored; reachable but redundant)
124 | {{- continue }}
125 | {{- end }}
126 | # {{ .Name }} (reachable)
127 | {{- if and . .IP }}
128 | {{- $ipv4 = .IP }}
129 | {{- end }}
130 | {{- if and . .GlobalIPv6Address }}
131 | {{- $ipv6 = .GlobalIPv6Address }}
132 | {{- end }}
133 | {{- if and (empty $ipv4) (empty $ipv6) }}
134 | # /!\ No IPv4 or IPv6 for this network!
135 | {{- end }}
136 | {{- else }}
137 | # (none)
138 | {{- end }}
139 | {{ if and $ipv6 $.globals.config.prefer_ipv6_network }}
140 | # IPv4 address: {{ if $ipv4 }}{{ $ipv4 }} (ignored; reachable but IPv6 prefered){{ else }}(none usable){{ end }}
141 | # IPv6 address: {{ $ipv6 }}
142 | {{- $_ := set $ "ip" (printf "[%s]" $ipv6) }}
143 | {{- else }}
144 | # IPv4 address: {{ if $ipv4 }}{{ $ipv4 }}{{ else }}(none usable){{ end }}
145 | # IPv6 address: {{ if $ipv6 }}{{ $ipv6 }}{{ if $ipv4 }} (ignored; reachable but IPv4 prefered){{ end }}{{ else }}(none usable){{ end }}
146 | {{- if $ipv4 }}
147 | {{- $_ := set $ "ip" $ipv4 }}
148 | {{- else if $ipv6}}
149 | {{- $_ := set $ "ip" (printf "[%s]" $ipv6) }}
150 | {{- end }}
151 | {{- end }}
152 | {{- end }}
153 |
154 | {{- /*
155 | * Template used as a function to get the port of the server in the given
156 | * container. This template only outputs debug comments; the port is
157 | * "returned" by storing the value in the provided dot dict.
158 | *
159 | * The provided dot dict is expected to have the following entries:
160 | * - "container": The container's RuntimeContainer struct.
161 | *
162 | * The return value will be added to the dot dict with key "port".
163 | */}}
164 | {{- define "container_port" }}
165 | {{- /* If only 1 port exposed, use that as a default, else 80. */}}
166 | # exposed ports (first ten):{{ range $index, $address := (sortObjectsByKeysAsc $.container.Addresses "Port") }}{{ if lt $index 10 }} {{ $address.Port }}/{{ $address.Proto }}{{ end }}{{ else }} (none){{ end }}
167 | {{- $default_port := when (eq (len $.container.Addresses) 1) (first $.container.Addresses).Port "80" }}
168 | # default port: {{ $default_port }}
169 | {{- $port := eq $.port "default" | ternary $default_port $.port }}
170 | # using port: {{ $port }}
171 | {{- $addr_obj := where $.container.Addresses "Port" $port | first }}
172 | {{- if and $addr_obj $addr_obj.HostPort }}
173 | # /!\ WARNING: Virtual port published on host. Clients
174 | # might be able to bypass nginx-proxy and
175 | # access the container's server directly.
176 | {{- end }}
177 | {{- $_ := set $ "port" $port }}
178 | {{- end }}
179 |
180 | {{- define "ssl_policy" }}
181 | {{- if eq .ssl_policy "Mozilla-Modern" }}
182 | ssl_protocols TLSv1.3;
183 | {{- /*
184 | * This ssl_ciphers directive is not used but necessary to get TLSv1.3 only.
185 | * see https://serverfault.com/questions/1023766/nginx-with-only-tls1-3-cipher-suites
186 | */}}
187 | ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384;
188 | ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
189 | ssl_prefer_server_ciphers off;
190 | {{- else if eq .ssl_policy "Mozilla-Intermediate" }}
191 | ssl_protocols TLSv1.2 TLSv1.3;
192 | 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';
193 | ssl_prefer_server_ciphers off;
194 | {{- else if eq .ssl_policy "Mozilla-Old" }}
195 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
196 | 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:@SECLEVEL=0';
197 | ssl_prefer_server_ciphers on;
198 | {{- else if eq .ssl_policy "AWS-TLS13-1-3-2021-06" }}
199 | ssl_protocols TLSv1.3;
200 | {{- /*
201 | * This ssl_ciphers directive is not used but necessary to get TLSv1.3 only.
202 | * see https://serverfault.com/questions/1023766/nginx-with-only-tls1-3-cipher-suites
203 | */}}
204 | ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384;
205 | ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
206 | ssl_prefer_server_ciphers on;
207 | {{- else if eq .ssl_policy "AWS-TLS13-1-2-2021-06" }}
208 | ssl_protocols TLSv1.2 TLSv1.3;
209 | 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';
210 | ssl_prefer_server_ciphers on;
211 | {{- else if eq .ssl_policy "AWS-TLS13-1-2-Res-2021-06" }}
212 | ssl_protocols TLSv1.2 TLSv1.3;
213 | ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
214 | ssl_prefer_server_ciphers on;
215 | {{- else if eq .ssl_policy "AWS-TLS13-1-2-Ext1-2021-06" }}
216 | ssl_protocols TLSv1.2 TLSv1.3;
217 | 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';
218 | ssl_prefer_server_ciphers on;
219 | {{- else if eq .ssl_policy "AWS-TLS13-1-2-Ext2-2021-06" }}
220 | ssl_protocols TLSv1.2 TLSv1.3;
221 | 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';
222 | ssl_prefer_server_ciphers on;
223 | {{- else if eq .ssl_policy "AWS-TLS13-1-1-2021-06" }}
224 | ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
225 | 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:@SECLEVEL=0';
226 | ssl_prefer_server_ciphers on;
227 | {{- else if eq .ssl_policy "AWS-TLS13-1-0-2021-06" }}
228 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
229 | 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:@SECLEVEL=0';
230 | ssl_prefer_server_ciphers on;
231 | {{- else if eq .ssl_policy "AWS-FS-1-2-Res-2020-10" }}
232 | ssl_protocols TLSv1.2;
233 | ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
234 | ssl_prefer_server_ciphers on;
235 | {{- else if eq .ssl_policy "AWS-FS-1-2-Res-2019-08" }}
236 | ssl_protocols TLSv1.2;
237 | 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';
238 | ssl_prefer_server_ciphers on;
239 | {{- else if eq .ssl_policy "AWS-FS-1-2-2019-08" }}
240 | ssl_protocols TLSv1.2;
241 | 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';
242 | ssl_prefer_server_ciphers on;
243 | {{- else if eq .ssl_policy "AWS-FS-1-1-2019-08" }}
244 | ssl_protocols TLSv1.1 TLSv1.2;
245 | 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:@SECLEVEL=0';
246 | ssl_prefer_server_ciphers on;
247 | {{- else if eq .ssl_policy "AWS-FS-2018-06" }}
248 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
249 | 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:@SECLEVEL=0';
250 | ssl_prefer_server_ciphers on;
251 | {{- else if eq .ssl_policy "AWS-TLS-1-2-Ext-2018-06" }}
252 | ssl_protocols TLSv1.2;
253 | 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';
254 | ssl_prefer_server_ciphers on;
255 | {{- else if eq .ssl_policy "AWS-TLS-1-2-2017-01" }}
256 | ssl_protocols TLSv1.2;
257 | 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';
258 | ssl_prefer_server_ciphers on;
259 | {{- else if eq .ssl_policy "AWS-TLS-1-1-2017-01" }}
260 | ssl_protocols TLSv1.1 TLSv1.2;
261 | 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:@SECLEVEL=0';
262 | ssl_prefer_server_ciphers on;
263 | {{- else if eq .ssl_policy "AWS-2016-08" }}
264 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
265 | 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:@SECLEVEL=0';
266 | ssl_prefer_server_ciphers on;
267 | {{- else if eq .ssl_policy "AWS-2015-05" }}
268 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
269 | 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:@SECLEVEL=0';
270 | ssl_prefer_server_ciphers on;
271 | {{- else if eq .ssl_policy "AWS-2015-03" }}
272 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
273 | 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:@SECLEVEL=0';
274 | ssl_prefer_server_ciphers on;
275 | {{- else if eq .ssl_policy "AWS-2015-02" }}
276 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
277 | 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:@SECLEVEL=0';
278 | ssl_prefer_server_ciphers on;
279 | {{- end }}
280 | {{- end }}
281 |
282 | {{- define "location" }}
283 | {{- $vpath := .VPath }}
284 | {{- $override := printf "/etc/nginx/vhost.d/%s_%s_location_override" .Host (sha1 .Path) }}
285 | {{- if and (eq .Path "/") (not (exists $override)) }}
286 | {{- $override = printf "/etc/nginx/vhost.d/%s_location_override" .Host }}
287 | {{- end }}
288 | {{- if exists $override }}
289 | include {{ $override }};
290 | {{- else }}
291 | {{- $keepalive := $vpath.keepalive }}
292 | location {{ .Path }} {
293 | {{- if eq $vpath.network_tag "internal" }}
294 | # Only allow traffic from internal clients
295 | include /etc/nginx/network_internal.conf;
296 | {{- end }}
297 |
298 | {{ $proto := $vpath.proto }}
299 | {{ $upstream := $vpath.upstream }}
300 | {{ $dest := $vpath.dest }}
301 | {{- if eq $proto "uwsgi" }}
302 | include uwsgi_params;
303 | uwsgi_pass {{ trim $proto }}://{{ trim $upstream }};
304 | {{- else if eq $proto "fastcgi" }}
305 | {{- if (exists "/etc/nginx/fastcgi.conf") }}
306 | include fastcgi.conf;
307 | {{- else if (exists "/etc/nginx/fastcgi_params") }}
308 | include fastcgi_params;
309 | {{- else }}
310 | # neither /etc/nginx/fastcgi.conf nor /etc/nginx/fastcgi_params found, fastcgi won't work
311 | {{- end }}
312 | root {{ trim .VhostRoot }};
313 | fastcgi_pass {{ trim $upstream }};
314 | {{- if ne $keepalive "disabled" }}
315 | fastcgi_keep_conn on;
316 | {{- end }}
317 | {{- else if eq $proto "grpc" }}
318 | grpc_pass {{ trim $proto }}://{{ trim $upstream }};
319 | {{- else if eq $proto "grpcs" }}
320 | grpc_pass {{ trim $proto }}://{{ trim $upstream }};
321 | {{- else }}
322 | proxy_pass {{ trim $proto }}://{{ trim $upstream }}{{ trim $dest }};
323 | set $upstream_keepalive {{ if ne $keepalive "disabled" }}true{{ else }}false{{ end }};
324 | {{- end }}
325 |
326 | {{- if (exists (printf "/etc/nginx/htpasswd/%s_%s" .Host (sha1 .Path) )) }}
327 | auth_basic "Restricted {{ .Host }}{{ .Path }}";
328 | auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s_%s" .Host (sha1 .Path)) }};
329 | {{- else if (exists (printf "/etc/nginx/htpasswd/%s" .Host)) }}
330 | auth_basic "Restricted {{ .HostIsRegexp | ternary "access" .Host }}";
331 | auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" .Host) }};
332 | {{- end }}
333 |
334 | {{- if (exists (printf "/etc/nginx/vhost.d/%s_%s_location" .Host (sha1 .Path) )) }}
335 | include {{ printf "/etc/nginx/vhost.d/%s_%s_location" .Host (sha1 .Path) }};
336 | {{- else if (exists (printf "/etc/nginx/vhost.d/%s_location" .Host)) }}
337 | include {{ printf "/etc/nginx/vhost.d/%s_location" .Host}};
338 | {{- else if (exists "/etc/nginx/vhost.d/default_location") }}
339 | include /etc/nginx/vhost.d/default_location;
340 | {{- end }}
341 | }
342 | {{- end }}
343 | {{- end }}
344 |
345 | {{- define "upstream" }}
346 | {{- $path := .Path }}
347 | {{- $vpath := .VPath }}
348 | upstream {{ $vpath.upstream }} {
349 | {{- $servers := 0 }}
350 | {{- $loadbalance := $vpath.loadbalance }}
351 | {{- if $loadbalance }}
352 | # From the container's loadbalance label:
353 | {{ $loadbalance }}
354 | {{- end }}
355 | {{- range $port, $containers := $vpath.ports }}
356 | {{- range $container := $containers }}
357 | # Container: {{ $container.Name }}
358 | {{- $args := dict "globals" $.globals "container" $container }}
359 | {{- template "container_ip" $args }}
360 | {{- $ip := $args.ip }}
361 | {{- $args = dict "container" $container "path" $path "port" $port }}
362 | {{- template "container_port" $args }}
363 | {{- if $ip }}
364 | {{- $servers = add1 $servers }}
365 | server {{ $ip }}:{{ $args.port }};
366 | {{- end }}
367 | {{- end }}
368 | {{- end }}
369 | {{- /* nginx-proxy/nginx-proxy#1105 */}}
370 | {{- if lt $servers 1 }}
371 | # Fallback entry
372 | server 127.0.0.1 down;
373 | {{- end }}
374 | {{- $keepalive := $vpath.keepalive }}
375 | {{- if and (ne $keepalive "disabled") (gt $servers 0) }}
376 | {{- if eq $keepalive "auto" }}
377 | keepalive {{ mul $servers 2 }};
378 | {{- else }}
379 | keepalive {{ $keepalive }};
380 | {{- end }}
381 | {{- end }}
382 | }
383 | {{- end }}
384 |
385 | {{- /* debug "endpoint" location template */}}
386 | {{- define "debug_location" }}
387 | {{- $debug_paths := dict }}
388 | {{- range $path, $vpath := .VHost.paths }}
389 | {{- $tmp_ports := dict }}
390 | {{- range $port, $containers := $vpath.ports }}
391 | {{- $tmp_containers := list }}
392 | {{- range $container := $containers }}
393 | {{- $tmp_containers = dict "Name" $container.Name | append $tmp_containers }}
394 | {{- end }}
395 | {{- $_ := set $tmp_ports $port $tmp_containers }}
396 | {{- end }}
397 | {{- $debug_vpath := deepCopy $vpath | merge (dict "ports" $tmp_ports) }}
398 | {{- $_ := set $debug_paths $path $debug_vpath }}
399 | {{- end }}
400 |
401 | {{- $debug_vhost := deepCopy .VHost }}
402 | {{- /* If it's a regexp, do not render the Hostname to the response to avoid rendering config breaking characters */}}
403 | {{- $_ := set $debug_vhost "hostname" (.VHost.is_regexp | ternary "Hostname is a regexp and unsafe to include in the debug response." .Hostname) }}
404 | {{- $_ := set $debug_vhost "paths" $debug_paths }}
405 |
406 | {{- $debug_response := dict
407 | "global" .GlobalConfig
408 | "request" (dict
409 | "host" "$host"
410 | "https" "$https"
411 | "http2" "$http2"
412 | "http3" "$http3"
413 | "ssl_cipher" "$ssl_cipher"
414 | "ssl_protocol" "$ssl_protocol"
415 | )
416 | "vhost" $debug_vhost
417 | }}
418 |
419 | {{- /*
420 | * The maximum line length in an nginx config is 4096 characters.
421 | * If we're nearing this limit (with headroom for the rest
422 | * of the directive), strip vhost.paths from the response.
423 | */}}
424 | {{- if gt (toJson $debug_response | len) 4000 }}
425 | {{- $_ := unset $debug_vhost "paths" }}
426 | {{- $_ := set $debug_response "warning" "Virtual paths configuration for this hostname is too large and has been stripped from response." }}
427 | {{- end }}
428 |
429 | location /nginx-proxy-debug {
430 | default_type application/json;
431 | return 200 '{{ toJson $debug_response }}{{ "\\n" }}';
432 | }
433 | {{- end }}
434 |
435 | {{- define "access_log" }}
436 | {{- when .Enable "access_log /var/log/nginx/access.log vhost;" "" }}
437 | {{- end }}
438 |
439 | # If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
440 | # scheme used to connect to this server
441 | map $http_x_forwarded_proto $proxy_x_forwarded_proto {
442 | default {{ if $globals.config.trust_downstream_proxy }}$http_x_forwarded_proto{{ else }}$scheme{{ end }};
443 | '' $scheme;
444 | }
445 |
446 | map $http_x_forwarded_host $proxy_x_forwarded_host {
447 | default {{ if $globals.config.trust_downstream_proxy }}$http_x_forwarded_host{{ else }}$host{{ end }};
448 | '' $host;
449 | }
450 |
451 | # If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
452 | # server port the client connected to
453 | map $http_x_forwarded_port $proxy_x_forwarded_port {
454 | default {{ if $globals.config.trust_downstream_proxy }}$http_x_forwarded_port{{ else }}$server_port{{ end }};
455 | '' $server_port;
456 | }
457 |
458 | # Include the port in the Host header sent to the container if it is non-standard
459 | map $server_port $host_port {
460 | default :$server_port;
461 | 80 '';
462 | 443 '';
463 | }
464 |
465 | # If the request from the downstream client has an "Upgrade:" header (set to any
466 | # non-empty value), pass "Connection: upgrade" to the upstream (backend) server.
467 | # Otherwise, the value for the "Connection" header depends on whether the user
468 | # has enabled keepalive to the upstream server.
469 | map $http_upgrade $proxy_connection {
470 | default upgrade;
471 | '' $proxy_connection_noupgrade;
472 | }
473 | map $upstream_keepalive $proxy_connection_noupgrade {
474 | # Preserve nginx's default behavior (send "Connection: close").
475 | default close;
476 | # Use an empty string to cancel nginx's default behavior.
477 | true '';
478 | }
479 | # Abuse the map directive (see ) to ensure
480 | # that $upstream_keepalive is always defined. This is necessary because:
481 | # - The $proxy_connection variable is indirectly derived from
482 | # $upstream_keepalive, so $upstream_keepalive must be defined whenever
483 | # $proxy_connection is resolved.
484 | # - The $proxy_connection variable is used in a proxy_set_header directive in
485 | # the http block, so it is always fully resolved for every request -- even
486 | # those where proxy_pass is not used (e.g., unknown virtual host).
487 | map "" $upstream_keepalive {
488 | # The value here should not matter because it should always be overridden in
489 | # a location block (see the "location" template) for all requests where the
490 | # value actually matters.
491 | default false;
492 | }
493 |
494 | # Apply fix for very long server names
495 | server_names_hash_bucket_size 128;
496 |
497 | # Default dhparam
498 | {{- if (exists "/etc/nginx/dhparam/dhparam.pem") }}
499 | ssl_dhparam /etc/nginx/dhparam/dhparam.pem;
500 | {{- end }}
501 |
502 | # Set appropriate X-Forwarded-Ssl header based on $proxy_x_forwarded_proto
503 | map $proxy_x_forwarded_proto $proxy_x_forwarded_ssl {
504 | default off;
505 | https on;
506 | }
507 |
508 | gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
509 |
510 |
511 | {{- /* See https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format for details and variables
512 | * LOG_FORMAT_ESCAPE sets the escape part of the log format
513 | * LOG_FORMAT sets the log format
514 | */}}
515 | {{- $logEscape := $globals.config.log_format_escape | default "default" | printf "escape=%s" }}
516 | {{- $logFormat := $globals.config.log_format | default `$host $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$upstream_addr"` }}
517 |
518 | {{- if $globals.config.enable_json_logs }}
519 | # JSON Logging enabled (via LOG_JSON env variable)
520 | {{- $logEscape = $globals.config.log_format_escape | default "json" | printf "escape=%s" }}
521 | {{- $logFormat = $globals.config.log_format | default `{"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"}` }}
522 | {{- end }}
523 |
524 | log_format vhost {{ $logEscape }} '{{ $logFormat }}';
525 |
526 | access_log off;
527 |
528 | {{- /* Lower the SSL policy of the http context
529 | * if at least one vhost use a TLSv1 or TLSv1.1 policy
530 | * so TLSv1 and TLSv1.1 can be enabled on those vhosts
531 | */}}
532 | {{- $httpContextSslPolicy := $globals.config.ssl_policy }}
533 | {{- $inUseSslPolicies := groupByKeys $globals.containers "Env.SSL_POLICY" }}
534 | {{- range $tls1Policy := list "AWS-TLS13-1-1-2021-06" "AWS-TLS13-1-0-2021-06" "AWS-FS-1-1-2019-08" "AWS-FS-2018-06" "AWS-TLS-1-1-2017-01" "AWS-2016-08" "AWS-2015-05" "AWS-2015-03" "AWS-2015-02" "Mozilla-Old" }}
535 | {{- if has $tls1Policy $inUseSslPolicies }}
536 | # Using Mozilla-Old SSL policy on the http context to allow TLSv1 and TLSv1.1
537 | {{- $httpContextSslPolicy = "Mozilla-Old" }}
538 | {{- break }}
539 | {{- end }}
540 | {{- end }}
541 |
542 | {{- template "ssl_policy" (dict "ssl_policy" $httpContextSslPolicy) }}
543 | error_log /dev/stderr;
544 |
545 | {{- if $globals.config.resolvers }}
546 | resolver {{ $globals.config.resolvers }};
547 | {{- end }}
548 |
549 | {{- if (exists "/etc/nginx/proxy.conf") }}
550 | include /etc/nginx/proxy.conf;
551 | {{- else }}
552 | # HTTP 1.1 support
553 | proxy_http_version 1.1;
554 | proxy_set_header Host $host$host_port;
555 | proxy_set_header Upgrade $http_upgrade;
556 | proxy_set_header Connection $proxy_connection;
557 | proxy_set_header X-Real-IP $remote_addr;
558 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
559 | proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
560 | proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
561 | proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
562 | proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
563 | proxy_set_header X-Original-URI $request_uri;
564 |
565 | # Mitigate httpoxy attack (see README for details)
566 | proxy_set_header Proxy "";
567 | {{- end }}
568 |
569 | {{- /* Precompute and store some information about vhost that use VIRTUAL_HOST_MULTIPORTS. */}}
570 | {{- range $vhosts_yaml, $containers := groupBy $globals.containers "Env.VIRTUAL_HOST_MULTIPORTS" }}
571 | {{- /* Print a warning in the config if VIRTUAL_HOST_MULTIPORTS can't be parsed. */}}
572 | {{- $parsedVhosts := fromYaml $vhosts_yaml }}
573 | {{- if (empty $parsedVhosts) }}
574 | {{- $containerNames := list }}
575 | {{- range $container := $containers }}
576 | {{- $containerNames = append $containerNames $container.Name }}
577 | {{- end }}
578 | # /!\ WARNING: the VIRTUAL_HOST_MULTIPORTS environment variable used for {{ len $containerNames | plural "this container" "those containers" }} is not a valid YAML string:
579 | # {{ $containerNames | join ", " }}
580 | {{- continue }}
581 | {{- end }}
582 |
583 | {{- range $hostname, $vhost := $parsedVhosts }}
584 | {{- $vhost_data := get $globals.vhosts $hostname | default (dict) }}
585 | {{- $paths := $vhost_data.paths | default (dict) }}
586 |
587 | {{- if (empty $vhost) }}
588 | {{ $vhost = dict "/" (dict) }}
589 | {{- end }}
590 |
591 | {{- range $path, $vpath := $vhost }}
592 | {{- if (empty $vpath) }}
593 | {{- $vpath = dict
594 | "dest" ""
595 | "port" "default"
596 | "proto" "http"
597 | }}
598 | {{- end }}
599 |
600 | {{- $dest := $vpath.dest | default "" }}
601 | {{- $port := $vpath.port | default "default" | toString }}
602 | {{- $proto := $vpath.proto | default "http" }}
603 |
604 | {{- $path_data := get $paths $path | default (dict) }}
605 | {{- $path_ports := $path_data.ports | default (dict) }}
606 | {{- $path_port_containers := get $path_ports $port | default (list) | concat $containers }}
607 | {{- $_ := set $path_ports $port $path_port_containers }}
608 | {{- $_ := set $path_data "ports" $path_ports }}
609 |
610 | {{- if (not (hasKey $path_data "dest")) }}
611 | {{- $_ := set $path_data "dest" $dest }}
612 | {{- end }}
613 |
614 | {{- if (not (hasKey $path_data "proto")) }}
615 | {{- $_ := set $path_data "proto" $proto }}
616 | {{- end }}
617 |
618 | {{- $_ := set $paths $path $path_data }}
619 | {{- end }}
620 | {{- $_ := set $vhost_data "paths" $paths }}
621 | {{- $_ := set $globals.vhosts $hostname $vhost_data }}
622 | {{- end }}
623 | {{- end }}
624 |
625 | {{- /* Precompute and store some information about vhost that use VIRTUAL_HOST. */}}
626 | {{- range $hostname, $containers := groupByMulti $globals.containers "Env.VIRTUAL_HOST" "," }}
627 | {{- /* Ignore containers with VIRTUAL_HOST set to the empty string. */}}
628 | {{- $hostname = trim $hostname }}
629 | {{- if not $hostname }}
630 | {{- continue }}
631 | {{- end }}
632 |
633 | {{- /* Drop containers with both VIRTUAL_HOST and VIRTUAL_HOST_MULTIPORTS set
634 | * (VIRTUAL_HOST_MULTIPORTS takes precedence thanks to the previous loop).
635 | */}}
636 | {{- range $_, $containers_to_drop := groupBy $containers "Env.VIRTUAL_HOST_MULTIPORTS" }}
637 | {{- range $container := $containers_to_drop }}
638 | {{- $containers = without $containers $container }}
639 | {{- end }}
640 | {{- end }}
641 | {{- if (eq (len $containers) 0) }}
642 | {{- continue }}
643 | {{- end }}
644 |
645 | {{- $vhost_data := get $globals.vhosts $hostname | default (dict) }}
646 | {{- $paths := $vhost_data.paths | default (dict) }}
647 |
648 | {{- $tmp_paths := groupByWithDefault $containers "Env.VIRTUAL_PATH" "/" }}
649 |
650 | {{- range $path, $containers := $tmp_paths }}
651 | {{- $dest := groupByKeys $containers "Env.VIRTUAL_DEST" | first | default "" }}
652 | {{- $proto := groupByKeys $containers "Env.VIRTUAL_PROTO" | first | default "http" | trim }}
653 |
654 | {{- $path_data := get $paths $path | default (dict) }}
655 | {{- $path_ports := $path_data.ports | default (dict) }}
656 | {{- range $port, $containers := groupByWithDefault $containers "Env.VIRTUAL_PORT" "default" }}
657 | {{- $path_port_containers := get $path_ports $port | default (list) | concat $containers }}
658 | {{- $_ := set $path_ports $port $path_port_containers }}
659 | {{- end }}
660 | {{- $_ := set $path_data "ports" $path_ports }}
661 |
662 | {{- if (not (hasKey $path_data "dest")) }}
663 | {{- $_ := set $path_data "dest" $dest }}
664 | {{- end }}
665 |
666 | {{- if (not (hasKey $path_data "proto")) }}
667 | {{- $_ := set $path_data "proto" $proto }}
668 | {{- end }}
669 |
670 | {{- $_ := set $paths $path $path_data }}
671 | {{- end }}
672 | {{- $_ := set $vhost_data "paths" $paths }}
673 | {{- $_ := set $globals.vhosts $hostname $vhost_data }}
674 | {{- end }}
675 |
676 | {{- /* Loop over $globals.vhosts and update it with the remaining informations about each vhost. */}}
677 | {{- range $hostname, $vhost_data := $globals.vhosts }}
678 | {{- $is_regexp := hasPrefix "~" $hostname }}
679 | {{- $upstream_name := or $is_regexp $globals.config.sha1_upstream_name | ternary (sha1 $hostname) $hostname }}
680 |
681 | {{- $vhost_containers := list }}
682 |
683 | {{- range $path, $vpath_data := $vhost_data.paths }}
684 | {{- $vpath_containers := list }}
685 | {{- range $port, $vport_containers := $vpath_data.ports }}
686 | {{ $vpath_containers = concat $vpath_containers $vport_containers }}
687 | {{- end }}
688 |
689 | {{- /* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external". */}}
690 | {{- $network_tag := groupByKeys $vpath_containers "Env.NETWORK_ACCESS" | first | default "external" }}
691 |
692 | {{- $loadbalance := groupByLabel $vpath_containers "com.github.nginx-proxy.nginx-proxy.loadbalance" | keys | first }}
693 | {{- $keepalive := groupByLabel $vpath_containers "com.github.nginx-proxy.nginx-proxy.keepalive" | keys | first | default "auto" }}
694 |
695 | {{- $upstream := $upstream_name }}
696 | {{- if (not (eq $path "/")) }}
697 | {{- $sum := sha1 $path }}
698 | {{- $upstream = printf "%s-%s" $upstream $sum }}
699 | {{- end }}
700 |
701 | {{- $_ := set $vpath_data "network_tag" $network_tag }}
702 | {{- $_ := set $vpath_data "upstream" $upstream }}
703 | {{- $_ := set $vpath_data "loadbalance" $loadbalance }}
704 | {{- $_ := set $vpath_data "keepalive" $keepalive }}
705 | {{- $_ := set $vhost_data.paths $path $vpath_data }}
706 |
707 | {{ $vhost_containers = concat $vhost_containers $vpath_containers }}
708 | {{- end }}
709 |
710 | {{- $userIdentifiedCert := groupByKeys $vhost_containers "Env.CERT_NAME" | first }}
711 |
712 | {{- $vhostCert := "" }}
713 | {{- if exists (printf "/etc/nginx/certs/%s.crt" $hostname) }}
714 | {{- $vhostCert = $hostname }}
715 | {{- end }}
716 |
717 | {{- $parentVhostCert := "" }}
718 | {{- if gt ($hostname | sprigSplit "." | len) 2 }}
719 | {{- $parentHostname := ($hostname | sprigSplitn "." 2)._1 }}
720 | {{- if exists (printf "/etc/nginx/certs/%s.crt" $parentHostname) }}
721 | {{- $parentVhostCert = $parentHostname }}
722 | {{- end }}
723 | {{- end }}
724 |
725 | {{- $trust_default_cert := groupByLabel $vhost_containers "com.github.nginx-proxy.nginx-proxy.trust-default-cert" | keys | first | default $globals.config.trust_default_cert | parseBool }}
726 | {{- $defaultCert := and $trust_default_cert $globals.config.default_cert_ok | ternary "default" "" }}
727 |
728 | {{- $cert := or $userIdentifiedCert $vhostCert $parentVhostCert $defaultCert }}
729 | {{- $cert_ok := and (ne $cert "") (exists (printf "/etc/nginx/certs/%s.crt" $cert)) (exists (printf "/etc/nginx/certs/%s.key" $cert)) }}
730 |
731 | {{- $enable_debug_endpoint := groupByLabel $vhost_containers "com.github.nginx-proxy.nginx-proxy.debug-endpoint" | keys | first | default $globals.config.enable_debug_endpoint | parseBool }}
732 | {{- $default := eq $globals.config.default_host $hostname }}
733 | {{- $https_method := groupByKeys $vhost_containers "Env.HTTPS_METHOD" | first | default $globals.config.https_method }}
734 | {{- $enable_http_on_missing_cert := groupByKeys $vhost_containers "Env.ENABLE_HTTP_ON_MISSING_CERT" | first | default $globals.config.enable_http_on_missing_cert | parseBool }}
735 | {{- /* When no trusted certs (default and/or vhost) are present we want to ensure that HTTP is enabled; hence switching from 'nohttp' or 'redirect' to 'noredirect' */}}
736 | {{- $https_method_disable_http := list "nohttp" "redirect" | has $https_method }}
737 | {{- if and $https_method_disable_http (not $cert_ok) $enable_http_on_missing_cert }}
738 | {{- $https_method = "noredirect" }}
739 | {{- end }}
740 | {{- $non_get_redirect := groupByLabel $vhost_containers "com.github.nginx-proxy.nginx-proxy.non-get-redirect" | keys | first | default $globals.config.non_get_redirect }}
741 |
742 | {{- $http2_enabled := groupByLabel $vhost_containers "com.github.nginx-proxy.nginx-proxy.http2.enable" | keys | first | default $globals.config.enable_http2 | parseBool }}
743 | {{- $http3_enabled := groupByLabel $vhost_containers "com.github.nginx-proxy.nginx-proxy.http3.enable" | keys | first | default $globals.config.enable_http3 | parseBool }}
744 |
745 | {{- $acme_http_challenge := groupByKeys $vhost_containers "Env.ACME_HTTP_CHALLENGE_LOCATION" | first | default $globals.config.acme_http_challenge }}
746 | {{- $acme_http_challenge_legacy := eq $acme_http_challenge "legacy" }}
747 | {{- $acme_http_challenge_enabled := false }}
748 | {{- if (not $acme_http_challenge_legacy) }}
749 | {{- $acme_http_challenge_enabled = parseBool $acme_http_challenge }}
750 | {{- end }}
751 |
752 | {{- /* Get the SERVER_TOKENS defined by containers w/ the same vhost, falling back to "". */}}
753 | {{- $server_tokens := groupByKeys $vhost_containers "Env.SERVER_TOKENS" | first | default "" | trim }}
754 |
755 | {{- /* Get the SSL_POLICY defined by containers w/ the same vhost, falling back to empty string (use default). */}}
756 | {{- $ssl_policy := groupByKeys $vhost_containers "Env.SSL_POLICY" | first | default "" }}
757 |
758 | {{- /* Get the HSTS defined by containers w/ the same vhost, falling back to "max-age=31536000". */}}
759 | {{- $hsts := groupByKeys $vhost_containers "Env.HSTS" | first | default $globals.config.hsts }}
760 |
761 | {{- /* Get the VIRTUAL_ROOT By containers w/ use fastcgi root */}}
762 | {{- $vhost_root := groupByKeys $vhost_containers "Env.VIRTUAL_ROOT" | first | default "/var/www/public" }}
763 |
764 | {{- $vhost_data = merge $vhost_data (dict
765 | "cert" $cert
766 | "cert_ok" $cert_ok
767 | "enable_debug_endpoint" $enable_debug_endpoint
768 | "default" $default
769 | "hsts" $hsts
770 | "https_method" $https_method
771 | "non_get_redirect" $non_get_redirect
772 | "http2_enabled" $http2_enabled
773 | "http3_enabled" $http3_enabled
774 | "is_regexp" $is_regexp
775 | "acme_http_challenge_legacy" $acme_http_challenge_legacy
776 | "acme_http_challenge_enabled" $acme_http_challenge_enabled
777 | "server_tokens" $server_tokens
778 | "ssl_policy" $ssl_policy
779 | "trust_default_cert" $trust_default_cert
780 | "upstream_name" $upstream_name
781 | "vhost_root" $vhost_root
782 | ) }}
783 | {{- $_ := set $globals.vhosts $hostname $vhost_data }}
784 | {{- end }}
785 |
786 |
787 | {{- /*
788 | * If needed, create a catch-all fallback server to send an error code to
789 | * clients that request something from an unknown vhost.
790 | *
791 | * This server must appear first in the generated config because nginx uses
792 | * the first `server` directive to handle requests that don't match any of
793 | * the other `server` directives. An alternative approach would be to add
794 | * the `default_server` option to the `listen` directives inside this
795 | * `server`, but some users inject a custom `server` directive that uses
796 | * `default_server`. Using `default_server` here would cause nginx to fail
797 | * to start for those users. See
798 | * .
799 | */}}
800 | {{- block "fallback_server" $globals }}
801 | {{- $globals := . }}
802 | {{- $http_exists := false }}
803 | {{- $https_exists := false }}
804 | {{- $default_http_exists := false }}
805 | {{- $default_https_exists := false }}
806 | {{- $http3_enabled := false }}
807 | {{- range $vhost := $globals.vhosts }}
808 | {{- $http := ne $vhost.https_method "nohttp" }}
809 | {{- $https := ne $vhost.https_method "nohttps" }}
810 | {{- $http_exists = or $http_exists $http }}
811 | {{- $https_exists = or $https_exists $https }}
812 | {{- $default_http_exists = or $default_http_exists (and $http $vhost.default) }}
813 | {{- $default_https_exists = or $default_https_exists (and $https $vhost.default) }}
814 | {{- $http3_enabled = or $http3_enabled $vhost.http3_enabled }}
815 | {{- end }}
816 | {{- $fallback_http := not $default_http_exists }}
817 | {{- $fallback_https := not $default_https_exists }}
818 | {{- /*
819 | * If there are no vhosts at all, create fallbacks for both plain http
820 | * and https so that clients get something more useful than a connection
821 | * refused error.
822 | */}}
823 | {{- if and (not $http_exists) (not $https_exists) }}
824 | {{- $fallback_https = true }}
825 | {{- end }}
826 | {{- if or $fallback_http $fallback_https }}
827 | server {
828 | server_name _; # This is just an invalid value which will never trigger on a real hostname.
829 | server_tokens off;
830 | {{ template "access_log" (dict "Enable" $globals.config.enable_access_log) }}
831 | http2 on;
832 | {{- if $fallback_http }}
833 | listen {{ $globals.config.external_http_port }}; {{- /* Do not add `default_server` (see comment above). */}}
834 | {{- if $globals.config.enable_ipv6 }}
835 | listen [::]:{{ $globals.config.external_http_port }}; {{- /* Do not add `default_server` (see comment above). */}}
836 | {{- end }}
837 | {{- end }}
838 | {{- if $fallback_https }}
839 | listen {{ $globals.config.external_https_port }} ssl; {{- /* Do not add `default_server` (see comment above). */}}
840 | {{- if $globals.config.enable_ipv6 }}
841 | listen [::]:{{ $globals.config.external_https_port }} ssl; {{- /* Do not add `default_server` (see comment above). */}}
842 | {{- end }}
843 | {{- if $http3_enabled }}
844 | http3 on;
845 | listen {{ $globals.config.external_https_port }} quic reuseport; {{- /* Do not add `default_server` (see comment above). */}}
846 | {{- if $globals.config.enable_ipv6 }}
847 | listen [::]:{{ $globals.config.external_https_port }} quic reuseport; {{- /* Do not add `default_server` (see comment above). */}}
848 | {{- end }}
849 | {{- end }}
850 | ssl_session_cache shared:SSL:50m;
851 | ssl_session_tickets off;
852 | {{- end }}
853 | {{- if $globals.config.default_cert_ok }}
854 | ssl_certificate /etc/nginx/certs/default.crt;
855 | ssl_certificate_key /etc/nginx/certs/default.key;
856 | {{- else }}
857 | # No default certificate found, so reject SSL handshake;
858 | ssl_reject_handshake on;
859 | {{- end }}
860 |
861 | {{- if (exists "/usr/share/nginx/html/errors/50x.html") }}
862 | error_page 500 502 503 504 /50x.html;
863 | location /50x.html {
864 | root /usr/share/nginx/html/errors;
865 | internal;
866 | }
867 | {{- end }}
868 | location ^~ / {
869 | return 503;
870 | }
871 | }
872 | {{- end }}
873 | {{- end }}
874 |
875 | {{- range $hostname, $vhost := $globals.vhosts }}
876 | {{- $default_server := when $vhost.default "default_server" "" }}
877 |
878 | {{- range $path, $vpath := $vhost.paths }}
879 | # {{ $hostname }}{{ $path }}
880 | {{ template "upstream" (dict "globals" $globals "Path" $path "VPath" $vpath) }}
881 | {{- end }}
882 |
883 | {{- if (eq $vhost.https_method "redirect") }}
884 | server {
885 | server_name {{ $hostname }};
886 | {{- if $vhost.server_tokens }}
887 | server_tokens {{ $vhost.server_tokens }};
888 | {{- end }}
889 | {{ template "access_log" (dict "Enable" $globals.config.enable_access_log) }}
890 | listen {{ $globals.config.external_http_port }} {{ $default_server }};
891 | {{- if $globals.config.enable_ipv6 }}
892 | listen [::]:{{ $globals.config.external_http_port }} {{ $default_server }};
893 | {{- end }}
894 |
895 | {{- if (or $vhost.acme_http_challenge_legacy $vhost.acme_http_challenge_enabled) }}
896 | # Do not HTTPS redirect Let's Encrypt ACME challenge
897 | location ^~ /.well-known/acme-challenge/ {
898 | auth_basic off;
899 | auth_request off;
900 | allow all;
901 | root /usr/share/nginx/html;
902 | try_files $uri =404;
903 | break;
904 | }
905 | {{- end }}
906 |
907 | {{- if $vhost.enable_debug_endpoint }}
908 | {{ template "debug_location" (dict "GlobalConfig" $globals.config "Hostname" $hostname "VHost" $vhost) }}
909 | {{- end }}
910 |
911 | location / {
912 | {{- $redirect_uri := "https://$host$request_uri" }}
913 | {{- if ne $globals.config.external_https_port "443" }}
914 | {{- $redirect_uri = printf "https://$host:%s$request_uri" $globals.config.external_https_port }}
915 | {{- end}}
916 | if ($request_method ~ (OPTIONS|POST|PUT|PATCH|DELETE)) {
917 | return {{ $vhost.non_get_redirect }} {{ $redirect_uri }};
918 | }
919 | return 301 {{ $redirect_uri }};
920 | }
921 | }
922 | {{- end }}
923 |
924 | server {
925 | {{- if $vhost.is_regexp }}
926 | {{- if or
927 | (printf "/etc/nginx/vhost.d/%s" $hostname | exists)
928 | (printf "/etc/nginx/vhost.d/%s_location" $hostname | exists)
929 | (printf "/etc/nginx/vhost.d/%s_location_override" $hostname | exists)
930 | (printf "/etc/nginx/htpasswd/%s" $hostname | exists)
931 | }}
932 | # https://github.com/nginx-proxy/nginx-proxy/issues/2529#issuecomment-2437609249
933 | # Support for vhost config file(s) named like a regexp ({{ $hostname }}) has been removed from nginx-proxy.
934 | # Please name your vhost config file(s) with the sha1 of the regexp instead ({{ $hostname }} -> {{ sha1 $hostname }}) :
935 | # - /etc/nginx/vhost.d/{{ sha1 $hostname }}
936 | # - /etc/nginx/vhost.d/{{ sha1 $hostname }}_location
937 | # - /etc/nginx/vhost.d/{{ sha1 $hostname }}_location_override
938 | # - /etc/nginx/htpasswd/{{ sha1 $hostname }}
939 | {{- end }}
940 | {{- end }}
941 |
942 | server_name {{ $hostname }};
943 | {{- if $vhost.server_tokens }}
944 | server_tokens {{ $vhost.server_tokens }};
945 | {{- end }}
946 | {{ template "access_log" (dict "Enable" $globals.config.enable_access_log) }}
947 | {{- if $vhost.http2_enabled }}
948 | http2 on;
949 | {{- end }}
950 | {{- if or (eq $vhost.https_method "nohttps") (eq $vhost.https_method "noredirect") }}
951 | listen {{ $globals.config.external_http_port }} {{ $default_server }};
952 | {{- if $globals.config.enable_ipv6 }}
953 | listen [::]:{{ $globals.config.external_http_port }} {{ $default_server }};
954 | {{- end }}
955 |
956 | {{- if (and (eq $vhost.https_method "noredirect") $vhost.acme_http_challenge_enabled) }}
957 | location /.well-known/acme-challenge/ {
958 | auth_basic off;
959 | allow all;
960 | root /usr/share/nginx/html;
961 | try_files $uri =404;
962 | break;
963 | }
964 | {{- end }}
965 | {{- end }}
966 | {{- if ne $vhost.https_method "nohttps" }}
967 | listen {{ $globals.config.external_https_port }} ssl {{ $default_server }};
968 | {{- if $globals.config.enable_ipv6 }}
969 | listen [::]:{{ $globals.config.external_https_port }} ssl {{ $default_server }};
970 | {{- end }}
971 |
972 | {{- if $vhost.http3_enabled }}
973 | http3 on;
974 | add_header alt-svc 'h3=":{{ $globals.config.external_https_port }}"; ma=86400;';
975 | listen {{ $globals.config.external_https_port }} quic {{ $default_server }};
976 | {{- if $globals.config.enable_ipv6 }}
977 | listen [::]:{{ $globals.config.external_https_port }} quic {{ $default_server }};
978 | {{- end }}
979 | {{- end }}
980 |
981 | {{- if $vhost.cert_ok }}
982 | {{- template "ssl_policy" (dict "ssl_policy" $vhost.ssl_policy) }}
983 |
984 | ssl_session_timeout 5m;
985 | ssl_session_cache shared:SSL:50m;
986 | ssl_session_tickets off;
987 |
988 | ssl_certificate /etc/nginx/certs/{{ (printf "%s.crt" $vhost.cert) }};
989 | ssl_certificate_key /etc/nginx/certs/{{ (printf "%s.key" $vhost.cert) }};
990 |
991 | {{- if (exists (printf "/etc/nginx/certs/%s.dhparam.pem" $vhost.cert)) }}
992 | ssl_dhparam {{ printf "/etc/nginx/certs/%s.dhparam.pem" $vhost.cert }};
993 | {{- end }}
994 |
995 | {{- if (exists (printf "/etc/nginx/certs/%s.chain.pem" $vhost.cert)) }}
996 | ssl_stapling on;
997 | ssl_stapling_verify on;
998 | ssl_trusted_certificate {{ printf "/etc/nginx/certs/%s.chain.pem" $vhost.cert }};
999 | {{- end }}
1000 |
1001 | {{- if (not (or (eq $vhost.https_method "noredirect") (eq $vhost.hsts "off"))) }}
1002 | set $sts_header "";
1003 | if ($https) {
1004 | set $sts_header "{{ trim $vhost.hsts }}";
1005 | }
1006 | add_header Strict-Transport-Security $sts_header always;
1007 | {{- end }}
1008 | {{- else if not $vhost.trust_default_cert | and $globals.config.default_cert_ok }}
1009 | # No certificate found for this vhost, and the default certificate isn't trusted, so reject SSL handshake.
1010 | ssl_reject_handshake on;
1011 | {{- else }}
1012 | # No certificate for this vhost nor default certificate found, so reject SSL handshake.
1013 | ssl_reject_handshake on;
1014 | {{- end }}
1015 | {{- end }}
1016 |
1017 | {{- $vhostFileName := $vhost.is_regexp | ternary (sha1 $hostname) $hostname }}
1018 |
1019 | {{- if (exists (printf "/etc/nginx/vhost.d/%s" $vhostFileName)) }}
1020 | include {{ printf "/etc/nginx/vhost.d/%s" $vhostFileName }};
1021 | {{- else if (exists "/etc/nginx/vhost.d/default") }}
1022 | include /etc/nginx/vhost.d/default;
1023 | {{- end }}
1024 |
1025 | {{- if $vhost.enable_debug_endpoint }}
1026 | {{ template "debug_location" (dict "GlobalConfig" $globals.config "Hostname" $hostname "VHost" $vhost) }}
1027 | {{- end }}
1028 |
1029 | {{- range $path, $vpath := $vhost.paths }}
1030 | {{- template "location" (dict
1031 | "Path" $path
1032 | "Host" $vhostFileName
1033 | "HostIsRegexp" $vhost.is_regexp
1034 | "VhostRoot" $vhost.vhost_root
1035 | "VPath" $vpath
1036 | ) }}
1037 | {{- end }}
1038 |
1039 | {{- if and (not (contains $vhost.paths "/")) (ne $globals.config.default_root_response "none")}}
1040 | location / {
1041 | return {{ $globals.config.default_root_response }};
1042 | }
1043 | {{- end }}
1044 | }
1045 | {{- end }}
1046 |
--------------------------------------------------------------------------------