From c1131b77458bd6de78d78ff86e013d0368442c6c Mon Sep 17 00:00:00 2001 From: Nihal Ahmed Date: Tue, 19 May 2026 22:47:34 +0000 Subject: [PATCH] Initial cloud project upload --- .gitignore | 1 + Cloud_Notes_Platform_Documentation.docx | Bin 0 -> 36416 bytes README.md | 66 ++++ app/Dockerfile | 13 + app/app.py | 414 ++++++++++++++++++++++++ app/requirements.txt | 2 + aws-deploy.sh | 50 +++ docker-compose.yml | 47 +++ nginx/nginx.conf | 14 + prepare-app.sh | 17 + remove-app.sh | 10 + ~$oud_Notes_Platform_Documentation.docx | Bin 0 -> 162 bytes 12 files changed, 634 insertions(+) create mode 100644 .gitignore create mode 100644 Cloud_Notes_Platform_Documentation.docx create mode 100644 README.md create mode 100644 app/Dockerfile create mode 100644 app/app.py create mode 100644 app/requirements.txt create mode 100644 aws-deploy.sh create mode 100644 docker-compose.yml create mode 100644 nginx/nginx.conf create mode 100644 prepare-app.sh create mode 100644 remove-app.sh create mode 100644 ~$oud_Notes_Platform_Documentation.docx diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2eea525 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/Cloud_Notes_Platform_Documentation.docx b/Cloud_Notes_Platform_Documentation.docx new file mode 100644 index 0000000000000000000000000000000000000000..df3ef0ad6564aa252d49be2ee08da4afbb5f63bf GIT binary patch literal 36416 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 + + + + + + Cloud Notes Platform + + + + + + + + +
+ +
+ +
+

Cloud Notes Platform

+ +

+ A modern cloud-native Flask application deployed with Kubernetes, + Docker containers, persistent storage, and automated deployment workflows. + This platform demonstrates scalable cloud infrastructure concepts and + production-ready deployment architecture. +

+
+ +
+ Running Mode: {{ mode }} +
+ +
+ +
+ +
+ +

Create New Note

+ +
+ + + + + +
+ +
+ +
+

Total Notes

+

{{ items|length }}

+
+ +
+

Infrastructure

+

K8s

+
+ +
+ +
+ +
+ +

Stored Notes

+ +
+ + {% for item in items %} + +
+ +
+ Note #{{ item.id }} + {{ item.created }} +
+ +
+ {{ item.text }} +
+ +
+ + {% else %} + +
+ +
+ No notes stored yet. +
+ +
+ + {% endfor %} + +
+ +
+ +
+ + + +
+ + + +""" + +@app.route("/", methods=["GET", "POST"]) +def index(): + + if request.method == "POST": + text = request.form.get("text", "").strip() + + if text: + + conn = get_db() + cur = conn.cursor() + + cur.execute( + "INSERT INTO items (text) VALUES (%s)", + (text,) + ) + + conn.commit() + + cur.close() + conn.close() + + return redirect(url_for("index")) + + conn = get_db() + cur = conn.cursor() + + cur.execute( + "SELECT id, text, created FROM items ORDER BY id DESC" + ) + + rows = cur.fetchall() + + items = [] + + for row in rows: + items.append({ + "id": row[0], + "text": row[1], + "created": row[2] + }) + + cur.close() + conn.close() + + mode = "Docker Compose + PostgreSQL" + + return render_template_string( + TEMPLATE, + items=items, + mode=mode + ) + + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000) \ No newline at end of file diff --git a/app/requirements.txt b/app/requirements.txt new file mode 100644 index 0000000..88c17be --- /dev/null +++ b/app/requirements.txt @@ -0,0 +1,2 @@ +Flask +psycopg2-binary \ No newline at end of file diff --git a/aws-deploy.sh b/aws-deploy.sh new file mode 100644 index 0000000..43d45b5 --- /dev/null +++ b/aws-deploy.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +echo "========================================" +echo "Cloud Notes Platform AWS Deployment" +echo "========================================" + +echo "" +echo "Updating Ubuntu packages..." +sudo apt update -y + +echo "" +echo "Installing Docker..." +sudo apt install docker.io docker-compose-v2 git nginx certbot python3-certbot-nginx -y + +echo "" +echo "Starting Docker service..." +sudo systemctl enable docker +sudo systemctl start docker + +echo "" +echo "Adding ubuntu user to Docker group..." +sudo usermod -aG docker ubuntu + +echo "" +echo "Creating environment configuration..." + +cat < .env +POSTGRES_PASSWORD=StrongPassword123 +EOF + +echo "" +echo "Building and starting containers..." +docker compose up -d --build + +echo "" +echo "Waiting for services..." +sleep 10 + +echo "" +echo "Currently running containers:" +docker ps + +echo "" +echo "Deployment completed successfully." + +echo "" +echo "Application URL:" +echo "https://notecloud.duckdns.org" + +echo "========================================" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1cc2f76 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,47 @@ +version: '3.8' + +services: + + backend: + build: ./app + container_name: flask-backend + restart: always + + environment: + DB_HOST: postgres + DB_NAME: mydb + DB_USER: admin + DB_PASSWORD: ${POSTGRES_PASSWORD} + + depends_on: + - postgres + + postgres: + image: postgres:15 + container_name: postgres-db + restart: always + + environment: + POSTGRES_DB: mydb + POSTGRES_USER: admin + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + + volumes: + - postgres_data:/var/lib/postgresql/data + + nginx: + image: nginx:latest + container_name: nginx-proxy + restart: always + + ports: + - "80:80" + + volumes: + - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf + + depends_on: + - backend + +volumes: + postgres_data: \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..c399d0b --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,14 @@ +server { + + listen 80; + + location / { + + proxy_pass http://backend:5000; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + + } + +} \ No newline at end of file diff --git a/prepare-app.sh b/prepare-app.sh new file mode 100644 index 0000000..d5476d8 --- /dev/null +++ b/prepare-app.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +echo "Starting Cloud Notes Platform deployment..." + +echo "Building and starting Docker containers..." +docker compose up -d --build + +echo "Waiting for containers to initialize..." +sleep 10 + +echo "Running containers:" +docker ps + +echo "Deployment completed successfully." + +echo "Application URL:" +echo "https://notecloud.duckdns.org" \ No newline at end of file diff --git a/remove-app.sh b/remove-app.sh new file mode 100644 index 0000000..347deb1 --- /dev/null +++ b/remove-app.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +echo "Stopping Cloud Notes Platform..." + +docker compose down + +echo "Removing unused Docker resources..." +docker system prune -f + +echo "Application removed successfully." \ No newline at end of file diff --git a/~$oud_Notes_Platform_Documentation.docx b/~$oud_Notes_Platform_Documentation.docx new file mode 100644 index 0000000000000000000000000000000000000000..b5f34d00fe7b8c651ca884be7527d733fca9680c GIT binary patch literal 162 gcmZP#POL1AXCM)