DEV Community

horlartundhey
horlartundhey

Posted on Edited on

DevOps Week 04: From Git Commits to a Live EC2 Server: Deploying CodeTrack with Nginx

From Git Commits to a Live EC2 Server: Deploying CodeTrack with Nginx

Introduction

One of the most important lessons I am learning in my DevOps journey is that writing code is only one part of building software.

A project also needs to be tracked, versioned, transferred, deployed, served, and verified.

For this project, I worked on CodeTrack, a static website that I first managed locally with Git and then deployed to a live AWS EC2 instance running Ubuntu and Nginx.

The goal was to simulate a basic real-world deployment workflow:

Local Development
        ↓
Git Tracking
        ↓
Git Staging
        ↓
Meaningful Commits
        ↓
Secure File Transfer
        ↓
AWS EC2
        ↓
Nginx
        ↓
Live Website
        ↓
Deployment Verification
Enter fullscreen mode Exit fullscreen mode

This exercise helped me connect concepts that I had previously learned separately: Git, Linux, AWS EC2, SSH, SCP, Nginx, HTTP, and basic deployment validation.


What I Built

The project was a static website called CodeTrack.

The deployment workflow involved:

  • Creating and managing the project files locally
  • Tracking the files with Git
  • Staging files intentionally
  • Creating a clean initial commit
  • Making a controlled homepage update
  • Creating a second meaningful commit
  • Transferring the project to an AWS EC2 instance using SCP
  • Serving the website using Nginx
  • Validating the deployment using curl
  • Confirming the application was accessible through the EC2 public IP

The assignment was designed to connect local version-control practices with a basic manual deployment workflow used in DevOps environments.


Part 1: Verifying the Git Repository

Before making any changes, I first verified that Git was installed and that I was working inside the correct project directory.

git --version
Enter fullscreen mode Exit fullscreen mode

This confirmed that Git was available on the system.

I then navigated into the CodeTrack project directory and checked the repository status:

git status
Enter fullscreen mode Exit fullscreen mode

This step is simple, but important.

Running commands in the wrong directory is a common mistake when working with Git. Before modifying files or creating commits, it is important to know exactly where you are and whether the directory is actually a Git repository.

The git status command provides information about:

  • The current branch
  • Untracked files
  • Modified files
  • Staged files
  • Changes waiting to be committed

This gave me a clear starting point before making any changes.


Part 2: Creating the Starter Files

The project required two basic files:

index.html
style.css
Enter fullscreen mode Exit fullscreen mode

I created them using:

touch index.html style.css
Enter fullscreen mode Exit fullscreen mode

Then I confirmed that they existed:

ls
Enter fullscreen mode Exit fullscreen mode

At this point, the project had its basic structure, but the files still needed their actual HTML and CSS content.

I then populated the files with the provided starter content.

This represents a common development workflow: first creating the basic project structure, then adding the implementation.


Part 3: Understanding Git Tracking and Staging

After creating the files, I checked the repository status again:

git status
Enter fullscreen mode Exit fullscreen mode

Because the files had not yet been added to Git, they appeared as untracked files.

This distinction is important.

A file can exist in the project directory without being tracked by Git.

The basic Git workflow looks like this:

Working Directory
        ↓
git add
        ↓
Staging Area
        ↓
git commit
        ↓
Repository History
Enter fullscreen mode Exit fullscreen mode

I staged the files:

git add index.html
git add style.css
Enter fullscreen mode Exit fullscreen mode

Then I checked the status again:

git status
Enter fullscreen mode Exit fullscreen mode

The files were now listed under:

Changes to be committed
Enter fullscreen mode Exit fullscreen mode

This confirmed that Git was ready to include them in the next commit.

One thing I learned from this process is that staging provides control over what goes into a commit. Instead of automatically committing every change in the project, I can deliberately choose which files should be included.


Part 4: Creating the First Commit

Once the files were staged, I created the initial commit:

git commit -m "Initial UI scaffold: add index.html and style.css"
Enter fullscreen mode Exit fullscreen mode

This created the first snapshot of the project.

A commit is essentially a saved point in the project's history.

The first commit represented the initial UI scaffold:

Initial UI Scaffold
├── index.html
└── style.css
Enter fullscreen mode Exit fullscreen mode

I then verified the commit history:

git log --oneline
Enter fullscreen mode Exit fullscreen mode

The purpose of using a meaningful commit message is to make the project history easier to understand.

Instead of seeing a history full of vague messages such as:

update
changes
fix
new
Enter fullscreen mode Exit fullscreen mode

a message like:

Initial UI scaffold: add index.html and style.css
Enter fullscreen mode Exit fullscreen mode

immediately explains what changed.

Good commit messages become a useful work log for developers and teams.


Part 5: Making a Controlled Change

After creating the initial commit, I made a controlled update to the homepage.

The changes included updating the homepage content, including the student information and group details required by the assignment.

After modifying index.html, I checked the repository status:

git status
Enter fullscreen mode Exit fullscreen mode

Git detected that the file had been modified.

This is different from the earlier untracked-file situation.

Previously:

index.html
Enter fullscreen mode Exit fullscreen mode

was a file Git had never seen before.

Now, Git already knew about the file because it had been included in the first commit.

Therefore, Git could compare the current version with the version stored in the repository and detect the changes.

I then staged only the modified file:

git add index.html
Enter fullscreen mode Exit fullscreen mode

After confirming the staging area, I created a second commit:

git commit -m "Update homepage content: heading, tagline, CTA button"
Enter fullscreen mode Exit fullscreen mode

I then checked the commit history again:

git log --oneline
Enter fullscreen mode Exit fullscreen mode

The history now contained two separate commits:

Update homepage content: heading, tagline, CTA button

Initial UI scaffold: add index.html and style.css
Enter fullscreen mode Exit fullscreen mode

This separation is useful because the project history now clearly shows two different stages of development:

  1. The initial UI was created.
  2. The homepage content was later updated.

If the second change introduced a problem, it could be reviewed or reverted separately from the original project scaffold.

This is one of the practical benefits of maintaining meaningful commits.


Part 6: Preparing the AWS EC2 Server

After completing the local Git workflow, the next step was to deploy the website to a live server.

The deployment target was an AWS EC2 instance running Ubuntu.

Before deploying, the server needed to have:

  • A running EC2 instance
  • SSH access
  • HTTP access through port 80
  • Nginx installed and running

The basic deployment architecture looked like this:

Browser
   │
   │ HTTP Request
   ▼
EC2 Public IP
   │
   ▼
Nginx
   │
   ▼
/var/www/html
   │
   ├── index.html
   └── style.css
Enter fullscreen mode Exit fullscreen mode

The EC2 Security Group needed to allow:

  • SSH traffic on port 22 from the appropriate IP address
  • HTTP traffic on port 80 for testing the website

This is an important security consideration.

SSH is necessary for server administration, but it should not be exposed more broadly than necessary.

HTTP, on the other hand, needs to be accessible to users who want to visit the website.


Part 7: Verifying Nginx

Before deploying the CodeTrack files, I verified the state of Nginx.

sudo systemctl status nginx --no-pager
Enter fullscreen mode Exit fullscreen mode

The expected result was:

Active: active (running)
Enter fullscreen mode Exit fullscreen mode

This confirmed that the Nginx service was running.

I also validated the Nginx configuration:

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

A successful result looked like:

nginx: configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Enter fullscreen mode Exit fullscreen mode

This is an important habit when working with Nginx.

Before restarting or reloading the service after configuration changes, it is safer to validate the configuration first.

A configuration error can cause Nginx to fail to restart.

If Nginx fails to restart in production, the website may become unavailable because Nginx is responsible for serving the HTTP traffic.

A basic recovery process would be:

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

Then, if there is a problem:

systemctl status nginx --no-pager
Enter fullscreen mode Exit fullscreen mode

And:

sudo journalctl -u nginx --no-pager -n 50
Enter fullscreen mode Exit fullscreen mode

These commands help identify the cause of the failure.

If a recent configuration change caused the issue, the basic rollback plan would be to restore the last known-good configuration, validate it again, and restart Nginx.


Part 8: Transferring the Website to EC2 with SCP

The CodeTrack files existed locally, but Nginx could only serve files that existed on the EC2 server.

To transfer the files, I used SCP.

SCP stands for Secure Copy Protocol.

It allows files to be transferred between computers over an SSH connection.

The basic idea was:

Local Computer
      │
      │ SCP over SSH
      ▼
AWS EC2 Instance
Enter fullscreen mode Exit fullscreen mode

The files were transferred to the server using a command similar to:

scp -i "your-key.pem" -r CodeTrack ubuntu@<EC2_PUBLIC_IP>:~/CodeTrack
Enter fullscreen mode Exit fullscreen mode

The important parts of this command are:

scp
Enter fullscreen mode Exit fullscreen mode

The secure copy command.

-i "your-key.pem"
Enter fullscreen mode Exit fullscreen mode

Specifies the SSH private key used for authentication.

-r
Enter fullscreen mode Exit fullscreen mode

Means recursive, which is required when copying a directory and its contents.

CodeTrack
Enter fullscreen mode Exit fullscreen mode

The local project directory.

ubuntu@<EC2_PUBLIC_IP>
Enter fullscreen mode Exit fullscreen mode

The remote server username and address.

The files were then transferred to the EC2 instance.

This was an important distinction for me:

Having a project committed to Git does not automatically make it available on a server.

The files still need to be transferred or retrieved by the deployment system.

In a manual deployment, SCP can be used.

In a more advanced CI/CD workflow, a pipeline could automatically build and deploy the application after changes are pushed to a repository.


Part 9: Performing a Pre-Deployment Check

Before replacing the existing content in the Nginx web root, I checked the current state of the server.

The Nginx web root was:

/var/www/html
Enter fullscreen mode Exit fullscreen mode

I checked the current Nginx status:

sudo systemctl status nginx --no-pager
Enter fullscreen mode Exit fullscreen mode

I validated the configuration:

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

I inspected the existing web root:

ls -la /var/www/html/
Enter fullscreen mode Exit fullscreen mode

And tested the current HTTP response:

curl -I http://localhost
Enter fullscreen mode Exit fullscreen mode

The expected response included:

HTTP/1.1 200 OK
Enter fullscreen mode Exit fullscreen mode

This pre-deployment check created a known baseline.

Before making a change, I knew:

  • Nginx was running
  • The configuration was valid
  • The web root contained existing files
  • The server was responding to HTTP requests

This is a useful operational habit.

Before making a potentially destructive change, understand the current state of the system first.


Part 10: Deploying CodeTrack to the Nginx Web Root

The files needed to be placed inside the directory Nginx was configured to serve.

The target directory was:

/var/www/html
Enter fullscreen mode Exit fullscreen mode

The old content was removed:

sudo rm -rf /var/www/html/*
Enter fullscreen mode Exit fullscreen mode

The CodeTrack files were copied into the web root:

sudo cp -r ~/CodeTrack/* /var/www/html/
Enter fullscreen mode Exit fullscreen mode

Permissions and ownership were then applied:

sudo chown -R www-data:www-data /var/www/html
Enter fullscreen mode Exit fullscreen mode

And:

sudo chmod -R 755 /var/www/html
Enter fullscreen mode Exit fullscreen mode

After the deployment, I validated the Nginx configuration again:

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

Then restarted Nginx:

sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

Finally, I confirmed that the expected files existed:

ls /var/www/html/
Enter fullscreen mode Exit fullscreen mode

The directory contained:

index.html
style.css
Enter fullscreen mode Exit fullscreen mode

At this point, the CodeTrack files had been placed in the location Nginx was serving.


Part 11: Verifying the Deployment with curl

A deployment should not be considered complete simply because the files were copied successfully.

The application needs to be tested.

I used:

curl -I http://localhost
Enter fullscreen mode Exit fullscreen mode

The expected response was:

HTTP/1.1 200 OK
Enter fullscreen mode Exit fullscreen mode

This confirmed that:

  1. The request reached the server.
  2. Nginx was running.
  3. Nginx was able to serve the deployed content.
  4. The server returned a successful HTTP response.

This is a simple but valuable deployment check.

It verifies the server from inside the machine before relying only on a browser.

The final step was opening the EC2 public IP in a browser and confirming that the CodeTrack application was accessible externally.


Understanding the Complete Deployment Flow

The complete workflow looked like this:

┌──────────────────────────┐
│ Local CodeTrack Project  │
└────────────┬─────────────┘
             │
             ▼
       git status
             │
             ▼
       git add
             │
             ▼
       git commit
             │
             ▼
      Controlled Changes
             │
             ▼
        Second Commit
             │
             ▼
          SCP Transfer
             │
             ▼
┌──────────────────────────┐
│      AWS EC2 Server      │
│         Ubuntu           │
└────────────┬─────────────┘
             │
             ▼
          Nginx
             │
             ▼
     /var/www/html
             │
             ▼
       CodeTrack Website
             │
             ▼
        HTTP 200 OK
             │
             ▼
        Browser Access
Enter fullscreen mode Exit fullscreen mode

This workflow demonstrated how multiple tools work together:

Tool Purpose
Git Track changes and maintain project history
Git Commit Save meaningful project snapshots
SSH Securely connect to the EC2 server
SCP Transfer files securely
AWS EC2 Provide the virtual server
Ubuntu Operating system for the server
Nginx Serve the website
curl Test HTTP responses
Browser Verify the application externally

What I Learned

This project helped me understand several important concepts more practically.

1. Git is more than just saving code

Git provides a history of how a project changes over time.

Creating separate commits for separate changes makes it easier to:

  • Review changes
  • Understand project history
  • Troubleshoot issues
  • Roll back changes

2. Staging provides control

The staging area acts as a checkpoint between the working directory and the commit.

The workflow is:

Make Changes
     ↓
Review Changes
     ↓
Stage Selected Files
     ↓
Commit
Enter fullscreen mode Exit fullscreen mode

This prevents unrelated changes from accidentally being included in the same commit.


3. Deployment requires verification

Copying files to a server is not enough.

A proper deployment should verify:

  • The service is running
  • The configuration is valid
  • The files exist in the correct location
  • The server returns the expected HTTP response
  • The application is accessible from the browser

4. Nginx is the bridge between the server and the browser

The browser does not directly open the index.html file from my local computer.

Instead, the request follows a path:

Browser
   ↓
EC2 Public IP
   ↓
Nginx
   ↓
/var/www/html/index.html
   ↓
HTTP Response
   ↓
Browser
Enter fullscreen mode Exit fullscreen mode

Understanding this request flow makes troubleshooting much easier.


5. Manual deployment helps explain CI/CD

Although this was a manual deployment, the underlying process is similar to what automated pipelines do:

Code Change
    ↓
Version Control
    ↓
Build
    ↓
Transfer
    ↓
Deploy
    ↓
Restart/Reload
    ↓
Verify
Enter fullscreen mode Exit fullscreen mode

A CI/CD pipeline automates many of these steps, but understanding the manual process first makes the automation easier to understand.


Final Thoughts

This CodeTrack project was more than simply putting a static website online.

It helped me connect several foundational DevOps concepts into one practical workflow.

I started with a local project, tracked it with Git, created meaningful commits, transferred the files securely to AWS, deployed them to an Ubuntu server, configured the web server, and verified the result using HTTP testing.

The biggest lesson for me was the importance of verification.

A deployment is not complete simply because a command ran successfully.

You need evidence.

Nginx is active
        +
Configuration is valid
        +
Files exist in the web root
        +
curl returns HTTP 200
        +
The browser loads the application
Enter fullscreen mode Exit fullscreen mode

Together, these checks provide much stronger confidence that the deployment is actually working.

This project is another step in my journey toward becoming a stronger Software Engineer with deeper skills in Linux, AWS, Git, Nginx, Cloud Engineering, and DevOps.


Acknowledgements

You can follow my graded progress throughout the cohort.

This project is part of the DevOps Micro Internship with Agentic AI Cohort 3.


Technologies Used

  • Git
  • AWS EC2
  • Ubuntu
  • Nginx
  • SSH
  • SCP
  • HTML
  • CSS
  • curl

DevOps #Linux #Git #AWS #EC2 #Nginx #CloudEngineering #SoftwareEngineering #Deployment #LearningInPublic

Top comments (0)