Files
baseos/readme.md
T
2026-05-07 15:53:15 +00:00

256 lines
8.8 KiB
Markdown

# @serve.zone/baseos
BaseOS is the serve.zone runtime layer for devices that should run on balenaOS-derived host systems but enroll only in Cloudly.
The first implementation target is intentionally small: a `baserunner` container runs on the device, talks to the local Balena Supervisor API when available, reports status to Cloudly, and prepares the update path for Onebox and other BaseOS services.
## Goals
- Use balenaOS as the proven host foundation for embedded and edge devices.
- Avoid BalenaCloud enrollment for serve.zone devices.
- Enroll devices directly in Cloudly with a Cloudly join token.
- Let Cloudly track BaseOS nodes, desired releases, rollout state, and update health.
- Let Onebox detect when it is running on BaseOS and delegate self-updates to BaseRunner.
- Keep the first version useful without pretending host OS updates are solved.
## Non-Goals For V1
- No BalenaCloud fleet enrollment.
- No openBalena dependency.
- No full Balena API replacement.
- No remote host OS updates until BaseOS has its own signed artifact channel.
- No silent use of Balena trademarks as serve.zone branding.
## Runtime Model
```text
balenaOS-derived host
Balena Supervisor
baserunner container
- Cloudly enrollment and heartbeat
- local Supervisor API access
- local BaseOS runtime API for Onebox, later
onebox container, later
- detects BaseOS through BaseRunner
- delegates self-update to BaseRunner
- runs Onebox-managed apps in its own runtime model
```
The current scaffold implements `baserunner`; the matching Cloudly registration and heartbeat handlers live in the `cloudly` repo. Onebox integration is still a later focused change.
## Levels
### Level 1: App-Layer Updates
Level 1 is the first production target.
BaseOS devices boot a balenaOS-derived image with `baserunner` preloaded. `baserunner` enrolls the node in Cloudly, reports Balena Supervisor/device state, and can ask the local Supervisor to check/apply application release updates.
Cloudly responsibilities:
- Store BaseOS node records.
- Issue and validate join tokens.
- Accept BaseRunner heartbeats.
- Track current BaseRunner/Onebox release metadata.
- Publish desired app-layer release state.
BaseRunner responsibilities:
- Persist a node ID and node token in a named volume.
- Report supervisor availability, OS version, supervisor version, release hash, update state, and IP information.
- Receive desired app-layer state from Cloudly heartbeats.
- Call Supervisor API endpoints such as `/ping`, `/v1/device`, `/v2/state/status`, and `/v1/update`.
Onebox responsibilities:
- Detect BaseOS via a local BaseRunner API and explicit environment such as `SERVEZONE_RUNTIME=baseos`.
- Disable direct self-replacement when running on BaseOS.
- Ask BaseRunner to perform BaseOS-safe app-layer updates.
Level 1 does not update the host OS remotely. Host OS updates are manual or deferred.
### Level 2: Cloudly-Managed Host OS Releases
Level 2 adds a Cloudly-owned BaseOS update channel.
Cloudly or a central serve.zone update service hosts signed BaseOS host OS artifacts. Devices are still enrolled only in Cloudly.
Artifact layout target:
```text
https://updates.serve.zone/baseos/<device-type>/<version>/manifest.json
https://updates.serve.zone/baseos/<device-type>/<version>/checksums.txt
https://updates.serve.zone/baseos/<device-type>/<version>/license-bundle.tar.gz
registry.serve.zone/baseos/hostapp/<device-type>:<version>
registry.serve.zone/baseos/baserunner:<version>
```
Cloudly responsibilities:
- Maintain approved BaseOS channels.
- Pin desired host OS versions per node or fleet.
- Verify release signatures before rollout.
- Track staged, applying, succeeded, failed, and rollback-needed states.
BaseRunner responsibilities:
- Verify release manifests and signatures.
- Hold update locks during critical work.
- Coordinate with the host update mechanism where available.
- Report detailed progress and failure logs.
This level requires careful work against balenaOS host update internals and licensing obligations for redistributed images.
### Level 3: Cloudly As A Balena-Compatible Backend
Level 3 is the largest option and should only happen if Level 2 is insufficient.
Cloudly would implement enough target-state and artifact APIs for a balenaOS-derived Supervisor to treat Cloudly as its backend. The device `config.json` would point to Cloudly-controlled endpoints instead of BalenaCloud endpoints.
Target endpoints would include equivalents for:
- API target state.
- Registry pulls.
- Delta service, if implemented.
- VPN or remote access, if required.
- Device diagnostics and logs, if required.
This level is effectively a focused openBalena-like backend inside serve.zone. It is not a first milestone.
## Cloudly-Only Enrollment
BaseOS devices should not need BalenaCloud identity.
Enrollment flow:
```text
1. User creates a BaseOS join token in Cloudly.
2. BaseOS image is flashed with BASEOS_CLOUDLY_URL and BASEOS_JOIN_TOKEN.
3. BaseRunner boots and registers against Cloudly.
4. Cloudly returns a node token.
5. BaseRunner stores the node token in /data/baseos/state.json.
6. Future heartbeats use the node token.
```
Current provisional HTTP endpoints used by this scaffold:
- `POST /baseos/v1/nodes/register`
- `POST /baseos/v1/nodes/heartbeat`
Cloudly implements these paths through its BaseOS manager. A deployed Cloudly instance must also have `baseosJoinToken` configured before new nodes can enroll.
## Supervisor API Usage
BaseRunner uses Balena Supervisor APIs only when `BALENA_SUPERVISOR_ADDRESS` and `BALENA_SUPERVISOR_API_KEY` are provided by the `io.balena.features.supervisor-api` service label.
Current calls:
- `GET /ping`
- `GET /v1/device?apikey=...`
- `GET /v2/state/status?apikey=...`
- `GET /v2/version?apikey=...`
- `POST /v1/update?apikey=...`
- `POST /v1/reboot?apikey=...`
The `docker-compose.yml` enables the supervisor API label for `baserunner`.
## Onebox Integration Plan
Onebox should detect BaseOS through explicit runtime signals, not by guessing from Balena environment variables alone.
Detection signals:
- `SERVEZONE_RUNTIME=baseos`
- `BASEOS_AGENT_URL` or equivalent local BaseRunner API URL
- successful BaseRunner handshake
Onebox behavior on BaseOS:
- Show BaseOS runtime in system status.
- Route self-update requests to BaseRunner.
- Avoid replacing its own container directly.
- Use update locks around backup/restore and migration operations.
## Security
- Join tokens must be one-time or short-lived.
- Node tokens must be long-lived machine tokens scoped to one BaseOS node.
- Host OS release manifests must be signed before Level 2.
- BaseRunner must reject unsigned or untrusted desired host OS updates.
- Supervisor API access is powerful; keep BaseRunner's local API private and minimal.
- Never log join tokens, node tokens, or Supervisor API keys.
## Licensing And Branding
balenaOS source components are open source, but trademarks are separate from copyright licenses.
BaseOS must:
- Preserve required upstream notices and license bundles.
- Provide source/license compliance for redistributed GPL/LGPL/Yocto components.
- Avoid presenting BaseOS as official Balena software.
- Replace public-facing branding when redistributing images.
- Use Balena names only where needed to describe compatibility or documented APIs.
## Implementation Milestones
### Milestone 1: BaseRunner Scaffold
- Deno CLI and daemon structure.
- Supervisor API client.
- Persistent node state.
- Provisional Cloudly register/heartbeat client.
- Balena compose service definition.
### Milestone 2: Shared Interfaces
- Add BaseOS node, runtime status, desired state, heartbeat, and registration contracts to `@serve.zone/interfaces`.
- Add machine role or scoped token model for BaseOS nodes.
### Milestone 3: Cloudly BaseOS Manager
- Join token validation through `baseosJoinToken`.
- Node registration.
- Heartbeat ingestion.
- Desired state storage.
- Admin/UI status views.
### Milestone 4: Onebox Runtime Detection
- Add BaseOS runtime manager to Onebox.
- Add status display.
- Route Onebox self-update through BaseRunner when running on BaseOS.
### Milestone 5: App Release Updates
- Build and publish BaseRunner release images.
- Add Onebox service image/release metadata.
- Let Cloudly request app-layer updates.
- Report update status and failures.
### Milestone 6: Host OS Release Channel
- Build BaseOS host OS images.
- Publish signed manifests and artifacts.
- Add Cloudly release approval and rollout controls.
- Add BaseRunner host update execution and reporting.
## Current Commands
```bash
deno task check
deno task start
deno task dev
deno task fmt
deno task lint
```
Run a one-shot status check:
```bash
deno run --allow-env --allow-net --allow-read=/data/baseos,. --allow-write=/data/baseos mod.ts status
```
Inside balenaOS, the `baserunner` service should be started from `docker-compose.yml` so the Supervisor API environment variables are injected.