Spin up ephemeral VMs on Kubernetes with a TypeScript/Express API and a modern React frontend. WebSocket‑friendly ingress, Prisma/PostgreSQL persistence, and a slick dark UI. 🚀
- 🔐 Auth: Signup/Login with JWT, cookie storage on the frontend
- 🖥️ VM Launcher: Create short‑lived VM workspaces via Kubernetes API
- 📦 Persistence: PostgreSQL via Prisma ORM
- 🧰 Infra: NGINX Ingress with WebSockets and HTTPS upstream
- 🧭 DX: Vite + React + TypeScript frontend, Tailwind‑style utility classes
- 🐳 Containerized: Dockerfiles for backend; docker‑compose for DB
k8sproject/
├─ src/ # Express API (TypeScript)
│ ├─ controllers/ # user, vm controllers
│ ├─ middlewares/ # auth/error/response
│ ├─ k8s/ # manifests + operations (create/delete)
│ └─ routes/ # /api/v1, /vm
├─ prisma/ # Prisma schema + migrations
├─ vm-app-frontend/ # React + Vite frontend
├─ k8s_local/ # Local cluster manifests
├─ testk8smanifests/ # Test ingress/service/deployment
├─ initDbScript/init.sql # DB bootstrap
├─ docker-compose.yml # Postgres (and optional Redis)
├─ Dockerfile # Backend container build
└─ readmeAssets/ # README images
- Entry:
src/index.ts - Routes:
POST /api/v1/signupPOST /api/v1/loginPOST /vm/createVM(Protected)
- Prisma models:
User,VM(seeprisma/schema.prisma) - Kubernetes ops:
src/k8s/operations/create.and.delete.vm.ts
Environment (.env in project root):
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
JWT_SECRET="change-me"
# Optional
REDIS_URL="redis://:password@localhost:6379"
PORT=4000
Install + Dev:
pnpm install
pnpm dev # runs src/index.ts with nodemonBuild + Run:
pnpm build
node dist/index.jsDocker (server listens on PORT, default 4000; Dockerfile EXPOSE is 3000 — set PORT to 3000 or map accordingly):
docker build -t vm-backend .
docker run -p 3000:3000 -e PORT=3000 --env-file .env vm-backendPrisma:
npx prisma migrate dev
npx prisma generate- Path:
vm-app-frontend/ - Runtime config via Vite env:
# vm-app-frontend/.env
VITE_BACKEND_URI=http://localhost:3000
Commands:
cd vm-app-frontend
pnpm install
pnpm dev
# build
pnpm build && pnpm previewAxios instance reads VITE_BACKEND_URI (see src/lib/api.ts). UI includes a dark/light toggle and glass/gradient theme.
Postgres 18+ expects mounting /var/lib/postgresql (parent dir). Compose is set to a named pgdata volume.
docker compose up -d postgresIf you previously used ./db_data at /var/lib/postgresql/data, see Postgres 18 migration notes. You can move old data out (fresh start) or run pg_upgrade.
Init script runs from initDbScript/init.sql.
- Test manifests:
testk8smanifests/(Service/Deployment/Ingress) - Ingress notes:
- WebSocket ready via
proxy-http-version: "1.1", extended timeouts - Cluster blocks
configuration-snippetfor security; using standard annotations - Backend is HTTPS; ingress proxies with
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- WebSocket ready via
Apply (example):
kubectl apply -f testk8smanifests/
# forward ingress locally if needed
kubectl -n ingress-nginx port-forward svc/ingress-nginx-controller 3000:80curl -X POST "$VITE_BACKEND_URI/api/v1/signup" \
-H 'Content-Type: application/json' \
-d '{"name":"John","email":"john@example.com","password":"Password@123"}'
curl -X POST "$VITE_BACKEND_URI/api/v1/login" \
-H 'Content-Type: application/json' \
-d '{"email":"john@example.com","password":"Password@123"}'For POST /vm/createVM include the authToken from login (frontend stores it in a cookie and sends in body as used by the app).
- Ingress 502s to backend: ensure
backend-protocol: "HTTPS"and (for self‑signed)proxy-ssl-verify: "off"or provide a CA viaproxy-ssl-secret. - Postgres 18 error about
/var/lib/postgresql/data: switch to/var/lib/postgresql(already done in compose) or migrate data as per upstream docs. - Container port mismatch: backend default
PORT=4000, DockerfileEXPOSE 3000; setPORT=3000in the container or map host accordingly.
- Fork the repo
- Create a feature branch
- Commit with clear messages
- Open a PR 🚀
Made with ❤️ by Suryansh — happy hacking!

