diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..c59690afd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,62 @@ +name: DevOps CI Pipeline + +on: + push: + branches: + - main + - ash-assignment + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + # Backend Setup + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install Backend Dependencies + run: | + cd backend + python -m pip install --upgrade pip + pip install -r dependencies.txt + + - name: Run Django Check + run: | + cd backend + python manage.py check + env: + DJANGO_SECRET_KEY: ${{ secrets.DJANGO_SECRET_KEY }} #This passes the secret into CI environment + FRONTEND_URL: http://127.0.0.1:3000 + BACKEND_URL: http://127.0.0.1:8000 + BE_ADMIN_EMAIL: admin@admin.com + BE_ADMIN_PASSWORD: admin + + # Frontend Setup + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: "18" + + - name: Install Frontend Dependencies + run: | + cd frontend + npm install + + - name: Build Frontend + run: | + cd frontend + npm run build + + # Docker Build + - name: Build Docker Images + run: | + docker build -t backend-image ./backend + docker build -t frontend-image ./frontend + diff --git a/Logs /docs/ActiionCI success.PNG b/Logs /docs/ActiionCI success.PNG new file mode 100644 index 000000000..982c8df6a Binary files /dev/null and b/Logs /docs/ActiionCI success.PNG differ diff --git a/Logs /docs/DockerContainers.PNG b/Logs /docs/DockerContainers.PNG new file mode 100644 index 000000000..13add3197 Binary files /dev/null and b/Logs /docs/DockerContainers.PNG differ diff --git a/Logs /docs/EC2-launched.PNG b/Logs /docs/EC2-launched.PNG new file mode 100644 index 000000000..771a7d1fd Binary files /dev/null and b/Logs /docs/EC2-launched.PNG differ diff --git a/Logs /docs/Frontend-visible.PNG b/Logs /docs/Frontend-visible.PNG new file mode 100644 index 000000000..1cfecafd1 Binary files /dev/null and b/Logs /docs/Frontend-visible.PNG differ diff --git a/Logs /docs/TerraformApply.PNG b/Logs /docs/TerraformApply.PNG new file mode 100644 index 000000000..3f7c8a1bc Binary files /dev/null and b/Logs /docs/TerraformApply.PNG differ diff --git a/README.md b/README.md index a08c64acd..e6d5cdd4e 100644 --- a/README.md +++ b/README.md @@ -81,4 +81,93 @@ Welcome, candidates! This project is a custom-built chatbot application that mim 2. Run `npm install` 3. Run `npm run dev` to start the frontend server -Go to `http://127.0.0.1:3000` and enjoy! \ No newline at end of file +Go to `http://127.0.0.1:3000` and enjoy! + + +📘 Deployment Guide +>Repository Setup + +Forked the original repository +Created feature branch: ash-assignment +Implemented all changes in isolated branch + +#>Local Application Setup + +Backend Setup + cd backend + python -m venv venv + pip install -r dependencies.txt + python manage.py migrate + python manage.py runserver + +Backend accessible at: + http://127.0.0.1:8000 + +Frontend Setup + cd frontend + npm install + npm run dev + +Frontend accessible at: + http://localhost:3000 + +#>Docker Configuration + +Created Dockerfiles for: + Django backend + Next.js frontend + Used Docker Compose to orchestrate services: + docker compose up --build + Verified running containers using: + docker ps + +#>CI/CD Setup (GitHub Actions) + +#Configured CI workflow to: + Install dependencies + Inject required environment variables via GitHub Secrets + Run Django system checks + Resolved issues related to: + DJANGO_SECRET_KEY + FRONTEND_URL + BACKEND_URL + Successfully validated CI pipeline execution. + +#>Infrastructure Provisioning Using Terraform + +#Created Terraform configuration to provision: +EC2 instance (t3.micro) +Security group (ports 22, 3000, 8000) + +Docker installation via user_data +Commands executed: + terraform init + terraform plan -var="key_name=YOUR_KEY_NAME" + terraform apply -var="key_name=YOUR_KEY_NAME" +Terraform output provided the EC2 public IP. + + +#>EC2 Deployment + +Connected via SSH: +ssh -i key.pem ubuntu@ + +#Steps performed: + Installed Docker Compose + Cloned repository + Started containers + docker-compose up --build -d +Application accessible at: + http://:3000 + + +Logs / Screenshots +Included: + Terraform apply success output + Docker running containers (docker ps) + CI pipeline success + +EC2 instance running in AWS +Infrastructure Cleanup + After testing: + terraform destroy -var="key_name=YOUR_KEY_NAME" diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 000000000..904380ae3 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,13 @@ +FROM python:3.10-slim + +WORKDIR /app + +COPY dependencies.txt . + +RUN pip install --no-cache-dir -r dependencies.txt + +COPY . . + +EXPOSE 8000 + +CMD ["gunicorn", "--bind", "0.0.0.0:8000", "backend.wsgi:application"] diff --git a/backend/backend/settings.py b/backend/backend/settings.py index 9de4f024a..1ce0d76c1 100644 --- a/backend/backend/settings.py +++ b/backend/backend/settings.py @@ -30,7 +30,7 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ["*"] # Application definition diff --git a/backend/dependencies.txt b/backend/dependencies.txt index 2363ba87e..a26950161 100644 --- a/backend/dependencies.txt +++ b/backend/dependencies.txt @@ -50,3 +50,4 @@ urllib3==2.0.5 uvicorn==0.27.1 virtualenv==20.24.5 yarl==1.9.2 +gunicorn diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..f3866180f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3.8' + +services: + backend: + build: ./backend + container_name: django_app + ports: + - "8000:8000" + environment: + - DJANGO_SECRET_KEY=devsecret + - BACKEND_URL=http://localhost:8000 + - FRONTEND_URL=http://localhost:3000 + + frontend: + build: ./frontend + container_name: nextjs_app + ports: + - "3000:3000" + depends_on: + - backend diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 000000000..286b56243 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,15 @@ +FROM node:18 + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install + +COPY . . + +RUN npm run build + +EXPOSE 3000 + +CMD ["npm", "run", "dev"] diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 000000000..cfdd23fd8 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,54 @@ +resource "aws_security_group" "devops_sg" { + name = "devops-assignment-sg" + description = "Allow SSH and app ports" + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 3000 + to_port = 3000 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 8000 + to_port = 8000 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +#-------EC2 Recource-----> + +resource "aws_instance" "devops_ec2" { + ami = "ami-0030e4319cbf4dbf2" # Ubuntu 22.04(us-east-1) + instance_type = var.instance_type + key_name = var.key_name + + vpc_security_group_ids = [aws_security_group.devops_sg.id] + + user_data = <<-EOF + #!/bin/bash + apt update -y + apt install -y docker.io + systemctl start docker + systemctl enable docker + EOF + + tags = { + Name = "DevOps-Assignment_Terraform" + } +} diff --git a/terraform/outputs.tf b/terraform/outputs.tf new file mode 100644 index 000000000..319706005 --- /dev/null +++ b/terraform/outputs.tf @@ -0,0 +1,3 @@ +output "instance_public_ip" { + value = aws_instance.devops_ec2.public_ip +} diff --git a/terraform/provider.tf b/terraform/provider.tf new file mode 100644 index 000000000..c1259402c --- /dev/null +++ b/terraform/provider.tf @@ -0,0 +1,3 @@ +provider "aws" { + region = "us-east-1" +} diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 000000000..e4719bab2 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,7 @@ +variable "instance_type" { + default = "t3.micro" +} + +variable "key_name" { + description = "Existing EC2 key pair name" +}