Running the hub
The hub is the only piece the browser talks to: it aggregates readings, persists history, serves the React dashboard, the REST API, the interactive API docs, and the live stream. This page walks through running it with Docker Compose.
Prerequisites
- Docker with the Compose plugin.
- At least one agent token + Steam account if you want live data right away (you can also add agents later from the admin UI). See Running an agent.
Images
The hub and agent are separate images, both published to GHCR:
- Hub:
ghcr.io/buco7854/bloodpoint-incentives/hub:latest - Agent:
ghcr.io/buco7854/bloodpoint-incentives/agent:latest
Compose pulls these by default. You can override them with HUB_IMAGE / AGENT_IMAGE in your .env (for a fork or a pinned tag). The hub image is the static Go binary that serves the SPA. The agent image is the Node runtime with the Steam libraries.
Walkthrough
A single .env file drives everything. Copy the example and edit it:
cp .env.example .envThe shipped docker-compose.yml defines a hub service, a hub-data volume, and one agent service (agent-1):
services:
hub:
image: ${HUB_IMAGE:-ghcr.io/buco7854/bloodpoint-incentives/hub:latest}
container_name: bloodpoint-hub
restart: unless-stopped
ports:
- '${PORT:-3000}:${PORT:-3000}'
env_file: .env
volumes:
- hub-data:/app/data
# - ./hub.yaml:/config/hub.yaml:ro
volumes:
hub-data:
agent-1-data:A few things to note:
env_file: .env: every variable in your.envreaches the hub container. This is also where compose reads theAGENTn_*variables and interpolates the same${AGENT1_TOKEN}into both the hub'sPROVISION_AGENTSand the agent container, so each token is declared once.hub-data:/app/data: the SQLite database (DB_PATH, default./data/bloodpoint.db) lives here. Keep it on a volume so your readings and history persist across restarts and upgrades.- The commented
./hub.yaml:/config/hub.yaml:romount is for the optional YAML config (see below).
Bring it up:
docker compose up -d # pulls the published hub + agent imagesThe hub comes up on http://localhost:3000. It serves the SPA at /, the interactive API docs at /docs, and the OpenAPI spec at /openapi.json.
First run: creating the first admin
On first run the hub has no admin account. There are two ways to create one:
- The
/setuppage: openhttp://localhost:3000/setupand create the first admin interactively. This page only works while there is no admin yet. - Bootstrap from env: set
ADMIN_BOOTSTRAP_USERandADMIN_BOOTSTRAP_PASSWORD(optionallyADMIN_BOOTSTRAP_EMAIL/ADMIN_BOOTSTRAP_NAME) before first boot to seed the admin without the setup page.
TIP
If MFA is enforced for admins (the default), the first admin enrolls a second factor on first login. See Authentication.
Gating the site
By default the dashboard and read API are public. To require a logged-in session to view the whole site, set:
REQUIRE_AUTH=trueThe /healthz endpoint and the /api/v1/agent/* ingest routes (which use per-agent token auth) stay exempt. When the gate is on, read endpoints accept a session or an API key.
Optional: full config in YAML
Instead of a long .env, you can point HUB_CONFIG at a YAML file carrying the entire hub config: settings, cadence, the provision: agent list, and an auth: block. See hub.example.yaml in the repo. The file supports ${ENV} interpolation, and any matching environment variable overrides the file (so the file is the baseline and env is the override). Keep secrets as ${VAR} so they stay in the environment, not in the file.
Uncomment the volume mount and set HUB_CONFIG:
volumes:
- hub-data:/app/data
- ./hub.yaml:/config/hub.yaml:roHUB_CONFIG=/config/hub.yamlBuilding the images yourself
The repo's Dockerfile has a hub and an agent target:
docker build --target hub -t bp-hub .
docker build --target agent -t bp-agent .Next steps
- Running an agent, get live data flowing.
- Configuration, every environment variable explained.
- Authentication, accounts, second factors, the gate.