diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 97dc880..868e4c6 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -5,10 +5,26 @@ openblox runs untrusted, machine-generated code in disposable Linux sandboxes. It is a **Go library first** and a daemon second. There is no control plane, no database, and no scheduler. A sandbox is a container; the container is the state. -## Non-goals +openblox is deliberately the layer *below* a sandbox platform. If you need +scheduling, tenancy or an API of your own, build them on top — the absence of a +control plane here is what makes that possible, rather than something you have +to work around. + +## The rule + +One line decides whether something belongs in openblox: + +> **How a sandbox is isolated is openblox's problem. +> Which sandbox runs where is yours.** -Stating these up front, because every one of them is a place a sandbox project -grows into a platform: +Isolation is the runtime, the egress policy, the filesystem, the user, the +capabilities, the resource caps and the lifetime bounds. Placement is +scheduling, queueing, tenancy, metering, fleet membership and snapshots. + +Every non-goal below is an application of that rule, not a separate opinion — +which is why the list has not grown and is not expected to. + +## Non-goals - **No multi-tenant SaaS.** No organizations, billing, usage metering, or audit log. - **No scheduler.** One host, one daemon. Not a fleet. @@ -17,8 +33,10 @@ grows into a platform: - **No sub-second cold starts.** Correctness and containment over latency. - **No database.** Container labels are the registry. -If you need those, you want a hosted platform. That is a legitimate need and -openblox is the wrong tool for it. +If you need those, build them on top of openblox or use a hosted platform. Both +are legitimate; neither belongs in here. A feature request that crosses the rule +is declined by pointing at the rule, which is the only way a project this small +stays this small. ## Shape diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f3d9ac5..8032eb8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,22 @@ # Contributing +## Scope + +Read this before proposing a feature. One rule decides what belongs in openblox: + +> **How a sandbox is isolated is openblox's problem. +> Which sandbox runs where is yours.** + +Isolation is in scope: runtimes, egress policy, filesystem, users, capabilities, +resource caps, lifetime bounds. Placement is not: scheduling, multi-node, tenancy, +metering, snapshot/resume, an API server, a database. + +openblox is the layer below a sandbox platform. Anything on the placement side is +something you can build on top, and keeping it out is what keeps this small enough +to audit. A PR that crosses the rule will be declined on that basis, however good +it is — so please open an issue before writing one. [ARCHITECTURE.md](ARCHITECTURE.md) +has the reasoning. + ## Setup ```bash diff --git a/README.md b/README.md index aa6d71a..dfa05f3 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,30 @@ openblox takes the third option: a substrate small enough to read in an afternoon, that you run yourself, with isolation supplied by gVisor rather than by hope. +## Where this sits + +openblox is the layer *below* a sandbox platform, not a smaller one. + +``` + your scheduler, your tenancy, your API ← yours to build, if you ever need it + ────────────────────────────────────── + openblox ← isolation, done correctly + ────────────────────────────────────── + Docker + gVisor ← the boundary itself +``` + +One rule decides what belongs here: + +> **How a sandbox is isolated is openblox's problem. +> Which sandbox runs where is yours.** + +Egress, capabilities, filesystem, resource caps, lifetime, runtime: openblox's. +Placement, queueing, tenancy, metering, snapshots: not openblox's, and not +planned. Build those on top when something actually asks for them. That is what +a lower layer is for, and it is why there is no control plane to adopt first. + +The comparison is `libvirt`, not OpenStack. + ## Secure by default The zero value of every option is the safe one. A sandbox created with no @@ -81,6 +105,16 @@ If the host cannot provide the requested isolation, `Create` fails with sandbox that is quietly less isolated than you asked for is worse than no sandbox, because you keep trusting it. +**Two levels of the same guarantee.** In the library, *your* code chooses: the +defaults are safe, and every relaxation is explicit and greppable at the call +site. Through [`openbloxd`](https://openblox.sh/security/#deploying-the-policy-broker-openbloxd) +the choice stops being the caller's at all — profiles live in the daemon's +config file and no request can reach them. A caller names a profile. It cannot +name an image, a runtime, a user, an egress policy, or a resource cap. + +That is the difference between weakening being **visible** and weakening being +**unreachable**, and it is the whole reason the daemon exists. + ## What you get | | | @@ -93,13 +127,18 @@ sandbox, because you keep trusting it. ## What it is not +The first three follow from the rule above — they are placement, not isolation. +The fourth is a trade made on purpose. + - **Not multi-tenant.** No organizations, auth, billing, or metering. Tenancy is the caller's concern. - **Not a fleet.** One host, one daemon. - **No snapshot, fork, or pause/resume.** Stop and re-create from a baked image. - **Not the fastest.** Correctness and containment over cold-start latency. -Those are deliberate. See [ARCHITECTURE.md](ARCHITECTURE.md) for the reasoning. +None of these are gaps waiting to be filled. They are the boundary that keeps +openblox small enough to be worth reading, and requests to cross it get declined +on that basis. See [ARCHITECTURE.md](ARCHITECTURE.md) for the reasoning. ## Install diff --git a/docs/index.md b/docs/index.md index 664bb3b..c39cd86 100644 --- a/docs/index.md +++ b/docs/index.md @@ -39,6 +39,29 @@ kernel with the host. openblox takes the third option: a substrate small enough to read in an afternoon, that you run yourself, with isolation supplied by gVisor rather than by hope. +## Where this sits + +openblox is the layer *below* a sandbox platform, not a smaller one. + +``` + your scheduler, your tenancy, your API ← yours to build, if you ever need it + ────────────────────────────────────── + openblox ← isolation, done correctly + ────────────────────────────────────── + Docker + gVisor ← the boundary itself +``` + +!!! quote "The rule" + **How a sandbox is isolated is openblox's problem. + Which sandbox runs where is yours.** + +Egress, capabilities, filesystem, resource caps, lifetime, runtime: openblox's. +Placement, queueing, tenancy, metering, snapshots: not openblox's, and not planned. +Build those on top when something actually asks for them. That is what a lower layer +is for, and it is why there is no control plane to adopt first. + +The comparison is `libvirt`, not OpenStack. + ## What you get
@@ -73,6 +96,9 @@ you run yourself, with isolation supplied by gVisor rather than by hope. - **Not a substitute for a threat model.** Read the [security model](security.md) and decide whether its guarantees match your workload. +The first two are the rule above, applied: they are placement, not isolation. They +are not gaps waiting to be filled. + ## Next - [Quick start](getting-started.md) — install, prerequisites, a working example