Skip to content

Akaal-Creatives/resonance

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Resonance logo

Resonance

Central WebSocket hub for multiple Laravel projects.
A single self-hosted Laravel Reverb instance with database-backed, runtime-manageable application credentials.

Status Laravel PHP PostgreSQL


What is Resonance?

Resonance replaces a shared, unmaintained soketi + soketi-manager stack with one dedicated Laravel Reverb server that provides real-time WebSocket connectivity to any number of independent Laravel projects.

Each consumer project is issued its own Pusher-protocol credential triplet (app_id / key / secret). Those credentials live in a database and can be created, rotated, disabled, and deleted at runtime — no redeploy, no config-file edits, no SSH.

Because Reverb speaks the Pusher wire protocol v7 (exactly as soketi did), consumer projects migrate with env-var-level changes only. Their application code and broadcast events are untouched.

Why

  • soketi is effectively unmaintained — no Node 20+ support, stalled releases — forcing a migration.
  • One server for all projects — current and future — instead of per-project infrastructure.
  • Runtime credential management — app creation-to-usable in under two minutes via the admin UI.
  • Minimal-risk cutover — per-project, zero-downtime, instant rollback by reverting env vars.

Architecture

[Project A] --HTTP broadcast (signed with key A)--> \
[Project B] --HTTP broadcast (signed with key B)-->  [nginx TLS] --> [Reverb :8080] <--reads--> [websocket_apps DB]
[Browsers ] --WSS (app key in URL)---------------->  /                                   ^
                                                                                          |
                                                          [Admin UI in Resonance] --------+ (CRUD)

Resonance is a small, single-purpose Laravel application. Its only responsibilities are:

  1. Running the long-lived reverb:start process (a single-threaded ReactPHP event loop).
  2. Owning the websocket_apps table.
  3. Providing a custom DatabaseApplicationProvider that Reverb resolves apps from.
  4. Serving the admin management UI/API.

It hosts no business logic from any consumer project.

The one constraint that shapes everything

Reverb's event loop is single-threaded. A blocking database query inside the per-connection lookup stalls every connected client for the duration of that query. The provider therefore serves all hot-path lookups from an in-process cache (an in-memory array keyed by key and app_id), refreshed lazily with a short TTL. This is a correctness requirement, not an optimisation.

Consequence to be aware of: a newly created or newly disabled app takes up to one TTL window (default 30 s) to become connectable / revoked. Sub-second revocation is a future enhancement, not part of v1.

Features

  • Database-driven apps — the Application option set (origins, ping interval, activity timeout, message size, connection cap, client-event policy) is stored per row.
  • Encrypted secrets at rest — via Laravel's encrypted cast (secrets must be retrievable, as Reverb signs with them).
  • Runtime CRUD — create, rotate, enable/disable, soft-delete apps without a deploy.
  • Instant-ish revocation — disabling an app removes it from the provider within one TTL window.
  • Admin panel (Filament) — app management, one-time credential display, audit log, and a "restart Reverb now" action for immediate propagation.
  • VisibilityLaravel Pulse with Reverb's built-in cards.
  • Drop-in for consumers — Pusher protocol v7 means Echo + pusher-js clients connect unchanged.

Tech stack

Layer Choice
Framework Laravel 12.x, PHP 8.2+
Realtime Laravel Reverb (exact minor pinned)
Database PostgreSQL
Admin UI Filament
Monitoring Laravel Pulse
Deploy Docker / container; nginx (or ingress) terminates WSS on 443 → Reverb :8080; reverb:start under Supervisor

Getting started

Status: Resonance is in active development (Phase 1). The commands below describe the target workflow; some pieces are still being built. See the roadmap.

# 1. Clone
git clone git@github.com:Akaal-Creatives/resonance.git
cd resonance

# 2. Install dependencies
composer install
pnpm install

# 3. Configure
cp .env.example .env
php artisan key:generate
# set DB_* to your PostgreSQL instance

# 4. Migrate
php artisan migrate

# 5. Create your first WebSocket app (prints credentials once)
php artisan res:app:create "My Project"

# 6. Start the Reverb server
php artisan reverb:start

Artisan commands

Command Purpose
php artisan res:app:create {name} Create an app; generates and prints app_id / key / secret once.
php artisan res:app:disable {key} Disable (revoke without deleting).
php artisan res:app:list List apps.
php artisan reverb:start Start the WebSocket server (production: under Supervisor).
php artisan reverb:restart Graceful restart — disconnects clients; Echo/pusher-js auto-reconnect.

Connecting a consumer project

Because both soketi and Reverb speak Pusher protocol v7, migrating a project is an env-var change only:

# Backend — broadcasting connection points at Resonance
PUSHER_APP_ID=<from res:app:create>
PUSHER_APP_KEY=<from res:app:create>
PUSHER_APP_SECRET=<from res:app:create>
PUSHER_HOST=ws.yourdomain.tld
PUSHER_PORT=443
PUSHER_SCHEME=https

Frontend Echo config updates its host and key the same way. Application code and broadcast events do not change. Rollback is reverting these variables.

Keep your existing pusher driver + pusher-js during cutover — do not bundle a driver or client-library migration into the switch.

Roadmap

Phase Scope
0 Decisions & prerequisites — Reverb version pin, soketi inventory, performance baseline.
1 Core — Resonance app skeleton, websocket_apps schema, DatabaseApplicationProvider, in-process cache, CLI. (current)
2 Management layer — Filament admin: CRUD, rotation, audit log, restart action.
3 Per-project migration off soketi — one project at a time, 48 h soak between each.
4 Operational hardening — Supervisor, nginx TLS, OS limits, monitoring, backups.
5 Decommission soketi.

Full detail lives in the internal requirements document (.tmp/resonance-requirements.md, not tracked in the repository).

Security

Resonance's database holds every consumer project's realtime credentials. Its APP_KEY and database are jointly a full-compromise target. Accordingly:

  • Secrets are encrypted at rest and excluded from logs.
  • Secrets are displayed in the UI only at creation / rotation time.
  • Admin access is restricted to named users; there is no self-registration.
  • Every credential-affecting action is written to an audit log.

Found a vulnerability? Please do not open a public issue — email the maintainers directly.

Contributing

See CONTRIBUTING.md. In short: conventional commits, branch from main, Pint + PHPStan clean, tests green — and never introduce blocking I/O on the Reverb event-loop path.

Licence

Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See LICENSE.

About

Self-hosted WebSocket hub built on Laravel Reverb. Serves realtime connectivity to multiple independent Laravel apps from a single server, with database-backed app credentials, runtime app management, and an admin UI. Pusher protocol compatible - a drop-in replacement for soketi.

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Contributors