diff --git a/guides/rtmp-server-ha-clustering/index.php b/guides/rtmp-server-ha-clustering/index.php index d51df35..798728e 100644 --- a/guides/rtmp-server-ha-clustering/index.php +++ b/guides/rtmp-server-ha-clustering/index.php @@ -67,16 +67,27 @@ - "1941:1941"

2. Join additional nodes

-

Each joiner needs an empty database (no prior streams or raft_* state) and the same secret:

+

Each joiner needs an empty database (no prior streams or raft_* state) and the same secret. A fresh join also needs a one-time join proof — CLUSTER_SECRET on its own can no longer enroll a learner. Mint the proof on an existing member with the normal API token, using the exact addresses the new node will advertise:

+
curl -sS -X POST http://10.0.0.1:8080/api/v1/cluster/join-proof \
+  -H "Authorization: Bearer <api-token>" \
+  -H "Content-Type: application/json" \
+  -d '{"node_id": 2, "control_addr": "10.0.0.2:1940", "media_addr": "10.0.0.2:1941"}'
+

The response carries a proof string. Start the joining node with it, plus the advertise addresses the proof was minted for:

CLUSTER_ENABLED=true
 CLUSTER_NODE_ID=2
 CLUSTER_JOIN=10.0.0.1:1940
+CLUSTER_JOIN_PROOF=<join-proof>
 CLUSTER_SECRET=<same-secret>
+CLUSTER_BIND=0.0.0.0:1940
+CLUSTER_MEDIA_BIND=0.0.0.0:1941
+CLUSTER_ADVERTISE_ADDR=10.0.0.2:1940
+CLUSTER_MEDIA_ADVERTISE_ADDR=10.0.0.2:1941
 LRTMP2_DB=/data/node2.db
+

A fresh join without CLUSTER_JOIN_PROOF is rejected before the join request is even sent. The proof is bound to the node ID and to both advertised addresses, so mint a new one if any of those values change. Restarting a node that already has local Raft state resumes instead of joining and needs no new proof.

Joined nodes start as learners. After catch-up, promote to voter:

curl -X POST http://10.0.0.1:8080/api/v1/cluster/nodes/2/promote \
   -H "Authorization: Bearer <api-token>"
-

Do not copy a live SQLite file from another node and join — that creates conflicting Raft state. To reseed, delete the node's DB files and join again.

+

Do not copy a live SQLite file from another node and join — that creates conflicting Raft state. To reseed, delete the node's DB files, mint a fresh join proof, and join again.

3. Operate from the API or panel

Useful authenticated endpoints:

@@ -86,6 +97,7 @@ GET/api/v1/clusterLeader, term, quorum, load GET/api/v1/cluster/nodesPeer list and health states GET/api/v1/cluster/streamsOwner, epoch, mesh subscriptions + POST/api/v1/cluster/join-proofMint a proof authorizing one fresh node join POST.../nodes/{id}/drainMark node DRAINING POST.../nodes/{id}/resumeMark node READY DELETE.../nodes/{id}Remove voter (releases its owners)