You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FreeDMR/docs/hdstack.md

6.9 KiB

HDStack multi-process deployment

HDStack raises the aggregate hotspot capacity of one FreeDMR container by running two to five independent FreeDMR HBP workers. It does not raise the connection limit of an individual worker.

Omitting HDSTACK, or setting HDSTACK=1, preserves the existing standard single-FreeDMR process layout. Setting HDSTACK to a value from 2 through 5 selects the generated multi-process layout:

hotspots -> proxy -> HBP workers -> no-HBP aggregator -> external FBP/OBP
                                      |
                                      +-> optional separate bridge.py instance

worker reports -> reporting MUX -> existing dashboard/reporting consumer

The aggregator owns all OpenBridge/FBP links from the main freedmr.cfg and has no HBP MASTER, PEER or XLXPEER system. The optional bridge.py process retains its own configuration and rules. The reporting MUX reads only worker reports; aggregator and bridge reporting are not included.

Container configuration

Add these environment values to the standard freedmr service:

environment:
  - HDSTACK=2
  - HDSTACK_BASEID=23400

HDSTACK_BASEID is the aggregator server ID. Worker IDs are allocated by adding their one-based worker number. For the example above, the aggregator is 23400 and the two workers are 23401 and 23402. With HDSTACK=5, worker IDs continue through 23405.

The separate bridge.py process is enabled by default. Disable it when the deployment does not require bridge rules or HBP peer/XLX connections:

environment:
  - HDSTACK_BRIDGE=0

HDSTACK_BRIDGE accepts only 0 or 1. It affects only multi-process mode. When disabled, no bridge configuration or rules file is required and no bridge.py process is started. Remove or disable any aggregator OpenBridge section intended only to connect to that bridge instance.

When the bridge is enabled, multi-process mode requires its existing inputs:

volumes:
  - '/etc/freedmr/freedmr.cfg:/opt/freedmr/freedmr.cfg'
  - '/etc/freedmr/freedmr-bridge.cfg:/opt/freedmr/freedmr-bridge.cfg:ro'
  - '/etc/freedmr/rules-bridge.py:/opt/freedmr/rules.py:ro'

The paths can be changed with:

environment:
  - HDSTACK_BRIDGE_CONFIG=/opt/freedmr/freedmr-bridge.cfg
  - HDSTACK_BRIDGE_RULES=/opt/freedmr/rules.py

The main freedmr.cfg remains the sysop-facing aggregator and worker-template configuration. It must contain one enabled [SYSTEM] stanza in MASTER mode. All enabled and disabled OPENBRIDGE sections are copied to the aggregator; this includes external FBP/OBP links and the configured link to bridge.py. Other protocol systems, including [SYSTEM] and [ECHO], are not copied to the aggregator.

Each worker receives the same [SYSTEM] policy. Only its base HBP port is derived. Worker and aggregator configuration files are generated privately in /dev/shm/freedmr-hdstack when the container starts. The mounted source configuration and bridge files are not changed.

When enabled, the bridge configuration must contain the reciprocal link to the aggregator and any PEER or XLXPEER systems used by bridge.py. Its rules.py remains the authority for bridge routing. Bridge reporting must either be disabled or use a port which does not collide with the worker reports or MUX.

Worker ports

The [SYSTEM] PORT and GENERATOR values define each worker range. With the standard values PORT=54000 and GENERATOR=100:

worker 1 -> 54000..54099
worker 2 -> 54100..54199
worker 3 -> 54200..54299
worker 4 -> 54300..54399
worker 5 -> 54400..54499

The generated ranges must fit within the UDP port range and must not collide with configured bridge, external OpenBridge or reporting ports.

Workers connect to the aggregator over generated loopback OBP v1 links. Worker ports are 7001 through 7005; reciprocal aggregator ports are 7101 through 7105. These links are private to the container.

Session assignment

The proxy rotates new DMR IDs through the configured worker ranges. With two workers the assignments are:

new session 1 -> worker 1
new session 2 -> worker 2
new session 3 -> worker 1
new session 4 -> worker 2

Within the selected worker range, the proxy retains its existing random choice of an available generated system port.

A DMR ID remains pinned to that exact generated port for the lifetime of its active proxy session. Moving it would start a new HBP login and reset its BRIDGES and OPTIONS state. The proxy does not rebalance or fail over an active session. Once the session expires, a later login by the same DMR ID is a new assignment. Affinity is not persisted across proxy restarts.

Existing explicit proxy configurations using DestportStart and DestportEnd continue to describe one range. The equivalent direct multi-range setting is:

[PROXY]
BackendPortRanges: [[54000, 54099], [54100, 54199]]

or:

FDPROXY_BACKEND_PORT_RANGES='[[54000,54099],[54100,54199]]'

The standard HDStack entrypoint supplies this setting automatically.

Proxy diagnostics

In multi-worker mode the proxy logs each backend number and port range during startup. With the standard two-worker layout this includes:

(PROXY)(HDSTACK) Backend:1 ports:54000-54099.
(PROXY)(HDSTACK) Backend:2 ports:54100-54199.

When FDPROXY_CLIENTINFO=1, as in the shipped Compose configuration, client assignment and removal messages include both the backend number and exact generated port. This makes round-robin assignment and retained session affinity visible without enabling packet-level debug logging. Single-backend startup output remains unchanged.

Reporting MUX

When reporting is enabled in the main configuration, worker report ports are derived from its REPORT_PORT. With the default output port 4321:

MUX output -> 4321
worker 1   -> 4322
worker 2   -> 4323
worker 3   -> 4324
worker 4   -> 4325
worker 5   -> 4326

The MUX preserves the existing netstring reporting protocol and the main configuration's REPORT_CLIENTS allow-list. It merges worker configuration and bridge snapshots and relays worker bridge events. System names are prefixed with the stable worker number to prevent collisions:

1:SYSTEM-001
2:SYSTEM-001

Only the system-name field is changed. The reporting protocol contains trusted Python pickle data and must remain on a trusted network.

A failed or malformed worker reporting source is isolated from healthy sources. Reporting failure does not affect the proxy or DMR traffic. If main reporting is disabled, worker reporting and the MUX are both disabled.

Limitations

HDStack deliberately provides no least-connections balancing, active backend failover, live migration, persistent affinity or automatic reconfiguration. A failed worker does not cause its active sessions to move to another worker. The separate bridge config and rules remain sysop-managed; the runtime generator does not create routing policy.

Powered by TurnKey Linux.