<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kingsley Erhatiemwonmon</title>
    <description>The latest articles on DEV Community by Kingsley Erhatiemwonmon (@kingsley-solution).</description>
    <link>https://dev.to/kingsley-solution</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4072855%2F5dce46af-671c-4ff8-9033-9be22277b8e4.jpg</url>
      <title>DEV Community: Kingsley Erhatiemwonmon</title>
      <link>https://dev.to/kingsley-solution</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kingsley-solution"/>
    <language>en</language>
    <item>
      <title>Building an Automated AWS Deployment Pipeline with Terraform and Bash</title>
      <dc:creator>Kingsley Erhatiemwonmon</dc:creator>
      <pubDate>Tue, 11 Aug 2026 10:46:42 +0000</pubDate>
      <link>https://dev.to/kingsley-solution/building-an-automated-aws-deployment-pipeline-with-terraform-and-bash-92m</link>
      <guid>https://dev.to/kingsley-solution/building-an-automated-aws-deployment-pipeline-with-terraform-and-bash-92m</guid>
      <description>&lt;p&gt;I recently completed a hands-on Cloud and DevOps project that combined AWS, Terraform, Bash, Linux, Git, and Nginx to automate the deployment of a web application.&lt;/p&gt;

&lt;p&gt;The objective was to build a repeatable workflow that could provision the required AWS infrastructure, configure an Ubuntu server, deploy an application from GitHub, and verify that the web server was running successfully.&lt;/p&gt;

&lt;p&gt;The result was a complete automated deployment workflow:&lt;/p&gt;

&lt;p&gt;Terraform provisions the infrastructure. Bash configures the server. Git provides the application source. Nginx serves the website. Health checks verify the deployment.&lt;/p&gt;

&lt;p&gt;By the end of the project, I had successfully:&lt;/p&gt;

&lt;p&gt;Provisioned a complete AWS network using Terraform&lt;/p&gt;

&lt;p&gt;Created a VPC and public subnet&lt;/p&gt;

&lt;p&gt;Created and configured an Internet Gateway&lt;/p&gt;

&lt;p&gt;Created a route table and route table association&lt;/p&gt;

&lt;p&gt;Configured a security group for SSH and HTTP access&lt;/p&gt;

&lt;p&gt;Dynamically selected an Ubuntu 24.04 AMI&lt;/p&gt;

&lt;p&gt;Launched an Ubuntu EC2 instance using the existing react-key key pair&lt;/p&gt;

&lt;p&gt;Used Terraform's templatefile() function to pass a Bash bootstrap script to the EC2 instance&lt;/p&gt;

&lt;p&gt;Automatically installed Git and Nginx&lt;/p&gt;

&lt;p&gt;Cloned a public GitHub repository&lt;/p&gt;

&lt;p&gt;Deployed the application to /var/www/html&lt;/p&gt;

&lt;p&gt;Configured ownership and file permissions&lt;/p&gt;

&lt;p&gt;Enabled and started Nginx&lt;/p&gt;

&lt;p&gt;Performed automated service and HTTP health checks&lt;/p&gt;

&lt;p&gt;Added useful Terraform outputs for the deployment&lt;/p&gt;

&lt;p&gt;Successfully deployed a live website on AWS&lt;/p&gt;

&lt;p&gt;This project gave me practical experience building an automated workflow from cloud infrastructure provisioning to application delivery.&lt;/p&gt;

&lt;p&gt;Project Structure&lt;br&gt;
The project was organised with a clear separation between infrastructure code, server automation, and application files:&lt;/p&gt;

&lt;p&gt;terraform-bash-automation/&lt;br&gt;
│&lt;br&gt;
├── .gitignore&lt;br&gt;
├── .terraform.lock.hcl&lt;br&gt;
├── README.md&lt;br&gt;
├── main.tf&lt;br&gt;
├── outputs.tf&lt;br&gt;
├── providers.tf&lt;br&gt;
├── variables.tf&lt;br&gt;
│&lt;br&gt;
├── app/&lt;br&gt;
│   ├── index.html&lt;br&gt;
│   └── style.css&lt;br&gt;
│&lt;br&gt;
└── scripts/&lt;br&gt;
    └── bootstrap.sh&lt;/p&gt;

&lt;p&gt;main.tf&lt;br&gt;
Contains the AWS infrastructure resources, including:&lt;/p&gt;

&lt;p&gt;VPC&lt;/p&gt;

&lt;p&gt;Public subnet&lt;/p&gt;

&lt;p&gt;Internet Gateway&lt;/p&gt;

&lt;p&gt;Route table&lt;/p&gt;

&lt;p&gt;Route table association&lt;/p&gt;

&lt;p&gt;Security group&lt;/p&gt;

&lt;p&gt;EC2 instance&lt;/p&gt;

&lt;p&gt;variables.tf&lt;br&gt;
Defines reusable input variables such as:&lt;/p&gt;

&lt;p&gt;AWS region&lt;/p&gt;

&lt;p&gt;Instance type&lt;/p&gt;

&lt;p&gt;Key pair name&lt;/p&gt;

&lt;p&gt;SSH CIDR&lt;/p&gt;

&lt;p&gt;Application repository URL&lt;/p&gt;

&lt;p&gt;outputs.tf&lt;br&gt;
Exposes useful information after deployment, including:&lt;/p&gt;

&lt;p&gt;EC2 instance ID&lt;/p&gt;

&lt;p&gt;Public IP address&lt;/p&gt;

&lt;p&gt;VPC ID&lt;/p&gt;

&lt;p&gt;Subnet ID&lt;/p&gt;

&lt;p&gt;Website URL&lt;/p&gt;

&lt;p&gt;scripts/bootstrap.sh&lt;br&gt;
Contains the Bash automation responsible for configuring the Ubuntu server and deploying the application.&lt;/p&gt;

&lt;p&gt;app/&lt;br&gt;
Contains the web application files used by the project.&lt;/p&gt;

&lt;p&gt;This structure kept the infrastructure, server configuration, and application files logically organised.&lt;/p&gt;

&lt;p&gt;The Architecture&lt;br&gt;
The project followed a clear division of responsibilities.&lt;/p&gt;

&lt;p&gt;Terraform: Infrastructure Provisioning&lt;br&gt;
Terraform was responsible for creating the AWS environment:&lt;/p&gt;

&lt;p&gt;Terraform&lt;br&gt;
    │&lt;br&gt;
    ├── VPC&lt;br&gt;
    ├── Public Subnet&lt;br&gt;
    ├── Internet Gateway&lt;br&gt;
    ├── Route Table&lt;br&gt;
    ├── Route Table Association&lt;br&gt;
    ├── Security Group&lt;br&gt;
    └── EC2 Instance&lt;/p&gt;

&lt;p&gt;Bash: Server Configuration and Deployment&lt;br&gt;
Once the EC2 instance launched, the Bash bootstrap script configured the server:&lt;/p&gt;

&lt;p&gt;EC2 Instance&lt;br&gt;
      │&lt;br&gt;
      ▼&lt;br&gt;
bootstrap.sh&lt;br&gt;
      │&lt;br&gt;
      ├── Update Ubuntu&lt;br&gt;
      ├── Install Git&lt;br&gt;
      ├── Install Nginx&lt;br&gt;
      ├── Clone Application Repository&lt;br&gt;
      ├── Deploy Application Files&lt;br&gt;
      ├── Configure Permissions&lt;br&gt;
      ├── Start Nginx&lt;br&gt;
      └── Run Health Checks&lt;/p&gt;

&lt;p&gt;The complete deployment flow was:&lt;/p&gt;

&lt;p&gt;Terraform&lt;br&gt;
    │&lt;br&gt;
    ▼&lt;br&gt;
AWS Infrastructure&lt;br&gt;
    │&lt;br&gt;
    ▼&lt;br&gt;
Ubuntu EC2 Instance&lt;br&gt;
    │&lt;br&gt;
    ▼&lt;br&gt;
Bash Bootstrap Script&lt;br&gt;
    │&lt;br&gt;
    ├── Git&lt;br&gt;
    ├── Nginx&lt;br&gt;
    ├── Application Deployment&lt;br&gt;
    └── Health Checks&lt;br&gt;
            │&lt;br&gt;
            ▼&lt;br&gt;
       Live Website&lt;/p&gt;

&lt;p&gt;Terraform answered:&lt;/p&gt;

&lt;p&gt;Where should the application run?&lt;/p&gt;

&lt;p&gt;Bash answered:&lt;/p&gt;

&lt;p&gt;How should the server become ready to run it?&lt;/p&gt;

&lt;p&gt;Provisioning the AWS Infrastructure&lt;br&gt;
The first major achievement was provisioning the required AWS infrastructure entirely through Terraform.&lt;/p&gt;

&lt;p&gt;The VPC used the CIDR block:&lt;/p&gt;

&lt;p&gt;10.0.0.0/16&lt;/p&gt;

&lt;p&gt;Inside the VPC, I created a public subnet:&lt;/p&gt;

&lt;p&gt;10.0.1.0/24&lt;/p&gt;

&lt;p&gt;The subnet was configured to automatically assign public IP addresses to instances launched within it.&lt;/p&gt;

&lt;p&gt;I also created an Internet Gateway and a route table with a default route:&lt;/p&gt;

&lt;p&gt;0.0.0.0/0 → Internet Gateway&lt;/p&gt;

&lt;p&gt;The route table was associated with the public subnet, creating the network path required for the EC2 instance to communicate with the internet.&lt;/p&gt;

&lt;p&gt;The resulting infrastructure was:&lt;/p&gt;

&lt;p&gt;Instead of manually creating these resources through the AWS Console, the infrastructure was defined as code and provisioned through Terraform.&lt;/p&gt;

&lt;p&gt;This made the environment repeatable and easier to manage.&lt;/p&gt;

&lt;p&gt;Configuring Network Access&lt;br&gt;
I created a security group for the web server.&lt;/p&gt;

&lt;p&gt;The security group allowed:&lt;/p&gt;

&lt;p&gt;SSH  → Port 22&lt;br&gt;
HTTP → Port 80&lt;/p&gt;

&lt;p&gt;HTTP access was required so that users could access the website through the EC2 instance's public IP address.&lt;/p&gt;

&lt;p&gt;SSH access was required for administrative access to the server.&lt;/p&gt;

&lt;p&gt;For a production environment, SSH access should be restricted to trusted IP addresses or replaced with a more secure access method such as AWS Systems Manager Session Manager.&lt;/p&gt;

&lt;p&gt;This project reinforced an important principle:&lt;/p&gt;

&lt;p&gt;Infrastructure automation must consider both functionality and security.&lt;/p&gt;

&lt;p&gt;Dynamically Selecting the Ubuntu AMI&lt;br&gt;
Rather than hardcoding an AMI ID, I configured Terraform to dynamically find the latest matching Ubuntu 24.04 AMI.&lt;/p&gt;

&lt;p&gt;This reduced dependence on a specific AMI ID and made the configuration more flexible.&lt;/p&gt;

&lt;p&gt;The EC2 instance was configured with:&lt;/p&gt;

&lt;p&gt;Operating System: Ubuntu 24.04&lt;br&gt;
Instance Type: t2.micro&lt;br&gt;
Key Pair: react-key&lt;br&gt;
Region: us-east-1&lt;/p&gt;

&lt;p&gt;Terraform then used the selected AMI when launching the instance.&lt;/p&gt;

&lt;p&gt;Connecting Terraform to Bash&lt;br&gt;
One of the most important parts of the project was connecting infrastructure provisioning with server configuration.&lt;/p&gt;

&lt;p&gt;I used Terraform's templatefile() function to pass the Bash bootstrap script to the EC2 instance:&lt;/p&gt;

&lt;p&gt;user_data = templatefile("${path.module}/scripts/bootstrap.sh", {&lt;br&gt;
  app_repo_url = var.app_repo_url&lt;br&gt;
})&lt;/p&gt;

&lt;p&gt;This created the following workflow:&lt;/p&gt;

&lt;p&gt;Terraform creates EC2&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
EC2 starts Ubuntu&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
User data executes&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
bootstrap.sh runs&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
Server becomes application-ready&lt;/p&gt;

&lt;p&gt;This meant the server could be automatically configured immediately after it was provisioned.&lt;/p&gt;

&lt;p&gt;No manual package installation or repetitive server setup was required.&lt;/p&gt;

&lt;p&gt;Automating Ubuntu Configuration with Bash&lt;br&gt;
The Bash script began with:&lt;/p&gt;

&lt;h1&gt;
  
  
  !/bin/bash
&lt;/h1&gt;

&lt;p&gt;set -euo pipefail&lt;/p&gt;

&lt;p&gt;This provided stronger error handling:&lt;/p&gt;

&lt;p&gt;-e stops execution when a command fails.&lt;/p&gt;

&lt;p&gt;-u treats undefined variables as errors.&lt;/p&gt;

&lt;p&gt;pipefail ensures failures inside pipelines are not silently ignored.&lt;/p&gt;

&lt;p&gt;The script also logged its output to:&lt;/p&gt;

&lt;p&gt;/var/log/bootstrap.log&lt;/p&gt;

&lt;p&gt;This provided a useful record of the bootstrap process for troubleshooting.&lt;/p&gt;

&lt;p&gt;The script then updated the Ubuntu system:&lt;/p&gt;

&lt;p&gt;apt-get update&lt;/p&gt;

&lt;p&gt;DEBIAN_FRONTEND=noninteractive apt-get upgrade -y&lt;/p&gt;

&lt;p&gt;It installed the required software:&lt;/p&gt;

&lt;p&gt;apt-get install -y git nginx&lt;/p&gt;

&lt;p&gt;This eliminated the need to manually connect to the server and install packages one by one.&lt;/p&gt;

&lt;p&gt;Automatically Deploying the Application&lt;br&gt;
The application source code was hosted in a public GitHub repository.&lt;/p&gt;

&lt;p&gt;The Bash script cloned the repository:&lt;/p&gt;

&lt;p&gt;git clone "$APP_REPO_URL" "$APP_DIR"&lt;/p&gt;

&lt;p&gt;The application was cloned into:&lt;/p&gt;

&lt;p&gt;/opt/mediplus&lt;/p&gt;

&lt;p&gt;The application files were then deployed to the Nginx web root:&lt;/p&gt;

&lt;p&gt;/var/www/html&lt;/p&gt;

&lt;p&gt;The deployment flow was:&lt;/p&gt;

&lt;p&gt;GitHub Repository&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
    git clone&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
  /opt/mediplus&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
  Copy application files&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
  /var/www/html&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
      Nginx&lt;/p&gt;

&lt;p&gt;This automated the process of retrieving and deploying the application.&lt;/p&gt;

&lt;p&gt;Configuring Ownership and Permissions&lt;br&gt;
After deploying the files, the script configured ownership:&lt;/p&gt;

&lt;p&gt;chown -R www-data:www-data "$WEB_ROOT"&lt;/p&gt;

&lt;p&gt;It then applied separate permissions to directories and files:&lt;/p&gt;

&lt;p&gt;find "$WEB_ROOT" -type d -exec chmod 755 {} \;&lt;br&gt;
find "$WEB_ROOT" -type f -exec chmod 644 {} \;&lt;/p&gt;

&lt;p&gt;This created a consistent permission structure for the deployed website.&lt;/p&gt;

&lt;p&gt;The deployment process therefore did more than simply copy files to the web root. It also configured the files with appropriate ownership and permissions for the Nginx web server.&lt;/p&gt;

&lt;p&gt;Starting Nginx and Verifying the Deployment&lt;br&gt;
The script enabled Nginx to start automatically:&lt;/p&gt;

&lt;p&gt;systemctl enable nginx&lt;/p&gt;

&lt;p&gt;It then restarted the service:&lt;/p&gt;

&lt;p&gt;systemctl restart nginx&lt;/p&gt;

&lt;p&gt;The deployment also included automated health checks.&lt;/p&gt;

&lt;p&gt;First, the script verified that Nginx was running:&lt;/p&gt;

&lt;p&gt;systemctl is-active --quiet nginx&lt;/p&gt;

&lt;p&gt;It then tested the local HTTP endpoint:&lt;/p&gt;

&lt;p&gt;curl --fail --silent --show-error &lt;a href="http://localhost" rel="noopener noreferrer"&gt;http://localhost&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was an important part of the automation.&lt;/p&gt;

&lt;p&gt;The script did not simply install Nginx and assume the deployment was successful.&lt;/p&gt;

&lt;p&gt;It verified that the service was active and responding.&lt;/p&gt;

&lt;p&gt;Automation should verify the result of the work it performs.&lt;/p&gt;

&lt;p&gt;Validating the Terraform Configuration&lt;br&gt;
Before applying the infrastructure, I followed the Terraform workflow:&lt;/p&gt;

&lt;p&gt;terraform fmt&lt;/p&gt;

&lt;p&gt;This formatted the Terraform configuration.&lt;/p&gt;

&lt;p&gt;I then validated the configuration:&lt;/p&gt;

&lt;p&gt;terraform validate&lt;/p&gt;

&lt;p&gt;Terraform returned:&lt;/p&gt;

&lt;p&gt;Success! The configuration is valid.&lt;/p&gt;

&lt;p&gt;Next, I reviewed the execution plan:&lt;/p&gt;

&lt;p&gt;terraform plan&lt;/p&gt;

&lt;p&gt;The plan showed:&lt;/p&gt;

&lt;p&gt;Plan: 7 to add, 0 to change, 0 to destroy.&lt;/p&gt;

&lt;p&gt;The seven resources were:&lt;/p&gt;

&lt;p&gt;VPC&lt;/p&gt;

&lt;p&gt;Public subnet&lt;/p&gt;

&lt;p&gt;Internet Gateway&lt;/p&gt;

&lt;p&gt;Route table&lt;/p&gt;

&lt;p&gt;Route table association&lt;/p&gt;

&lt;p&gt;Security group&lt;/p&gt;

&lt;p&gt;EC2 instance&lt;/p&gt;

&lt;p&gt;This allowed me to review the proposed infrastructure before applying the changes.&lt;/p&gt;

&lt;p&gt;Successfully Provisioning the Infrastructure&lt;br&gt;
After reviewing the plan, I ran:&lt;/p&gt;

&lt;p&gt;terraform apply&lt;/p&gt;

&lt;p&gt;Terraform successfully created the AWS infrastructure:&lt;/p&gt;

&lt;p&gt;Apply complete! Resources: 7 added, 0 changed, 0 destroyed.&lt;/p&gt;

&lt;p&gt;At this point, the infrastructure provisioning phase was complete.&lt;/p&gt;

&lt;p&gt;Terraform had successfully created the environment required to host the application.&lt;/p&gt;

&lt;p&gt;The EC2 instance was then automatically configured through the Bash bootstrap process.&lt;/p&gt;

&lt;p&gt;Adding Useful Terraform Outputs&lt;br&gt;
I added Terraform outputs to make important deployment information easier to retrieve.&lt;/p&gt;

&lt;p&gt;Running:&lt;/p&gt;

&lt;p&gt;terraform output&lt;/p&gt;

&lt;p&gt;returned:&lt;/p&gt;

&lt;p&gt;instance_id        = "i-033bb416c07a6ce37"&lt;br&gt;
instance_public_ip = "3.90.108.152"&lt;br&gt;
subnet_id          = "subnet-0c7c604e4595302aa"&lt;br&gt;
vpc_id             = "vpc-05ebdb39e31d9b674"&lt;br&gt;
website_url        = "&lt;a href="http://3.90.108.152" rel="noopener noreferrer"&gt;http://3.90.108.152&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;These outputs made it easy to retrieve key deployment details without manually searching through the AWS Console.&lt;/p&gt;

&lt;p&gt;This was a small but valuable improvement to the usability of the Terraform project.&lt;/p&gt;

&lt;p&gt;The Final Achievement&lt;br&gt;
The final result was a live website deployed on AWS through an automated workflow.&lt;/p&gt;

&lt;p&gt;The complete process was:&lt;/p&gt;

&lt;p&gt;Terraform&lt;br&gt;
    │&lt;br&gt;
    ▼&lt;br&gt;
Create AWS Infrastructure&lt;br&gt;
    │&lt;br&gt;
    ├── VPC&lt;br&gt;
    ├── Public Subnet&lt;br&gt;
    ├── Internet Gateway&lt;br&gt;
    ├── Route Table&lt;br&gt;
    ├── Security Group&lt;br&gt;
    └── EC2 Instance&lt;br&gt;
            │&lt;br&gt;
            ▼&lt;br&gt;
      Bash Bootstrap&lt;br&gt;
            │&lt;br&gt;
            ├── Update Ubuntu&lt;br&gt;
            ├── Install Git&lt;br&gt;
            ├── Install Nginx&lt;br&gt;
            ├── Clone GitHub Repository&lt;br&gt;
            ├── Deploy Application&lt;br&gt;
            ├── Configure Permissions&lt;br&gt;
            ├── Start Nginx&lt;br&gt;
            └── Run Health Checks&lt;br&gt;
                    │&lt;br&gt;
                    ▼&lt;br&gt;
              Live Website&lt;/p&gt;

&lt;p&gt;What I built was more than a simple EC2 deployment.&lt;/p&gt;

&lt;p&gt;I created the infrastructure required to host the application, automated the configuration of the operating system, deployed the application from GitHub, configured the web server, and verified that the service was running successfully.&lt;/p&gt;

&lt;p&gt;The result was a repeatable workflow that transformed a clean AWS environment into a working application server.&lt;/p&gt;

&lt;p&gt;Key Lessons from the Project&lt;br&gt;
Infrastructure as Code&lt;br&gt;
Terraform allowed the AWS infrastructure to be defined declaratively and provisioned consistently.&lt;/p&gt;

&lt;p&gt;Automation&lt;br&gt;
Bash eliminated repetitive manual server configuration steps.&lt;/p&gt;

&lt;p&gt;Separation of Responsibilities&lt;br&gt;
Terraform managed the infrastructure.&lt;/p&gt;

&lt;p&gt;Bash managed server configuration and application deployment.&lt;/p&gt;

&lt;p&gt;This separation made the overall workflow easier to understand and maintain.&lt;/p&gt;

&lt;p&gt;Verification&lt;br&gt;
The deployment included service and HTTP health checks instead of assuming that successful commands automatically meant a successful deployment.&lt;/p&gt;

&lt;p&gt;Security Awareness&lt;br&gt;
The deployment worked, but production environments require careful consideration of network access, especially SSH exposure.&lt;/p&gt;

&lt;p&gt;Restricting SSH access to trusted IP addresses or using a managed access solution such as AWS Systems Manager Session Manager would be more appropriate for a production environment.&lt;/p&gt;

&lt;p&gt;Final Thoughts&lt;br&gt;
This project was a practical step forward in my Cloud and DevOps journey.&lt;/p&gt;

&lt;p&gt;I combined:&lt;/p&gt;

&lt;p&gt;AWS&lt;/p&gt;

&lt;p&gt;Terraform&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Linux&lt;/p&gt;

&lt;p&gt;Git&lt;/p&gt;

&lt;p&gt;Nginx&lt;/p&gt;

&lt;p&gt;Infrastructure as Code&lt;/p&gt;

&lt;p&gt;Server automation&lt;/p&gt;

&lt;p&gt;Application deployment&lt;/p&gt;

&lt;p&gt;Health checks&lt;/p&gt;

&lt;p&gt;The most important achievement was building a repeatable process that could take a clean AWS environment and automatically transform it into a working application server.&lt;/p&gt;

&lt;p&gt;The final workflow can be summarised simply:&lt;/p&gt;

&lt;p&gt;Terraform provisions the infrastructure.&lt;/p&gt;

&lt;p&gt;Bash configures the server.&lt;/p&gt;

&lt;p&gt;Git provides the application source.&lt;/p&gt;

&lt;p&gt;Nginx serves the website.&lt;/p&gt;

&lt;p&gt;Health checks verify the deployment.&lt;/p&gt;

&lt;p&gt;This project gave me valuable hands-on experience with the complete path from cloud infrastructure to application delivery.&lt;/p&gt;

&lt;h1&gt;
  
  
  DevOps #AWS #Terraform #Bash #InfrastructureAsCode #CloudEngineering #Linux #Nginx #Git #Automation
&lt;/h1&gt;

</description>
      <category>automation</category>
      <category>aws</category>
      <category>devops</category>
      <category>terraform</category>
    </item>
  </channel>
</rss>
