Binary Farm is a Bun-based container management plane for a small cluster of Docker hosts.
Today it is a real control plane, not just a mock dashboard. It can persist hosts, enroll and bootstrap runners, inspect live runtime state, manage apps and compose stacks, store encrypted secrets, track activity, expose an internal OCI-style registry surface, and serve a React UI for day-to-day operations.
Binary Farm currently centers on these workflows:
- Host inventory and runner enrollment
- SSH-based host bootstrap for the remote runner binary
- Cluster dashboard with rolled-up host telemetry and activity
- Managed single-container apps with deploy, logs, stop, restart, and kill actions
- Managed compose stacks with deploy, history, and rollback
- Runtime inventory for images, volumes, and networks
- Encrypted secret storage with secret-to-env resolution during deploy
- Model records plus inferred models discovered from running apps
- Operator auth with local passwords, sessions, CSRF protection, and optional OIDC
- System settings for cluster naming, management URL, org email domain, and OIDC
- Embedded registry endpoints under
/v2/*backed by local storage and SQLite metadata - Simple catalog entries from
catalog/*.yamlthat can be deployed as stacks
The UI pages and API surface broadly match that list. The older README was more aspirational than the code; this file describes the code as it exists now.
The project is split into a Bun server and a React frontend.
- Backend: srv/app.ts
- Frontend router: src/router.tsx
- Database and persistence layer: srv/db/db.ts
- Schema bootstrap: srv/init.sql
The Bun server:
- serves the SPA from
dist/ - exposes JSON APIs under
/api/* - exposes websocket endpoints for runners and dashboard updates
- proxies local runtime state when the control plane host itself is being managed
- dispatches Docker commands either locally or to connected remote runners
The React app is a protected SPA with sections for dashboard, hosts, agents, apps, catalog, stacks, images, secrets, network, volumes, settings, and management.
Binary Farm currently persists its control-plane state in SQLite at:
- default:
data/binary-farm.sqlite - override with
BINARY_FARM_DB_PATH
Current persisted tables include:
hostsrunnerssecretsmanaged_appsmanaged_stacksmanaged_stack_historymanaged_modelsactivity_logcontrol_plane_stateregistry_*tables for repository, manifest, blob, and tag metadataswarmsoperator_usersoperator_sessions
Important current behaviors:
- Secret values are stored encrypted at rest.
- A control-plane encryption key is generated automatically and stored in control-plane state.
- A bootstrap admin account is created automatically on first launch if no local admin exists.
- The bootstrap credentials are printed once to the server console.
The current auth model is operator-based, not team-based yet.
Roles today:
operatoradmin
Current auth features:
- local username/password login
- signed session tokens
- CSRF checks for non-safe methods
- login throttling
- password change flow
- operator session revocation on password reset
- optional OIDC login
- optional org email domain gate for creating operators
Relevant files:
- srv/routes/auth.ts
- srv/auth/session.ts
- srv/auth/config.ts
- srv/security.ts
Current security posture around Docker is also important:
- users do not talk to Docker directly
- the control plane authorizes actions
- a local runtime adapter or remote runner executes a constrained Docker command set
- secrets are resolved server-side at deploy time
That keeps Docker access behind the control plane rather than exposing raw engine access in the UI.
Binary Farm tracks hosts and their runtime state through a combination of persisted enrollment data and live telemetry snapshots.
There are two execution paths:
- local runtime execution for the control-plane host
- remote execution through a websocket-connected runner
Host and runner capabilities include:
- listing hosts
- creating, updating, and deleting hosts
- enrolling a runner and issuing a one-time token
- verifying SSH connectivity before bootstrap
- copying and launching the compiled runner on a remote host
- sending Docker commands to a host through
/api/hosts/:id/commands
Relevant files:
- srv/routes/hosts.ts
- srv/runner.ts
- srv/ws/runner.ts
- srv/runtime/local.ts
- srv/runtime/state.ts
- srv/ssh-bootstrap.ts
The dashboard is backed by live and persisted data. It currently shows:
- host rollup metrics
- top apps
- activity stream
- control-plane navigation map
Relevant files:
- src/pages/overview/page.tsx
- srv/routes/system.ts
Hosts are persisted records with optional SSH key material and associated runner enrollment. The UI supports listing, adding, editing, and bootstrapping hosts. Swarm-related views also exist.
Managed apps are single-container definitions stored in SQLite. An app can include:
- image
- command
- env
- secret env bindings
- ports
- volumes
- labels
- restart policy
- optional host assignment
- optional stack association
- optional network
Current app APIs support:
- create, read, update, delete
- deploy to a selected or best-fit host
- runtime inspection by matching live containers
- logs with search, tail, and timestamps support
- stop, restart, and kill
Relevant files:
- srv/routes/apps.ts
- src/pages/apps/page.tsx
- src/pages/apps/logs.tsx
Managed stacks store compose YAML plus environment and secret bindings. They support:
- create, read, update, delete
- deploy
- deployment metadata
- history snapshots
- rollback to a prior snapshot
- runtime container matching by compose namespace or Binary Farm labels
Relevant files:
- srv/routes/stacks.ts
- src/pages/stacks/page.tsx
Secrets are cluster-scoped today. They are stored encrypted and can be bound into app and stack deploys as environment variables.
Relevant files:
- srv/routes/secrets.ts
- src/pages/secrets/page.tsx
Binary Farm has a dedicated models API and an Agents UI section.
Current model behavior:
- persist named model records
- attach records to hosts, apps, or stacks
- infer model-like endpoints from running apps
- summarize explicit and inferred models
Relevant files:
- srv/routes/models.ts
- src/pages/agents/page.tsx
These sections are inventory-driven today.
Images:
- aggregate runtime images across hosts
- pull images to a host
- remove images from a host
Volumes:
- aggregate runtime volumes across hosts
- summarize attached vs unused volumes
- remove a volume from a host
Networks:
- aggregate runtime network inventory across hosts
Relevant files:
- srv/routes/images.ts
- srv/routes/volumes.ts
- srv/routes/networks.ts
Swarm support is present and admin-gated. It currently supports:
- initialize swarm on a manager host
- persist swarm metadata and tokens
- join a host to a swarm
- make a host leave a swarm
- inspect host swarm status
- delete a swarm record
Relevant file:
- srv/routes/swarm.ts
Catalog entries are YAML files in catalog/. The API reads metadata from those files and the UI can deploy an entry by:
- reading the YAML file
- creating a managed stack
- deploying it to a best-fit host
Current catalog metadata fields:
namedescriptionimageversionstacktags
Relevant files:
- catalog/postgres.yaml
- srv/routes/catalog.ts
- src/pages/catalog/page.tsx
Binary Farm exposes registry endpoints under /v2/*.
Current registry behavior includes:
- basic auth using operator credentials
- admin-only write operations
- repository, tag, manifest, and blob metadata stored in SQLite
- backing blob and manifest bodies stored on disk
- local image listing routes in the app UI
This is an embedded registry surface, not just a placeholder.
Relevant file:
- srv/registry/registry.ts
Settings currently manage:
- environment label
- management plane URL
- cluster name
- org email domain
- OIDC configuration
- local host id
Management currently includes:
- list operators
- create operators
- reset operator passwords
- inspect control-plane activity
Relevant files:
- srv/routes/settings.ts
- src/pages/settings/page.tsx
- srv/routes/operators.ts
- src/pages/management/page.tsx
Prerequisites:
- Bun
- Docker available on the control-plane host for local runtime features
Install dependencies:
bun installStart the server in watch mode:
bun run devBuild the frontend and compiled runner binary:
bun run buildRun the production server:
bun run prodThe app listens on port 3000 by default.
Useful environment variables:
PORTENVIRONMENTBINARY_FARM_DB_PATHBINARY_FARM_LOCAL_HOST_IDBINARY_FARM_LOCAL_HOSTNAMEBINARY_FARM_LOCAL_IP
A simple containerized setup is included:
- Dockerfile
- docker-compose.yml
The compose file currently:
- builds the app image
- runs with
network_mode: host - mounts the repo into
/opt/binary-farm - stores SQLite data in a named volume
The current SPA includes these sections:
//hosts/hosts/runners/hosts/swarm/agents/agents/models/apps/apps/add/apps/logs/:appId/apps/registry/catalog/stacks/stacks/add/stacks/history/images/images/pull/secrets/secrets/add/secrets/scopes/network/network/fabric/network/hosts/volumes/volumes/usage/settings/settings/security/management/management/activity
A few things are still clearly in-progress:
- the auth model is still
operatorandadmin, not the future team-based model we discussed - some UI sections still carry placeholder naming or extra framing compared with the underlying functionality
- the catalog is intentionally minimal and file-backed
- registry behavior exists, but it is still a local embedded implementation rather than a full external registry product
- some sections are inventory-first and lighter on mutation flows than apps and stacks
A few project choices are worth preserving:
- Bun is the runtime, build tool, and SQLite host
- the UI is data-backed and operationally focused
- secrets are encrypted and resolved at deploy time
- the runner model keeps Docker access behind the control plane
- stack history and rollback are first-class persisted concepts
That combination is the real center of the project today.