DocsGetting started

KHUB documentation

Everything KHUB does, how to use it, and how it fits together — organizations and projects, Git and pull requests, CI/CD, chat, templates, and administration.

Overview#

KHUB is a self-hosted software delivery platform: source control, code review, CI/CD, artifact registries, project planning, and real-time collaboration, unified under one authorization model and one deployment. It is built to replace the combination of GitHub/GitLab + Jira + Slack + a private npm/Docker registry with a single system an organization runs on its own infrastructure.

Design goals#

  • One authorization model. A single role and permission graph governs Git access, CI/CD, package publishing, issue tracking, and chat — not a separate ACL system per subsystem.
  • Everything is an API first. The web application is a client of the same REST API documented at /api/docs (Swagger/OpenAPI) that external integrations use. The MCP server exposes that entire API to LLM agents with zero bespoke integration code.
  • Standards-compliant where a standard exists. The container registry implements the OCI Distribution Specification; provisioning implements SCIM 2.0; SSO implements SAML 2.0; the package registry implements the npm registry HTTP API. Existing tooling (docker, npm, your IdP) works against KHUB without a plugin.
  • Auditable by default. Every privileged mutation — permission changes, deletions, settings changes, impersonation — is written to an append-only audit log, independent of whether audit logging was explicitly enabled for that action.

Component inventory#

ComponentTechnologyResponsibility
apps/webNext.js 14 (App Router), React, TanStack QueryThe browser UI. A pure API client — it holds no authorization logic of its own beyond hiding controls a user can't use; the API enforces every permission server-side regardless of what the UI renders.
apps/apiNestJS (Node.js), Prisma ORMThe single source of truth: REST API, WebSocket gateway (chat/voice), Git Smart HTTP and Git LFS endpoints, OCI Distribution registry, npm registry, SCIM/SAML endpoints, webhook dispatch, and the CI/CD control plane.
services/runnerNode.js, BullMQ, dockerodePolls the CI job queue and executes pipeline jobs in isolated, resource-limited Docker containers. Horizontally scalable — run as many as you want, differentiated by tags.
services/ssh-gitNode.jsA minimal SSH server (ssh://) that authenticates against KHUB-issued SSH keys and proxies git-upload-pack/git-receive-pack to the same bare repositories the API's Smart HTTP endpoint serves.
services/mcpNode.js, @modelcontextprotocol/sdkA stateless bridge that turns KHUB's live OpenAPI spec into Model Context Protocol tools — see MCP integration.
packages/databasePrisma schema + migrationsThe canonical relational data model (PostgreSQL), shared by apps/api and services/runner.
packages/permissionsPure TypeScriptThe authorization engine — role → permission resolution, visibility cascade, and merge-eligibility checks. Framework-agnostic and unit-testable in isolation from NestJS.
PostgreSQL—System of record for every relational entity.
Redis—Backs the BullMQ job queue that dispatches CI/CD jobs to runners.
Caddy—TLS-terminating reverse proxy; routes by path prefix to the API, web app, and MCP bridge (see Deployment & self-hosting).

Request flow at a glance#

text
                              ┌───────────────┐
                 HTTPS        │     Caddy     │
   clients ───────────────────▶  (TLS + path  │
   (browser, git, docker,     │   routing)    │
    npm, MCP client)          └───┬───┬───┬───┘
                                  │   │   │
                    /api/*        │   │   │  /v2/* (OCI), /*.git (Smart HTTP),
                    ┌─────────────┘   │   └───────────────────┐
                    │                 │ /mcp                  │
                    ▼                 ▼                       ▼
             ┌─────────────┐   ┌─────────────┐         (same apps/api
             │  apps/web   │   │ services/mcp│          process serves
             │  (Next.js,  │   │ (MCP bridge)│          all of these)
             │  SSR + API  │   └──────┬──────┘
             │  calls)     │          │ forwards Bearer token as-is
             └──────┬──────┘          ▼
                    │           ┌───────────┐
                    └──────────▶│ apps/api  │◀──── ssh:// ──── services/ssh-git
                                │ (NestJS)  │
                                └─────┬─────┘
                       ┌──────────────┼──────────────┐
                       ▼              ▼              ▼
                 ┌──────────┐  ┌────────────┐  ┌──────────────┐
                 │PostgreSQL│  │ Redis/BullMQ│  │ Git/LFS/OCI/ │
                 │          │  │ (ci-jobs)  │  │ package blob │
                 └──────────┘  └─────┬──────┘  │   storage    │
                                     ▼          └──────────────┘
                             services/runner
                             (Docker-isolated
                              job execution,
                              N replicas)

Every arrow into apps/api is subject to the same authentication and authorization layer regardless of entry point — a git push over SSH, a docker push, an MCP tool call, and a click in the web UI all resolve permissions through the exact same code path in packages/permissions.