Skip to content

Joining streamers

cluster.control.nodes

Central stores cluster configuration and decides which streams each streamer runs. To add a machine, the operator opens a join window and provides its address and join token to the machine. Once registered, the streamer obtains a persistent identity, synchronizes settings and reports its state.

Joining does not require copying every stream configuration to the new server. Central delivers assignments, and the operator manages the machine through streamer settings. See installation for deploying Sapsan itself.

Prerequisites

Joining requires:

  • Central address: an HTTP or HTTPS address of the management group reachable from the streamer.
  • Join token: the secret of an active join window obtained by the operator from central.
  • Persistent state directory: a writable directory that survives process or container restarts.
  • Compatible installation: the deployment and license must permit participation in the selected cluster.

The streamer initiates synchronization connections. Reverse requests from central and media reads by neighboring streamers also require correct addresses for the machine. See connectivity and delivery for address directions and purposes.

Join window

The permit_join action opens a window for one hour and issues a join token. Streamers holding that token can register while the window is open. It is temporary permission to create a registration, rather than a permanent streamer password. There is no separate manual approval for each machine: possession of the active token permits registration.

Open the window through the central management API with an administrative key:

curl -fsS -X POST \
  -H "Authorization: Bearer $ADMIN_KEY" \
  https://central.example/central/api-v4/nodes/permit-join

No request body is required. In the response, token contains the join token, open indicates the window state, and remaining_secs gives its remaining lifetime in seconds. Save the token for the machines being added. An ordinary GET on the same URL does not disclose it; retrieve it again for an active window using an administratively authenticated GET /central/api-v4/nodes/permit-join/reveal.

Repeating permit_join while the window is open extends it with the same token. Opening a window after closure or expiry generates a new token. Extending an active window therefore preserves the token already supplied to machines being installed.

One window token can join several streamers. Close the window when they have joined. Closing it or letting it expire does not revoke existing registrations: joined streamers continue synchronization using their own credentials.

curl -fsS -X DELETE \
  -H "Authorization: Bearer $ADMIN_KEY" \
  https://central.example/central/api-v4/nodes/permit-join

A streamer retries a denied initial registration. Check that the window is open and the machine has its current token. If a window expired before a new one was opened, provide the new token to the streamer that has not yet registered.

Enabling managed mode

Configure the connection locally in managed_by:

managed_by:
  url: https://central.example
  name: streamer-01
  join_token: "JOIN_TOKEN_FROM_CENTRAL"
  state_dir: /var/lib/sapsan/central
Field Purpose
url A central address or a list of addresses in one management group.
name An operator label; defaults to the machine hostname.
join_token Initial registration token; no longer used when a saved identity exists.
state_dir Directory for persistent identity and cached configuration. If omitted, the installation's writable state directory containing server.id is used.

The group address can be a list:

managed_by:
  url:
    - https://central-1.example
    - https://central-2.example
  join_token: "JOIN_TOKEN_FROM_CENTRAL"

The list specifies address preference. On network failure the streamer tries other group addresses. It also persists addresses learned from central for use after restart. Do not mix independent clusters: these are alternate entry points to one management group.

An address without a scheme defaults to http://. Specify https:// explicitly and configure the server certificate to use TLS.

The process environment supports the same settings:

Variable Setting
CENTRAL_URL managed_by.url; separate multiple addresses with commas.
NODE_NAME managed_by.name.
JOIN_TOKEN managed_by.join_token.
STATE_DIR managed_by.state_dir.

Environment values override matching configuration settings. Remove obsolete connection variables when moving an installation to another cluster.

managed_by enables managed mode. The central section configures the management component itself and does not replace managed_by. Combining managed_by with another external configuration source, config_external, is not allowed.

Persistent identity

Successful registration returns node_id and a secret node_key. The streamer saves them in identity.json inside state_dir for subsequent synchronization. node_id is the API identifier; neither name nor the hostname is that identity.

On an ordinary restart the streamer loads its identity instead of registering again. No new join window is needed even after the old token expires. Changing the machine label does not create a new registration.

Preserve the state directory during upgrades and container recreation. Losing identity.json loses the streamer's credentials; a corrupt file produces an error instead of silently creating another registration. Copying it to a second machine transfers the same identity rather than joining a new streamer.

The file contains a secret and is created with permissions 0600. Limit access to the process and installation administrators. Do not include identity files or tokens in public diagnostic reports.

Authentication in both directions

Management and media reads use different credentials:

Direction Access mechanism
Streamer → central After joining, the streamer presents node_key as a Bearer secret. Central identifies its registration by this key.
Central → streamer management API Central provisions a separate api_auth account for HTTP Basic and delivers it in managed configuration, for example for session reads and management actions.
Streamer → another streamer Inter-server media and archive reads use a separate signed JWT ticket. Neighboring streamers do not receive node_key.

Requests in both directions therefore have their own authorization mechanisms. This does not automatically configure mutual TLS. With HTTPS, the client performs normal TLS server certificate verification; joining does not pin a separate central key or issue a client certificate.

Check the configured address and use HTTPS or a protected network to carry management secrets. Possession of a join token alone does not authenticate the central server to which it is sent.

Inter-server tickets use Ed25519 signatures and are verified locally by the recipient. Their current lifetime is 24 hours, with renewal by central before expiry. An unexpired saved ticket can support peer reads during temporary central unavailability, but does not grant indefinite access without renewal.

Configuration ownership

In managed mode central owns the stream list: local streams are not merged with assignments and do not become a fallback on connection loss. Create streams and change placement through central. See stream placement.

Server settings have configuration layers. Central delivers streamer settings, but local include files and environment values can override individual fields. A value saved in central can therefore differ from the effective machine value. The interface marks overrides separately; see streamer management for application order.

Update configuration and monitor its application through central. The machine retains the management group address and startup settings needed to connect.

When central is unavailable

The streamer caches received settings and its stream slice on disk. Already applied streams continue running during temporary management connection loss; a local stream list does not replace their configuration.

After restart, the streamer can restore operation from a saved cache and then resume synchronization. Without a usable cache, as on first startup, it needs central to obtain assignments. The join token itself contains no stream configuration.

A rejected node_key does not turn the streamer into a new member: it reports an error and keeps already applied configuration. Restoring the management connection requires operator action. Opening a new join window does not repair an existing registration.

Cached operation does not give the streamer an independent control plane. New assignments and central changes wait for connectivity, and inter-server tickets expire. Continued delivery also depends on sources, disks and other streamers.

Verifying a join

After startup, check:

  1. The streamer appears in the central registry with the expected label and current connection state.
  2. The state directory survives restart and the same registration is reused.
  3. Central can reach the machine API address and neighboring streamers can reach its private delivery address.
  4. Settings are delivered and acknowledged as applied; environment values do not override the required settings.
  5. Assigned streams run, and any required inter-server reads use a valid ticket.

Assess connectivity and configuration application separately from media health. Registration alone does not establish source reachability or storage health; losing central does not immediately stop already running media.