feat(agent): ship a Node 12 executable for Windows Server 2008 R2
Build and Deploy Remote Control Support / Test (push) Successful in 10s
Build and Deploy Remote Control Support / Build Image (push) Successful in 37s
Build and Deploy Remote Control Support / Deploy to Portainer (push) Successful in 6s

Machines that cannot install Node 22 had no way to run the agent at all, which
left them stuck on direct mode — and direct mode only works when the hub can
route to the VNC port, which it often cannot.

agent.js now resolves the two Node 22 globals it uses through fallbacks: `ws`
for the control and tunnel sockets, and http/https for the single enrolment
POST. Node 22 loads neither, since `globalThis.WebSocket || require('ws')`
short-circuits. The require and the http/https references are static so the
bundler can follow them.

A new Docker stage bundles that file with a Node 12 runtime — the last line
supporting Windows 7 and Server 2008 R2 — into one self-contained .exe, served
from /download/agent.exe and linked from the enrolment page. The route answers
503 rather than 404 in a dev checkout, where the build has not run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-12 00:55:57 -07:00
co-authored by Claude Opus 5
parent 88be2bf867
commit cecaf74a0a
8 changed files with 141 additions and 12 deletions
+15
View File
@@ -1,5 +1,6 @@
'use strict';
const fs = require('fs');
const http = require('http');
const path = require('path');
const express = require('express');
@@ -67,6 +68,20 @@ app.get('/download/agent.js', (_req, res) => {
res.sendFile(path.join(__dirname, '..', 'agent', 'agent.js'));
});
// Windows Server 2008 R2 (and Windows 7) cannot install any Node the agent
// would run on — Node 14 dropped them. `pnpm build:agent-exe` bundles the same
// agent.js with a Node 12 runtime into one file that needs nothing installed.
// Built in CI, so a dev checkout will not have it; say so rather than 404.
const AGENT_EXE = path.join(__dirname, '..', 'dist', 'rcs-agent.exe');
app.get('/download/agent.exe', (_req, res) => {
if (!fs.existsSync(AGENT_EXE)) {
return res.status(503).type('text/plain')
.send('the Windows agent executable was not built into this deployment (pnpm build:agent-exe)');
}
res.download(AGENT_EXE, 'rcs-agent.exe');
});
app.use('/novnc', express.static(NOVNC_DIR, { maxAge: '7d', immutable: true }));
app.use(express.static(PUBLIC_DIR));