control plane

Pulse

Service registry and shared configuration layer. Beacon apps register with it out of the box, and any Go service can join through the client SDK at pkg/sdk — tap into shared indexers, quality profiles, download clients, and media-handling settings with a single client instance.

Port :9696 Go 1.25 Postgres MIT

What Pulse does

Service registry

Each Beacon service registers on startup with its name, type, URL, and capabilities, then heartbeats periodically. Move Pilot to a new host — Prism picks up the address on the next heartbeat cycle with no config edits.

Indexer management

Indexers — the search APIs that catalog torrent and Usenet releases — usually mean a Torznab or Newznab endpoint. Add one to Pulse and it's auto-assigned to every service whose capabilities match the indexer's catalog category: Movies-tagged indexers reach Prism, TV-tagged reach Pilot. A built-in catalog with pre-filled setting schemas, one-click add, and a tester that verifies connectivity before saving make first-time setup quick.

Quality profile management

A quality profile is a ranked list of acceptable resolutions, sources, and codecs plus an upgrade cutoff — what the manager will and won't grab, and when it stops looking for something better. Profiles live in Pulse and mirror to Pilot and Prism with a managed_by_pulse flag: synced copies are read-only, local-only profiles still work for per-app overrides. Edit a 1080p cutoff once in Pulse and both services update on the next sync.

Shared download clients

When Haul registers as a download client, Pulse auto-creates the entry and shares its address and API key with Pilot and Prism through the registration handshake. No manual key-copy step, no "add download client in each app's settings."

WebSocket event stream

Pulse pushes live updates over /ws and fires per-service sync hooks the moment shared state changes — indexer added, quality profile edited, settings updated. Consumers don't have to wait for the next 30-second poll.

Go client SDK

A drop-in SDK at pkg/sdk for any Go service. Register with retry backoff, auto-heartbeat on a 30-second tick, discover peers by type or capability, pull assigned indexers, and read shared config — all with one client instance.

Dashboard

React 19 + TypeScript UI embedded in the Go binary. No separate server to run.

Pulse dashboard showing VPN connection panel, registered services with health, and download throughput
Dashboard — VPN status, registered services, live throughput
Pulse indexers list with Torznab category badges across eleven configured indexers
Indexers — centrally managed, auto-assigned by content category
Pulse quality profiles list — Any, HD-1080p, HD-720p, SD, Ultra-HD
Quality profiles — defined here, pushed to every consumer

Advanced features

API surface

Full REST API (Huma v2 + Chi v5) under /api/v1/. OpenAPI docs at /api/docs. WebSocket event stream at /ws. Everything the UI does is available over HTTP.

SDK — register and pull

pkg/sdk
client, _ := sdk.NewWithRetry(sdk.Config{
    PulseURL:    "http://pulse:9696",
    ServiceName: "pilot",
    ServiceType: "media-manager",
    APIURL:      "http://pilot:8383",
    Capabilities: []string{"content:tv", "supports_torrent"},
})
indexers, _ := client.MyIndexers(ctx)
clients,  _ := client.DiscoverByType(ctx, "download-client")

Storage

Postgres-backed state with Goose migrations and SQLC-generated type-safe query code. Zero configuration out of the box — all settings editable in the UI or via PULSE_* environment variables.

Tag management

Central tag registry with usage counts. Tags drive indexer assignment (tv, movies, all), notification routing, and library filtering across every service — managed once in Pulse.

Getting started with Pulse

Standalone Docker for a single-service install. Full stack compose in beacon-stack/deploy.

docker
docker run -d \
  --name pulse \
  -p 9696:9696 \
  -v /path/to/config:/config \
  ghcr.io/beacon-stack/pulse:latest

Open http://localhost:9696 — Pulse starts with zero additional configuration.

Environment variables

Variable Default Description
PULSE_PORT9696Host port for the web UI and API. Set in .env if 9696 is taken on your host.
PULSE_CONFIG_PATH./config/pulseWhere Pulse's config.yaml and cached state live. Override to put configs on a different volume.
PULSE_FLARESOLVERR_URLFlareSolverr endpoint for Cloudflare-protected indexers. Opt-in: uncomment in docker-compose.yml and set COMPOSE_PROFILES=flaresolverr.
PULSE_DASHBOARD_DOCKER_SOCKETPath to the Docker socket. Enables container resource panels in the dashboard. Opt-in: uncomment both this var and the /var/run/docker.sock mount in docker-compose.yml.
PULSE_DASHBOARD_GLUETUN_URLGluetun control-server URL for the dashboard's VPN panel. Auto-set to http://vpn:8000 when the VPN overlay is active.
LOG_LEVELinfoSet once in .env; Compose passes the same value to every Beacon service. debug, info, warn, error.
TZUTCIANA timezone (e.g. America/New_York). Set once in .env and applied to every service for log timestamps and scheduled tasks.