Files
cloud-host/ARCHITECTURE.md
keyhan a87bc49393 docs: sync README + ARCHITECTURE to the Kaniko build pipeline
Update both docs to match the code after reverting the build-pipeline revamp:
Kaniko with per-runtime generated Dockerfiles, disk/PVC + git source, no
Nixpacks/MinIO/Trivy/registry-GC/build-queue. Also refreshes the stack
(Next.js 16, NestJS 11), mobile-OTP auth, the three Helm charts, project
structure, and local + cluster deploy steps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 19:27:32 +03:30

15 KiB

🏗️ CloudHost PaaS — System Architecture

Overview

CloudHost is a self-service PaaS that lets users deploy applications onto Kubernetes clusters managed by a super admin. Source code (uploaded archive or git repo) is turned into a container image inside the cluster with Kaniko, then rolled out via Helm. It includes a full billing/wallet system, automated lifecycle management, managed databases/services, Elasticsearch-backed logging, and a bilingual (Persian/English) panel.

Supported runtimes — each built from a platform-maintained Dockerfile template: Node.js, Laravel, Go, PHP, Python, Django, .NET, and WordPress (official image).


🧱 High-Level Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        USERS / ADMINS  (Browser)                 │
└──────────────────────────┬──────────────────────────────────────┘
                           │ HTTPS
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│              FRONTEND — Next.js 16 (App Router, bilingual)       │
│   Landing │ Auth (OTP) │ Deploy Wizard │ Dashboard │ Admin Panel │
└──────────────────────────┬──────────────────────────────────────┘
                           │ REST /api/v1 (JSON)
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                     BACKEND — NestJS 11                          │
│  Auth · Users · Admin · Applications · Deployments · Clusters    │
│  Build · Billing · Lifecycle · Snapshots · Tickets · Access ·    │
│  Notifications · Kubernetes/Helm/Registry                        │
└───┬───────────┬───────────────────┬───────────────┬─────────────┘
    │           │                   │               │
    ▼           ▼                   ▼               ▼
┌────────┐ ┌────────┐         ┌──────────┐ ┌──────────────────┐
│Postgres│ │ Redis  │         │ Registry │ │   Kubernetes     │
│  16    │ │(cache/ │         │  (:2)    │ │   Cluster(s)     │
│        │ │ Bull)  │         └──────────┘ │  ┌────────────┐  │
└────────┘ └────────┘                      │  │ Build Jobs │  │
                                           │  │  (Kaniko)  │  │
                                           │  └────────────┘  │
                                           │  Helm releases   │
                                           │  (user apps)     │
                                           └──────────────────┘

🧩 Module Overview

Module Purpose
Auth Mobile-number + OTP (SMS) and password login; JWT access/refresh; Passport strategies; role guards
Users User CRUD, profile, phone verification
Admin Super-admin user-detail dashboard and operations
Applications App CRUD, code upload (→ disk), git config, runtime/version metadata
Application-migrations Import / migrate existing applications (Bull queue)
Build build.service — runtime detection + per-runtime Dockerfile generation, Kaniko image builds inside K8s
Deployments Deploy orchestration (build → Helm), history, stop/restart
Kubernetes K8s API wrapper, Helm CLI wrapper, registry service
Clusters Multi-cluster management, kubeconfig storage, default cluster
Billing Wallet (deposit/deduct), transaction ledger, invoices, pricing catalog, coupons/discounts
Lifecycle Interval scanner: auto-suspend expired apps, auto-delete after grace period
Snapshots Application snapshot/backup & restore
Tickets Support ticket system (technical/sales departments)
Access Time-limited external access to app services via temporary NodePort grants (Bull queue)
Notifications User-facing notifications
Common / Config Shared enums, guards, decorators; env & TypeORM config

🔧 Tech Stack

Frontend: Next.js 16 (App Router) + Tailwind CSS v4

Reason Detail
SSR & SEO Server-side rendering for fast initial loads and a public landing/blog
App Router React Server Components, layouts, locale routing under app/[lang]/
Bilingual fa-IR (default) + en-US; middleware.ts also splits landing vs authenticated panel
React Query Server state, caching, polling for live build/deploy status
Zustand Lightweight client auth store
TypeScript End-to-end type safety

Backend: NestJS 11 (Node.js 20)

Reason Detail
Modular Each domain is a self-contained module
@kubernetes/client-node Direct K8s API interaction (Jobs, Deployments, logs, scale)
Helm CLI Shell-out to helm for chart-based app deployments
Bull (Redis) Async queues for service-access grants and application migrations
TypeORM PostgreSQL ORM. synchronize is development-only; production schema changes ship as idempotent SQL migrations / ALTER ... IF NOT EXISTS

Build System: Kaniko (in-cluster)

Reason Detail
No Docker daemon Builds run as unprivileged K8s Jobs in cloudhost-builds
Runtime detection detectRuntime() infers Node.js / Laravel / WordPress from source files; the app may also pin a runtime explicitly
Per-runtime Dockerfiles generateDockerfile() emits a tailored Dockerfile for Node.js, Laravel, WordPress, Go, PHP, Python, Django, or .NET
WordPress Templated Dockerfile + custom entrypoint that merges wp-content
Source ingestion Uploaded archives saved to disk and streamed into a per-build PVC (helper pod + kubectl cp); git repos cloned in-pod
Registry push Native push to the in-cluster (insecure) registry

Deployment: Helm v3 Charts

Reason Detail
Templated manifests One cloudhost-app chart handles all runtimes + attached services
Rollback Built-in revision history
Persistence DB/app PVCs and secrets use keep policies so they survive helm uninstall
Ingress Traefik by default (k3s); INGRESS_CLASS=nginx for ingress-nginx

🔄 Build & Deploy Flow

User triggers deploy (panel)
    │
    ▼
Backend runs the build-and-deploy pipeline, creating a Kubernetes Job in `cloudhost-builds`:

  ┌─ init: prepare source  (uploaded zip → disk → helper pod + `kubectl cp` → build PVC) ─┐
  │      …or…                                                                              │  → /workspace/source
  └─ init: git-clone       (clone repo; token injected into the URL for private repos) ───┘
                                   │
                                   ▼
  The platform detects the runtime and generates a Dockerfile for it
  (Node.js / Laravel / WordPress / Go / PHP / Python / Django / .NET)
                                   │
                                   ▼
  container: kaniko        → build image (cache per user) → push to in-cluster registry
                                   │
                                   ▼
        HelmService install/upgrade `cloudhost-app`
                                   │
                                   ▼
        Helm creates: Namespace, Deployment, Service, Ingress (+TLS), per-app
        DB/Redis/RabbitMQ, PVCs, Secrets, registry pull secret, log shipper
                                   │
                                   ▼
                 App live at https://<subdomain>.<PLATFORM_DOMAIN>

Notes:

  • The build runs inline within the deploy request (it is not queued); build progress/logs are tracked in memory and polled by the frontend. This assumes a single active backend replica for an in-flight build.
  • Bull/Redis queues are used by other subsystems (service-access grants, application migrations), not by the image build.

🔐 Security Architecture

  • Mobile-OTP + password authentication; JWT access + refresh
  • Live role/active-status enforcement — JwtStrategy reads the user from the DB each request
  • Role-Based Access Control (user / admin / technical / sales)
  • K8s namespace isolation per user; scoped ServiceAccounts
  • Resource quotas & limit ranges; expandable per-app storage
  • Secrets stored as K8s Secrets (env vars, DB creds)
  • Input validation (class-validator), Helmet headers, Bcrypt password hashing

💰 Billing & Lifecycle Flow

ACTIVE ──(expires)──► SUSPENDED ──(grace)──► PENDING_DELETION ──► DELETED
  ▲                       │                        │
  └────── payment ────────┘                        │
  └────── payment (within grace) ──────────────────┘

DOCKED ── user removed the service; data retained until the plan expires
  • Billing cycles: HOURLY | MONTHLY | YEARLY
  • Wallet: deposits, deductions, refunds, gateway payments; invoices with coupons/discounts
  • Grace periods: admin-configurable via the PlatformSettings entity (per cycle)
  • Lifecycle scanner: runs on an interval (default 60s); suspends expired apps (scale to 0, data retained) and deletes them after the grace period

⚠️ The lifecycle scanner and other interval jobs assume a single backend replica — guard them (e.g. a Redis lock) before scaling the control plane horizontally.


📦 Helm Charts

cloudhost-platform — control plane

Deploys the API, UI, PostgreSQL, and Redis into a namespace (default cloudhost).

Template Purpose
backend-deployment.yaml / backend-service.yaml / backend-pvc.yaml NestJS API + uploads PVC
frontend-deployment.yaml / frontend-service.yaml Next.js UI
postgres-*.yaml / redis-*.yaml Control-plane database & queue
ingress.yaml Frontend / API / panel host rules (+ TLS)
secret.yaml JWT, DB, registry, SMS and other platform secrets
migrations-configmap.yaml / migrations-job.yaml Optional SQL migration Job (migrations.enabled)
namespace.yaml / _helpers.tpl / NOTES.txt Namespace + chart helpers

Key values: ingress.enabled, ingress.tls.*, ingress.frontend.host / ingress.api.host, postgres.password, secrets.jwtSecret, migrations.enabled.

cloudhost-app — a single user application

Template Purpose
deployment.yaml App pod (imagePullSecret, probes, WordPress volumes, env)
service.yaml / ingress.yaml ClusterIP + ingress with TLS
secret.yaml User env vars as a K8s Secret
db-deployment.yaml / db-service.yaml / db-pvc.yaml / db-secret.yaml Optional managed PostgreSQL/MySQL/MariaDB/MongoDB
redis-deployment.yaml / rabbitmq-deployment.yaml Optional attached services
app-storage-pvc.yaml App persistent storage
storageclass.yaml Expandable StorageClass (created on demand)
registry-pull-secret.yaml imagePullSecret for the in-cluster registry
fluent-bit-configmap.yaml / log-shipper-configmap.yaml / _log-shipper.tpl / elasticsearch-credentials-secret.yaml Per-app log shipping to Elasticsearch

cloudhost-logging — observability

Elasticsearch / Kibana / Fluent-bit stack for centralized build and runtime logs (also see backend/k8s/logging/).


📁 Project Structure

cloud-host/
├── ARCHITECTURE.md  README.md  RUNBOOK.fa.md  CHANGELOG.md  CONTRIBUTING.md
├── UPGRADE.md  UPGRADE.en.md   docker-compose.yml
├── backend/                         # NestJS 11 API
│   ├── Dockerfile
│   ├── helm/{cloudhost-platform, cloudhost-app, cloudhost-logging}/
│   ├── k8s/{logging, mail}/         # standalone manifests
│   ├── migrations/                  # SQL migrations (one-off Jobs in prod)
│   └── src/
│       ├── main.ts / app.module.ts
│       ├── auth/  users/  admin/    # OTP auth, users, super-admin dashboard
│       ├── applications/  application-migrations/
│       ├── deployments/             # orchestration (build → Helm)
│       ├── build/                   # build.service: runtime detection + per-runtime Dockerfiles + Kaniko
│       ├── kubernetes/              # K8s client, Helm, registry
│       ├── clusters/                # multi-cluster management
│       ├── billing/  lifecycle/  snapshots/  tickets/  access/  notifications/
│       ├── common/                  # enums, guards, decorators
│       └── config/                  # env + TypeORM config
└── frontend/                        # Next.js 16 (App Router, fa-IR / en-US)
    ├── Dockerfile                   # ARG NEXT_PUBLIC_API_URL
    └── src/
        ├── middleware.ts            # locale routing + landing/panel split
        ├── app/[lang]/{page, login, register, blog, dashboard/*}
        ├── components/  hooks/  lib/  types/
        └── i18n/                    # dictionaries, provider, switcher

🔮 Future Considerations

  1. Per-app horizontal autoscaling (HPA) based on CPU/memory
  2. WebSocket/SSE for real-time build log streaming (currently polled)
  3. A Redis-backed build queue (so builds survive a replica restart and the control plane can scale out)
  4. In-cluster image vulnerability scanning (report-only)
  5. GitOps integration (e.g. ArgoCD) and git-push-to-deploy
  6. Automated control-plane database backups (scheduled pg_dump + retention)
  7. App marketplace with pre-built templates