// public hub source

Build or Test Your Own Hub

SignalForge is the public community surface for operators. The public hub source is signalforge-node: the buildable hub stack people clone, inspect, and run.

The public hub source lives at github.com/CptPlastic/signalforge-node.

One public source path: clone signalforge-node, generate config, run the Compose stack. Docker Desktop is enough for a first local test.

What Belongs

What Stays Out

Fastest Operator Path

Use the public hub source, official images, Docker Desktop, and the Compose environment helper:

git clone https://github.com/CptPlastic/signalforge-node.git
cd signalforge-node
SIGNALFORGE_PUBLIC_URL=http://localhost:3000 make init-env
make install-up
curl http://localhost:8080/api/v1/health

The helper writes .env.production, generates a strong PostgreSQL password, and asks for the hub URL, name, ports, and optional Mailjet settings. The production Compose stack runs the web console, Go API, and PostgreSQL as separate services with one command. For a laptop test, open http://localhost:3000 after the stack starts.

The latest public tag is published at /p7-scanner-update.json.

Off-Grid Cells

A hub can run as a closed cell with no Mailjet account, no directory refresh, and no update manifest fetch. Operators sign in with email and password; the API bootstraps the first admin from environment variables on startup.

Off-grid is a deployment posture, not a separate product. The same images and compose files work for public federated hubs and for air-gapped field cells — you choose which outbound integrations to enable.
# .env.production excerpt — off-grid cell
AUTH_BOOTSTRAP_EMAIL=admin@local.signalforge
AUTH_BOOTSTRAP_PASSWORD=change-me-strong
AUTH_PASSWORD_LOGIN_ENABLED=true
AUTH_AUTO_APPROVE_USERS=true

UPDATE_CHECK_URL=
HUB_DIRECTORY_URL=
HUB_FEDERATION_ENABLED=false

# Optional: local transcription (same worker as online hubs)
TRANSCRIPTION_WORKER_TOKEN=generate-a-long-random-token

Radio sets support groups mode: pick talkgroup_group names seen in call metadata instead of individual talkgroup IDs, then share a public player link that follows new traffic in those groups automatically. Federation and directory listing remain optional when the cell later joins a wider network.

Hub API

Each hub exposes the same API surface for recorder ingest, public players, federation, hub identity, sources, calls, and radio sets. See SignalForge Hub API.

Recorder CLI

The recommended recorder path is the cross-platform signalforge CLI, also installed as sf. It checks hub connectivity, validates source keys, inspects audio folders, uploads single files, and can watch a folder for stable audio files.

sf recorder check --source-key sk_live_REPLACE_WITH_SOURCE_KEY
sf recorder inspect --input ./calls
  sf recorder watch --input ./calls --source-key sk_live_REPLACE_WITH_SOURCE_KEY
  sf update check

Local Build From Source

cd server
go test ./...
go build ./...
cd client
npm install
npm run build
cd tools/signalforge-cli
  go build -o dist/signalforge ./cmd/signalforge
docker compose up --build -d

Peer Test Stack

cp .env.peer.example .env.peer
  docker compose --env-file .env.peer -f docker-compose.peer.yml up -d

Trust Model