Federated analytics across institutions. The data never moves.
A FLAME analysis is a container that travels to the data. Hub builds the analysis image,
ships it to the nodes that joined a project, and collects the results, without ever seeing a row.
Documentation · Quick start · Services · Packages · Contributing
Institutions each run a node (PrivateAIM/node); Hub is the centre that decides what runs where. This monorepo is the central half: five backend services, a Nuxt frontend, 19 shared TypeScript libraries, and the documentation site.
- Project. A researcher proposes a project and picks the nodes it should run on. Each node's institution approves or rejects taking part.
- Analysis. Within the project, the researcher uploads analysis code and picks a master image. Each node approves the analysis again before its configuration is locked.
- Build. The worker builds a container image from the code and the master image and pushes it to each node's project in the container registry.
- Run. Each node pulls the image and runs it next to its own data. Only results flow back to Hub's storage; the data itself never leaves the institution.
📖 Projects · Analyses · Approval
Requires Node.js 24, npm, and Docker.
npm ci # install
npm run build # build all packages (Nx, dependency-aware)
npm run test # run the test matrix
npm run lint # lintdocker compose up -d # MySQL + Postgres only
npm run dev --workspace=apps/server-core # Core API
npm run dev --workspace=apps/client-ui # Nuxt frontend
npm run dev --workspace=docs # Documentation siteThe repository's docker-compose.yml provides only the databases. The backend services also
need Authup (OAuth2), Redis and RabbitMQ, which you run yourself. For the
complete stack with all services and infrastructure, use
hub-deployment.
📖 Local setup · API reference · Deployment
flowchart LR
subgraph hub [FLAME Hub]
ui[client-ui]
core[server-core]
worker[server-core-worker]
storage[server-storage]
telemetry[server-telemetry]
messenger[server-messenger]
end
authup[(Authup)]
mq{{RabbitMQ}}
registry[(Container registry)]
nodes[FLAME nodes 1…N]
ui --> core & storage & telemetry
core <--> mq <--> worker
worker -- push image --> registry
nodes -- pull image --> registry
nodes -- status --> core
nodes -- results --> storage
nodes <--> messenger
hub -. tokens .-> authup
Each backend service follows the same hexagonal (ports & adapters) architecture. All of them ship in one Docker image, and the container's arguments pick the service and its command:
docker run ghcr.io/privateaim/hub core cli start # Core API
docker run ghcr.io/privateaim/hub storage cli start # likewise: telemetry, messenger
docker run ghcr.io/privateaim/hub core-worker start # worker
docker run ghcr.io/privateaim/hub ui start # frontendEvery entity endpoint answers with a { data, meta } envelope, and every query-capable GET
publishes the vocabulary it accepts under meta.schema, so a client never has to read server
source to build a valid query.
| Service | Responsibility |
|---|---|
server-core |
Main REST API — analyses, projects, nodes, registries |
server-core-worker |
Background worker — Docker image build & distribution |
server-storage |
File and object storage, on MinIO / S3 or the filesystem |
server-telemetry |
Log aggregation and events, backed by VictoriaLogs |
server-messenger |
Durable store-and-forward message broker |
client-ui |
Nuxt 4 web application |
Shared libraries, published to npm as @privateaim/*.
| Package | Responsibility | Version |
|---|---|---|
kit |
Crypto, domain events, permissions, realms | |
errors |
HubError, typed subclasses, code → HTTP-status mapping |
Models, contracts and typed clients, one set per service area.
| Package | Responsibility | Version |
|---|---|---|
core-kit |
Domain models and types for the core service | |
core-http-kit |
HTTP client for the core API | |
core-realtime-kit |
WebSocket event contracts for the core API | |
storage-kit |
Storage domain types and HTTP client | |
telemetry-kit |
Telemetry domain types and validators | |
messenger-kit |
Messenger contracts and crypto types | |
messenger-http-kit |
HTTP client for the messenger broker |
Building blocks shared across the backend services.
| Package | Responsibility | Version |
|---|---|---|
server-kit |
Logging, auth, AMQP, Redis, dependency injection | |
server-db-kit |
TypeORM utilities and migration support | |
server-http-kit |
HTTP middleware and OpenAPI generation | |
server-realtime-kit |
Socket.io server helpers | |
server-storage-kit |
Storage service components | |
server-telemetry-kit |
Telemetry components and Winston transport | |
server-core-worker-kit |
Worker task definitions | |
server-test-kit |
Shared test fakes and helpers |
| Package | Responsibility | Version |
|---|---|---|
client-vue |
Vue 3 component library | |
client-vue-theme |
vuecs-based theme — design tokens and chrome |
FLAME Hub runs on a stack of open-source libraries maintained by the same author: Authup (identity and access), Routup (HTTP routing), Hapic (HTTP clients), validup (validation), ilingo (i18n), and vuecs (Vue components and theming).
Before starting work on a pull request, please review the contributing guidelines and the code of conduct.
Created and maintained by Peter Placzek (@tada5hi), with contributions from the PrivateAIM team.
If you use FLAME Hub in academic work, please cite it — citation metadata lives in
CITATION.cff, which GitHub renders as a "Cite this repository" button.
Made with 💚 · Published under Apache 2.0.