Control remote fleet workers over SSH with user, host, and key path
Some checks are pending
offline / test (push) Waiting to run

NS1 is marchon@70.88.205.138 using ~/.ssh/id_ed25519. Private key
bytes stay off git. Spawn, health, and kill go through ssh; remote
workers bind loopback only.
This commit is contained in:
George Lambert 2026-09-11 13:31:21 -04:00
parent b325f6f697
commit e89e006542
12 changed files with 425 additions and 34 deletions

View file

@ -44,14 +44,17 @@
<label>id <input name="id" required placeholder="ns1-b"/></label>
<label>host <input name="host" required placeholder="10.0.0.12"/></label>
<label>kind
<select name="kind"><option value="local">local</option><option value="agent">agent</option></select>
<select name="kind"><option value="local">local</option><option value="ssh">ssh</option><option value="agent">agent</option></select>
</label>
<label>user <input name="user" value="marchon"/></label>
<label>ssh port <input name="sshPort" type="number" value="22"/></label>
<label>identity file <input name="identityFile" placeholder="~/.ssh/id_ed25519" value="~/.ssh/id_ed25519"/></label>
<label>capacity <input name="capacity" type="number" min="1" value="8"/></label>
<label>roles <input name="roles" value="*" placeholder="tree-node,archive-worm"/></label>
<button type="submit">Add machine</button>
</form>
<table>
<thead><tr><th>Machine</th><th>Host</th><th>Kind</th><th>Capacity</th><th>Running</th><th>RTT ms min / avg / p50 / p90</th><th></th></tr></thead>
<thead><tr><th>Machine</th><th>SSH / host</th><th>Kind</th><th>Capacity</th><th>Running</th><th>RTT ms min / avg / p50 / p90</th><th></th></tr></thead>
<tbody id="machines"></tbody>
</table>
<h2>Services</h2>
@ -74,13 +77,14 @@ async function draw() {
const on = m.enabled;
return `<tr class="${on ? (m.running > 0 ? 'state-operational' : '') : 'state-down'}">
<td><strong>${m.id}</strong><br><span style="color:#5b6d78">${m.title || ''}</span></td>
<td><code>${m.host}${m.kind === 'agent' ? ':' + m.agentPort : ''}</code></td>
<td><code>${m.kind === 'ssh' ? (m.user || 'marchon') + '@' : ''}${m.host}${m.kind === 'agent' ? ':' + m.agentPort : ''}${m.kind === 'ssh' && m.identityFile ? ' key=' + m.identityFile : ''}</code></td>
<td>${m.kind} ${on ? '<span class="pill good">on</span>' : '<span class="pill bad">off</span>'}</td>
<td>${m.running} / ${m.capacity}</td>
<td>${m.available} avail</td>
<td>${rttCell(m.rtt)}</td>
<td>
<button onclick="act('/api/machines/${m.id}/${on ? 'disable' : 'enable'}')">${on ? 'disable' : 'enable'}</button>
${m.kind === 'ssh' ? `<button onclick="act('/api/machines/${m.id}/check')">ssh-check</button>` : ''}
</td>
</tr>`;
}).join('');
@ -126,6 +130,9 @@ document.getElementById('addMachine').addEventListener('submit', async (e) => {
id: f.id.value,
host: f.host.value,
kind: f.kind.value,
user: f.user.value,
sshPort: Number(f.sshPort.value || 22),
identityFile: f.identityFile.value,
capacity: Number(f.capacity.value || 8),
roles,
enabled: true,