Commit graph

12 commits

Author SHA1 Message Date
Claude
f32d93947b
Add host metrics widgets (Phase 6): CPU/mem/disk/network/processes/ports/firewall/login dashboard
Ports Termix's per-host metrics collector logic onto ArchNest's own SSH
connection helpers (not its multi-user/cache/session scaffolding), exposed via
a new authenticated REST endpoint and a dedicated /host-metrics page with
client-side polling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-19 15:38:30 +00:00
Claude
c37ad3d0d4
Phase 5: RDP/VNC/Telnet remote desktop via guacamole-lite + guacd
Adds a remote_desktop integration type and a /api/guacamole websocket
route that drives guacamole-lite's ClientConnection directly (bypassing
its Server class, which would otherwise attach an unfiltered upgrade
listener that conflicts with the existing @fastify/websocket routes).
The frontend RemoteDesktop page renders the Guacamole protocol stream
via guacamole-common-js. Verified end-to-end against a real guacd and
VNC server, including in an actual browser session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-19 15:25:10 +00:00
Claude
52646d866d
Phase 4: Docker container management (REST CRUD/actions/stats/logs + exec terminal)
Extends the existing Engine-API-based docker integration adapter rather than
porting Termix's SSH+CLI approach, since ArchNest's docker integrations only
ever configure a baseUrl. Adds backend/src/docker/{client,exec}.ts and
backend/src/routes/docker.ts (REST + websocket exec-terminal via raw socket
hijack), and a new Containers page wired into the sidebar/router.

Verified end-to-end against a real dockerd instance and a real container in
this sandbox, which caught and fixed a genuine bug: calling /exec/{id}/resize
before starting the exec hangs the daemon indefinitely; fixed by setting the
initial size via ConsoleSize at exec-create time instead.
2026-06-19 12:28:30 +00:00
Claude
7edf4548d9
Phase 3: remote file manager (SFTP list/edit/upload/download/rename/delete/chmod)
Ephemeral per-request SFTP connections, whole-file-in-memory view/edit
with a 50MB cap and binary detection, streaming download for files of
any size, multipart upload. No sudo/permission-elevation or
server-to-server transfer in this pass (documented gaps, matching
Termix's own scope for the latter).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-19 11:56:04 +00:00
Claude
eaa971bb5a
Phase 2: SSH tunnels (local/remote/dynamic SOCKS5 port forwarding)
- backend/src/ssh/connect.ts: extracted shared SSH-connect logic
  (jump-host chaining, TOFU host-key verification) out of terminal.ts
  so tunnels can reuse it.
- backend/src/tunnels/manager.ts + socks5.ts: in-memory tunnel
  runtime manager supporting local forward (forwardOut), remote
  forward (forwardIn), and dynamic SOCKS5 proxying, with automatic
  reconnect/retry and an auto-start-on-boot option. New `tunnels`
  table persists configs as the saved presets.
- backend/src/routes/tunnels.ts: REST CRUD + connect/disconnect.
- src/pages/Tunnels.tsx: new /tunnels page (sidebar entry added) to
  create, start/stop, and delete tunnels with live status polling.
- Verified end-to-end against a real ssh2 test server handling real
  forwardOut/forwardIn requests and a real upstream TCP echo server -
  all three tunnel modes moved real data, and disconnect correctly
  tore down the local listener.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-19 11:40:59 +00:00
Claude
27abbc8ce1
Phase 1c: OPKSSH cert auth, tmux session monitor/reattach, session logging
- terminal.ts: connectWithCertificate() shells out to system ssh via
  node-pty for OpenSSH certificate auth (ssh2 has no native support);
  list_tmux WS message + tmuxSession connect param for tmux
  attach/create with shell-injection-safe name validation;
  sessionLogging config field appends terminal output to disk.
- Settings.tsx: certificate secret field and sessionLogging checkbox
  for SSH host integrations.
- Terminal.tsx: tmux session picker in each pane's header.
- Verified end-to-end against a real test SSH server running real
  bash/tmux processes (plain shell, tmux create+list, session log
  written to disk). Cert auth path type-checks but is unverified in
  this sandbox (no ssh CLI available) - documented as a gap in
  TERMIX_MIGRATION.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-19 11:28:51 +00:00
Claude
5d56a1d902
Phase 1b: SSH jump-host chaining, TOFU host-key verification, multi-host Settings UI
Terminal connections can now reference a jumpHostIntegrationId on the SSH
integration config; the backend connects to the jump host first and tunnels
to the real target via ssh2's forwardOut(), rather than connecting directly.

Added an ssh_host_keys table and a hostVerifier callback that accepts and
stores a host's fingerprint on first connect, then hard-rejects on any
mismatch on subsequent connects (trust-on-first-use).

Settings previously only ever showed/edited one integration per type, which
silently prevented configuring more than one SSH host at all. Added a
dedicated multi-host SSH section (per-host Save/Test/Delete, Add SSH Host,
and a Jump Host dropdown) so jump-host chaining is actually usable from the UI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-19 11:04:46 +00:00
Claude
71f49e0700
Add Phase 1a: core SSH terminal (Termix migration)
Implements the minimal-viable terminal described in TERMIX_MIGRATION.md
Phase 1a: a real interactive SSH session in the browser over a
WebSocket, using xterm.js on the frontend and ssh2 on the backend.
Reuses ArchNest's existing SSH integrations (host/port/username/
password/privateKey/passphrase) instead of introducing a second,
duplicate host-management system the way Termix has one.

Backend: new /api/terminal WebSocket route (registered via
@fastify/websocket) handling connect/input/resize/disconnect messages,
authenticated via a JWT passed as a query param (browsers can't set
custom headers on the WS handshake). Extracted the integration secret
loader out of routes/integrations.ts into db/secrets.ts so the new
terminal route can reuse it without duplicating the decrypt logic.

Frontend: new Terminal.tsx page listing configured SSH hosts and
rendering an xterm.js terminal wired to the WebSocket; wired into
App.tsx at /terminal. vite.config.ts's dev proxy now forwards
WebSocket upgrades (ws: true) so this works under `npm run dev`.

Verified end-to-end against a real (test) ssh2-based SSH server:
connect, shell banner, keystroke echo, and prompt redraw all worked
correctly over the actual WebSocket protocol.

Deliberately deferred to Phase 1b/1c per the migration doc: jump-host
chaining, tab/split-pane UI, terminal theme/font settings, OPKSSH cert
auth, tmux session monitor, session recording.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-19 10:52:04 +00:00
Claude
7524690ebd
Add SSH integration adapter for local infra without an API
Many self-hosted machines have no management API, so add an SSH-based
adapter (using ssh2) that connects with password or key auth and probes
hostname/disk/mem/load via a single shell command, surfacing health
status like the other integrations. Also fixes routes/integrations.ts's
hardcoded type enum, which was out of sync with the IntegrationType
union and rejected the new 'ssh' type.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-18 21:06:16 +00:00
Claude
49c49635a9
Remove remaining mock data: fake user identity, notification badge, system status
TopBar, Sidebar, and the Settings profile form previously showed a hardcoded
"ArchNest Ops" identity, a fake unread-notification count, and a static "All
Systems Operational" indicator. These now use the real logged-in user (with
a new PUT /api/auth/me endpoint to edit display name/email/avatar) and real
integration health for the sidebar status dot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-18 20:08:30 +00:00
Claude
3b920fcfb2
Replace mock data on Glance and Infrastructure with real backend data
Adds an events table + logEvent helper for a genuine activity log, and
a /api/integrations/resources aggregate endpoint backed by a new optional
listResources adapter method (implemented for Docker via its containers API).
StatusCards, MiddleRow, BottomRow, and Infrastructure now render real
integration/resource/event data instead of hardcoded numbers, with empty
states where no data source exists yet (AWS cost, historical trends).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-18 19:56:10 +00:00
Claude
a0b71c7028
Add backend skeleton: Fastify + SQLite API with auth and integrations
- Single-user JWT auth with a first-run /api/setup endpoint, gated by
  GET /api/system/setup-status, to back an upcoming enrollment page
- SQLite schema for users, integrations, secrets (AES-256-GCM encrypted),
  bookmarks, and bookmark categories
- Integration adapter registry with real health-check adapters for
  Uptime Kuma and Docker, stubs for the rest, wired to
  POST /api/integrations/:id/test
- CRUD routes for integrations and bookmarks
- backend/ as its own Docker service in docker-compose.yml, Vite dev
  proxy for /api, .env.example for required secrets

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
2026-06-18 19:04:48 +00:00