Building a Scalable and Secure 3 Tier Web Infrastructure on AWS: A Step-by-Step Guide
Introduction: In today's digital landscape, establishing a robust and scalable web infrastructure is paramount for businesses to ensure the seamless delivery of online services. Amazon Web Services (AWS) offers a plethora of tools and services to facilitate the creation of such infrastructures. In this comprehensive guide, we'll walk through the detailed process of building a fully functional web hosting environment on AWS, covering everything from VPC setup to Jenkins automation. By following this detailed guide, you'll learn how to leverage AWS services to create a secure, scalable, and automated web infrastructure for hosting PHP websites.
Step 1: Setting Up the Virtual Private Cloud (VPC)
Guide: To begin, we'll set up a Virtual Private Cloud (VPC) on AWS to provide a virtual network environment for our web infrastructure.
Steps:
Navigate to the AWS Management Console and access the VPC service.
Create a New VPC:
Click on "Create VPC" and provide a name for your VPC.
Specify the CIDR block for your VPC (e.g., 10.0.0.0/16).
Choose the default tenancy option or opt for dedicated tenancy if required.
Configure Subnets:
Navigate to the "Subnets" section and click on "Create subnet".
Create two public subnets and two private subnets in different Availability Zones.
Assign appropriate CIDR blocks to each subnet (e.g., public subnets: 10.0.1.0/24, 10.0.2.0/24; private subnets: 10.0.3.0/24, 10.0.4.0/24).
Set Up Route Tables:
Navigate to the "Route Tables" section and click on "Create route table".
Create two route tables: one for public subnets and one for private subnets.
Associate the public route table with the public subnets and configure the routes to the internet gateway.
Associate the private route table with the private subnets.
Configure Internet Gateway (IGW):
Navigate to the "Internet Gateways" section and click on "Create internet gateway".
Attach the internet gateway to your VPC.
Set Up NAT Gateway (for private subnet internet access):
Navigate to the "NAT Gateways" section and click on "Create NAT gateway".
Choose the subnet associated with the NAT gateway and allocate an Elastic IP address.
Update the route table of the private subnets to route internet-bound traffic through the NAT gateway.
Step 2: Deploying the Relational Database Service (RDS)
Guide: Next, we'll provision an Amazon RDS instance to host our MySQL database for the PHP website.
Steps:
Access the RDS service in the AWS Management Console.
Launch a New RDS Instance:
Click on "Create database" and choose the MySQL engine.
Select the appropriate instance size, storage type, and allocated storage.
Configure the database instance settings, including DB instance identifier, master username, and password.
Choose the VPC and subnets where you want to deploy the RDS instance.
Configure additional settings such as database name, port, backup retention period, and monitoring options.
Review and launch the RDS instance.
Step 3: Provisioning the EC2 Instance and Creating Security Group.
Guide: Now, let's launch an EC2 instance to host our PHP website and configure it with Apache httpd server, PHP, MySQL client, and other necessary packages.
Steps:
Access the EC2 service in the AWS Management Console.
Create a New Security Group:
Click on the "Create security group" button.
Security group name: Enter a descriptive name for your security group.
Description: Optionally, provide a brief description of the security group.
VPC: Choose the appropriate VPC for your Security Group.
Define Inbound Rules: Specify the inbound traffic rules to allow access to your HasNode blog. For example:
HTTP (Port 80): Allow incoming traffic from anywhere (0.0.0.0/0) to access your blog via HTTP.
HTTPS (Port 443): Allow incoming traffic from anywhere (0.0.0.0/0) to access your blog via HTTPS.
SSH (Port 22): Allow incoming SSH traffic only from trusted IP addresses or your own IP address for administrative purposes.
MYSQL/Aurora (Port 3306):Allow incoming SSH traffic only from your instances private IP address or your own IP address for administrative purposes.
Review and Create: Review the security group configuration to ensure it meets your requirements. Then, click on the "Create security group" button to create the security group.
Launch a New EC2 Instance:
Click on "Launch Instance" and choose the Amazon Linux 2 AMI.
Select an appropriate instance type based on your workload requirements.
Configure instance details, including VPC, subnet, IAM role, and security group settings.
Add storage volumes as needed and configure additional settings.
Review and launch the instance.
Connect to the EC2 Instance:
- Once the instance is launched, connect to it via SSH using the provided key pair.
Install Apache httpd Server:
Update the package repository:
sudo yum update -y
Install Apache httpd server:
sudo yum install httpd -y
Install PHP and MySQL Client:
Install PHP and MySQL client packages:
sudo yum install php php-mysql -y
Install Git :
Install Git:
sudo yum install git -y
Set up folder for website and configure SSL certificate:
Set up folder in to store your website files:
cd /var/www/html mkdir "your_folder_name"
Create SSL certificate if you don't already have one
Configure your SSL Private and .pem Key:
Copy your SSL private key into example.com.key and .pem key in example.com.pem
cd /etc/ssl
mkdir private/
cd private/
sudo nano example.com.key
sudo nano example.com.pem
Step 4: Creating a Git Repository and Adding PHP Website Code
Guide: Before configuring Jenkins for automation, let's set up a Git repository to version control our PHP website code and add the code to the repository.
Steps :
Create a Git Repository:
If you haven't already done so, sign in to your GitHub account.
Click on the "+" icon in the upper-right corner of the GitHub interface and select "New repository."
Provide a name for your repository, optionally add a description, and choose whether to make it public or private.
Optionally, initialize the repository with a README file.
Click on the "Create repository" button.
Export SSH Key from Local PC and Add to GitHub Account:
Open a terminal on your local machine.
Check if you have an existing SSH key by running:
ls -al ~/.ssh
If you don't have an SSH key, generate one by running:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
Follow the prompts to create a new SSH key.
Once the SSH key is generated, add it to your SSH agent by running:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_rsa
Now, copy the SSH public key to your clipboard by running:
xclip -sel clip < ~/.ssh/id_rsa.pub
In your GitHub account settings, navigate to "SSH and GPG keys" and click on "New SSH key."
Paste the copied SSH public key into the "Key" field and give it a relevant title.
Click on the "Add SSH key" button to save the key to your GitHub account.
Clone the Remote Repository to Your Local Machine:
In the terminal, navigate to the directory where you want to clone the repository.
Clone the repository using the SSH URL provided by GitHub:
git clone git@github.com:your_username/your_repository.git
Replace
your_username
with your GitHub username andyour_repository
with the name of your repository.
Add PHP Website Code to the Repository:
Navigate to the directory where the repository was cloned.
Copy your PHP website code into this directory.
Stage all the files in your PHP website directory for committing by running:
git add .
Commit the staged files with a descriptive message:
git commit -m "Initial commit"
Push your code to the remote repository:
git push -u origin master
This command pushes your code to the
master
branch of the remote repository.
Now your PHP website code is safely stored in a Git repository, ready for Jenkins to automate deployment.
Step 5: Configuring Jenkins for Automation
Guide: Jenkins will enable us to automate the deployment process by continuously integrating changes made to our Git repository and deploying them to the web server.
Steps:
Install Jenkins:
SSH into your EC2 instance.
Install Java before installing Jenkins:
sudo amazon-linux-extras install java-openjdk11
Add the Jenkins repository to yum:
sudo wget -O /etc/yum.repos.d/jenkins.repo \ https://pkg.jenkins.io/redhat-stable/jenkins.repo
Import the Jenkins key:
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
Install Jenkins:
sudo yum install jenkins -y
Start and Enable Jenkins:
Start the Jenkins service:
sudo systemctl start jenkins
Enable Jenkins to start on boot:
sudo systemctl enable jenkins
Access Jenkins Web Interface:
Open a web browser and navigate to
http://your_ec2_instance_public_ip:8080
Follow the on-screen instructions to complete the Jenkins setup wizard.
Install Required Plugins:
Once Jenkins is set up, go to "Manage Jenkins" > "Manage Plugins".
Install the following plugins:
Publish Over SSH: For deploying files to the web server.
Git: For integrating with Git repositories.
Configure Jenkins Credentials:
Go to "Manage Jenkins" > "System" .
Add Jenkins URL.
Add Git credentials for accessing the Git repository.
Add SSH credentials for accessing the web server.
Create a Jenkins Job:
Click on "New Item" to create a new Jenkins job.
Choose "Freestyle project" and provide a name for your job.
Configure the job settings:
Specify the Github project URL.
Configure Repository URL.
Add credentials choose kind "SSH Username with private key", Specify Id,Username,Private key.
Specify Branch to build.
Configure the build triggers to trigger the job on Git commits and build environment.
Select server and setup transfer set.
Apply the job configuration and Save.
Add Jenkins URL in git repository Webhooks.
Go to setting of you git repository.
Select webhooks and click on Add webhook.
Under Payload URL enter your Jenkins URL and in the end of URL add
/github-webhook/
and select content type as application json.
Click on add Webhook.
Now Jenkins is configured to automate the deployment process of your PHP website.
Step 6: Configuring Apache httpd Server
Guide: Apache httpd Server will serve as the web server for hosting our PHP website. We'll configure Apache to serve the website files and set up virtual hosts.
Steps :
Update Hosts File:
Configure Virtual Hosts: Navigate to the Apache configuration directory: cd /etc/httpd/conf/. Add the following configuration to httpd.conf :
<VirtualHost *:443> ServerAdmin webmaster@example.com DocumentRoot "/var/www/html/your_website" ServerName your_domain.com # SSL/TLS Configuration SSLEngine on SSLCertificateFile /etc/ssl/private/example.com.pem SSLCertificateKeyFile /etc/ssl/private/example.com.key <Directory "/var/www/html/your_website"> AllowOverride All Require all granted </Directory> ErrorLog "logs/my_codeigniter_app_ssl_access.log" CustomLog "/var/log/httpd/your_website_access.log" combined </VirtualHost>
Replace your_domain.com with your actual domain name.
Save and exit the editor.
Restart the Apache service to apply the changes:
sudo systemctl restart httpd
Step 7: Configuring Website Code with RDS DB Endpoint
Guide: To ensure that your PHP website communicates with the RDS database, we need edit the website code files to integrate with the RDS DB endpoint.
Steps:
Edit Website Code Files with RDS DB Endpoint:
Locate the PHP files in your website codebase that interact with the database (e.g.,
config.php
,db.php
).Update the database connection parameters to use the RDS DB endpoint, including the hostname, username, password, and database name.
For example:
$hostname = 'your_rds_db_endpoint';
$username = 'your_rdb_username';
$password = 'your_rdb_password';
$database = 'your_website_db_name';
- Save the changes to the PHP files.
By configuring Apache and updating the website code with the RDS DB endpoint, your PHP website will be able to connect to the database hosted on RDS seamlessly.
Step 8: Creating an AMI Image and Launch Template of EC2 Instance
Guide: To ensure consistency and scalability, we'll create an Amazon Machine Image (AMI) of our EC2 instance and create a Launch Template using the AMI image for future instance launches.
Steps:
Creating an AMI Image:
Log in to the AWS Management Console and navigate to the EC2 service.
Select the EC2 instance you want to create an AMI from.
Right-click on the instance and choose "Image and templates" > "Create image".
Provide a name and description for your AMI.
Optionally, configure additional settings such as instance type, storage volumes, and tags.
Click on "Create image" to initiate the AMI creation process.
Wait for the AMI creation process to complete. Once done, your custom AMI will be available in the AMIs section.
Creating a Launch Template:
After the AMI creation process is complete, navigate to the EC2 service in the AWS Management Console.
Click on "Launch templates" from the navigation pane.
Click on "Create launch template" and provide a name and description for your template.
Under "AMI ID", select the custom AMI you created earlier.
Configure other settings such as instance type, network settings, storage, and security groups as per your requirements.
Optionally, add tags for better organization.
Click on "Create launch template" to save your configuration.
By creating an AMI image and a Launch Template, you can easily replicate your configured EC2 instance and launch new instances with the same settings in the future.
Step 9: Creating a Target Group and Application Load Balancer
Guide: To achieve high availability and distribute traffic across multiple instances, we'll set up an Application Load Balancer (ALB), a Target Group, and configure Cloudflare DNS records to point to the ALB.
Steps:
Creating a Target Group:
Navigate to the EC2 service in the AWS Management Console.
Click on "Target Groups" from the navigation pane.
Click on "Create target group" and provide a name and description for your target group.
Configure the target group settings, including the target type (instances), protocol, port, and health checks.
Click on "Create target group" to save your configuration.
Creating an Application Load Balancer (ALB):
Still in the EC2 service, click on "Load Balancers" from the navigation pane.
Click on "Create Load Balancer" and select "Application Load Balancer".
Configure the load balancer settings, including name, scheme, listener configuration, and availability zones.
Associate the previously created target group with the ALB.
Configure security settings and optionally add tags.
Click on "Create" to create the ALB.
By creating a Target Group and an Application Load Balancer, you'll be able to distribute incoming traffic across multiple instances for improved reliability and scalability of your web application.
Step 10: Adding Auto Scaling to Your EC2 Instances
Guide: Auto Scaling helps maintain application availability and allows you to automatically adjust the number of EC2 instances in your fleet based on demand. Here's how to set it up:
Steps:
Navigate to the EC2 service in the AWS Management Console.
Click on "Auto Scaling Groups" from the navigation pane.
Click on "Create Auto Scaling group" and follow these steps:
Choose the launch template option.
Select the launch template you created earlier.
Configure the auto scaling group details, including name, subnet, and desired capacity.
Set up scaling policies:
Define scaling policies based on metrics such as CPU utilization, network traffic, or custom CloudWatch metrics.
Configure scaling policies to add or remove instances based on thresholds.
Associate the auto scaling group with the Application Load Balancer:
In the load balancing section, select the Application Load Balancer you created earlier.
Configure health checks and other settings as necessary.
Complete the creation process.
Set up notifications (optional):
- Configure notifications to be alerted when auto scaling events occur.
Review and create the auto scaling group.
Step 11: Configuring CloudFront Distribution
Guide: CloudFront will act as a content delivery network (CDN) to cache and serve our website content globally, improving its performance and reliability.
Steps:
Create a CloudFront Distribution:
Access the CloudFront service in the AWS Management Console.
Click on "Create Distribution" > "Get Started" under the Web delivery method.
Configure the distribution settings:
Origin Domain Name: Select the origin domain name of your website (e.g., the Elastic Load Balancer hostname).
Viewer Protocol Policy: Choose "Redirect HTTP to HTTPS" for enhanced security.
Distribution Settings: Configure additional settings as per your requirements.
Click on "Create Distribution".
Note Down the CloudFront Distribution DNS Name:
- Once the CloudFront distribution is created, note down the provided CloudFront domain name (e.g.,
d1234567890.cloudfront.net
).
- Once the CloudFront distribution is created, note down the provided CloudFront domain name (e.g.,
Update DNS Records:
Once the CloudFront distribution is created, note down the provided CloudFront domain name.
Update your DNS records (e.g., in Cloudflare) to point your domain to the CloudFront distribution.
Test the website:
Wait for the CloudFront distribution to be deployed (usually takes a few minutes).
Access your website using the domain name to ensure it's serving content correctly.
By configuring CloudFront and noting down the CloudFront distribution DNS name, you're ready to update your DNS records accordingly for your domain.
Conclusion: Congratulations! You have successfully built a scalable and secure web infrastructure on AWS using services like VPC, RDS, EC2, Jenkins, Apache httpd Server, CloudFront, and more. By following this comprehensive guide, you've learned how to provision, configure, and automate the deployment of a PHP website, ensuring optimal performance and reliability for your users. Keep exploring AWS services and best practices to further enhance your web hosting environment.