End-to-End Setup: AWS + PuTTY + GitHub + Docker

How to set up connects between AWS, PuTTY, GitHub, and Docker

This document walks through the complete setup process — from a blank AWS account to a running, automatically-deploying multi-container web application. Follow the sections in order.


Overview of What We're Building

GitHub (code repository + CI/CD automation)
    ↕  push triggers workflow
GitHub Actions (automated pipeline)
    ↕  SSH deploys to server
AWS EC2 (virtual Linux server)
    ↕  Docker runs containers on the server
Docker Compose (runs 3 services: docs, database, CMS)
    ↕  images pulled from DockerHub
DockerHub (public image registry)

AWS S3 (hosts images referenced in markdown docs)

Phase 1 — AWS: Launch Your EC2 Instance

1.1 Log Into AWS Academy

  1. Go to https://awsacademy.instructure.com/login/canvas
  2. Log in with your student email
  3. Open the AWS Academy Learner Lab course
  4. Go to Modules → Launch AWS Academy Learner Lab
  5. Click Start Lab — wait for the indicator next to "AWS" to turn green
  6. Click AWS to open the AWS Management Console

1.2 Launch the EC2 Instance

  1. In the console, go to Services → Compute → EC2
  2. Click Launch Instance
  3. Configure:
Setting Value
Name Final Project
AMI Red Hat Enterprise Linux 9 — Free tier eligible
Instance Type t3.medium
Key Pair Create new (see 1.3 below)
Network/Security Group Create security group; check "Allow SSH traffic from Anywhere"
Storage 1x 10 GiB gp3
  1. Click Launch Instance
  2. Click View all instances — wait for state to change from Pending to Running

1.3 Create and Save Your Key Pair

This is done inside the launch wizard at the Key Pair step.

  1. Click Create new key pair
  2. Name: Western-Student (or any name you will remember)
  3. Key pair type: RSA
  4. Format: .ppk for Windows/PuTTY — .pem for Mac/Linux terminal
  5. Click Create key pair — the file downloads immediately
  6. Save this file. Back it up. If it is lost, you cannot access the instance.

1.4 Get Your Instance's Public Address

  1. Go to EC2 → Instances
  2. Click on your instance ID
  3. Copy the Public IPv4 DNS — it looks like: ec2-XX-XX-XX-XX.compute-1.amazonaws.com
  4. Save this — you will use it for PuTTY, GitHub Secrets, and browser access

This address resets each time the instance is stopped and restarted.


Phase 2 — PuTTY: Connect to Your Instance

PuTTY is the SSH client for Windows that lets you control your EC2 instance from a terminal on your local machine.

2.1 Install PuTTY (Windows)

  1. Go to https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
  2. Download the MSI ("Windows Installer") 64-bit x86 option
  3. Run the installer (accept all defaults)

2.2 Configure PuTTY to Connect to Your Instance

  1. Open PuTTY
  2. In Session, set Host Name to your EC2 Public IPv4 DNS from Phase 1.4
  3. In the left tree, go to Connection → Data
    • Set Auto-login username to ec2-user
  4. Go to Connection → SSH → Auth → Credentials
    • Click Browse next to "Private key file for authentication"
    • Select your .ppk key file downloaded in Phase 1.3
  5. Go to Window → Appearance
    • Click Change under Font settings
    • Set font to Consolas, size 14
  6. Navigate back to Session
    • Under Saved Sessions, type DevOps Server
    • Click Save
  7. Click Open
  8. On the first connection, a security prompt appears — click Accept
  9. You are now logged into your EC2 instance as ec2-user

2.3 Connecting on Mac/Linux (No PuTTY Required)

ssh -l ec2-user -i ~/.ssh/Western-Student ec2-XX-XX-XX-XX.compute-1.amazonaws.com

Replace the address with your actual Public IPv4 DNS. On first connection, type yes to accept the host key.

2.4 Update Your Instance (Do This First Every Session)

Once connected via PuTTY or SSH, immediately run:

sudo dnf -y update

This applies all security and software updates. Run this after every fresh launch.


Phase 3 — Instance Software Setup (via PuTTY/SSH Terminal)

All commands in this phase are run inside the terminal connected to your EC2 instance — not on your local machine.

3.1 Install Docker

# Add the Docker repository
sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo

# Install Docker and dependencies
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Start Docker and enable it on boot
sudo systemctl start docker
sudo systemctl enable docker

# Add ec2-user to the docker group (avoids needing sudo for docker commands)
sudo usermod -aG docker ec2-user

# Log out and back in for the group change to take effect
exit

Reconnect via PuTTY after the exit command.

3.2 Install Git

sudo dnf install -y git

3.3 Configure Git with Your Identity

git config --global user.name "Your Name"
git config --global user.email "your@email.com"

These values appear on every commit. Use the same email as your GitHub account.


Phase 4 — GitHub: Repository Setup

This phase happens on your local machine and in GitHub.com.

4.1 Create a GitHub Account

  1. Go to https://github.com
  2. Click Sign up and follow the prompts
  3. Verify your email address

4.2 Generate an SSH Key on Your Local Machine

In a terminal (Git Bash on Windows, Terminal on Mac/Linux):

ssh-keygen -t rsa -b 4096 -C your_email@example.com
eval "$(ssh-agent -s)"          # Start the SSH agent
ssh-add ~/.ssh/id_rsa           # Add your key to the agent
cat ~/.ssh/id_rsa.pub           # Print your public key — copy the output

4.3 Add Your SSH Key to GitHub

  1. Go to GitHub → click your profile photo → Settings
  2. Click SSH and GPG keys → New SSH key
  3. Paste the key you copied from cat ~/.ssh/id_rsa.pub
  4. Give it a name (e.g., DevOps SSH Key)
  5. Click Add SSH key

4.4 Test the SSH Connection

ssh -T git@github.com

Expected response: "Hi username! You've successfully authenticated..."

4.5 Create Your Repository on GitHub

  1. On GitHub, click the green New button
  2. Name the repository (e.g., final-project)
  3. Set visibility to Public
  4. Check Add a README file
  5. Click Create repository

4.6 Clone the Repository to Your Local Machine

  1. On your repo page, click the green Code button
  2. Copy the SSH URL
  3. In your terminal:
git clone git@github.com:yourusername/final-project.git
cd final-project

4.7 Create Your Project Files Locally

Inside the repo folder, create your markdown documentation files:

touch version-control.md
touch linux-fundamentals.md
touch cloud-infrastructure.md
touch containerization.md
touch index.md

Edit these files in VS Code (code .) with your reference content. The index.md should link to each file.

4.8 Stage, Commit, and Push

git add .
git commit -m "Initial documentation files"
git push origin main

Go to your GitHub repo in the browser and verify the files appear.

4.9 Create the GitHub Actions Workflow

mkdir -p .github/workflows

Create .github/workflows/deploy.yml with the following content:

name: Deploy to EC2

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v3

    - name: Deploy to EC2
      env:
        PRIVATE_KEY: ${{ secrets.EC2_SSH_KEY }}
        HOST: ${{ secrets.EC2_HOST }}
        USER: ec2-user
      run: |
        echo "$PRIVATE_KEY" > private_key.pem
        chmod 600 private_key.pem
        ssh -o StrictHostKeyChecking=no -i private_key.pem ${USER}@${HOST} '
        cd /home/ec2-user/final-project &&
        git pull origin main &&
        docker compose down &&
        docker compose up -d
        '

Update the cd path to wherever you clone the repo on the instance in Phase 5.

git add .
git commit -m "Add GitHub Actions deploy workflow"
git push origin main

Phase 5 — Connect Instance to GitHub via SSH

This creates a second SSH key — this one is on the EC2 instance so it can pull from GitHub. It is separate from the key used to connect to the instance.

5.1 Generate an SSH Key on the EC2 Instance

In your PuTTY/SSH terminal connected to the instance:

ssh-keygen -t rsa -b 4096 -C your_email@example.com

Accept the default location. Do not set a passphrase for automated workflows.

cat ~/.ssh/id_rsa.pub

Copy the full output.

5.2 Add the Instance's Key to GitHub

  1. Go to GitHub → Settings → SSH and GPG keys → New SSH key
  2. Paste the key from the instance
  3. Name it something like EC2 Instance Key
  4. Click Add SSH key

5.3 Clone Your Repo on the Instance

cd ~
git clone git@github.com:yourusername/final-project.git
cd final-project
pwd

Note the path output by pwd — you will need this for your deploy.yml workflow and docker-compose.yml.


Phase 6 — Add Secrets to GitHub

Go to your GitHub repo → Settings → Secrets and variables → Actions

Click New repository secret and add each of the following:

Secret Name Where to Get the Value
EC2_SSH_KEY Contents of the .pem key file you downloaded in Phase 1.3 (open in a text editor and copy everything)
EC2_HOST Your EC2 Public IPv4 DNS from Phase 1.4
AWS_ACCESS_KEY_ID AWS Academy → AWS Details → Show → AWS CLI
AWS_SECRET_ACCESS_KEY AWS Academy → AWS Details → Show → AWS CLI
AWS_SESSION_TOKEN AWS Academy → AWS Details → Show → AWS CLI
AWS_REGION us-east-1
S3_BUCKET_NAME Your S3 bucket name

After saving, secrets are not visible — only their names appear. To update a secret, overwrite it by creating a new one with the same name.


Phase 7 — Docker: Set Up the Multi-Container Application

Run all commands on the EC2 instance via PuTTY/SSH.

7.1 Create the Docker Compose File

Navigate to your cloned repo on the instance:

cd ~/final-project

Create docker-compose.yml:

services:
  documentation:
    image: kobucom/pandoc:local1
    container_name: doc-final-project
    ports:
      - "8081:80"
    volumes:
      - /home/ec2-user/final-project:/usr/local/apache2/htdocs
    networks:
      - final-network
    restart: unless-stopped

  database:
    image: mysql:8.0
    container_name: database-final-project
    environment:
      - MYSQL_ROOT_PASSWORD=ComplexPass123!!
      - MYSQL_DATABASE=cms
    volumes:
      - mysql-final-data:/var/lib/mysql
    networks:
      - final-network
    restart: unless-stopped

  cms:
    image: joomla:latest
    container_name: joomla-final-project
    ports:
      - "8090:80"
    environment:
      - JOOMLA_DB_HOST=database
      - JOOMLA_DB_USER=root
      - JOOMLA_DB_PASSWORD=ComplexPass123!!
      - JOOMLA_DB_NAME=cms
    volumes:
      - web-final-data:/var/www/html
    depends_on:
      - database
    networks:
      - final-network
    restart: unless-stopped

networks:
  final-network:
    driver: bridge

volumes:
  mysql-final-data:
    driver: local
  web-final-data:
    driver: local

Replace the volume path under documentation with the actual path output by pwd in Phase 5.3.

7.2 Start All Containers

docker compose up -d

The -d flag runs all containers in the background (detached mode).

7.3 Verify All Containers Are Running

docker ps

You should see three containers running: doc-final-project, database-final-project, and joomla-final-project.

7.4 Open the Required Ports in AWS Security Group

Containers run on ports 8081 and 8090. These must be open in the EC2 security group.

  1. Go to EC2 → Security Groups
  2. Select your instance's security group
  3. Click Edit inbound rules → Add rule
  4. Add:
    • Type: Custom TCP, Port: 8081, Source: Anywhere-IPv4
    • Type: Custom TCP, Port: 8090, Source: Anywhere-IPv4
  5. Click Save rules

7.5 Access Your Running Services

In a browser, replace YOUR-EC2-DNS with your actual Public IPv4 DNS:

Service URL
Documentation http://YOUR-EC2-DNS:8081
Joomla CMS setup http://YOUR-EC2-DNS:8090

7.6 Complete the Joomla Installation

  1. Navigate to http://YOUR-EC2-DNS:8090
  2. Follow the installation wizard
  3. On the database configuration step, enter:
Setting Value
Database Type MySQLi
Database Host database (the service name from docker-compose.yml)
Database User root
Database Password ComplexPass123!!
Database Name cms
  1. Complete the remaining wizard steps

7.7 Push Docker Compose File to GitHub

git add docker-compose.yml
git commit -m "Add Docker Compose configuration"
git push origin main

Pushing to main will trigger the GitHub Actions workflow. Watch it run in GitHub → Actions tab.


Phase 8 — S3: Add Images to Your Documentation

8.1 Create an S3 Bucket

  1. In AWS Console, go to S3 → Create bucket
  2. Name it with "final" in the name (e.g., final-docs-yourusername)
  3. Uncheck Block all public access
  4. Check the acknowledgment box
  5. Click Create bucket

8.2 Apply a Public Read Bucket Policy

  1. Click your bucket → Permissions tab → Bucket policy → Edit
  2. Paste (replacing YOUR_BUCKET_NAME):
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
    }
  ]
}
  1. Click Save changes

8.3 Upload Screenshots to S3

  1. Click your bucket → Objects tab → Upload → Add files
  2. Select your screenshot images
  3. Click Upload
  4. Click on an uploaded file and copy its URL

8.4 Reference S3 Images in Your Markdown Files

In your local markdown files:

![Description of image](https://your-bucket-name.s3.us-east-1.amazonaws.com/screenshot.png)

8.5 Commit and Push — Watch CI/CD Deploy

git add .
git commit -m "Add S3 images to documentation"
git push origin main
  1. Go to GitHub → Actions tab
  2. Watch the workflow run automatically
  3. Wait for it to complete (green checkmark)
  4. Refresh http://YOUR-EC2-DNS:8081 — your images should appear, served from S3

Phase 9 — Tighten Security

After verifying everything works, restrict the security group to only the ports you actually use.

9.1 Modify the Security Group

  1. Go to EC2 → Security Groups → Edit inbound rules
  2. Remove the "All traffic" rule if it exists
  3. Keep only:
    • SSH (port 22) — for terminal access via PuTTY
    • Custom TCP port 8081 — for the documentation service
    • Custom TCP port 8090 — for the Joomla CMS
  4. Click Save rules

9.2 Secure Your Database Password (Production Best Practice)

The MYSQL_ROOT_PASSWORD in docker-compose.yml is stored in plain text. In a production environment, use one of these approaches instead:

Option 1 — Environment file (.env):

Create a .env file in the same directory as docker-compose.yml:

MYSQL_ROOT_PASSWORD=ComplexPass123!!

Reference it in docker-compose.yml:

environment:
  - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}

Add .env to .gitignore so it is never committed to GitHub.

Option 2 — Docker Secrets (requires Docker Swarm mode — more advanced):

Passwords are stored encrypted and injected into containers at runtime without appearing in any configuration file.


Full Workflow Summary

Once everything is set up, your day-to-day workflow looks like this:

1. Edit markdown files locally in VS Code
2. git add .
3. git commit -m "describe your change"
4. git push origin main
        ↓
5. GitHub Actions automatically:
   - SSHs into your EC2 instance
   - Pulls the latest code from GitHub
   - Restarts Docker containers
        ↓
6. Refresh your browser at http://YOUR-EC2-DNS:8081
   to see the updated documentation — images served from S3

Quick Reference: Where Everything Lives

Component Location
GitHub repo https://github.com/yourusername/final-project
EC2 instance AWS Console → EC2 → Instances
Repo on instance /home/ec2-user/final-project
Docker Compose file /home/ec2-user/final-project/docker-compose.yml
Deploy workflow .github/workflows/deploy.yml
S3 bucket AWS Console → S3 → your bucket name
Documentation site http://YOUR-EC2-DNS:8081
Joomla CMS http://YOUR-EC2-DNS:8090
GitHub Secrets Repo → Settings → Secrets and variables → Actions