diff --git a/sk1/README.md b/sk1/README.md
new file mode 100644
index 0000000..e6eeede
--- /dev/null
+++ b/sk1/README.md
@@ -0,0 +1,112 @@
+# Calculator Web Application on Azure Kubernetes Service (AKS)
+
+---
+
+
+##Application Description
+This project is a simple web-based calculator that performs basic mathematical operations.
+It allows users to calculate expressions and save the results. A "Show History" button displays previously saved calculations.
+
+Built with:
+
+- Frontend: HTML/CSS/JavaScript served via Nginx
+
+- Backend: Flask (Python) application connected to a PostgreSQL database
+
+- Database: PostgreSQL 15
+
+---
+
+##Public Cloud Environment
+- Provider: Microsoft Azure
+
+- Service Used: Azure Kubernetes Service (AKS)
+
+- Certificate Issuer: cert-manager with Let's Encrypt
+
+- Domain: https://aliscloudwork.tech
+
+---
+
+
+##Kubernetes and Cloud Components
+- Deployments:
+ - Frontend Deployment (Nginx server)
+ - Backend Deployment (Flask server)
+ - PostgreSQL Deployment (Database server)
+
+- Services:
+ - Frontend Service (ClusterIP)
+ - Backend Service (ClusterIP)
+ - PostgreSQL Service (ClusterIP)
+ - Ingress Controller Service (LoadBalancer)
+
+- Ingress:
+ - Ingress resource used to route traffic and enable HTTPS
+
+- Persistent Volume:
+ - PostgreSQL database uses a Persistent Volume Claim (PVC) for data persistence
+
+- Certificate Management:
+ - cert-manager with Let's Encrypt to generate HTTPS certificates automatically
+
+---
+
+
+##Files Included
+
+- prepare-app.sh: Script to deploy all Kubernetes objects and services automatically
+
+- remove-app.sh: Script to delete all Kubernetes objects and services
+
+- kubi/*.yaml: Kubernetes deployment, service, ingress, PVC configuration files
+
+- backend/Dockerfile: Dockerfile for the Flask backend application
+
+- frontend/Dockerfile: Dockerfile for the Nginx frontend application
+
+- frontend/default.conf: Nginx configuration file for routing
+
+- README.md: This documentation file
+
+---
+
+
+##How to View and Use the Application
+Open a web browser and visit: https://aliscloudwork.tech
+
+Use the calculator to perform operations.
+
+Click the "Show History" button to view saved calculations.
+
+---
+
+##Running Scripts
+
+- To deploy the application:
+ - ```bash prepare-app.sh```
+- To delete the application:
+ - ```bash remove-app.sh```
+
+---
+
+
+##External Sources and Tools Used
+- DockerHub for container images
+
+- Let's Encrypt for SSL certificates
+
+- cert-manager for Kubernetes certificate automation
+
+- Azure CLI for AKS management
+
+- Official documentation for Nginx, Flask, Kubernetes YAML syntax
+
+---
+
+##Final Notes
+- HTTPS is fully functional.
+
+- Kubernetes ensures all components are modular and recover automatically.
+
+- Database uses persistent storage for calculation history.
diff --git a/sk1/backend/Dockerfile b/sk1/backend/Dockerfile
new file mode 100644
index 0000000..504dd68
--- /dev/null
+++ b/sk1/backend/Dockerfile
@@ -0,0 +1,9 @@
+FROM python:3.10-slim
+
+WORKDIR /app
+
+COPY app.py .
+
+RUN pip install Flask flask_sqlalchemy psycopg2-binary flask-cors
+
+CMD ["python", "app.py"]
diff --git a/sk1/backend/app.py b/sk1/backend/app.py
new file mode 100644
index 0000000..81f6af9
--- /dev/null
+++ b/sk1/backend/app.py
@@ -0,0 +1,35 @@
+from flask import Flask, request, jsonify
+from flask_sqlalchemy import SQLAlchemy
+from flask_cors import CORS
+
+app = Flask(__name__)
+CORS(app, resources={r"/*": {"origins": "*"}})
+
+app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:yourpassword@postgres-service:5432/calculator'
+app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
+
+db = SQLAlchemy(app)
+
+class Calculation(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ expression = db.Column(db.String(100))
+ result = db.Column(db.String(100))
+
+with app.app_context():
+ db.create_all()
+
+@app.route('/save', methods=['POST'])
+def save_calc():
+ data = request.json
+ calc = Calculation(expression=data['expression'], result=data['result'])
+ db.session.add(calc)
+ db.session.commit()
+ return jsonify({'message': 'Saved'}), 201
+
+@app.route('/history', methods=['GET'])
+def history():
+ calcs = Calculation.query.all()
+ return jsonify([{'expression': c.expression, 'result': c.result} for c in calcs])
+
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port=5000)
diff --git a/sk1/cluster-issuer.yaml b/sk1/cluster-issuer.yaml
new file mode 100644
index 0000000..36910fb
--- /dev/null
+++ b/sk1/cluster-issuer.yaml
@@ -0,0 +1,14 @@
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-prod
+spec:
+ acme:
+ server: https://acme-v02.api.letsencrypt.org/directory
+ email: muhammed.tariq.ali.razvi@student.tuke.sk
+ privateKeySecretRef:
+ name: letsencrypt-prod
+ solvers:
+ - http01:
+ ingress:
+ class: nginx
diff --git a/sk1/default-backend.yaml b/sk1/default-backend.yaml
new file mode 100644
index 0000000..b3092f7
--- /dev/null
+++ b/sk1/default-backend.yaml
@@ -0,0 +1,18 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: default-backend
+ namespace: default
+ annotations:
+ kubernetes.io/ingress.class: nginx
+spec:
+ rules:
+ - http:
+ paths:
+ - pathType: Prefix
+ path: /
+ backend:
+ service:
+ name: frontend
+ port:
+ number: 80
diff --git a/sk1/frontend/= b/sk1/frontend/=
new file mode 100644
index 0000000..e69de29
diff --git a/sk1/frontend/CACHED b/sk1/frontend/CACHED
new file mode 100644
index 0000000..e69de29
diff --git a/sk1/frontend/Dockerfile b/sk1/frontend/Dockerfile
new file mode 100644
index 0000000..6f9e9b3
--- /dev/null
+++ b/sk1/frontend/Dockerfile
@@ -0,0 +1,10 @@
+# Use official Nginx Alpine image
+FROM nginx:alpine
+
+# Copy static files
+COPY index.html /usr/share/nginx/html/
+COPY style.css /usr/share/nginx/html/
+COPY script.js /usr/share/nginx/html/
+
+# Copy nginx configuration
+COPY default.conf /etc/nginx/conf.d/default.conf
diff --git a/sk1/frontend/[auth] b/sk1/frontend/[auth]
new file mode 100644
index 0000000..e69de29
diff --git a/sk1/frontend/[internal] b/sk1/frontend/[internal]
new file mode 100644
index 0000000..e69de29
diff --git a/sk1/frontend/default.conf b/sk1/frontend/default.conf
new file mode 100644
index 0000000..64d98ed
--- /dev/null
+++ b/sk1/frontend/default.conf
@@ -0,0 +1,17 @@
+server {
+ listen 80;
+
+ location / {
+ root /usr/share/nginx/html;
+ index index.html;
+ try_files $uri $uri/ =404;
+ }
+
+ location /history {
+ proxy_pass http://backend:5000;
+ }
+
+ location /save {
+ proxy_pass http://backend:5000;
+ }
+}
diff --git a/sk1/frontend/exporting b/sk1/frontend/exporting
new file mode 100644
index 0000000..e69de29
diff --git a/sk1/frontend/index.html b/sk1/frontend/index.html
new file mode 100644
index 0000000..306b1fe
--- /dev/null
+++ b/sk1/frontend/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+ Calculator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sk1/frontend/naming b/sk1/frontend/naming
new file mode 100644
index 0000000..e69de29
diff --git a/sk1/frontend/script.js b/sk1/frontend/script.js
new file mode 100644
index 0000000..6a9789f
--- /dev/null
+++ b/sk1/frontend/script.js
@@ -0,0 +1,50 @@
+const display = document.getElementById('display');
+const buttons = document.querySelectorAll('#buttons button');
+const historyList = document.getElementById('history-list');
+const historyBtn = document.getElementById('history');
+
+let expression = '';
+
+buttons.forEach(button => {
+ button.addEventListener('click', () => {
+ if (button.id === 'clear') {
+ expression = '';
+ display.value = '';
+ } else if (button.id === 'equals') {
+ try {
+ const result = eval(expression);
+ display.value = result;
+ sendToBackend(expression, result);
+ expression = result.toString();
+ } catch (e) {
+ display.value = 'Error';
+ expression = '';
+ }
+ } else {
+ expression += button.textContent;
+ display.value = expression;
+ }
+ });
+});
+
+historyBtn.addEventListener('click', () => {
+ fetch('http://aliscloudwork.tech/history') // Kubernetes DNS for backend service
+ .then(res => res.json())
+ .then(data => {
+ historyList.innerHTML = '';
+ data.forEach(item => {
+ const li = document.createElement('li');
+ li.textContent = `${item.expression} = ${item.result}`;
+ historyList.appendChild(li);
+ });
+ })
+ .catch(err => alert('Failed to load history'));
+});
+
+function sendToBackend(expr, res) {
+ fetch('http://aliscloudwork.tech/save', {
+ method: 'POST',
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({expression: expr, result: res})
+ }).catch(err => console.log('Failed to save:', err));
+}
diff --git a/sk1/frontend/style.css b/sk1/frontend/style.css
new file mode 100644
index 0000000..2bc3d97
--- /dev/null
+++ b/sk1/frontend/style.css
@@ -0,0 +1,38 @@
+body {
+ font-family: Arial, sans-serif;
+ display: flex;
+ justify-content: center;
+ padding: 20px;
+}
+
+#calculator {
+ border: 2px solid #333;
+ padding: 10px;
+ width: 300px;
+}
+
+#display {
+ width: 100%;
+ height: 40px;
+ font-size: 1.5em;
+ margin-bottom: 10px;
+ text-align: right;
+ padding-right: 10px;
+}
+
+#buttons button {
+ width: 22%;
+ height: 40px;
+ margin: 3px 1%;
+ font-size: 1.2em;
+}
+
+#history-list {
+ margin-top: 10px;
+ list-style-type: none;
+ padding-left: 0;
+ max-height: 150px;
+ overflow-y: auto;
+ border-top: 1px solid #ccc;
+}
+
diff --git a/sk1/frontend/transferring b/sk1/frontend/transferring
new file mode 100644
index 0000000..e69de29
diff --git a/sk1/frontend/writing b/sk1/frontend/writing
new file mode 100644
index 0000000..e69de29
diff --git a/sk1/ingress-svc.yaml b/sk1/ingress-svc.yaml
new file mode 100644
index 0000000..8156962
--- /dev/null
+++ b/sk1/ingress-svc.yaml
@@ -0,0 +1,45 @@
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ kubectl.kubernetes.io/last-applied-configuration: |
+ {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app.kubernetes.io/component":"controller","app.kubernetes.io/instance":"ingress-nginx","app.kubernetes.io/name":"ingress-nginx","app.kubernetes.io/part-of":"ingress-nginx","app.kubernetes.io/version":"1.12.1"},"name":"ingress-nginx-controller","namespace":"ingress-nginx"},"spec":{"externalTrafficPolicy":"Local","ipFamilies":["IPv4"],"ipFamilyPolicy":"SingleStack","ports":[{"appProtocol":"http","name":"http","port":80,"protocol":"TCP","targetPort":"http"},{"appProtocol":"https","name":"https","port":443,"protocol":"TCP","targetPort":"https"}],"selector":{"app.kubernetes.io/component":"controller","app.kubernetes.io/instance":"ingress-nginx","app.kubernetes.io/name":"ingress-nginx"},"type":"LoadBalancer"}}
+ creationTimestamp: "2025-04-28T13:26:46Z"
+ finalizers:
+ - service.kubernetes.io/load-balancer-cleanup
+ labels:
+ app.kubernetes.io/component: controller
+ app.kubernetes.io/instance: ingress-nginx
+ app.kubernetes.io/name: ingress-nginx
+ app.kubernetes.io/part-of: ingress-nginx
+ app.kubernetes.io/version: 1.12.1
+ name: ingress-nginx-controller
+ namespace: ingress-nginx
+ resourceVersion: "54668"
+ uid: 346026d8-8939-400c-985e-c63915980d81
+spec:
+ allocateLoadBalancerNodePorts: true
+ clusterIP: 10.0.10.162
+ clusterIPs:
+ - 10.0.10.162
+ externalTrafficPolicy: Local
+ healthCheckNodePort: 31025
+ internalTrafficPolicy: Cluster
+ ipFamilies:
+ - IPv4
+ ipFamilyPolicy: SingleStack
+ ports:
+ - name: http
+ port: 80
+ protocol: TCP
+ targetPort: 80
+ - name: https
+ port: 443
+ protocol: TCP
+ targetPort: 443
+ selector:
+ app.kubernetes.io/component: controller
+ app.kubernetes.io/instance: ingress-nginx
+ app.kubernetes.io/name: ingress-nginx
+ sessionAffinity: None
+ type: LoadBalancer
diff --git a/sk1/kubi/backend-deployment.yaml b/sk1/kubi/backend-deployment.yaml
new file mode 100644
index 0000000..a37f7a8
--- /dev/null
+++ b/sk1/kubi/backend-deployment.yaml
@@ -0,0 +1,19 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: backend
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: backend
+ template:
+ metadata:
+ labels:
+ app: backend
+ spec:
+ containers:
+ - name: backend
+ image: ali0313/backend:latest
+ ports:
+ - containerPort: 5000
diff --git a/sk1/kubi/backend-service.yaml b/sk1/kubi/backend-service.yaml
new file mode 100644
index 0000000..4414135
--- /dev/null
+++ b/sk1/kubi/backend-service.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: backend
+spec:
+ selector:
+ app: backend
+ ports:
+ - port: 5000
+ targetPort: 5000
diff --git a/sk1/kubi/frontend-deployment.yaml b/sk1/kubi/frontend-deployment.yaml
new file mode 100644
index 0000000..7194c72
--- /dev/null
+++ b/sk1/kubi/frontend-deployment.yaml
@@ -0,0 +1,19 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: frontend
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: frontend
+ template:
+ metadata:
+ labels:
+ app: frontend
+ spec:
+ containers:
+ - name: frontend
+ image: ali0313/frontend:latest
+ ports:
+ - containerPort: 80
diff --git a/sk1/kubi/frontend-service.yaml b/sk1/kubi/frontend-service.yaml
new file mode 100644
index 0000000..0682f2b
--- /dev/null
+++ b/sk1/kubi/frontend-service.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: frontend
+spec:
+ selector:
+ app: frontend
+ ports:
+ - protocol: TCP
+ port: 80
+ targetPort: 80
+ type: ClusterIP
diff --git a/sk1/kubi/ingress.yaml b/sk1/kubi/ingress.yaml
new file mode 100644
index 0000000..d411d50
--- /dev/null
+++ b/sk1/kubi/ingress.yaml
@@ -0,0 +1,23 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: app-ingress
+ annotations:
+ cert-manager.io/cluster-issuer: "letsencrypt-prod"
+spec:
+ ingressClassName: nginx
+ tls:
+ - hosts:
+ - aliscloudwork.tech
+ secretName: tls-secret
+ rules:
+ - host: aliscloudwork.tech
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: frontend
+ port:
+ number: 80
diff --git a/sk1/kubi/postgres-deployment.yaml b/sk1/kubi/postgres-deployment.yaml
new file mode 100644
index 0000000..3ad2b64
--- /dev/null
+++ b/sk1/kubi/postgres-deployment.yaml
@@ -0,0 +1,35 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: postgres
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: postgres
+ template:
+ metadata:
+ labels:
+ app: postgres
+ spec:
+ containers:
+ - name: postgres
+ image: postgres:15
+ env:
+ - name: POSTGRES_DB
+ value: calculator
+ - name: POSTGRES_USER
+ value: postgres
+ - name: POSTGRES_PASSWORD
+ value: yourpassword
+ - name: PGDATA
+ value: /var/lib/postgresql/data/pgdata # ← Keep this
+ ports:
+ - containerPort: 5432
+ volumeMounts:
+ - mountPath: /var/lib/postgresql/data # ← CHANGE HERE (one level up)
+ name: pgdata
+ volumes:
+ - name: pgdata
+ persistentVolumeClaim:
+ claimName: pgdata-pvc
diff --git a/sk1/kubi/postgres-service.yaml b/sk1/kubi/postgres-service.yaml
new file mode 100644
index 0000000..99ac9a9
--- /dev/null
+++ b/sk1/kubi/postgres-service.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: postgres-service
+spec:
+ selector:
+ app: postgres
+ ports:
+ - port: 5432
+ targetPort: 5432
+
diff --git a/sk1/kubi/pvc.yaml b/sk1/kubi/pvc.yaml
new file mode 100644
index 0000000..7580530
--- /dev/null
+++ b/sk1/kubi/pvc.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: pgdata-pvc
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
diff --git a/sk1/prepare-app.sh b/sk1/prepare-app.sh
new file mode 100755
index 0000000..b55933f
--- /dev/null
+++ b/sk1/prepare-app.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+echo "Starting application deployment..."
+# Apply Persistent Volume Claim
+kubectl apply -f kubi/pvc.yaml
+
+# Deploy PostgreSQL
+kubectl apply -f kubi/postgres-deployment.yaml
+kubectl apply -f kubi/postgres-service.yaml
+
+# Deploy Backend
+kubectl apply -f kubi/backend-deployment.yaml
+kubectl apply -f kubi/backend-service.yaml
+
+# Deploy Frontend
+kubectl apply -f kubi/frontend-deployment.yaml
+kubectl apply -f kubi/frontend-service.yaml
+
+
+# Apply cert-manager ClusterIssuer
+kubectl apply -f cluster-issuer.yaml
+
+# Apply Ingress
+kubectl apply -f kubi/ingress.yaml
+
+echo "Deployment completed successfully!"
diff --git a/sk1/remove-app.sh b/sk1/remove-app.sh
new file mode 100755
index 0000000..6b08373
--- /dev/null
+++ b/sk1/remove-app.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+echo "Starting application removal..."
+
+# Delete Ingress
+kubectl delete -f kubi/ingress.yaml
+
+# Delete cert-manager ClusterIssuer
+kubectl delete -f cluster-issuer.yaml
+
+# Delete Frontend
+kubectl delete -f kubi/frontend-service.yaml
+kubectl delete -f kubi/frontend-deployment.yaml
+
+# Delete Backend
+kubectl delete -f kubi/backend-service.yaml
+kubectl delete -f kubi/backend-deployment.yaml
+
+# Delete PostgreSQL
+kubectl delete -f kubi/postgres-service.yaml
+kubectl delete -f kubi/postgres-deployment.yaml
+
+# Delete Persistent Volume Claim
+kubectl delete -f kubi/pvc.yaml
+
+echo "Application resources removed successfully!"