Files
baseos/readme.md
T

195 lines
8.3 KiB
Markdown

# @serve.zone/baseos
BaseOS is the Cloudly-enrolled runtime layer for balenaOS-derived devices in the serve.zone ecosystem. The current package provides `BaseRunner`, a small Deno service/container that stores device identity, reports runtime status to Cloudly, and talks to the local Balena Supervisor API when that API is exposed.
## Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
## What Exists Today
BaseOS is not a full operating system distribution in this repository. It is the first app-layer runtime component for a future Cloudly-managed BaseOS device flow.
Implemented now:
- `BaseRunner` loads configuration from environment variables.
- It persists `nodeId` and `nodeToken` state in JSON.
- It registers with Cloudly through provisional BaseOS HTTP endpoints.
- It sends periodic heartbeats with runtime and Supervisor status.
- It checks Balena Supervisor availability through `/ping`.
- It reads Supervisor device and target-state status when credentials are available.
- It can request an app-layer update through the Supervisor `/v1/update` endpoint.
- It ships a Dockerfile and `docker-compose.yml` for running `baserunner` as a balenaOS service.
Explicit non-goals for the current package:
- It does not enroll devices in BalenaCloud.
- It does not replace openBalena.
- It does not implement a Balena-compatible backend.
- It does not perform host OS updates.
- It does not provide a full image build pipeline by itself.
## Runtime Model
```text
balenaOS-derived host
Balena Supervisor
baserunner container
- persistent BaseOS node state
- Cloudly registration and heartbeat
- Supervisor status reads
- Supervisor app update requests
Cloudly
/baseos/v1/nodes/register
/baseos/v1/nodes/heartbeat
```
The matching Cloudly handlers live in the `cloudly` repository. A Cloudly deployment must be configured with a valid BaseOS join token before new devices can enroll.
## Configuration
`BaseRunner.fromEnv()` reads these environment variables:
| Variable | Purpose |
| --- | --- |
| `BASEOS_CLOUDLY_URL` | Cloudly base URL. Without it, Cloudly sync is reported as `not-configured`. |
| `BASEOS_JOIN_TOKEN` | Initial enrollment token used before a node token exists. |
| `BASEOS_NODE_TOKEN` | Existing machine token for heartbeats. Usually persisted after registration. |
| `BASEOS_NODE_ID` | Optional fixed node ID. A UUID is generated if missing. |
| `BASEOS_STATE_PATH` | State file path. Defaults to `/data/baseos/state.json`. |
| `BASEOS_HEARTBEAT_INTERVAL_MS` | Heartbeat interval. Defaults to `60000`. |
| `BALENA_SUPERVISOR_ADDRESS` | Supervisor API base URL injected by balenaOS when enabled. |
| `BALENA_SUPERVISOR_API_KEY` | Supervisor API key injected by balenaOS when enabled. |
The provided compose file enables Supervisor API access with the `io.balena.features.supervisor-api: '1'` label and stores state in the `baseos-data` volume.
## CLI
```bash
deno run --allow-env --allow-net --allow-read=/data/baseos,. --allow-write=/data/baseos mod.ts <command>
```
| Command | Purpose |
| --- | --- |
| `start` | Start BaseRunner and keep the process alive. This is the default command. |
| `status` | Print runtime, Supervisor, and Cloudly status as JSON. |
| `check-supervisor` | Print Supervisor API configuration and availability. |
| `request-update [--force]` | Ask the Balena Supervisor to check/apply app release updates. |
| `help` | Print command help. |
Example one-shot status check:
```bash
deno run --allow-env --allow-net --allow-read=/data/baseos,. --allow-write=/data/baseos mod.ts status
```
Run the container shape used by balenaOS:
```bash
docker compose up --build baserunner
```
## Cloudly Enrollment Flow
```text
1. Cloudly operator creates or configures a BaseOS join token.
2. Device boots with BASEOS_CLOUDLY_URL and BASEOS_JOIN_TOKEN.
3. BaseRunner creates or loads local state.
4. BaseRunner POSTs runtime status to /baseos/v1/nodes/register.
5. Cloudly returns a node token when registration is accepted.
6. BaseRunner saves the node token and uses it for future heartbeats.
7. BaseRunner POSTs runtime status to /baseos/v1/nodes/heartbeat on each interval.
```
Registration payloads contain the current runtime status object. Heartbeat responses can include desired state, but this package currently records connectivity and does not yet perform host-level rollout control.
## Supervisor API Usage
Supervisor calls are made only when `BALENA_SUPERVISOR_ADDRESS` is configured. Calls that require authorization also require `BALENA_SUPERVISOR_API_KEY`.
Current endpoints:
| Endpoint | Purpose |
| --- | --- |
| `GET /ping` | Availability check. |
| `GET /v1/device?apikey=...` | Device state. |
| `GET /v2/state/status?apikey=...` | App target-state/status. |
| `GET /v2/version?apikey=...` | Supervisor version. |
| `POST /v1/update?apikey=...` | Request app release update. |
| `POST /v1/reboot?apikey=...` | Request reboot. |
## Programmatic Usage
```typescript
import { BaseRunner, SupervisorClient, CloudlyConnector } from './mod.ts';
const runner = BaseRunner.fromEnv();
await runner.start();
```
Exported modules:
| Export | Purpose |
| --- | --- |
| `BaseRunner` | Runtime coordinator and heartbeat loop. |
| `SupervisorClient` | Minimal Balena Supervisor API client. |
| `CloudlyConnector` | Cloudly register/heartbeat HTTP client. |
| BaseOS types | Runtime status, desired state, and connector result interfaces. |
| `runCli` | CLI entry point for embedding or tests. |
## Development
```bash
deno task start
deno task dev
deno task check
deno task lint
deno task fmt
deno task test
```
`deno task test` currently delegates to `deno check mod.ts`.
Source map:
| Path | Purpose |
| --- | --- |
| `mod.ts` | Module exports and CLI execution. |
| `ts/cli.ts` | Command routing. |
| `ts/classes.baserunner.ts` | Main runtime state and heartbeat loop. |
| `ts/classes.cloudlyconnector.ts` | Cloudly HTTP client. |
| `ts/classes.supervisorclient.ts` | Supervisor API client. |
| `ts/types.ts` | Runtime and connector contracts. |
| `docker-compose.yml` | balenaOS-style service definition. |
| `Dockerfile` | Deno container image for BaseRunner. |
## Security Notes
- Treat join tokens, node tokens, and Supervisor API keys as secrets.
- Keep the BaseRunner container private to the device; Supervisor API access is powerful.
- Prefer short-lived or one-time join tokens in Cloudly.
- Do not log token values in device provisioning or fleet diagnostics.
- Host OS release signing and host update enforcement are future work, not current functionality.
## License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
### Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
### Company Information
Task Venture Capital GmbH\
Registered at District Court Bremen HRB 35230 HB, Germany
For any legal inquiries or further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.