# Pool members & enrollment

### Member tab layout

Click a member in the tab bar to open its <span class="font-semibold" data-streamdown="strong">workspace</span>. Sub-tabs:

<div class="ui-scroll-area" data-direction="horizontal" data-scroll-padding="4" data-visibility="hover" id="bkmrk-tab-purpose-control-"><div class="ui-scroll-area__viewport"><div class="ui-scroll-area__content"><table><thead class="bg-muted/80" data-streamdown="table-header"><tr class="border-border border-b" data-streamdown="table-row"><th class="whitespace-nowrap px-4 py-2 text-left font-semibold text-sm" data-streamdown="table-header-cell">Tab</th><th class="whitespace-nowrap px-4 py-2 text-left font-semibold text-sm" data-streamdown="table-header-cell">Purpose</th></tr></thead><tbody class="divide-y divide-border bg-muted/40" data-streamdown="table-body"><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content"><span class="font-semibold" data-streamdown="strong">Control panel</span></div></td><td><div class="md-table-cell-content">Host ops: reboot, updates, hostname, TLS domain (non-HAProxy PEM)</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content"><span class="font-semibold" data-streamdown="strong">Security</span></div></td><td><div class="md-table-cell-content">UFW firewall, SSH enable/disable, firewall backup</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content"><span class="font-semibold" data-streamdown="strong">Status</span></div></td><td><div class="md-table-cell-content">Live HAProxy traffic stats from heartbeat (`show stat`)</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content"><span class="font-semibold" data-streamdown="strong">Cron &amp; Jobs</span></div></td><td><div class="md-table-cell-content">Scheduled tasks + job timeline</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content"><span class="font-semibold" data-streamdown="strong">Restore Backups</span></div></td><td><div class="md-table-cell-content">List snapshots, scoped backup/restore</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content"><span class="font-semibold" data-streamdown="strong">Recipes</span></div></td><td><div class="md-table-cell-content">One-click enable flows (admin socket, SSH, Let’s Encrypt, agent update)</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content"><span class="font-semibold" data-streamdown="strong">Monitoring</span></div></td><td><div class="md-table-cell-content">Member-level alert thresholds</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content"><span class="font-semibold" data-streamdown="strong">Settings</span></div></td><td><div class="md-table-cell-content">Display name, hostname, allowed IPs, geo, remove member</div></td></tr></tbody></table>

</div></div></div>HAProxy-specific <span class="font-semibold" data-streamdown="strong">Management</span> actions (install, reload, drain, TLS failover) are surfaced on <span class="font-semibold" data-streamdown="strong">Control panel</span> and via <span class="font-semibold" data-streamdown="strong">Recipes</span> — the dedicated HAProxy tab exists in code but is hidden until product-ready.

[![HAProxy-HM3.png](https://docs.serversctl.com/uploads/images/gallery/2026-06/scaled-1680-/haproxy-hm3.png)](https://docs.serversctl.com/uploads/images/gallery/2026-06/haproxy-hm3.png)

### Enrollment security model

Each heartbeat must satisfy:

1. <span class="font-semibold" data-streamdown="strong">Bearer token</span> — 48-character enrollment secret (hashed in D1)
2. <span class="font-semibold" data-streamdown="strong">`CF-Connecting-IP`</span> — must match allowed source IP(s)
3. <span class="font-semibold" data-streamdown="strong">JSON `hostname`</span> — must match enrolled hostname

Mismatch → <span class="font-semibold" data-streamdown="strong">403</span> (IP) or credential errors.

### Agent environment

<div class="ui-scroll-area" data-direction="horizontal" data-scroll-padding="4" data-visibility="hover" id="bkmrk-variable-purpose-bal"><div class="ui-scroll-area__viewport"><div class="ui-scroll-area__content"><table><thead class="bg-muted/80" data-streamdown="table-header"><tr class="border-border border-b" data-streamdown="table-row"><th class="whitespace-nowrap px-4 py-2 text-left font-semibold text-sm" data-streamdown="table-header-cell">Variable</th><th class="whitespace-nowrap px-4 py-2 text-left font-semibold text-sm" data-streamdown="table-header-cell">Purpose</th></tr></thead><tbody class="divide-y divide-border bg-muted/40" data-streamdown="table-body"><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content">`BALCTL_API_BASE`</div></td><td><div class="md-table-cell-content">Worker URL (e.g. `https://serversctl.com`)</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content">`BALCTL_ENROLLMENT_SECRET`</div></td><td><div class="md-table-cell-content">From Add member modal</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content">`BALCTL_HOSTNAME`</div></td><td><div class="md-table-cell-content">Override OS hostname</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content">`BALCTL_DECLARE_IP`</div></td><td><div class="md-table-cell-content">Declare public IPv4 in heartbeat</div></td></tr><tr class="border-border border-b" data-streamdown="table-row"><td><div class="md-table-cell-content">`BALCTL_PROBE_PUBLIC_IP=1`</div></td><td><div class="md-table-cell-content">Probe public IP if not declared</div></td></tr></tbody></table>

</div></div></div>Agent runs as <span class="font-semibold" data-streamdown="strong">root</span> for HAProxy install, backup/restore, admin socket, and cert writes.