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.
What Belongs
- Go server and database migrations.
- React web console.
- SignalForge CLI recorder runtime and legacy recorder build scripts.
- Dockerfiles, compose files, and the environment helper for local, production-style, Portainer, and peer-stack deployments.
- Operator documentation, update manifest behavior, and SignalHub federation docs.
- Example environment files with safe placeholders.
What Stays Out
- Real
.envfiles. - API keys, source upload keys, mail credentials, webhook URLs, database passwords, and operator-only deployment notes.
- Generated build output, local volumes, or machine-specific config.
- Anything that makes one operator's hub look official by default.
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.
# .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
- Anyone can run a hub.
- Direct peering uses invite tokens.
- SignalForge can list known hubs.
- Verified and official status require maintainer approval.
- Remote sources stay labeled with their origin hub.