diff --git a/Q1/Dashboard/Dockerfile b/Q1/Dashboard/Dockerfile new file mode 100644 index 0000000..9cc8c20 --- /dev/null +++ b/Q1/Dashboard/Dockerfile @@ -0,0 +1,13 @@ + +# Minimal static-file server for just the dashboard, so it can be deployed +# as its own service on Ghaymah, separate from the API container. +FROM nginx:alpine + +# nginx's default port is 80; most container platforms (Ghaymah included, +# per its port-configuration step) let you pick which port the service +# listens on, so we keep nginx's default here and just set that port +# when creating the service. +COPY index.html /usr/share/nginx/html/index.html + +EXPOSE 80 + \ No newline at end of file diff --git a/Q1/Dashboard/index.html b/Q1/Dashboard/index.html new file mode 100644 index 0000000..d170cf9 --- /dev/null +++ b/Q1/Dashboard/index.html @@ -0,0 +1,213 @@ + + + + + +لوحة مراقبة الـ API + + + + +
+

مراقبة النظام

+ +
+ الحالة: جاري التحميل... +
+
+ زمن الاستجابة: — ms +
+
+ عدد الطلبات الإجمالي: +
+ +
+ التشغيل: — + آخر تحديث: — +
+ +
+ +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/Q1/README.md b/Q1/README.md new file mode 100644 index 0000000..62e193f --- /dev/null +++ b/Q1/README.md @@ -0,0 +1,84 @@ +# API + Health Monitor + Dashboard (for ghaymah.systems) + +This is your uploaded project (`server.js`, `monitor.sh`, `index.html`, +`Dockerfile`) with three functional bugs fixed and a couple of production +hardening tweaks. Nothing about your architecture changed. + +## What was wrong and what I changed + +1. **`index.html` was fetching the wrong URL.** + `const API_URL = "";` then `fetch(API_URL)` calls the *current page* + (`/`), not `/health` — so it was trying to `JSON.parse()` an HTML page + and always fell into the `catch` block ("Offline"), even when the API + was healthy. Fixed to `fetch('/health')`. + +2. **`server.js` had no route serving `index.html`.** + The dashboard needs to be reachable somewhere. I added + `express.static('public')` and moved `index.html` into `public/`, so the + dashboard is served at `/` and the plain-text welcome message moved to + `/api` so the two don't collide. + +3. **`monitor.sh` referenced `$response_time`, which was never set** — the + response-time column was always empty. Fixed by measuring it directly + with `curl -w "%{time_total}"`. Also added a fallback JSON parser for + when `jq` isn't installed, and an optional CSV log file. + +4. **Dockerfile ran `npm init -y && npm install` on every build**, with no + lockfile/manifest — slow, non-reproducible, and re-downloads + dependencies on every rebuild even if nothing changed. Added a real + `package.json` and split `COPY package.json` from `COPY server.js` so + Docker caches the `npm install` layer. Also switched + `node:20-alpine3.16` (an older, unsupported Alpine point release) to + `node:20-alpine` (current supported tag). + +## Files + +``` +. +├── Dockerfile +├── package.json +├── server.js +├── public/ +│ └── index.html ← dashboard, served at / +└── monitor.sh ← external checker, run it against the deployed URL +``` + +## Run locally + +```bash +npm install +npm start +# open http://localhost:3000 -> dashboard +# open http://localhost:3000/health -> raw JSON +``` + +In another terminal, point the monitor at it: + +```bash +chmod +x monitor.sh +./monitor.sh http://localhost:3000 30 +``` + +## Build & run with Docker + +```bash +docker build -t api-health-demo . +docker run -d -p 3000:3000 --name api-health-demo api-health-demo +``` + +## `/health` response shape + +```json +{ + "status": "Online", + "uptime_seconds": 42, + "request_count": 17, + "response_time_ms": 3, + "timestamp": "2026-07-27T20:10:00.000Z" +} +``` + +## Deploy to ghaymah.systems + +See `DEPLOY_GHAYMAH.md` for the step-by-step (build → push → create +service → set port 3000 → point `monitor.sh` at the live URL). \ No newline at end of file diff --git a/Q1/index.html b/Q1/index.html deleted file mode 100644 index ab0818e..0000000 --- a/Q1/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - لوحة مراقبة الـ API - - - - -
-

مراقبة النظام

- -
- الحالة: جاري التحميل... -
-
- زمن الاستجابة: 0 ms -
-
- عدد الطلبات الإجمالي: 0 -
-
- - - - \ No newline at end of file diff --git a/Q1/package.json b/Q1/package.json new file mode 100644 index 0000000..043f98f --- /dev/null +++ b/Q1/package.json @@ -0,0 +1,14 @@ +{ + "name": "api-health-monitor-demo", + "version": "1.0.0", + "private": true, + "description": "Simple Express API with /health endpoint, monitored and dashboarded, deployed on ghaymah.systems", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "cors": "^2.8.5", + "express": "^4.19.2" + } +} \ No newline at end of file diff --git a/Q1/server.js b/Q1/server.js index 5d007da..95b9d2d 100644 --- a/Q1/server.js +++ b/Q1/server.js @@ -1,35 +1,44 @@ const express = require('express'); const cors = require('cors'); +const path = require('path'); + const app = express(); app.use(cors()); +// --- Simple in-memory metrics (reset when the process restarts) --------- let requestCount = 0; let lastResponseTime = 0; app.use((req, res, next) => { - requestCount++; - const start = Date.now(); - res.on('finish', () => { - lastResponseTime = Date.now() - start; - }); - next(); + requestCount++; + const start = Date.now(); + res.on('finish', () => { + lastResponseTime = Date.now() - start; + }); + next(); }); +// Serve the dashboard (public/index.html) at the root, plus any static assets +app.use(express.static(path.join(__dirname, 'public'))); + +// --- Health check used by the monitor script and by ghaymah's platform -- app.get('/health', (req, res) => { - res.json({ - status: 'Online', - uptime_seconds: process.uptime(), - request_count: requestCount, - response_time_ms: lastResponseTime - }); + res.json({ + status: 'Online', + uptime_seconds: Math.round(process.uptime()), + request_count: requestCount, + response_time_ms: lastResponseTime, + timestamp: new Date().toISOString(), + }); }); -app.get('/', (req, res) => { - res.send('Welcome to the Backend API!'); +// Plain-text info route, separate from the dashboard which now owns '/' +app.get('/api', (req, res) => { + res.send('Welcome to the Backend API! Health check available at /health'); }); const PORT = process.env.PORT || 3000; -app.listen(PORT, () => { - console.log(`API is running on port ${PORT}`); +app.listen(PORT, '0.0.0.0', () => { + console.log(`API is running on port ${PORT}`); }); \ No newline at end of file diff --git a/README.md b/README.md index a2d26d1..2931b5e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,113 @@ -# Ghaymah-Exam-GamalMohamed-SRE +# Ghaymah SRE Project +This repository contains a full set of SRE and DevOps deliverables for the Ghaymah platform. It includes a health-monitoring web app, a containerized dashboard, an incident postmortem, CI/CD guidance, and a high-traffic architecture design. + +## Project Overview + +The project is organized into five main parts: + +- Q1: API health monitoring app and dashboard +- Q2: Incident postmortem and resilience recommendations +- Q3-CICD: CI/CD workflow and deployment strategy +- Q4: High-traffic architecture design for 15,000 RPS +- Q5: Containerized monitoring service for uptime and SSL checks + +## Repository Structure + +```text +Ghaymah_Task/ +├── Q1/ +│ ├── Dashboard/ +│ ├── Dockerfile +│ ├── monitor.sh +│ ├── package.json +│ ├── README.md +│ └── server.js +├── Q2/ +│ └── readme,md +├── Q3-CICD/ +│ ├── README.md +│ └── workflow.yml +├── Q4/ +│ ├── GhaymahAPI.png +│ └── README.md +├── Q5/ +│ ├── Dockerfile +│ ├── Entrypoint.sh +│ ├── README.md +│ ├── index.html +│ └── monitor.py +└── README.md +``` + +## What Each Part Includes + +### Q1 — API Health Monitor and Dashboard +This section provides a lightweight web service that exposes a health endpoint and serves a dashboard for monitoring service status, response time, and request count. + +Key files: +- [Q1/server.js](Q1/server.js) +- [Q1/monitor.sh](Q1/monitor.sh) +- [Q1/Dashboard/index.html](Q1/Dashboard/index.html) + +### Q2 — Incident Postmortem +This section documents a major outage caused by memory exhaustion and proposes mitigation strategies such as autoscaling, pagination, and observability improvements. + +Key file: +- [Q2/readme,md](Q2/readme,md) + +### Q3-CICD — Continuous Integration and Deployment +This section outlines the CI/CD workflow for automating build, test, and deployment processes for the platform. + +Key files: +- [Q3-CICD/workflow.yml](Q3-CICD/workflow.yml) +- [Q3-CICD/README.md](Q3-CICD/README.md) + +### Q4 — High-Traffic Architecture Design +This section explains how to design a scalable architecture for handling 15,000 requests per second, covering load balancing, caching, database replication, and storage planning. + +Key files: +- [Q4/README.md](Q4/README.md) +- [Q4/GhaymahAPI.png](Q4/GhaymahAPI.png) + +### Q5 — Containerized Monitoring Service +This section contains a Dockerized monitoring solution that checks uptime, latency, SSL expiry, and dashboard availability using a simple Python script. + +Key files: +- [Q5/Dockerfile](Q5/Dockerfile) +- [Q5/monitor.py](Q5/monitor.py) +- [Q5/Entrypoint.sh](Q5/Entrypoint.sh) + +## How to Use This Repository + +1. Review the documentation in each folder. +2. Run the applications locally as described in their own README files. +3. Use the CI/CD workflow from Q3-CICD for deployment automation. +4. Reference Q4 for the large-scale architecture approach. +5. Use Q5 as a container-based monitoring example. + +## Technologies Used + +- Node.js / Express +- Python +- Docker +- HTML / CSS / JavaScript +- GitHub Actions workflow-based CI/CD + +## Summary + +This project demonstrates a practical SRE approach covering monitoring, incident response, automation, scalability, and container-based operations for a production-style platform. + +--- + +## Author + +**Gamal Mohamed** + +DevSecOps Engineer + +Qabilah Profile + +``` +https://qabilah.com/profile/gamalmohammed0909/ +``` \ No newline at end of file diff --git a/docs/Screenshot 2026-07-27 at 23-54-33 Ghaymah Cloud.png b/docs/Screenshot 2026-07-27 at 23-54-33 Ghaymah Cloud.png new file mode 100644 index 0000000..91ff0ff Binary files /dev/null and b/docs/Screenshot 2026-07-27 at 23-54-33 Ghaymah Cloud.png differ diff --git a/docs/Screenshot 2026-07-27 at 23-54-52 Site Watch — Status.png b/docs/Screenshot 2026-07-27 at 23-54-52 Site Watch — Status.png new file mode 100644 index 0000000..8419a43 Binary files /dev/null and b/docs/Screenshot 2026-07-27 at 23-54-52 Site Watch — Status.png differ diff --git a/docs/Screenshot 2026-07-27 at 23-56-18 .png b/docs/Screenshot 2026-07-27 at 23-56-18 .png new file mode 100644 index 0000000..4033b24 Binary files /dev/null and b/docs/Screenshot 2026-07-27 at 23-56-18 .png differ diff --git a/docs/Screenshot 2026-07-27 at 23-56-33 .png b/docs/Screenshot 2026-07-27 at 23-56-33 .png new file mode 100644 index 0000000..59bb52b Binary files /dev/null and b/docs/Screenshot 2026-07-27 at 23-56-33 .png differ diff --git a/docs/Screenshot 2026-07-27 at 23-57-37 Ghaymah Cloud.png b/docs/Screenshot 2026-07-27 at 23-57-37 Ghaymah Cloud.png new file mode 100644 index 0000000..cb3bdbc Binary files /dev/null and b/docs/Screenshot 2026-07-27 at 23-57-37 Ghaymah Cloud.png differ diff --git a/docs/Screenshot 2026-07-27 at 23-57-45 لوحة مراقبة الـ API.png b/docs/Screenshot 2026-07-27 at 23-57-45 لوحة مراقبة الـ API.png new file mode 100644 index 0000000..9ec4a13 Binary files /dev/null and b/docs/Screenshot 2026-07-27 at 23-57-45 لوحة مراقبة الـ API.png differ diff --git a/docs/brave_screenshot_deploy.ghaymah.systems.png b/docs/brave_screenshot_deploy.ghaymah.systems.png new file mode 100644 index 0000000..1d42d72 Binary files /dev/null and b/docs/brave_screenshot_deploy.ghaymah.systems.png differ