Merge pull request #41 from AnsoCode/feature/fix-remote-proxy-order

Fix Remote Node System Stats: Remove Broken getDocker() Branch
This commit is contained in:
Anso
2026-03-19 22:08:16 -04:00
committed by GitHub
2 changed files with 3 additions and 26 deletions
+1
View File
@@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
- **Fixed:** Remote node system stats, container stats, logs, and exec returning errors — `remoteNodeProxy` middleware was already positioned before API route definitions, but `/api/system/stats` contained a dead remote branch that called `NodeRegistry.getDocker()` for remote nodes, which throws since remote nodes have no direct Docker socket access. Removed the broken branch; remote requests are correctly intercepted by the proxy middleware before reaching any route handler.
- **Added:** Background image update checker — `ImageUpdateService` polls OCI-compliant registries (Docker Hub, GHCR, LSCR, etc.) every 6 hours using manifest digest comparison against local `RepoDigests`. Results cached in a new `stack_update_status` SQLite table. A pulsing blue dot badge appears in the stack list sidebar for stacks with available updates. Manual refresh available via `POST /api/image-updates/refresh` (rate-limited to once per 10 minutes).
- **Fixed:** `AppStoreView` and `GlobalObservabilityView` using raw `fetch()` instead of `apiFetch()` — all calls now inject the `x-node-id` header so templates, deploys, stacks, and logs are correctly proxied to the active remote node.
- **Fixed:** `HostConsole` WebSocket URL missing `?nodeId=` query parameter — the upgrade handler now receives the active node ID and routes the PTY session to the correct node.
+2 -26
View File
@@ -1139,35 +1139,11 @@ app.get('/api/logs/global/stream', async (req: Request, res: Response) => {
// Get host system stats
app.get('/api/system/stats', async (req: Request, res: Response) => {
try {
const nodeId = req.nodeId ?? NodeRegistry.getInstance().getDefaultNodeId();
const node = NodeRegistry.getInstance().getNode(nodeId);
const rxSec = Math.max(0, globalDockerNetwork.rxSec);
const txSec = Math.max(0, globalDockerNetwork.txSec);
if (node && node.type === 'remote') {
// Remote node: use Docker daemon info for CPU/RAM - disk is not available via Docker API
const docker = NodeRegistry.getInstance().getDocker(nodeId);
const info = await docker.info();
res.json({
cpu: {
usage: '0',
cores: info.NCPU ?? 0,
},
memory: {
total: info.MemTotal ?? 0,
used: 0,
free: info.MemTotal ?? 0,
usagePercent: '0',
},
disk: null,
network: { rxBytes: 0, txBytes: 0, rxSec, txSec },
});
return;
}
// Local node: use systeminformation for accurate host metrics
// Remote node requests are intercepted and proxied by remoteNodeProxy before reaching here.
// This handler only runs for local nodes.
const [currentLoad, mem, fsSize] = await Promise.all([
si.currentLoad(),
si.mem(),