Docker Compose: How to create multiple SSL (free -letsencrpyt) WordPress/Static websites on a Google Cloud Virtual Machine
5 min read
I maintained multiple WordPress and other non-PHP sites for a long time. I never needed SSL because there is nothing to secure but Google kind of made it very hard to use HTTP on the chrome browser a few years ago. I was looking for a free or cheap option that won't break my bank as these are non-money-making sites. Following are the steps, I did to secure my websites. I gave the GCP example but my sites are running on Azure as I get a free $50 credit every month. GCP gives you a free micro server credit so if you don't have a lot of traffic, you can technically host multiple sites on GCP too for free.
I am using Docker Compose to host multiple WordPress sites and getting the SSL certificates painlessly using certbot docker image. You can always extend this to fits your need.
- Get an external reserve IP Address
- Update DNS settings with the new IP in your Domain Registry. I am going to use my hufta.com website for example. I also need SSL for www so I added a CNAME. You can add multiple CNAMEs if you need like dev, etc. Anyway, a wildcard is possible but I didn't go that route as it requires more steps.
- Create a Debian-based Virtual Machine on any cloud provider. Attach the static IP to this machine. Below is an example of the GCP with firewall settings.
- SSH into your VM.
a) Install docker in your VM. Follow the steps from https://docs.docker.com/engine/install/debian/ Run the following commands in order
b) Install git
sudo apt-get install git
c) Download the latest WordPress gz file in your VM https://wordpress.org/download/
d) Clone the following repository in your home directory
git clone https://github.com/ssudershan/dockercomposesslwp.git
The web directory under dockercomposesslwp is your root directory for all your websites. I am going to create a subdirectory hufta under web. All the hufta.com traffic will go to this subfolder and it's controlled by etc/nginx/hufta.conf Following steps are to set up the hufta.com domain but you need to update conf files based on your domain name. You need to create a new conf file for each of the websites(domains) you are going to host.
e) Pay attention to hufta.conf. The SSL is disabled as we don't have SSL yet. Start Docker compose
sudo docker compose up -d
f) get the SSL for hufta.com You have to update certBot.sh for your own domain. I will explain more later.
sudo sh ./certBot.sh
g) if certBot is successful no error message will be shown. Shutdown docker compose
sudo docker compose down
h) uncomment SSL etc/nginx/hufta.conf as the SSL is installed and we are ready to go to the next step
listen 443 default_server ssl; server_name hufta.com www.hufta.com hufta.org www.hufta.org; fastcgi_param HTTPS on; ssl_certificate /etc/nginx/ssl/hufta.com/live/hufta.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/hufta.com/live/hufta.com/privkey.pem; ssl_protocols TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5; ssl_session_cache shared:SSL:10m; ssl_session_timeout 5m;
i) start docker compose
sudo docker compose up -d
Go to your browser and type your website URL (hufta.com for me) and follow WordPress installation.
EXPLANATION and NEXT STEPS
certBot.sh script gets your SSL for the domain. It downloads a file to your web server and makes sure that the file can be read through your domain. Once these steps are complete the SSL files are generated.
docker run -it --rm --name certbot -v /$(pwd)/etc/ssl/hufta.com:/etc/letsencrypt -v /$(pwd)/var/log/letsencrypt:/var/log/letsencrypt -v /$(pwd)/web/letsencrypt/:/var/www certbot/certbot:latest -t certonly --quiet --agree-tos --renew-by-default --email email@example.com --webroot -w /var/www -d hufta.com -d www.hufta.com
/$(pwd)/etc/ssl/hufta.com:/etc/letsencrypt - This is the location the SSL will be stored and as you can see in etc/nginx/hufta.com, the SSL location is configured. You can create a copy of certBot.sh and run it for each domain and set it up appropriately.
ssl_certificate /etc/nginx/ssl/hufta.com/live/hufta.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/hufta.com/live/hufta.com/privkey.pem;
/$(pwd)/var/log/letsencrypt:/var/log/letsencrypt - This is the location for you log files. /$(pwd)/web/letsencrypt/:/var/www - This is root for certbot and it will download a file under ./well-known/acme-challenge folder.
-d options are for your domains.
Also, --email firstname.lastname@example.org option is required only the first time. Afterward, you can remove and put these shell scripts to run on the cron job. The SSL is valid for 90 days so make sure you renew it before that time period.
- docker-compose.yml - This is a straightforward Nginx, WordPress, and MySQL server setup in it. Why didn't I use the LAMP image? With my option, I can create a subfolder and can have a static-based or non-PHP-based app. All I need to add a conf file in the etc/Nginx folder for that domain. I tried PHP image instead of WordPress but I was getting MySQL to connect error. With the WordPress image, I got what I needed. The only nuance was it checks WordPress in the root folder if not then it will download the WordPress files. If you see in the root folder there are empty index.php and wp-includes/version.php. It checks these two files if they exist then it doesn't copy the whole WordPress files.
- How to scale? a)Remove MySQL from the docker compose and either create a separate MySQL server or use MySQL service from the cloud provider. b) Create an image after successful setup and deploying multiple instances and load balance the instances.
Youtube Link: youtu.be/HiT76Xbl2B0