OpenFrame OSS Tenant: a self-hostable MSP platform in Java and Rust
Code base for OSS OpenFrame single tenant version
At a glance
- What is it?
- The open-source foundation of the OpenFrame platform from Flamingo, a polyglot microservice system for managed service providers that pairs Spring Boot services with a Rust endpoint agent, per-tenant OAuth2 and JWTs, Kafka and NATS event streaming, and a six-service edge topology on fixed ports. The cost is a very large operational surface for a single-tenant install.
- Who is it for?
- OpenFrame OSS Tenant suits a managed service provider that already runs Java and wants device management, remote scripting, AI-assisted support and multi-tenant isolation in one self-hosted stack, and that is prepared to run six services plus Kafka, NATS, MongoDB, Cassandra, Pinot and Redis. It does not suit a small team that wants a single binary, and it does not suit a deployment that cannot keep a per-tenant OAuth2 and JWT issuance model in order.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What OpenFrame OSS Tenant is
OpenFrame OSS Tenant is the multi-service, multi-tenant open-source foundation of the OpenFrame platform, an AI-powered managed service provider platform built by Flamingo that replaces expensive proprietary software with intelligent automation.
The functional scope it claims covers device management, real-time messaging, AI-assisted support with Mingo AI for technicians and Fae for end clients, and event-driven automation, across what the README calls a polyglot microservice architecture built on Spring Boot in Java and Rust.
The feature list is worth reading closely, because it tells you what the product is for. AI-assisted support with streaming LLMs and real-time response delivery. A cross-platform Rust agent, `openframe-client`, that runs as a system service on Windows, macOS and Linux, supports script execution and tool management, and self-updates via Velopack. Full tenant isolation with per-tenant OAuth2 clients, RSA-signed JWTs and `TenantAwareMongoTemplate` database scoping. Real-time event streaming over Apache Kafka and NATS JetStream for device events, script execution results and AI message chunk delivery. Remote management with script execution in bash, PowerShell, Python and Nushell, plus scheduling, live commands and compliance checking. Integrated tool management for MeshCentral, FleetMDM and custom tool agents. SSO with Google and Microsoft OIDC through the Spring Authorization Server. A GraphQL API powered by Netflix DGS with full multi-tenant scoping.
The repository is not archived and the last push was on 2026-10-15. The releases are tagged `latest` from 2026-09-19, 1.1.5 from 2026-08-14 and 1.1.3 from 2026-08-13, so the tags are moving quickly and the `latest` tag is not a version number.
One detail is worth flagging early: the repository description calls this the code base for the OSS OpenFrame single tenant version, while the README describes the architecture as multi-tenant with full tenant isolation. Those are different products, and which one you get is worth confirming before you plan a deployment around it.
Six services, fixed ports, and where the traffic goes
The architecture section says that all client traffic passes through the Spring Cloud Gateway, that backend services communicate over HTTP and GraphQL internally and asynchronously over Kafka and NATS JetStream, and that the Rust agent communicates exclusively over NATS.
The component table fixes the topology. The API Service on port 8080 is Java with Spring Boot 3.3 and serves REST and GraphQL APIs for tickets, dialogs, AI settings and tenant management. The Authorization Server on 8082 runs the Spring Authorization Server and handles multi-tenant OAuth2 and OIDC, RSA-signed JWT issuance and SSO with Google and Microsoft. The Gateway on 8081 does security enforcement, JWT validation, routing and WebSocket proxying. The External API on 8083 is a rate-limited public REST API with API key management. The Stream Service on 8085 uses Kafka Streams for real-time event normalization and enrichment, and writes to Cassandra and Pinot. The Client Service on 8084 handles agent lifecycle management and tool orchestration, over NATS.
The agent, `openframe-client`, is Rust and has no port of its own, since it is a system service on the managed endpoint rather than a server. It does device registration, script execution and self-update.
The data layer underneath holds six stores: MongoDB as the primary tenant-scoped datastore, Apache Cassandra for time-series storage, Apache Pinot for real-time analytics, Redis for cache and sessions, Apache Kafka for event streaming and NATS JetStream for agent messaging. A shared frontend library, `@flamingo-stack/openframe-frontend-core`, is published to npm.
So the picture is a gateway in front, five Java services behind it, six datastores, and a Rust agent that talks to the platform over NATS while also reaching the API.
Tenant isolation is implemented in three specific places
The multi-tenancy claim is worth unpacking, because in a system of this size it usually means several separate mechanisms rather than one switch.
The README names three. There are per-tenant OAuth2 clients, so each tenant authenticates as its own client rather than sharing one. JWTs are RSA-signed, and the Authorization Server performs that issuance. And the data layer uses `TenantAwareMongoTemplate` for database scoping, which is a MongoDB template that applies the tenant filter automatically rather than relying on every query remembering to add it.
That third one is the load-bearing piece. A template that scopes queries by default is a design decision with a cost: queries that legitimately need to cross tenant boundaries need an escape hatch, and any query that goes around the template bypasses the isolation. The same is true of the GraphQL API, which the README says carries full multi-tenant scoping.
Combined with the gateway doing JWT validation and routing, and the External API having its own API key management with rate limiting, the isolation story is enforced at several layers rather than one. That is the right shape for a platform that hosts multiple clients, and it is also a lot of places to look when something goes wrong.
The Stream Service is the one to watch in a multi-tenant deployment, since it consumes events from Kafka and writes into Cassandra and Pinot, and event streams do not naturally carry a tenant filter. The README says the Stream Service does event normalization and enrichment, and that the AI message chunk delivery is part of the streaming path, but it does not describe how tenant scoping is applied to the event topics.
The Rust agent and its install path
The endpoint agent is the part of the system that touches every managed machine, and it is written in Rust with async-nats, tokio and Velopack.
Velopack is the self-update mechanism, and the README describes the agent as self-updating via Velopack. That matters for an RMM agent, because the alternative is an update mechanism the operator drives, and a fleet of endpoints that only update when a human visits each one is a fleet with a long tail of old versions.
The script execution capability is broader than you might expect from an RMM tool. The README lists bash, PowerShell, Python and Nushell, which is a deliberate spread across Windows, Linux and macOS, and the Nushell inclusion is the unusual one. Alongside script execution there is scheduling, live commands and compliance checking across all managed endpoints.
The install command is `sudo./target/release/openframe-client install`, taking three flags: `--serverUrl` for the OpenFrame instance, `--initialKey` for the bootstrap credential and `--orgId` for the organisation the endpoint belongs to.
The `--initialKey` name suggests a credential that is exchanged for something better on first contact, and `--orgId` binds the endpoint to an organisation in the platform. Both are worth thinking about in the context of fleet provisioning, since the initial key has to reach the endpoint somehow.
There is a diagnostic command, which is the sort of thing an RMM agent needs and which the README documents as an agent doctor check:
cd clients/openframe-client
./target/debug/openframe-client doctorThat runs against the debug build, and the `--help` output of the built binary is documented as a verification step.
Building the whole thing from source
The prerequisites are JDK 21 with OpenJDK 21 recommended, Apache Maven 3.9 or newer, and Rust 1.78 or newer on stable, installed through rustup.
The clone and build sequence is:
git clone https://github.com/flamingo-stack/openframe-oss-tenant.git
cd openframe-oss-tenant
mvn clean install -DskipTests
cd clients/openframe-client
OPENFRAME_VERSION=0.0.0-dev cargo build
cd ../..The Maven build is a reactor build over the whole monorepo, and `-DskipTests` is on the documented path, which is what you want when you are trying the system out rather than contributing to it. The Rust build is separate, and the `OPENFRAME_VERSION` environment variable is how the agent's version is set at build time, with `0.0.0-dev` as the development value.
A single service can be run from the reactor without installing everything:
mvn spring-boot:run -pl openframe/services/openframe-apiThe `-pl` flag selects the `openframe-api` module, and the module path tells you the layout, with services under `openframe/services/` and the agent under `clients/openframe-client`.
The repository root has the deployment material as well: `helm-values.yaml` for Helm values, a `manifests/` directory, a `configs/` directory, `docs/`, and a `pom.xml` for the reactor. There is a `renovate.json` for dependency updates, a `.trivyignore` for the container vulnerability scanner, a `.mvn/` directory for Maven configuration, and an `openframe-oss-tenant.code-workspace` file for the VS Code workspace.
The agent binary can be checked without installing it:
./clients/openframe-client/target/debug/openframe-client --helpThe licence is custom, and the legal files are in the repository
The licence is not one GitHub can classify. The README links a `LICENSE.md` whose badge reads Flamingo AI Unified v1.0, and the licence field is listed as Other with a pointer to that file.
That means the terms are in the file and nowhere else, and the badge is the only summary. A team evaluating this project needs to read `LICENSE.md` rather than assume MIT, Apache or something similar, because a custom AI-focused licence can and does include restrictions that a standard one would not.
The repository root is also unusually well stocked with legal and policy documents: `TERMS.md`, `PRIVACY.md`, `PAYMENT-TERMS.md` and `SECURITY.md`. The presence of a payment terms file in an open source repository is worth noting, since it suggests the open source edition is governed by terms that differ from the commercial offering, which is the pattern for a company whose core product is commercial and whose foundation is open.
There is also a `CLAUDE.md` file at the root, which is the artefact a project uses to describe itself to a coding agent. Its presence in a platform repository of this size suggests the team relies on agents in its development workflow, and it is a file worth reading because it usually records the conventions an automated contributor is expected to follow.
The `CONTRIBUTING.md` file is also there, and the README points at the OpenFrame platform site and the Flamingo site for the wider context.
Where OpenFrame OSS Tenant is the wrong tool
The first wrong case is a team that wants a single process. This is six services, six datastores and an agent, and the README describes the data layer as MongoDB, Cassandra, Pinot, Redis, Kafka and NATS JetStream. That is an infrastructure project before it is a software project, and the operational cost of running Kafka and two analytical databases is not trivial.
The second wrong case is a single managed device, or a handful. The platform is built for an MSP with a fleet, with per-tenant OAuth2 clients, tenant-scoped templates, an authorization server, RMM tooling, AI support agents and a tool orchestration layer. None of that pays for itself at small scale.
The third is a deployment that cannot run a NATS and Kafka pair alongside a Rust agent on every endpoint. The agent communicates exclusively over NATS, so an environment that blocks outbound NATS, or a fleet of machines you do not control, rules out the agent and with it the device management and remote execution features.
The fourth is a team that needs a clear answer on what the open source edition actually is. The repository description says single tenant while the README describes a multi-tenant platform with full tenant isolation, and a custom licence sits alongside terms, privacy and payment documents. That ambiguity has to be resolved with the project before you build on it, and the resolution is not in the repository.
What the project does offer is a complete, self-hostable MSP platform that you can deploy and extend on your own infrastructure, with the multi-tenancy, the identity and the AI support pieces already assembled rather than left to each integrator.
Editorial conclusion
OpenFrame OSS Tenant suits a managed service provider that already runs Java and wants device management, remote scripting, AI-assisted support and multi-tenant isolation in one self-hosted stack, and that is prepared to run six services plus Kafka, NATS, MongoDB, Cassandra, Pinot and Redis. It does not suit a small team that wants a single binary, and it does not suit a deployment that cannot keep a per-tenant OAuth2 and JWT issuance model in order. Before adopting it, read `TERMS.md`, `PRIVACY.md` and `PAYMENT-TERMS.md` alongside the custom licence in `LICENSE.md`, confirm the six documented ports and the data stores in `helm-values.yaml` and `manifests/` fit your cluster, and read the `CLAUDE.md` file in the repository root, which is an unusual artefact to find in a platform repository.
Frequently asked questions
What services make up OpenFrame OSS Tenant?
Six: the API Service on port 8080, the Gateway on 8081, the Authorization Server on 8082, the External API on 8083, the Client Service on 8084 and the Stream Service on 8085, plus the Rust `openframe-client` agent that runs on managed endpoints.
How does OpenFrame OSS Tenant isolate tenants?
Through per-tenant OAuth2 clients, RSA-signed JWTs issued by the Authorization Server, and `TenantAwareMongoTemplate` database scoping in the data layer, with the Gateway validating JWTs and the GraphQL API carrying multi-tenant scoping.
What do I need to build OpenFrame OSS Tenant?
JDK 21, Apache Maven 3.9 or newer and Rust 1.78 or newer. The backend builds with `mvn clean install -DskipTests` and the agent with `OPENFRAME_VERSION=0.0.0-dev cargo build` from `clients/openframe-client`.
Which databases and streaming systems does OpenFrame use?
MongoDB as the primary tenant-scoped datastore, Apache Cassandra for time-series storage, Apache Pinot for real-time analytics, Redis for cache and sessions, Apache Kafka with Kafka Streams for event streaming, and NATS JetStream for agent messaging.
How is the OpenFrame agent installed on an endpoint?
With `sudo ./target/release/openframe-client install` passing `--serverUrl`, `--initialKey` and `--orgId`. It installs as a system service on Windows, macOS and Linux and self-updates via Velopack.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/flamingo-stack-openframe-oss-tenant)Was this useful?