Commit Graph
6 Commits
Author SHA1 Message Date
rmancinasandClaude Opus 5 cfda6b19b7 feat(install): one-command device registration for macOS, Windows and Linux
Registering a machine meant reading a multi-step page, installing Node, and
running three commands in the right order. Now it is one line per platform.

The hub serves scripts/install.sh and scripts/install.ps1 with its own address
and the enrolment token substituted in, so the published command carries
everything and there is nothing to fill in:

  curl -fsSL https://support.freakma.com/install.sh?token=TOKEN | sh
  irm https://support.freakma.com/install.ps1?token=TOKEN | iex

That output is piped straight into a shell, so the token — the only untrusted
value in either file — is refused unless it matches the base64url shape that
randomToken produces.

Each script checks for a usable runtime and stops with instructions rather than
guessing, warns when nothing is serving RFB on the loopback, installs per-user
with no root or administrator, and registers a login-scoped service: launchd on
macOS, a lingering systemd user service on Linux, a logon task on Windows. The
Windows script uses Node 22 when it is present and falls back to the bundled
executable otherwise, which is what lets one command cover both Windows 11 and
Server 2008 R2.

It registers a logon task rather than a service on purpose: services run in
session 0 and cannot draw on the interactive desktop, so the "ask first" consent
prompt would never appear.

Also adds /docs — a per-OS setup guide with service management and a
troubleshooting table — and reworks the enrolment page into OS tabs that open on
whichever platform the reader is sitting at.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 11:37:12 -07:00
rmancinasandClaude Opus 5 cecaf74a0a 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>
2026-08-12 00:55:57 -07:00
rmancinasandClaude Opus 5 88be2bf867 fix(http): 400 on malformed JSON body instead of 500
Build and Deploy Remote Control Support / Test (push) Successful in 11s
Build and Deploy Remote Control Support / Build Image (push) Successful in 47s
Build and Deploy Remote Control Support / Deploy to Portainer (push) Successful in 7s
express.json() raising a parse error was falling through to the generic
500 handler, which reads as a server fault for what is a bad request.
Also maps the body-size limit to 413.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 23:55:48 -07:00
rmancinasandClaude Opus 5 30feb5f61b fix(deploy): publish on 5910, 8091 is taken on the Swarm ingress
Build and Deploy Remote Control Support / Test (push) Successful in 11s
Build and Deploy Remote Control Support / Build Image (push) Successful in 47s
Build and Deploy Remote Control Support / Deploy to Portainer (push) Successful in 9s
The first real deploy failed with "port '8091' is already in use by
service 'ai-training-lab_ai-lab' as an ingress port". Worth noting the
port answered nothing when probed over HTTP — a Swarm ingress
reservation survives the service behind it being down, so probing is not
a way to find a free port.

5910 is VNC display :10 and sits clear of the 809x web-app block.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 23:52:48 -07:00
rmancinasandClaude Opus 5 8af9d39ffd feat(ui): warm-graphite design system and particle background
Build and Deploy Remote Control Support / Test (push) Successful in 18s
Build and Deploy Remote Control Support / Build Image (push) Failing after 20s
Build and Deploy Remote Control Support / Deploy to Portainer (push) Skipped
Reworks the console's look away from generic dark-mode defaults: the
neutral ramp carries a faint violet cast, and the signal palette now
distinguishes connection topology by colour — mint for live agents,
iris for direct connections, copper for consent-required machines.

Type contrast comes from pairing the platform mono against the platform
sans rather than a webfont, since the box this runs on has no internet.

particles.js draws a proximity-linked node field: full strength on the
login and public pages, frozen static in the console, and entirely
absent from the viewer, where every frame belongs to the remote desktop.
It caps DPR at 2, scales node count to viewport area, throttles to 30fps,
cancels rAF when the tab is hidden, and honours prefers-reduced-motion.

app.js and viewer.js are unchanged; the particle layer mounts itself and
tracks the console via MutationObserver on #app.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 23:40:16 -07:00
rmancinasandClaude Opus 5 999717f77b feat: self-hosted remote support over VNC
Browser-based remote control (noVNC) with invite links, per-user access
control, garagedoor SSO and a persisted client list.

The hub proxies RFB rather than pointing the browser at a VNC server. That
is what lets it authenticate upstream with a stored password the browser
never sees, and enforce view-only by dropping input messages on the
client->server stream instead of hiding buttons.

Machines are reachable two ways: direct TCP for LAN hosts, or an outbound
agent tunnel for anything behind NAT. Node 22's global WebSocket keeps the
agent dependency-free, and node:sqlite keeps the image free of native
builds.

Ships with an end-to-end suite that boots the real server against a fake
VNC server and a fake auth service (72 assertions), plus Gitea Actions
CI/CD to Portainer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 23:37:35 -07:00