├── .gitignore ├── LICENSE ├── README.md ├── conf.d ├── custom-nginx ├── default.conf └── example.com ├── docker-compose.yml ├── nginx-amplify.yml ├── snippets ├── certbot-standalone.conf ├── certbot-webroot.conf ├── proxy.conf └── ssl.conf ├── ssl └── cli.ini ├── swarm-scripts ├── certbot-certonly.sh ├── certbot-renew.sh ├── certbot.sh ├── nginx-test.sh ├── nginx-update.sh └── stack-deploy.sh └── swarm.yml /.gitignore: -------------------------------------------------------------------------------- 1 | conf.d/* 2 | !conf.d/custom-nginx 3 | !conf.d/default.conf 4 | !conf.d/example.com 5 | ssl 6 | !ssl/cli.ini 7 | ssl-log 8 | www 9 | geoip 10 | protect 11 | snippets/* 12 | !snippets/certbot-standalone.conf 13 | !snippets/certbot-webroot.conf 14 | !snippets/proxy.conf 15 | !snippets/ssl.conf 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nginx-Proxy 2 | 3 | This docker-compose.yml users the **official nginx** and the **official certbot** container. It has optimized nginx configuration to be used as a https proxy together with certbot. Following my instructions you should get an A+ rating at [ssllabs.com](https://www.ssllabs.com/ssltest). 4 | 5 | The container will use the network **www-network** as a proxy-tier. Add every container to this network that servers as a upstream http host. 6 | 7 | ### Table of Contents 8 | **[How To Use](#how-to-use)**
9 | **[Docker Swarm](#docker-swarm)**
10 | **[Update](#update)**
11 | **[Nginx](#nginx)**
12 | **[Let's Encrypt SSL Certificates](#lets-encrypt-ssl-certificates)**
13 | **[Let's Encrypt SSL Certificates on Swarm Mode](#lets-encrypt-ssl-certificates-on-swarm-mode)**
14 | **[Get A+ SSL Rating](#get-a-ssl-rating)**
15 | **[Password protection](#password-protection)**
16 | **[IP-based protection](#ip-based-protection)**
17 | **[GeoIP blocking](#geoip-blocking)**
18 | 19 | ## Directory structure 20 | 21 | ``` 22 | . 23 | ├── conf.d # Site-specific configuration 24 | │ ├── example.com.conf 25 | │ ├── ... 26 | ├── protect # HTTP Password Protection 27 | │ ├── .htpasswd 28 | ├── snippets # Config we want to reuse at conf.d files 29 | │ ├── certbot-webroot.conf # Serves Let's encrypt .well-known files 30 | │ ├── certbot-standalone.conf # as alternative method 31 | │ ├── proxy.conf 32 | │ ├── ssl.conf 33 | 34 | ``` 35 | 36 | ## How To Use 37 | 38 | ### 1. Clone this repo 39 | 40 | ```bash 41 | mkdir -p /docker/00-nginx-proxy 42 | cd /docker/00-nginx-proxy 43 | git clone https://github.com/sebastian13/docker-compose-nginx-proxy.git . 44 | ``` 45 | 46 | ### 2. Prepare for SSL 47 | ```bash 48 | mkdir -p ./ssl/test 49 | openssl req -x509 -nodes -days 3650 -newkey rsa:4096 \ 50 | -keyout ./ssl/test/selfsigned.key \ 51 | -out ./ssl/test/selfsigned.crt 52 | # Optional, run in a separate session 53 | screen 54 | openssl dhparam -out ssl/dhparams4096.pem 4096 55 | ``` 56 | 57 | ### 3. Create your site's config 58 | ```bash 59 | cp conf.d/{example.com,yoursite.com.conf} 60 | ``` 61 | Replace *example.com* with your domain, and set your *$upstream container*. 62 | 63 | ### 4. Enable recommended http settings 64 | ```bash 65 | cp conf.d/custom-nginx{,.conf} 66 | ``` 67 | 68 | ### 5. Create docker network www-network 69 | ```bash 70 | docker network create www-network 71 | ``` 72 | 73 | ### 6. Ready to go 74 | ```bash 75 | docker compose up -d 76 | ``` 77 | 78 | ## Docker Swarm 79 | 80 | To run this project on a docker stack, skip 5. and 6. and continue here: 81 | 82 | ### 0. Network 83 | If you previously used the `www-network`, stop all containers and remove the network. The stack will recreate the network in swarm scope. 84 | 85 | ```bash 86 | docker stop $(docker ps -q) 87 | docker network remove www-network 88 | ``` 89 | 90 | ### 1. Create Swarm 91 | ```bash 92 | docker swarm init 93 | ``` 94 | 95 | ### 2. Deploy Stack 96 | ```bash 97 | docker stack deploy proxystack -c swarm.yml 98 | 99 | # Alternatively, run the helper script 100 | cd swarm-scripts 101 | ./stack-deploy.sh 102 | ``` 103 | 104 | 105 | ## Update 106 | 107 | To get the most recent version of this repo run: 108 | 109 | ``` 110 | git fetch --all && \ 111 | git reset --hard origin/master && \ 112 | docker compose pull && \ 113 | docker compose down && \ 114 | docker compose up -d 115 | ``` 116 | 117 | ## Nginx 118 | 119 | I'm using the [official nginx container](https://hub.docker.com/_/nginx/) here. All volumes will be mounted read-only. 120 | 121 | ### Manually reload the configuration 122 | As you change site-specific configuration in *conf.d*, you should consider reloading the configuration instead of restarting the container. This is because your container will not start if the configuration contains errors. 123 | 124 | ``` 125 | docker exec nginx-proxy nginx -s reload 126 | ``` 127 | 128 | ### Amplify Agent 129 | You can use the free monitoring tool [NGINX Amplify](https://amplify.nginx.com) the following way: 130 | 131 | 1. Create a **amplify.env** containing 132 | 133 | ``` 134 | AMPLIFY_IMAGENAME=example.com 135 | API_KEY=123456 136 | ``` 137 | 138 | 2. Start the container the following way: 139 | 140 | ``` 141 | docker compose -f nginx-amplify.yml up -d --build 142 | ``` 143 | 144 | ## Let's Encrypt SSL Certificates 145 | 146 | *If using docker swarm, jump to [Let's Encrypt SSL Certificates on Swarm Mode](#lets-encrypt-ssl-certificates-on-swarm-mode)* 147 | 148 | ### Request a new Certificate 149 | 150 | ``` 151 | docker compose run --rm certbot certonly \ 152 | --agree-tos --no-eff-email --hsts --webroot -w /var/www \ 153 | --rsa-key-size 4096 --cert-name=example.com \ 154 | -m mail@example.com -d example.com 155 | ``` 156 | 157 | Then, link the certificate in your nginx site.conf + reload the nginx-proxy. 158 | 159 | 160 | ### List existing Certificates 161 | ```shell 162 | docker compose run --rm certbot certificates 163 | ``` 164 | 165 | ### Delete existing Certificates 166 | ```shell 167 | docker compose run --rm certbot delete --cert-name example.com 168 | ``` 169 | 170 | ### Renew Certificates 171 | 172 | Define a Cronjob like this, to renew the certificates periodically. Use chronic from [moreutils](https://manpages.debian.org/jessie/moreutils/chronic.1.en.html) if you like. 173 | 174 | ``` 175 | 0 0 * * * cd /docker/00-nginx-proxy && chronic docker compose run --rm --use-aliases certbot renew && chronic docker exec nginx-proxy nginx -s reload 176 | ``` 177 | 178 | To manually check your certificates for renewal run `docker compose up certbot`. 179 | 180 | ## Let's Encrypt SSL Certificates on Swarm Mode 181 | 182 | ### Request a new Certificate 183 | 184 | ``` 185 | ./swarm-scripts/certbot-certonly.sh -m mail@example.com -d example.com -d www.example.co 186 | ``` 187 | 188 | ### List existing Certificates 189 | ```shell 190 | ./swarm-scripts/certbot.sh certificates 191 | ``` 192 | 193 | ### Delete existing Certificates 194 | ```shell 195 | ./swarm-scripts/certbot.sh delete --cert-name example.com 196 | ``` 197 | 198 | ### Renew Certificates 199 | 200 | ```shell 201 | ./swarm-scripts/certbot-renew.sh 202 | ``` 203 | 204 | Define a Cronjob like this, to renew the certificates periodically. Use chronic from [moreutils](https://manpages.debian.org/jessie/moreutils/chronic.1.en.html) if you like. 205 | 206 | ``` 207 | 0 0 * * * chronic /docker/00-nginx-proxy/swarm-scripts/certbot-renew.sh 208 | ``` 209 | 210 | ## Get A+ SSL Rating 211 | 212 | 1. Generate your own Diffie-Hellman parameters. Put it inside the directory **ssl**. 213 | 214 | `openssl dhparam -out ssl/dhparams4096.pem 4096` 215 | 216 | 2. Include the **ssl.conf snippet** at your site specific configuration. Also, include the **ssl\_trusted\_certificate**. 217 | 218 | ``` 219 | server { 220 | ... 221 | ssl_trusted_certificate /etc/nginx/ssl/live/example.com/chain.pem; 222 | include /etc/nginx/snippets/ssl.conf; 223 | ... 224 | } 225 | ``` 226 | 227 | ## Password protection 228 | 229 | To protect your site with basic http authentication, create a .htpasswd file, spin up an apache container by running the following. 230 | 231 | ```bash 232 | docker run -i --rm -v /docker/00-nginx-proxy/protect:/etc/nginx/protect httpd /bin/bash 233 | ``` 234 | 235 | For every user run the following. You will be asked to supply and confirm a password. 236 | 237 | ```bash 238 | htpasswd -c /etc/nginx/protect/.htpasswd first_user 239 | htpasswd /etc/nginx/protect/.htpasswd another_user 240 | ``` 241 | 242 | In the site's .conf file add the following. 243 | 244 | ``` 245 | server { 246 | ... 247 | location / { 248 | auth_basic "Restricted Content"; 249 | auth_basic_user_file /etc/nginx/protect/.htpasswd; 250 | } 251 | } 252 | ``` 253 | 254 | You can find detailed instructions at [digitalocean](https://www.digitalocean.com/community/tutorials/how-to-set-up-password-authentication-with-nginx-on-ubuntu-14-04) 255 | 256 | ## IP based protection 257 | 258 | Add your IP Address to the domain's .conf file, and deny everyone else. 259 | 260 | ``` 261 | server { 262 | ... 263 | location / { 264 | allow 1.2.3.4; 265 | deny all; 266 | } 267 | } 268 | ``` 269 | 270 | ## GeoIP blocking 271 | 272 | ``` 273 | mkdir geoip 274 | cd geoip 275 | curl -O https://centminmod.com/centminmodparts/geoip-legacy/GeoIP.dat.gz 276 | curl -o GeoLiteCity.dat.gz https://centminmod.com/centminmodparts/geoip-legacy/GeoLiteCity.gz 277 | gunzip *.gz 278 | ``` 279 | 280 | add to nginx.conf after pid ... : 281 | 282 | ``` 283 | load_module modules/ngx_http_geoip_module.so; 284 | ``` 285 | 286 | -------------------------------------------------------------------------------- /conf.d/custom-nginx: -------------------------------------------------------------------------------- 1 | ## Additional http settings 2 | 3 | # hide server information 4 | server_tokens off; 5 | 6 | # Enable gzip 7 | gzip on; 8 | gzip_vary on; 9 | gzip_min_length 1024; 10 | gzip_proxied expired no-cache no-store private auth; 11 | gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml; 12 | gzip_disable "MSIE [1-6]\."; 13 | -------------------------------------------------------------------------------- /conf.d/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen [::]:80 default_server ipv6only=on; 4 | 5 | listen 443 ssl default_server; 6 | listen [::]:443 ssl default_server ipv6only=on; 7 | http2 on; 8 | 9 | # Catch-all 10 | server_name _; 11 | 12 | # Serve Let's Ecnrypt verification files 13 | include /etc/nginx/snippets/certbot-standalone.conf; 14 | 15 | # Self signed cert as a fallback and to handle the 'no "ssl_certificate" is defined' error log message 16 | ssl_certificate /etc/nginx/ssl/test/selfsigned.crt; 17 | ssl_certificate_key /etc/nginx/ssl/test/selfsigned.key; 18 | 19 | # Return nothing 20 | location / { 21 | return 444; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /conf.d/example.com: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | listen [::]:80; 4 | server_name example.com; 5 | 6 | include /etc/nginx/snippets/certbot-standalone.conf; 7 | 8 | # Discourage deep links by using a permanent redirect to home page of HTTPS site 9 | # return 301 https://$host; 10 | 11 | # Alternatively, redirect all HTTP links to the matching HTTPS page 12 | location / { 13 | return 301 https://$host$request_uri; 14 | } 15 | } 16 | 17 | server { 18 | server_name example.com; 19 | listen 443 ssl; 20 | http2 on; 21 | 22 | # ssl_certificate /etc/nginx/ssl/live/example.com/fullchain.pem; 23 | # ssl_certificate_key /etc/nginx/ssl/live/example.com/privkey.pem; 24 | # ssl_trusted_certificate /etc/nginx/ssl/live/example.com/chain.pem; 25 | 26 | include /etc/nginx/snippets/ssl.conf; 27 | include /etc/nginx/snippets/certbot-standalone.conf; 28 | 29 | location / { 30 | # Optional IP based restriction 31 | # allow 1.2.3.4; 32 | # deny all; 33 | 34 | # Optional Password protection 35 | # auth_basic "Restricted Content"; 36 | # auth_basic_user_file /etc/nginx/protect/.htpasswd; 37 | 38 | # Upstream 39 | resolver 127.0.0.11 valid=30s; 40 | set $upstream container_name; 41 | proxy_pass http://$upstream; 42 | 43 | include /etc/nginx/snippets/proxy.conf; 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | ### NGINX-PROXY 2 | ### 3 | ### Author: Sebastian Plocek 4 | ### https://github.com/sebastian13/docker-compose-nginx-proxy 5 | 6 | services: 7 | nginx-proxy: 8 | image: nginx 9 | container_name: nginx-proxy 10 | restart: always 11 | ports: 12 | - "443:443" 13 | - "80:80" 14 | volumes: 15 | - ./www:/var/www:ro 16 | - ./conf.d:/etc/nginx/conf.d:ro 17 | - ./ssl:/etc/nginx/ssl:ro 18 | - ./snippets:/etc/nginx/snippets:ro 19 | - ./protect:/etc/nginx/protect:ro 20 | 21 | # Let's Encrypt / Certbot 22 | # Check README.md to know how to issue new certs. 23 | certbot: 24 | image: certbot/certbot 25 | container_name: certbot 26 | depends_on: 27 | - nginx-proxy 28 | volumes: 29 | - ./ssl:/etc/letsencrypt 30 | - ./ssl-log:/var/log/letsencrypt 31 | - ./www/.well-known:/var/www/.well-known 32 | profiles: 33 | - certbot 34 | command: [ 35 | "renew", 36 | ] 37 | 38 | # Use the same external network in $upstream containers. 39 | networks: 40 | default: 41 | name: www-network 42 | external: true 43 | -------------------------------------------------------------------------------- /nginx-amplify.yml: -------------------------------------------------------------------------------- 1 | ### NGINX-PROXY with Amplify Agent 2 | ### 3 | ### Author: Sebastian Plocek 4 | ### https://github.com/sebastian13/docker-compose-nginx-proxy 5 | 6 | version: '3' 7 | 8 | services: 9 | nginx-proxy: 10 | image: nginx-amplify 11 | build: 12 | context: https://github.com/nginxinc/docker-nginx-amplify.git 13 | container_name: nginx-proxy 14 | restart: always 15 | ports: 16 | - "443:443" 17 | - "80:80" 18 | volumes: 19 | - ./www:/var/www:ro 20 | - ./conf.d:/etc/nginx/conf.d:ro 21 | - ./ssl:/etc/nginx/ssl:ro 22 | - ./snippets:/etc/nginx/snippets:ro 23 | - ./protect:/etc/nginx/protect:ro 24 | networks: 25 | - proxy-tier 26 | env_file: 27 | - ./amplify.env 28 | 29 | # Let's Encrypt / Certbot 30 | # Check README.md to know how to issue new certs. 31 | certbot: 32 | image: certbot/certbot 33 | container_name: certbot 34 | depends_on: 35 | - nginx-proxy 36 | volumes: 37 | - ./ssl:/etc/letsencrypt 38 | - ./ssl-log:/var/log/letsencrypt 39 | - ./www/.well-known:/var/www/.well-known 40 | command: [ 41 | "renew", 42 | ] 43 | 44 | # Use the same external network in $upstream containers. 45 | networks: 46 | proxy-tier: 47 | external: 48 | name: www-network -------------------------------------------------------------------------------- /snippets/certbot-standalone.conf: -------------------------------------------------------------------------------- 1 | location ^~ /.well-known/acme-challenge/ { 2 | default_type "text/plain"; 3 | resolver 127.0.0.11 valid=30s; 4 | set $certbot certbot:80; 5 | proxy_pass http://$certbot; 6 | } 7 | -------------------------------------------------------------------------------- /snippets/certbot-webroot.conf: -------------------------------------------------------------------------------- 1 | location ^~ /.well-known/acme-challenge/ { 2 | default_type "text/plain"; 3 | alias /var/www/.well-known/acme-challenge/; 4 | } 5 | -------------------------------------------------------------------------------- /snippets/proxy.conf: -------------------------------------------------------------------------------- 1 | proxy_set_header Host $host; 2 | proxy_set_header X-Forwarded-For $remote_addr; 3 | proxy_set_header X-Real-IP $remote_addr; 4 | proxy_set_header X-Forwarded-Proto $scheme; 5 | proxy_buffering off; 6 | -------------------------------------------------------------------------------- /snippets/ssl.conf: -------------------------------------------------------------------------------- 1 | # To generate run 'openssl dhparam -out ssl/dhparams4096.pem 4096' 2 | ssl_dhparam /etc/nginx/ssl/dhparams4096.pem; 3 | 4 | # SSL session cache 5 | ssl_session_timeout 1h; 6 | ssl_session_cache shared:SSL:5m; 7 | ssl_session_tickets off; 8 | 9 | # TLS Support 10 | ssl_protocols TLSv1.2 TLSv1.3; 11 | ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM'; 12 | ssl_prefer_server_ciphers on; 13 | ssl_ecdh_curve secp384r1; 14 | 15 | # OCSP Stapling 16 | ssl_stapling on; 17 | ssl_stapling_verify on; 18 | resolver 127.0.0.11 ipv6=off valid=600s; 19 | resolver_timeout 5s; 20 | 21 | # Reduce ssl buffer size 22 | ssl_buffer_size 4k; 23 | 24 | # Enable HSTS 25 | add_header Strict-Transport-Security 'max-age=63072000; includeSubDomains; preload'; 26 | 27 | # Prevent the browser from doing MIME-type sniffing 28 | add_header X-Content-Type-Options nosniff; 29 | 30 | # Avoid click-jacking attacks 31 | # The frame-ancestors directive obsoletes the X-Frame-Options header. 32 | add_header Content-Security-Policy "frame-ancestors 'self';"; 33 | -------------------------------------------------------------------------------- /ssl/cli.ini: -------------------------------------------------------------------------------- 1 | # Certbot's global configuration file 2 | # https://certbot.eff.org/docs/using.html#configuration-file 3 | 4 | # Use a 4096 bit RSA key instead of 2048 5 | rsa-key-size = 4096 -------------------------------------------------------------------------------- /swarm-scripts/certbot-certonly.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # 5 | # This helper requests a new certificate by running 6 | # ./certbot-certonly.sh -m mail@example.com -d example.com -d www.example.com 7 | # 8 | 9 | # If no argument is passed, display help 10 | if [ $# -eq 0 ] 11 | then 12 | echo "To request a new certificate run:" 13 | echo "./certbot-certonly.sh -m mail@example.com -d example.com -d www.example.co" 14 | exit 15 | fi 16 | 17 | docker run -it --rm \ 18 | --name="certbot" \ 19 | --network="www-network" \ 20 | -v /docker/00-nginx-proxy/ssl:/etc/letsencrypt \ 21 | -v /docker/00-nginx-proxy/ssl-log:/var/log/letsencrypt \ 22 | certbot/certbot certonly --standalone \ 23 | --agree-tos --no-eff-email --hsts --rsa-key-size 4096 \ 24 | $@ 25 | 26 | scriptPath="$(dirname "$0")" 27 | source $scriptPath/nginx-test.sh 28 | source $scriptPath/nginx-update.sh 29 | -------------------------------------------------------------------------------- /swarm-scripts/certbot-renew.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # 5 | # Renews existing certificates, tests the nginx configuration 6 | # and restarts the nginx proxy service on all nodes 7 | # 8 | 9 | docker run --rm \ 10 | --name="certbot" \ 11 | --network="www-network" \ 12 | -v /docker/00-nginx-proxy/ssl:/etc/letsencrypt \ 13 | -v /docker/00-nginx-proxy/ssl-log:/var/log/letsencrypt \ 14 | certbot/certbot renew \ 15 | --standalone 16 | 17 | scriptPath="$(dirname "$0")" 18 | source $scriptPath/nginx-update.sh 19 | -------------------------------------------------------------------------------- /swarm-scripts/certbot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # 5 | # Run an arbitrary certbot. Use 6 | # ./certbot.sh help 7 | # to display available commands. 8 | # 9 | # Use 10 | # ./certbot.sh certificates 11 | # to list existing certificates 12 | # 13 | 14 | # If no argument is passed, display help 15 | if [ $# -eq 0 ] 16 | then 17 | echo "Run an arbitrary certbot command, e.g.:" 18 | echo " > ./certbot.sh help ... to display help" 19 | echo " > ./certbot.sh certificates ... to list certificates" 20 | exit 21 | fi 22 | 23 | docker run -it --rm \ 24 | --name="certbot" \ 25 | --network="www-network" \ 26 | -v /docker/00-nginx-proxy/ssl:/etc/letsencrypt \ 27 | -v /docker/00-nginx-proxy/ssl-log:/var/log/letsencrypt \ 28 | certbot/certbot $@ 29 | -------------------------------------------------------------------------------- /swarm-scripts/nginx-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Test the nginx configuration on the current node 5 | # 6 | 7 | SERVICE="proxystack_nginx" 8 | docker exec -it $(docker ps --filter "name=$SERVICE" -q --no-trunc | head -n1) nginx -t 9 | -------------------------------------------------------------------------------- /swarm-scripts/nginx-update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Restart the nginx service on all nodes 5 | # 6 | 7 | SERVICE="proxystack_nginx" 8 | docker exec $(docker ps --filter "name=$SERVICE" -q --no-trunc | head -n1) nginx -t 9 | docker service update --force --quiet --update-parallelism 1 --update-delay 30s $SERVICE 10 | -------------------------------------------------------------------------------- /swarm-scripts/stack-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Deploy nginx proxy to your nodes 5 | # 6 | # To stop the services, run 7 | # > docker stack rm proxystack 8 | # 9 | 10 | docker stack deploy proxystack -c ../swarm.yml 11 | -------------------------------------------------------------------------------- /swarm.yml: -------------------------------------------------------------------------------- 1 | ### NGINX-PROXY 2 | ### Works in Swarm Mode 3 | ### 4 | ### Author: Sebastian Plocek 5 | ### https://github.com/sebastian13/docker-compose-nginx-proxy/tree/docker-swarm 6 | 7 | version: '3.9' 8 | 9 | services: 10 | nginx: 11 | image: nginx 12 | ports: 13 | - target: 443 14 | published: 443 15 | mode: host 16 | - target: 80 17 | published: 80 18 | mode: host 19 | volumes: 20 | - /docker/00-nginx-proxy/www:/var/www:ro 21 | - /docker/00-nginx-proxy/conf.d:/etc/nginx/conf.d:ro 22 | - /docker/00-nginx-proxy/ssl:/etc/nginx/ssl:ro 23 | - /docker/00-nginx-proxy/snippets:/etc/nginx/snippets:ro 24 | - /docker/00-nginx-proxy/protect:/etc/nginx/protect:ro 25 | networks: 26 | - attachable 27 | deploy: 28 | mode: global 29 | update_config: 30 | parallelism: 1 31 | delay: 30s 32 | restart_policy: 33 | condition: any 34 | delay: 30s 35 | max_attempts: 120 36 | window: 30s 37 | endpoint_mode: dnsrr 38 | 39 | networks: 40 | attachable: 41 | name: www-network 42 | driver: overlay 43 | attachable: true 44 | driver_opts: 45 | encrypted: "true" 46 | --------------------------------------------------------------------------------