Blog-Background

My Solution Architect Associate Resume Project Part 3 – Automating WordPress and Nginx Installation and configuration

"What I cannot create, I do not understand" Richard Feynman

In the last article we launched an EC2 instance using AWS-CLI version 2 and made a stupid little script to chain all the commands we used, after that, we installed the LEMP stack manually.

Today I’m going to start writing our EC2 bootstrap script and pass it via the user-data, so as soon as the instance is running, it automatically install and configure all the packages we need for the LEMP stack and configure WordPress.

Objective

  • Installing and configuring WordPress
  • Configure Nginx for WordPress

It would be very easy to just install and configure everything manually, then create an AMI to use it to create new replicas in an auto-scaling group or any other way, but I wanna see if I can automate everything from the ground up without having to use any previous state to launch new infrastructure, so if you using this project you don’t need to do anything manually hopefully just one command and you have everything built from scratch.

I will start with a very straightforward installation of the stack since I will pass this as a bootstrap script through the user-data, it already gets to run as root so no need to use sudo.

#!/bin/bash

#Update and install LEMP stack packages and dependencies for WordPress
function installPackages {
    yum update -y
    yum module install php nginx mariadb -y
    yum install php-mysqlnd php-fpm php-json unzip -y
}

If you are wondering about yum module this is the Application Streams that was introduced in RHEL-8.


Installing and configuring WordPress

Since Nginx serves content from /var/www/html on RHEL-8(this would be different on each distribution) am going to serve my website from the same directory and start by creating the directory, then downloading, extracting, and finally configuring WordPress there

#!/bin/bash


#this is just the name of the wordpress website directory
site_url='wordpress'

#Update and install LEMP stack packages and dependencies for WordPress
function installPackages {
    yum update -y
    yum module install php nginx mariadb -y
    yum install php-mysqlnd php-fpm php-json unzip -y
}

#Installing and configuring WordPress
function installWordPress {
    mkdir /var/www/$site_url
    cd /var/www/$site_url
    curl https://wordpress.org/latest.tar.gz -o ./latest.tar.gz
    tar -xzvf ./latest.tar.gz
    cp -r wordpress/* .
    rm -rf latest.tar.gz wordpress 
    find . -type d -exec chmod 755 {} \;
    find . -type f -exec chmod 644 {} \;
    chown -R nginx:nginx wp-content
}

The commands are pretty straight forward for anyone with little bash knowledge like myself. I’m creating a directory for the website, then changing my location to that directory, downloading and extracting WordPress, cleaning its files after extraction, adjusting the files and directories permissions according to WordPress recommendations here, and lastly changing the ownership of the website directory to Nginx to run as a less privileged user.


Configuring Nginx for WordPress

Now that we have WordPress installed, we need to figure out how to configure Nginx to serve our WordPress site.

A quick search leads me to two solid links for configuring Nginx for WordPress, one by Nginx and another one surprise surprise by WordPress. Both have detailed recipes however it’s not self-explanatory, so I went with the Nginx one as it seems more simple to me.

I started taking each line in the configuration(each directive to be concise) and head to the Nginx documentation to read what exactly is this and what does it do and understand how Nginx really works.

After reading a lot of documentation from Nginx and understanding on a very simple level how everything kinda works, I figured that I have two main files that I need to configure, the global main Nginx configuration file /etc/nginx/nginx.conf where I’m just going to comment the server directive inside it, as I will be adding my own server configuration in a separate file under /etc/nginx/conf.d/ and leave the rest as is.

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;
}

after removing the general HTTP server configuration that nginx provide upon installation and leaving the rest of the default configuration as is, I started creating my own separate server configuration file for the WordPress site using the recipe from the Nginx website I mentioned earlier

upstream php {
    server unix:/run/php-fpm/www.sock;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name wordpress;

    root /var/www/wordpress;

    index index.php;

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_intercept_errors on;
        fastcgi_pass php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires max;
        log_not_found off;
    }
}

I think now is a good time to create a git repo to commit these configuration files to it so I can simply download and add them to /etc/nginx/ during the bootstrapping process.

I went ahead and created a git repo that I will be adding all files and scripts to as we progressing along through this series you can find it through the following link

Highly-Avaialble-Wordpress-via-Terraform

Now let’s add these configuration files to the bootstrap script,

function configuringNginx {
    github_raw_url='https://raw.githubusercontent.com/MohamedHajr/Highly-Avaialble-Wordpress-via-Terraform/master/configurations'
    curl "$github_raw_url/wordpress.conf" -o /etc/nginx/conf.d/wordpress.conf
    curl "$github_raw_url/nginx.conf" > /etc/nginx/nginx.conf
}

All am doing here is just downloading the raw files that GitHub provides and adding them in the proper Nginx directory, by now the whole script looks like this,

#!/bin/bash

#normally I would use my wesbiste url like hajr.io
site_url='wordpress'

#Update and install LEMP stack packages and dependencies for WordPress
function installPackages {
    yum update -y
    yum module install php nginx mariadb -y
    yum install php-mysqlnd php-fpm php-json unzip -y
}

#Installing and configuring WordPress
function installWordPress {
    mkdir /var/www/$website
    cd /var/www/$website
    curl https://wordpress.org/latest.tar.gz -o ./latest.tar.gz
    tar -xzvf ./latest.tar.gz
    cp -r wordpress/* .
    rm -rf latest.tar.gz wordpress 
    find . -type d -exec chmod 755 {} \;
    find . -type f -exec chmod 644 {} \;
    chown -R nginx:nginx wp-content
}

function configuringNginx {
    github_raw_url='https://raw.githubusercontent.com/MohamedHajr/Highly-Avaialble-Wordpress-via-Terraform/master/configurations'
    curl "$github_raw_url/wordpress.conf" -o /etc/nginx/conf.d/wordpress.conf
    curl "$github_raw_url/nginx.conf" > /etc/nginx/nginx.conf
}

#Executing everything
installPackages
installWordPress
configuringNginx

#Spining everything
systemctl enable --now nginx php-fpm mariadb

Lets test everything works

So now that I have my bootstrap script ready, I’m just gonna pass it to the ec2 run-instances command in the script that we created in the previous blog, so that ec2 runs the script as soon as the instance is up and running,

#!/bin/bash
#No error handling for simplicty sake

echo "Enter the region: "
read REGION
echo "  "
echo "Enter the key pair name: "
read KEY_PAIR_NAME
echo "Enter AMI Image Id: "
read AMI_ID

#Create the keyPair for ssh
aws ec2 create-key-pair --key-name $KEY_PAIR_NAME --query 'KeyMaterial' --output text > ~/.ssh/$KEY_PAIR_NAME.pem --region $REGION
echo "Key pair created sucessfully and saved to ~/.ssh/$KEY_PAIR_NAME."

chmod 400 ~/.ssh/$KEY_PAIR_NAME.pem

#Assumimg I have only one vpc in that region the default one
VPC_ID=`aws ec2 describe-vpcs --query 'Vpcs[0].VpcId' --output text --region $REGION`
echo "Successfully got the default VPC ID $VPC_ID....."

SG_ID=`aws ec2 create-security-group --group-name ssh-http --description "Allows SSH and HTTP traffic" --vpc-id $VPC_ID --query 'GroupId' --output text --region $REGION`
echo "Successfully created the security group with Id $SG_ID....."

echo "Allowing SSH & HTTP traffic on $SG_ID......"
aws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 22 --cidr 0.0.0.0/0 --region $REGION >> /dev/null
aws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 80 --cidr 0.0.0.0/0 --region $REGION >> /dev/null

echo "Launching the instance....."
aws ec2 run-instances --image-id $AMI_ID --count 1 --instance-type t2.micro --key-name $KEY_PAIR_NAME --security-group-ids $SG_ID --user-data file://bootstrap.sh --region $REGION

As you can see in the last command am passing the bootstrap script using the --user-data option so ec2 begin executing it as soon as the instance is up and running.

Now if we head to the browser and write the public IP or dns name for the ec2 instance we should see a page like this, which means that Nginx is configured successfully and serving our WordPress website.

Wrapping Up

Today we installed and configured WordPress and Nginx successfully using a couple of bash scripts, in the next part we will figure out how to configure and secure MariaDB, to make it ready to be used by WordPress.

Thank you so much for reading thus far and looking forward seeing you the next part.

Share this post

Share on facebook
Share on twitter
Share on linkedin
Share on pinterest
Share on print
Share on email
Recent Comments

    Leave a Reply

    Your email address will not be published. Required fields are marked *