Architecture
Aliran has five peer-to-peer components. Transport, discovery, and replication are fully serverless (Hyperswarm DHT — the mechanics are in How peers find each other). The panel is the logical authority for accounts and catalog, and it is the only online dependency, and only for new logins.
flowchart LR
subgraph Origin
OBS[OBS / RTSP / HLS / file]
end
OBS -->|ingest| B[broadcaster
Linux, headless]
B -->|encrypted feed
Hyperdrive| SW((Hyperswarm DHT))
B -->|register stream| P[panel
accounts + catalog + OPRF]
R[repeater
keyless super-peer] <-->|mirror + serve
ciphertext| SW
L[library
VOD titles] -->|encrypted VOD drives
seed| SW
L -->|register type:'vod'| P
P <-->|login / catalog / entitlement| C1[client APK]
P <-->|login / catalog / entitlement| C2[client APK]
SW <-->|replicate + re-seed| C1
SW <-->|replicate + re-seed| C2
C1 <-->|mesh re-seed| C2
Components
Broadcaster (Linux)
Ingests an existing stream (OBS RTMP push, or a pull from RTSP/HLS/file), transcodes it to live HLS, writes the encrypted segments into a Hyperdrive, and seeds it over Hyperswarm. It registers the stream and its metadata with the panel. Playback "live" is handled by HLS semantics — the P2P layer just moves bytes.
Client (Android phone + TV)
A React Native (react-native-tvos) app embedding Bare via
react-native-bare-kit. Inside Bare: Hyperswarm, a Hyperdrive replica, and a
localhost HTTP server with Range support. react-native-video plays
http://127.0.0.1:<port>/index.m3u8. The client both downloads and
re-seeds — distribution scales with viewers. (The same engine also ships
as aliran-kit, a native Kotlin SDK for non-RN Android apps — one APK
from Android 5.0, with the engine active on 10+; see the
SDK guide.)
Panel (Linux/desktop)
A single-writer, panel-signed Hyperbee holding the account DB and stream catalog, plus an assets Hyperdrive (posters/art). It serves an OPRF login RPC (the brute-force choke point) and issues session and entitlement tokens. Today a deployment runs one panel node — viewers only need it online for new logins. Availability is handled operationally with a warm standby plus a failover runbook (backup & rotation).
Repeater (Linux, optional)
A keyless regional super-peer (repeater.md) — the
Open-Connect analog. Configured with only the panel's public key and a
channel selection, it mirrors chosen channels' live windows raw at the
block level (the catalog's feedKey plus the panel-published blobsKey)
and serves that ciphertext to viewers, absorbing fan-out so the origin
broadcaster's per-channel egress drops to roughly one stream per repeater.
It holds no grants and cannot watch what it serves.
Library (Linux, optional — VOD)
The standalone VOD service (VOD library):
operator-registered video files become encrypted, P2P-seeded on-demand
titles (type:'vod' + durationSec in the catalog, granted exactly like
channels). It is deliberately separate from the broadcaster: ingest is a
one-shot transcode burst and then a static seed — none of the live
pipeline's lifecycle applies, and it runs on whatever box has the disk and
spare CPU. One Corestore plus one Hyperswarm carry every title. A title
keeps all its segments (seek uses HTTP Range over demand-paged P2P
blocks), so disk use equals title size, reclaimed only by delete.
Key data flows
- Login: client → panel OPRF RPC (blinded password, PoW) → derives a key → verifies against the signed DB → unwraps stream keys. See security-model.md.
- Catalog: the panel appends signed metadata; clients
bee.watch()for live updates. - Stream join: the client takes
feedKeyfrom the catalog and theencryptionKeyit unsealed at login (not from the catalog), joins the feed swarm, replicates (decrypting), serves locally, and plays. - Redirect channels: a catalog entry can instead carry
{redirect: true, url}— the client plays the operator's https HLS URL directly (no feed, no swarm join). See content-management.md.
Sequence diagrams
Login (OPRF — brute-force resistant)
sequenceDiagram
participant C as Client
participant P as Panel (OPRF + throttle)
participant DB as Signed account DB (replicated)
C->>C: solve proof-of-work, then blind(password)
C->>P: login(username, blindedPassword, pow)
P->>P: verify PoW, check lockout(username, peerKey)
P-->>C: OPRF(oprfKey, blindedPassword)
Note over P: never sees password or result
C->>C: rwd = unblind(...), wrapKey = Argon2id(rwd, salt)
C->>DB: read signed user/
C->>C: verify against record, unwrap stream keys
C->>C: seal session in Keystore (long TTL)
Stream join & playback
sequenceDiagram
participant U as UI (RN)
participant B as Bare backend
participant SW as Hyperswarm
participant V as react-native-video
U->>B: play(streamId)
B->>B: feedKey from catalog + encryptionKey unsealed at login
B->>SW: join(feed topic) — server+client (re-seed)
SW-->>B: replicate encrypted segments (from broadcaster + peers)
B->>B: start localhost HTTP server (Range) over decrypting drive
B-->>U: { port }
U->>V: source = http://127.0.0.1:port/index.m3u8
V->>B: GET /index.m3u8, /segN.ts (Range)
B-->>V: decrypted HLS bytes → live playback