Hive is the central ingest and dashboard server for Bumblebee fleet scans. Endpoints POST NDJSON batches over HTTPS; Hive stores them in SQLite and serves a web UI plus read APIs.
Endpoint (MDM / launchd / cron)
bumblebee scan --output http --http-url https://hive.example.com/v1/ingest
│
▼
Hive (cmd/hive)
POST /v1/ingest → SQLite → GET /v1/* → Dashboard UI
Wire format matches transport.md. State promotion follows state-model.md.
No local Go or Node required — the image builds the UI and receiver inside Docker.
# From the repo root
docker compose up --build- Dashboard: http://localhost:8080
- Ingest:
POST http://localhost:8080/v1/ingest - Default bearer token:
dev-token-change-me(set indocker-compose.yml)
Data persists in the hive-data Docker volume (/data/hive.db inside the container).
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --buildThen point Bumblebee at the same URL with --http-auth none (loopback HTTP only).
From the same machine as Docker (WSL, macOS, or Linux):
export BUMBLEBEE_TOKEN=dev-token-change-me # skip if using docker-compose.dev.yml + --http-auth none
bumblebee scan --profile baseline \
--output http \
--http-url http://127.0.0.1:8080/v1/ingest \
--http-auth bearer \
--http-token-env BUMBLEBEE_TOKEN \
--http-allow-insecure127.0.0.1 is treated as loopback, so plain HTTP is allowed without TLS for local testing.
From another host on your LAN, publish port 8080 and use your machine’s IP; for non-loopback HTTP you still need --http-allow-insecure or HTTPS in front of Hive.
Edit HIVE_TOKEN and the -token flag in docker-compose.yml, then:
docker compose down
docker compose up --buildRequires Go 1.25.10+ (see toolchain in go.mod). If go mod tidy fails with
toolchain not available, install Go manually instead of relying on auto-download:
# Linux / WSL (amd64) — example
curl -fsSL https://go.dev/dl/go1.25.10.linux-amd64.tar.gz -o /tmp/go.tgz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf /tmp/go.tgz
export PATH=/usr/local/go/bin:$PATH
go version # should report go1.25.10
# Or use the official version manager
go install golang.org/dl/go1.25.10@latest
go1.25.10 download
export PATH="$(go1.25.10 env GOROOT)/bin:$PATH"Corporate networks that block proxy.golang.org must use a full install from
https://go.dev/dl/ — auto toolchain download will not work.
# Build UI
cd web && npm install && npm run build && cd ..
go mod tidy
# Start receiver (serves API + static UI)
go run ./cmd/hive -listen :8080 -web web/dist
# Or API only
go run ./cmd/hive -listen :8080| Mode | Flags / env |
|---|---|
none (dev) |
-auth none |
| Bearer | -auth bearer -token SECRET or HIVE_TOKEN |
| HMAC | -auth hmac-sha256 -hmac-key SECRET or HIVE_HMAC_KEY |
Endpoints use the matching Bumblebee flags (--http-auth, --http-token-env, etc.). Use the same secret on Hive and endpoints.
SQLite file path: -db hive.db (default). WAL mode enabled.
export BUMBLEBEE_TOKEN="<same as Hive bearer token>"
export BUMBLEBEE_DEVICE_ID="<MDM device id>"
bumblebee scan \
--profile baseline \
--output http \
--http-url https://hive.example.com/v1/ingest \
--http-auth bearer \
--http-token-env BUMBLEBEE_TOKEN \
--http-gzip \
--device-id-env BUMBLEBEE_DEVICE_IDSee deployment-macos.md for launchd examples.
| Method | Path | Description |
|---|---|---|
| GET | /v1/health |
Liveness |
| GET | /v1/stats |
Fleet aggregates |
| GET | /v1/endpoints |
All endpoints |
| GET | /v1/endpoints/{id} |
Endpoint + recent runs |
| GET | /v1/runs |
Run list (?endpoint_id=&profile=&limit=) |
| GET | /v1/runs/{id} |
Run metadata |
| GET | /v1/runs/{id}/packages |
Package records (?ecosystem=&q=&limit=&offset=) |
| GET | /v1/runs/{id}/findings |
Finding records |
| GET | /v1/findings |
Fleet-wide findings (?severity=&ecosystem=) |
docker build -f Dockerfile.hive -t bumblebee-hive .
docker run --rm -p 8080:8080 -v hive-data:/data \
bumblebee-hive -listen :8080 -db /data/hive.db -auth bearer -token YOUR_TOKEN -web /web- Raw lines land in
inventory_records_raw. - Each
scan_summaryupsertsinventory_runs. - When
status=complete, package rows for that(endpoint_id, profile, run_id)replaceinventory_currentfor that endpoint/profile. deepruns are stored but should not drive retirement logic for baseline/project current state (operational policy).
endpoint_id = device:<device_id> when endpoint.device_id is set; otherwise host:<hostname>:<uid>.