2dd882bf345c94fff9c7cb0f578085bfbaab2762
The useQuery hook for unanswered ticket counts was called after two conditional early returns (isLoading and not isAuthenticated), violating React rules of hooks. Moved it before the returns and added isAuthenticated to the enabled condition.
☁️ CloudHost — Self-Service PaaS Platform
A self-service Platform-as-a-Service (PaaS) that lets developers deploy Node.js and Laravel applications onto Kubernetes with zero DevOps overhead. Super admins manage clusters, quotas, and users; developers simply push code and deploy.
Architecture Overview
┌─────────────┐ ┌─────────────────┐ ┌──────────────┐
│ Next.js 14 │ REST │ NestJS API │ K8s │ Kubernetes │
│ Frontend │◄───────►│ Backend │◄──────►│ Cluster(s) │
└─────────────┘ └────────┬────────┘ └──────────────┘
│
┌──────────┼──────────┐
▼ ▼ ▼
PostgreSQL Redis Container
(Bull) Registry
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, Tailwind CSS, React Query, Zustand |
| Backend API | NestJS 10, TypeORM, Passport JWT, Bull (Redis) |
| Build Engine | Kaniko (in-cluster, daemon-less Docker builds) |
| Orchestrator | @kubernetes/client-node, Handlebars YAML templates |
| Database | PostgreSQL 16 |
| Queue | Redis 7 + BullMQ |
Features
For Developers
- 🚀 One-click deploys from a Git URL or uploaded code archive
- 🟢 Node.js (with
npm run build&npm start) support - 🟣 Laravel (PHP 8.3 + Nginx + Supervisor) support
- 🗄️ Managed databases — PostgreSQL or MySQL provisioned automatically
- 📊 Live logs & deployment history
- 🔒 Environment variables managed as Kubernetes Secrets
- ⚙️ Resource controls — CPU, memory, replica count
For Super Admins
- 🖥️ Multi-cluster management — register/remove Kubernetes clusters
- 👥 User management — activate, deactivate, change roles
- 📈 Quotas — per-cluster limits (CPU, memory, max apps)
- 🔐 RBAC — role-based guards on every endpoint
Project Structure
host/
├── ARCHITECTURE.md # Detailed architecture document
├── docker-compose.yml # Local dev / production compose
│
├── backend/ # NestJS API
│ ├── Dockerfile
│ ├── package.json
│ ├── src/
│ │ ├── main.ts
│ │ ├── app.module.ts
│ │ ├── auth/ # JWT auth (register, login, refresh)
│ │ ├── users/ # User CRUD + admin ops
│ │ ├── applications/ # Application CRUD
│ │ ├── deployments/ # Deployment pipeline orchestration
│ │ ├── clusters/ # Cluster management (admin)
│ │ ├── kubernetes/ # K8s client & manifest generator
│ │ ├── build/ # Kaniko build jobs (Bull queue)
│ │ ├── common/ # Enums, decorators, guards
│ │ └── config/ # Env configuration loader
│ └── templates/ # Handlebars K8s YAML templates
│
└── frontend/ # Next.js 14 App Router
├── Dockerfile
├── package.json
└── src/
├── app/
│ ├── login/ # Auth pages
│ ├── register/
│ └── dashboard/ # Protected dashboard
│ ├── apps/ # App list & detail
│ ├── deploy/ # 4-step deploy wizard
│ └── admin/ # Admin: users & clusters
├── components/
├── lib/ # API client, auth store
└── types/ # TypeScript interfaces
Quick Start
Prerequisites
| Tool | Version |
|---|---|
| Node.js | ≥ 20 |
| Docker & Compose | ≥ 24 |
| PostgreSQL | 16 (or use Docker) |
| Redis | 7 (or use Docker) |
1. Clone & Install
git clone <repo-url> host && cd host
# Backend
cd backend && npm install && cd ..
# Frontend
cd frontend && npm install && cd ..
2. Environment Variables
# Backend
cp backend/.env.example backend/.env
# Edit backend/.env with your DB, JWT, Redis, and registry settings
# Frontend
cp frontend/.env.local.example frontend/.env.local
3. Run with Docker Compose (recommended)
docker compose up --build
This spins up PostgreSQL, Redis, Backend (port 4000), and Frontend (port 3000).
Open http://localhost:3000 in your browser.
4. Run Locally (development)
# Terminal 1 — Backend
cd backend
npm run start:dev
# Terminal 2 — Frontend
cd frontend
npm run dev
API Endpoints
All endpoints are prefixed with /api/v1.
Auth
| Method | Path | Description |
|---|---|---|
| POST | /auth/register | Create account |
| POST | /auth/login | Get JWT tokens |
| POST | /auth/refresh | Refresh access token |
Applications
| Method | Path | Description |
|---|---|---|
| POST | /applications | Create app |
| GET | /applications | List user's apps |
| GET | /applications/:id | Get app details |
| PATCH | /applications/:id | Update app |
| DELETE | /applications/:id | Delete app |
Deployments
| Method | Path | Description |
|---|---|---|
| POST | /applications/:appId/deployments | Trigger deploy |
| GET | /applications/:appId/deployments | List deployments |
| GET | /deployments/:id | Deployment detail |
| GET | /deployments/:id/logs | Get pod logs |
| POST | /deployments/:id/stop | Stop deployment |
| POST | /deployments/:id/restart | Restart deployment |
Users (authenticated)
| Method | Path | Description |
|---|---|---|
| GET | /users/me | Current user |
| PATCH | /users/me | Update profile |
Admin — Users
| Method | Path | Description |
|---|---|---|
| GET | /users | List all users |
| PATCH | /users/:id/activate | Activate user |
| PATCH | /users/:id/deactivate | Deactivate user |
| PATCH | /users/:id/role | Change role |
Admin — Clusters
| Method | Path | Description |
|---|---|---|
| POST | /clusters | Add cluster |
| GET | /clusters | List clusters |
| GET | /clusters/:id | Cluster details |
| PATCH | /clusters/:id | Update cluster |
| DELETE | /clusters/:id | Remove cluster |
📖 Full Swagger docs available at
http://localhost:4000/docswhen the backend is running.
Deployment Flow
Developer creates app → Uploads code / provides Git URL
│
▼
Build Service creates Kaniko Job in K8s
│
▼
Kaniko builds Docker image → Pushes to Container Registry
│
▼
Kubernetes Service generates manifests from Handlebars templates:
• Namespace • Deployment • Service • Ingress
• Database (optional) • PVC • Secret
│
▼
Applies manifests to target cluster via @kubernetes/client-node
│
▼
App is live at https://<subdomain>.apps.yourdomain.com
Kubernetes Templates
The platform dynamically generates K8s manifests using Handlebars templates located in backend/templates/:
| Template | Purpose |
|---|---|
namespace.yaml |
Per-user namespace with resource quotas |
deployment.yaml |
App deployment with health probes & resources |
service.yaml |
ClusterIP service |
ingress.yaml |
Ingress with TLS (cert-manager annotations) |
database.yaml |
PostgreSQL or MySQL StatefulSet |
pvc.yaml |
Persistent volume claim for databases |
secret.yaml |
Environment variables as K8s Secrets |
Security
- JWT access + refresh tokens with configurable expiry
- Bcrypt password hashing (12 rounds)
- Helmet HTTP security headers
- RBAC role-based route guards (
@Roles(UserRole.ADMIN)) - Namespace isolation — each user deploys to their own K8s namespace
- Secrets — env vars stored as K8s Secrets, never in plain manifests
- Input validation —
class-validatoron all DTOs
Configuration
All configuration is via environment variables. See backend/.env.example for the full list:
| Variable | Description | Default |
|---|---|---|
PORT |
Backend port | 4000 |
DB_HOST |
PostgreSQL host | localhost |
DB_PORT |
PostgreSQL port | 5432 |
DB_USERNAME |
Database user | cloudhost |
DB_PASSWORD |
Database password | — |
DB_NAME |
Database name | cloudhost |
JWT_SECRET |
JWT signing secret | — |
JWT_EXPIRES_IN |
Access token TTL | 15m |
REDIS_HOST |
Redis host | localhost |
REDIS_PORT |
Redis port | 6379 |
REGISTRY_URL |
Container registry URL | — |
PLATFORM_DOMAIN |
Base domain for app subdomains | apps.localhost |
License
MIT
Languages
TypeScript
96.3%
HTML
1.2%
Shell
0.7%
Go Template
0.5%
CSS
0.5%
Other
0.7%