Creating an Infrastructure, by integrating Terraform and Ansible on AWS

Akhilesh Jain
12 min readMar 26, 2021


In this article, we will create an Infrastructure, which includes an EC2 Instance on which Wordpress Application will be installed and for the backend purpose for this application will be MySQL Database Engine, which will be created using AWS-RDS Service.

A similar type of Infrastructure, I have created using AWS-RDS fore backend and Kubernetes Pods for frontend which have wordpress application deployed on it. Link for the following article is:

So, to create this Infrastructure and configuring the same, we will use Automation Tool Terraform and Configuration Management Tool as Ansible.

What is Terraform?
Terraform is an open-source infrastructure as code software tool that provides a consistent CLI workflow to manage hundreds of cloud services.
→ Basically I am using this tool to deploy RDS Service of AWS, which will create this Engine with code.

To Install Terraform and use it, I have created a article, do refer this:

RDS — This is a Database Service provided by AWS, In this Service I will be using MySQL Engine.

What is Ansible?
Ansible is a Configuration Management tool through which we can create and configure servers, clusters, VM’s and other things very easily.
→ So, in this Task, I will be using Ansible to create an EC2 Instance, and then installing Wordpress on it and configure it. Configuring here means some credentials that we have to give it on browser, instead we can give it initially also. In later part we will see to that file also.

So Let’s Start:

Firstly, we will be Creating our DB Instance using Terraform. I have used module approach for creating the same, as it is a better way of creating and managing it. Using this, we can create multiple Deployments of Services at the same time.
So, Following is the Structure of the folder:

So in this Folder ‘Task_18’, I have created:

  • 1 folder which contains a file ‘’, which will create multiple resources like Configuring to AWS, Creating Security Group, Creating a DB Instance, Creating a local file so that, all the credentials I want can be fetched and copied easily.
  • ‘’ file which contains a module which will be called, when we run this file. In this module, I have passed some variables to the file.
  • ‘’ file contains 3 variables, which contains the value of my name, username, password (of this username) of the Database.

→ These variables can only be transferred to the inner code of modules, if the main file and the variable file are at the same location.

Following is the code for file:

# Initializing Modulemodule "rds" {
source = "./rds"
rdsusername = var.rdsusername
rdspasswd = var.rdspasswd
# rdsdbname = var.rdsdbname

Following is the code for file:

variable "rdsusername" {
type = string
default = "admin"
description = "Username for database"
variable "rdspasswd" {
type = string
default = "admin12345"
description = "Password for AWS-RDS MySQL Database"
# #WORDPRESS_DB_NAME(Database Name)
# variable "rdsdbname" {
# type = string
# default = "mysqldb"
# description = "Name of AWS-RDS MySQL Database"
# }

Following is the code for file:

# Declaring Variables
variable "rdspasswd" {}
variable "rdsusername" {}
# variable "rdsdbname" {}
# Logging into AWS using IAM role
provider "aws" {
region = "ap-south-1"
profile = "akhil"
# Using Default VPC
resource "aws_default_vpc" "default" {
tags = {
Name = "Default VPC"
# Creating a Security Group for our DB Instance
resource "aws_security_group" "sg" {
name = "db-wizard"
description = "Allow Database inbound traffic"
vpc_id =
ingress {
description = "MYSQL/Aurora"
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = [""]
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [""]
tags = {
Name = "sg-for-db"
# Creating DB Instance in RDS
resource "aws_db_instance" "default" {
identifier = "wpdatabase"
engine = "mysql"
engine_version = "5.7.21"
name = "mysqldb"
username = var.rdsusername
password = var.rdspasswd
allocated_storage = 20
max_allocated_storage = 25
storage_type = "gp2"
availability_zone = "ap-south-1b"
instance_class = "db.t2.micro"
port = 3306
publicly_accessible = true
skip_final_snapshot = true
vpc_security_group_ids = [ "${}" ]
tags = {
Name = "awsrds"
depends_on = [,
#WORDPRESS_DB_HOST (Database Host)
output "rds_dbhost" {
value = aws_db_instance.default.endpoint
output "rds_dbname" {
value =
# Creating a Local file, which contains details of our Login Details #in Wordpressresource "local_file" "credentials" {
content = "WORDPRESS_DB_HOST => ${aws_db_instance.default.endpoint}\n WORDPRESS_DB_USER ${aws_db_instance.default.username}\n WORDPRESS_DB_PASSWORD ${aws_db_instance.default.password}\n WORDPRESS_DB_NAME ${}"
filename = "details"

So now we will run the Code using the Terminal:

cmd> terraform init

→ This command is used once to install the required plugins.

cmd> terraform apply --auto-approve

→ This command will deploy everything we have written on our Code.

So, until this is created, Lets see the Code written on Ansible VM.

As I have used the concept of Dynamic Inventory in Ansible, which will automatically fetch the results from AWS Console that, how many Instances with their Names and all are there currently running.

So, for this also, I have created a article before which uses the concept of Dynamic Inventory. Following is the link:

Following is the Directory Structure of the Required Task in my Anisble VM, on which my Ansible is pre-installed.

  • ‘ansible.cfg’ — This file is the configuration file which ansible uses to see the hosts, permissions to the user, location of roles, keys etc.
inventory = ./hosts
host_key_checking = false
remote_user = ec2-user
private_key_file = ./key123.pem
ask_pass = false
become = true
become_method = sudo
become_user = root
become_ask_pass = false
  • ‘key123.pem’ — This is the private key attached to our Instance.
  • ‘vars.yml’ — This is the file which consists of the variables which are actually some credentials and some are like URL and destinaton for the wordpress application.
dest_var: /var/www/html/
  • ‘vault.yml’ — This file is used to store the credentials of my IAM User.
ak: 'xxx--your access key---'
sak: '---your-secret access key---'
  • ‘vault_pass_file.yml’ — This is the file which consists of password of vault.
#This is the password of my Vault
  • ‘setup.yml’ — This is the playbook, which is used to create EC2 Instance, Security Group and installing some python libraries.
- name: "Creating 1 VM and some python libaries"
hosts: localhost
gather_facts: false
- vault.yml
- name: "installing boto"
name: "boto"
executable: pip3
- name: "installing boto3"
name: "boto3"
executable: pip3
- name: "creating security group"
aws_access_key: "{{ ak }}"
aws_secret_key: "{{ sak }}"
name: 'launch-wizard-1'
description: 'sg with rule descriptions'
vpc_id: 'vpc-224d514a'
Name: "task18-sg"
region: "ap-south-1"
- proto: tcp
from_port: 22
to_port: 22
rule_desc: allow all on port 22 for ssh
- proto: tcp
- 80
rule_desc: allow all on port 80 for webserver
- proto: all
from_port: 0
to_port: 0

- name: "Creating Wordpress Instance"
count: 1
image: "ami-0a9d27a9f4f5c0efc"
instance_type: t2.micro
region: "ap-south-1"
wait: yes
Name: ArthTask18
group: "launch-wizard-1"
key_name: "key123"
state: present
aws_access_key: "{{ ak }}"
aws_secret_key: "{{ sak }}"
  • ‘playbook.yml’ — This is the playbook which is used to install the Wordpress Application and Install some Packages over the Instance, Start and Stop the services and many more..
- name: Deploying HTTPD Servers
hosts: tag_Name_ArthTask18
- vars.yml
- name: Install Packages
- "httpd"
- "php-mysqlnd"
- "php-fpm"
- "mariadb-server"
- "php-json"
- "firewalld"
state: present
- name:
url: "{{ url_var }}"
dest: "/root/"

- name: Extracting Wordpress Package
src: "/root/wordpress-5.7.tar.gz"
dest: "/root/"
remote_src: yes
- name: stop firewalld
name: "firewalld"
state: stopped
- name: service httpd start
name: "httpd"
state: started
enabled: yes
- name: Copying Extracted file to webserver default location
src: "/root/wordpress"
dest: "{{ dest_var }}"
remote_src: yes

- name: Making Selinux Permissive
policy: targeted
state: permissive
- name: copy content
src: "wp-config.j2"
dest: "{{ dest_var }}wordpress/wp-config.php"
force: true
  • ‘wp-config.j2’ — This file is a jinja template, which has some features through which we can add some variables and some loops, but this file consists of some variables currently.
* The base configuration for WordPress
* The wp-config.php creation script uses this file during the
* installation. You don't have to use the web site, you can
* copy this file to "wp-config.php" and fill in the values.
* This file contains the following configurations:
* * MySQL settings
* * Secret keys
* * Database table prefix
* @link
* @package WordPress
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', "{{ WORDPRESS_DB_NAME }}" );
/** MySQL database username */
define( 'DB_USER', "{{ WORDPRESS_DB_USERNAME }}" );
/** MySQL database password */
/** MySQL hostname */
define( 'DB_HOST', "{{ WORDPRESS_DB_HOST}}" );
/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );
/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
* Authentication Unique Keys and Salts.
* Change these to different unique phrases!
* You can generate these using the {@link secret-key service}
* You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
* @since 2.6.0
define( 'AUTH_KEY', 'put your unique phrase here' );
define( 'SECURE_AUTH_KEY', 'put your unique phrase here' );
define( 'LOGGED_IN_KEY', 'put your unique phrase here' );
define( 'NONCE_KEY', 'put your unique phrase here' );
define( 'AUTH_SALT', 'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT', 'put your unique phrase here' );
define( 'NONCE_SALT', 'put your unique phrase here' );
* WordPress Database Table prefix.
* You can have multiple installations in one database if you give each
* a unique prefix. Only numbers, letters, and underscores please!
$table_prefix = 'wp_';
* For developers: WordPress debugging mode.
* Change this to true to enable the display of notices during development.
* It is strongly recommended that plugin and theme developers use WP_DEBUG
* in their development environments.
* For information on other constants that can be used for debugging,
* visit the documentation.
* @link
define( 'WP_DEBUG', false );
/* That's all, stop editing! Happy publishing. *//** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';
  • ‘hosts/’ — This file consist of python code which is used to Create the Resources over AWS.
  • ‘hosts/ec2.ini’ —This file is used to take the Credentials of the IAM User created in AWS.
  • ‘wp-config-sample.php’ — This is the sample file in which we have to add the Database Details like Database Name, Username, Password, Hostname of RDS. To make it usable, we have to rename this file as wp-config.php .


→ Pre-created Key Pair

We have run the Terraform Script, so following has been created:

→ To run the Ansible Setup file:

ansible-playbook setup.yml --vault-pass-file=vault_pass_file

→ EC2 Instance and Security Group has been created:

—EC2 Instance

→ To run the playbook.yml

ansible-playbook playbook.yml

So, I have done SSH to the Instance and following are the Screenshots:

— To check the hosts and adding it to playbook.yml, using the following Command:

./hosts/ --list

— We can see that “tag_name_Arth_Task18”, is the required for us, there are other Host Groups also, which we can also take.

→ Now Using the Applications(Wordpress and MySQL), which we have created, a page comes in which we have to create a User, and after Creation, the following page comes:

So, I have Created a Post after Logging in.

After Logout and again logging in:

→ Now we have to check the Database(MySQL), if whatever we create are stored or not, so we login to the database and check:

mysql> Select + from wp_posts

→ So, As we can see that, Everything we created on Wordpress has been stored in AWS RDS Database.

→ So we can delete the Database which is in RDS, using terraform only. using the following command:

→ The resources created by Ansible can be deleted manually or using same file but we can edit the file and change state to absent, and run the Playbook again.

I have created a Video on how it works !!!

I have learned of these tools, under the mentorship of Mr. Vimal Daga Sir under Arth Training and Hybrid Multi Cloud Training.

I hope this article is Informative and Explanatory. Hope you like it !!!

Please give some claps, if you liked this article !!!

For any suggestions or if any reader find any flaw in this article, please email me to “”

Thank You Readers, for viewing this !!!



Akhilesh Jain

I am a student and persuing under graduation in computer science and engineering.