diff --git a/environments/cutlergyor/apache2/docker-compose.yaml b/environments/cutlergyor/apache2/docker-compose.yaml index 399e6c4..68ea5f8 100644 --- a/environments/cutlergyor/apache2/docker-compose.yaml +++ b/environments/cutlergyor/apache2/docker-compose.yaml @@ -9,7 +9,6 @@ services: - "42001:80" - "42002:443" volumes: - - cutler_letsencrypt:/etc/letsencrypt - cutler_photos:/var/www/html/cutler/frontend/web/uploads/profile environment: FITNESS_DB_HOST: cutlerdb @@ -19,8 +18,8 @@ services: FITNESS_DB_PASSWORD: cutler_prod FITNESS_MAIL_HOST: cutlermail FITNESS_MAIL_PORT: 1025 - FITNESS_MAIL_USERNAME: - FITNESS_MAIL_PASSWORD: + FITNESS_MAIL_USERNAME: test + FITNESS_MAIL_PASSWORD: test cutlerdb: image: mariadb:10.1 @@ -40,9 +39,9 @@ services: networks: cutler_network: + volumes: cutler_photos: {} - cutler_letsencrypt: {} cutler_mariadb: {} networks: diff --git a/environments/cutlergyor/proxy/certbot-dryrun.sh b/environments/cutlergyor/proxy/certbot-dryrun.sh new file mode 100644 index 0000000..5ce962f --- /dev/null +++ b/environments/cutlergyor/proxy/certbot-dryrun.sh @@ -0,0 +1 @@ +docker-compose run --rm certbot certonly --webroot --webroot-path /var/www/certbot/ --dry-run -d rschneider.hu diff --git a/environments/cutlergyor/proxy/certbot-renew.sh b/environments/cutlergyor/proxy/certbot-renew.sh new file mode 100644 index 0000000..ad79322 --- /dev/null +++ b/environments/cutlergyor/proxy/certbot-renew.sh @@ -0,0 +1 @@ +docker compose run --rm certbot renew diff --git a/environments/cutlergyor/proxy/certbot-run.sh b/environments/cutlergyor/proxy/certbot-run.sh new file mode 100644 index 0000000..a48b58d --- /dev/null +++ b/environments/cutlergyor/proxy/certbot-run.sh @@ -0,0 +1 @@ +docker-compose run --rm certbot certonly --webroot --webroot-path /var/www/certbot/ -d rschneider.hu diff --git a/environments/cutlergyor/proxy/docker-compose.yaml b/environments/cutlergyor/proxy/docker-compose.yaml new file mode 100644 index 0000000..a0672f0 --- /dev/null +++ b/environments/cutlergyor/proxy/docker-compose.yaml @@ -0,0 +1,22 @@ +version: '3' + +# volume descriptiosn +# ./certbot/www/ -> used to do the challange +# ./certbot/conf/ -> used to store the ssl artifacts generated by certbot + +services: + webserver: + image: nginx:latest + ports: + - 80:80 + - 443:443 + restart: always + volumes: + - ./nginx/conf/:/etc/nginx/conf.d/:ro + - ./certbot/www:/var/www/certbot/:ro + - ./certbot/conf/:/etc/nginx/ssl/:ro + certbot: + image: certbot/certbot:latest + volumes: + - ./certbot/www/:/var/www/certbot/:rw + - ./certbot/conf/:/etc/letsencrypt/:rw diff --git a/environments/cutlergyor/proxy/nginx/conf/default.conf b/environments/cutlergyor/proxy/nginx/conf/default.conf new file mode 100644 index 0000000..052e1c8 --- /dev/null +++ b/environments/cutlergyor/proxy/nginx/conf/default.conf @@ -0,0 +1,29 @@ +server { + listen 80; + listen [::]:80; + + server_name rschneider.hu www.rschneider.hu; + server_tokens off; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://rschneider.hu$request_uri; + } +} + +server { + listen 443 default_server ssl http2; + listen [::]:443 ssl http2; + + server_name rschneider.hu; + + ssl_certificate /etc/nginx/ssl/live/rschneider.hu/fullchain.pem; + ssl_certificate_key /etc/nginx/ssl/live/rschneider.hu/privkey.pem; + + location / { + proxy_pass http://rschneider.hu:40001; + } +} diff --git a/environments/cutlergyor/proxy/readme.md b/environments/cutlergyor/proxy/readme.md new file mode 100644 index 0000000..b9fbcba --- /dev/null +++ b/environments/cutlergyor/proxy/readme.md @@ -0,0 +1,193 @@ + +# Nginx+certbot proxy + +source: https://mindsers.blog/post/https-using-nginx-certbot-docker/ + +# copy of above page + +This post is free for all to read thanks to the investment Mindsers Blog's subscribers have made in our independent publication. If this work is meaningful to you, I invite you to become a subscriber today. + +As it is a really common task, this post will guide you through with a step-by-step process to protect your website (and your users) using HTTPS. The specific part here is that we will do this in a docker environment. + +In this post, I will use Docker Compose to make the tutorial simpler and because I like the infrastructure as code movement. + +Nginx as a server +To be able to use nginx as a server for any of our projects, we have to create a Docker Compose service for it. Docker will handle the download of the corresponding image and all the other tasks we used to do manually without Docker. + +version: '3' + +services: +webserver: +image: nginx:latest +ports: +- 80:80 +- 443:443 +At anytime during the tutorial, you can run docker compose up to start the environment and see if everything goes well. + +We have now a working raw installation of nginx that listens to ports 80 for HTTP and 443 for HTTPS. + +version: '3' + +services: +webserver: +image: nginx:latest +ports: +- 80:80 +- 443:443 +restart: always +As I want the server to be always up and running, I tell Docker that it should take care of restarting the "webserver" service when it unexpectedly shuts down. + +version: '3' + +services: +webserver: +image: nginx:latest +ports: +- 80:80 +- 443:443 +restart: always +volumes: +- ./nginx/conf/:/etc/nginx/conf.d/:ro +The ultimate goal of our installation isn't to serve the default welcome page of nginx. So, we need a way to update the nginx configuration and declare our website. + +To accomplish that, we use the "volumes" feature of Docker. This means we map the folder located at /etc/nginx/conf.d/ from the docker container to a folder located at ./nginx/conf/ on our local machine. Every file we add, remove or update into this folder locally will be updated into the container. + +Note that I add a :ro at the end of the volume declaration. ro means "read-only". The container will never have the right to update a file into this folder. It is not a big deal, but consider it as a best practice. It can avoid wasting a few precious hours of debugging. + +Now update the Docker Compose file as below: + +version: '3' + +services: +webserver: +image: nginx:latest +ports: +- 80:80 +- 443:443 +restart: always +volumes: +- ./nginx/conf/:/etc/nginx/conf.d/:ro +- ./certbot/www:/var/www/certbot/:ro +And add the following configuration file into your ./nginx/conf/ local folder. Do not forget to update using your own data. + +server { +listen 80; +listen [::]:80; + + server_name example.org www.example.org; + server_tokens off; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://example.org$request_uri; + } +} +The configuration is simple. We explain to nginx that it has to listen to port 80 (either on IPv4 or IPv6) for the specific domain name example.org. + +By default, we want to redirect someone coming on port 80 to the same route but on port 443. That's what we do with the location / block. + +But the specificity here is the other location block. It serves the files Certbot need to authenticate our server and to create the HTTPS certificate for it. + +Basically, we say "always redirect to HTTPS except for the /.well-know/acme-challenge/ route". + +We can now reload nginx by doing a rough docker compose restart or if you want to avoid service interruptions (even for a couple of seconds) reload it inside the container using docker compose exec webserver nginx -s reload. + +Create the certificate using Certbot +For now, nothing will be shown because nginx keeps redirecting you to a 443 port that's not handled by nginx yet. But everything is fine. We only want Certbot to be able to authenticate our server. + +To do so, we need to use the docker image for certbot and add it as a service to our Docker Compose project. + +version: '3' + +services: +webserver: +image: nginx:latest +ports: +- 80:80 +- 443:443 +restart: always +volumes: +- ./nginx/conf/:/etc/nginx/conf.d/:ro +- ./certbot/www:/var/www/certbot/:ro +certbot: +image: certbot/certbot:latest +volumes: +- ./certbot/www/:/var/www/certbot/:rw +We now have two services, one for nginx and one for Certbot. You might have noticed they have declared the same volume. It is meant to make them communicate together. + +Certbot will write its files into ./certbot/www/ and nginx will serve them on port 80 to every user asking for /.well-know/acme-challenge/. That's how Certbot can authenticate our server. + +Note that for Certbot we used :rw which stands for "read and write" at the end of the volume declaration. If you don't, it won't be able to write into the folder and authentication will fail. + +You can now test that everything is working by running docker compose run --rm certbot certonly --webroot --webroot-path /var/www/certbot/ --dry-run -d example.org. You should get a success message like "The dry run was successful". + +Now that we can create certificates for the server, we want to use them in nginx to handle secure connections with end users' browsers. + +Certbot create the certificates in the /etc/letsencrypt/ folder. Same principle as for the webroot, we'll use volumes to share the files between containers. + +version: '3' + +services: +webserver: +image: nginx:latest +ports: +- 80:80 +- 443:443 +restart: always +volumes: +- ./nginx/conf/:/etc/nginx/conf.d/:ro +- ./certbot/www:/var/www/certbot/:ro +- ./certbot/conf/:/etc/nginx/ssl/:ro +certbot: +image: certbot/certbot:latest +volumes: +- ./certbot/www/:/var/www/certbot/:rw +- ./certbot/conf/:/etc/letsencrypt/:rw +Restart your container using docker compose restart. Nginx should now have access to the folder where Certbot creates certificates. + +However, this folder is empty right now. Re-run Certbot without the --dry-run flag to fill the folder with certificates: + +$ docker compose run --rm certbot certonly --webroot --webroot-path /var/www/certbot/ -d example.org +Since we have those certificates, the piece left is the 443 configuration on nginx. + +server { +listen 80; +listen [::]:80; + + server_name example.org www.example.org; + server_tokens off; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://example.org$request_uri; + } +} + +server { +listen 443 default_server ssl http2; +listen [::]:443 ssl http2; + + server_name example.org; + + ssl_certificate /etc/nginx/ssl/live/example.org/fullchain.pem; + ssl_certificate_key /etc/nginx/ssl/live/example.org/privkey.pem; + + location / { + # ... + } +} +Reloading the nginx server now will make it able to handle secure connection using HTTPS. Nginx is using the certificates and private keys from the Certbot volumes. + +Renewing the certificates +One small issue you can have with Certbot and Let's Encrypt is that the certificates last only 3 months. You will regularly need to renew the certificates you use if you don't want people to get blocked by an ugly and scary message on their browser. + +But since we have this Docker environment in place, it is easier than ever to renew the Let's Encrypt certificates! + +$ docker compose run --rm certbot renew +This small "renew" command is enough to let your system work as expected. You just have to run it once every three months. You could even automate this process…