Deploy a simple WordPress in AWS

Using Terraform and Ansible to create a simple WordPress Deployment

WordPress Diagram

The code discussed in this article can be found in my public GitHub repository.


Features

Deploy WordPress using Infrastructure as Code into AWS

Terraform – Terraform’s Infrastructure as Code to Deploy resources in AWS.

Ansible will be used to construct and configure the MariaDB database server in the private subnet and a WordPress server in the public subnet.

All the AWS resources created below comply with an AWS Free Tier Plan.

These resources are compliant with a free tier plan. But don’t leave them running! There is a limit of EC2 hours allowed in a free tier plan!

This exercise will perform the following tasks using Terraform HCL code:

  • A module to create a VPC with security groups and routing
  • A module to create two S3 buckets
    • We’ll copy some ansible code to one of the S3 buckets
    • We’ll put Terraform remote state in the other S3 bucket
  • Build code that creates EC2 instances for a WordPress server and a MariaDB server using Terraform
  • Create an IAM policy that allows an EC2 instance to copy files from the S3 bucket
  • Build a code that creates the “Controller” server
  • Use the Controller to execute Ansible playbooks for configuring WordPress and MariaDB

Requirements

  • Must have an AWS account
  • Install AWS CLI, and Configure AWS CLI
  • Install Terraform
  • An EC2 Key Pair for AWS CLI (for connecting using SSH protocol)
  • Recommend using your own domain (either register a new domain in AWS or register a domain from any registrar service of your choice).
  • AWS Administrator account or an account with the following permissions:
    • ability to create IAM policies
    • Create and Manage changes in Route 53
    • Create VPC, subnets, routing, and security groups
    • Create and manage EC2 resources
    • Create an Ec2 Key Pair for the region
    • Create and manage an S3 Bucket for Terraform Remote State
    • Create an S3 bucket for the Ansible playbooks and other configuration files

So let’s get started

Please create the folder structure shown below:

S3 Buckets

An S3 bucket can be created using the AWS Management console, or an even faster method would be to use AWS Command Line Interface (AWS CLI) to create an S3 Bucket.

You may not require server-side encryption or versioning for this exercise. If multiple personnel use the same S3 bucket, you would undoubtedly want to consider enabling version control. If your team believes specific parameters are sensitive information, I suggest server-site encryption.

An S3 bucket name must be globally unique, that means literrally a unique name in ALL AWS regions

  • Create an S3 bucket for the Terraform remote state
    • It can be any S3 bucket name of your choice, but of course, I recommend a name something like “your_nickname.terraform.state”
  • Create an S3 bucket to hold configuration files for WordPress, MariaDB, and Ansible playbooks
    • I recommend a name like “your_nickname.ansible_files”

Creating the VPC

The VPC will be making:

  • One public subnet for the WordPress website and another server I call the Controller
  • One private subnet for the database server
  • NAT instances instead of a NAT gateway and the associative routing
  • Security Groups
  • Output data that other modules will use to obtain data.

Make sure you have configured an S3 bucket for Terraform Remote State and name the bucket something like “name-terraform-states.”

Create the following code “vpc.tf” in the VPC folder

Create the code “variables.tf” in the VPC folder

Create a file “security_groups.tf in the VPC folder

Create “output.tf” in the VPC folder

Create a folder named “Servers”

We are creating an Ec2 instance for WordPress in the public subnet and another EC2 instance in the private subnet.

Create the file “servers.tf” in the servers folder

Create “bootstrap_db.sh”

Create “bootstrap_wp.sh”

Create a folder named Ansible

There are Nine files placed in the Ansible folder. All the files for Ansible will be in my GitHub repository. Be sure to edit the appropriate files as stated below to personalize your choices for things like DB password.

  • ansible.cfg
  • hosts.ini
  • provision-db.yml
  • provision-wp.yml

The other five files will be placed into the MariaDB server and the WordPress server by Ansible.

  • Files for MariaDB
    • 50-server.cnf
    • vars.yml
  • Files for WordPress
    • dir.conf
    • example.com.conf
    • wordpress.zip

Edit “vars.yml” to reflect your choices of USERNAME, PASSWORD, DBNAME, NEW_ADMIN, NEW_ADMIN_PASSWORD. Ensure you also edit wp-config.php in the “wordpress.zip” archive to reflect the same.

Uncompress wordpress.zip and edit “wp-config.php.” Lines 23,26, and 29 reflect your choices of DB_NAME, DB_USER, and DB_PASSWORD. Make sure they match “vars.yml.”

Create an S3 bucket for the above files

If you have not already created an S3 bucket to hold the ansible files, please do so now.

Copy the files from my Github repository Ansible folder to the S3 bucket.

When we use the command to apply Terraform, the files will automatically be copied from our S3 bucket into the controller server below as part of the bootstrap_controller.sh. So make sure you have configured our S3 bucket and placed the Ansible files into that bucket before running Terraform Apply command.

Create a folder named Controller

A Controller is where all the magic happens. We are creating a jump server (I call it a controller).

After deploying the VPC infrastructure and placing the Ansible files into an S3 bucket, we create three servers (WordPress, MariaDB, and Controller).

We will then use SSH to connect to our Controller and Ansible playbooks to configure MySQL on the MariaDB server and to configure WordPress settings on the WordPress server.

Create the “controller.tf” file in the controller folder

Create the “variables.tf” file in the Controller folder

Create the file “bootstrap_controller.sh”

Create the S3 Policy in the Controller folder

This will give our controller permission to copy files from our S3 bucket. Be sure to edit the ARN information to reflect the appropriate S3 bucket name for your deployment.

Provisioning

  1. Make an S3 bucket for Terraform Remote state.
    • Be sure to use the name of the S3 bucket in “VPC.tf, servers.tf, controller.tf
  2. Make an S3 bucket for the Ansible files.
    • Be sure to change the S3 Bucket name in S3_policy.tf (lines 16), shown above, to your S3 bucket name for Ansible files.
  3. Be sure to change the variables in the VPC folder with variables of your choice.
  4. Be sure to change the variables in the server folder to variables of your choice.
  5. Change the vars.yml to reflect your dbname, user name, etc.
  6. Be sure to uncompress the wordpress.zip file, edit the wp-config.php to reflect your dbname and user name of your choice, update the example.com.conf file to your domain name, and as well edit the content of example.com.conf to your domain name. Once the edits are complete, compress the files back into wordpress.zip.
  7. Be sure to copy the ansible files into the bucket you created for the Ansible files
  8. In your terminal, go to the VPC folder and execute the following commands:
    1. Terraform init
    2. terraform validate
    3. Terraform apply 
  9. In your terminal, go to the server folder and execute the following commands:
    1. Terraform init
    2. terraform validate
    3. Terraform apply 
  10. In your terminal, go to the controller folder and execute the following commands:
    1. Terraform init
    1. terraform validate
    2. Terraform apply 

Running the Ansible configuration on the Controller

First, we are going to set up our SSH credentials. This assumes you have already configured an EC2 key pair and assigned the key in the above terraform code. You must have already placed an EC2 key into your ssh directory.

  • Add EC2 key pair into SSH credentials by issuing the following command
    • ssh-add ~/.ssh/your-key-name.pem
  • Then connect to the Controller with “-A” option of SSH command to forward the authentication agent to our Controller. “-A” allows us to connect to the Controller, then jump to our servers inside AWS public and private networks. “-A” as an SSH option also enables the authentication agent for Ansible playbooks to use the very same EC2 key pair to manage MariaDB and WordPress servers.”
    • ssh -A ec2-user@1.2.3.4 (where 1.2.3.4 represents the public IP address of the Controller)
  • Once connected to the Controller, change the directory to the WordPress directory (this directory may not exist if you connect to the Controller too soon, as it takes a couple of minutes for the bootstrap to configure the Controller)
    • cd WordPress
  • First, we can configure the MariaDB server with Ansible
    • ansible-playbook provision-db.yml
    • for some reason, the handler at the end of the Ansible playbook doesn’t restart MySQL, and WordPress gets a “cannot connect to database error.” If this does happen to you (most likely, I might add), then we need to connect to the DB server and restart MySQL
      • ssh ubuntu@10.0.101.30
      • sudo -i
      • service MySQL restart
    • The final step is to run the Ansible playbook to configure the WordPress server
      • ansible-playbook provision-wp.yml

If you want to actually test WordPress feel free, you’ll need to create a record for your domain. Goto Route 53, register a domain, create an “A record” and assign the public IP address of WordPress Instance.

Or, if you do not want to use your domain (I recommend the practice of using your domain, but hey, what do I know, hee hee), open your browser and put in the public IP address of the WordPress server.

Open a browser and type in your domain.

If you have followed the exercise correctly, then you should see the following

Initial WordPress Screen

This is not for production!

All public websites should have an application firewall in between the Web Server and its internet connection, this exercise doesn’t create the application firewall. So do not use this configuration for production

All websites should have monitoring and a method to scrape log events to detect and alert for potential problems with the deployment.

This exercise uses resources compatible with the AWS Free Tier plan. It does not have sufficient compute sizing to support a production workload.

It is a good idea to remove All resources when you have completed this exercise, so as not to incur costs

Exit mobile version
%%footer%%