Skip to content

feat: show live disk usage on server tiles - #5484

Open
JoshuaRileyDev wants to merge 7 commits into
Dokploy:canaryfrom
JoshuaRileyDev:feature/server-disk-usage-upstream
Open

JoshuaRileyDev wants to merge 7 commits into
Dokploy:canaryfrom
JoshuaRileyDev:feature/server-disk-usage-upstream

Conversation

@JoshuaRileyDev

@JoshuaRileyDev JoshuaRileyDev commented Sep 19, 2026

Copy link
Copy Markdown

Summary

Adds a focused server disk-usage readout to each active server tile.

Changes

  • Adds a protected server.diskUsage query that runs a portable df -kP / command locally over SSH.
  • Shows a taller progress bar with bottom spacing immediately above “Setup Server”.
  • Shows the used percentage and free space in gigabytes with a smaller summary row, plus a refresh button and loading state.
  • This branch is based directly on upstream canary; fork-only seeding and Portless changes are excluded.

Visual comparison

Area Before After
Server tile Before After

Test plan

  • pnpm exec biome check --write apps/dokploy/components/dashboard/settings/servers/show-servers.tsx
  • pnpm --filter dokploy typecheck
  • Logged into the local Tailscale-served app, verified the percentage/free-GB display, and refreshed the SSH-backed value.

Risks

  • The value reflects the root filesystem reported by the target server and requires the server’s configured SSH key.
  • If the command cannot be reached or parsed, the tile shows “Unavailable” without blocking server actions.

Rollback

Revert the commits on this branch.

RetriggerConfidence Score: 4/5

The PR should not merge until its free-space and utilization calculations use actually available filesystem capacity; the SSH fan-out and missing parser tests should also be addressed.

Summary

This PR adds an authorized, SSH-backed disk-usage query and displays its result with refresh controls on every active server tile.

  • Adds root-filesystem collection to the server-health service.
  • Adds organization and accessible-server checks at the tRPC boundary.
  • Adds a progress bar, free-space summary, refresh action, and unavailable state to the server dashboard.
  • The current calculation misrepresents available capacity on filesystems with reserved blocks, and the per-tile query introduces unbounded SSH fan-out.

Reviews (1) · Last reviewed commit: "test: refresh disk usage screenshot"

export const getServerDiskUsage = async (
serverId?: string,
): Promise<ServerDiskUsage> => {
const command = "df -kP / 2>/dev/null | awk 'NR==2 {print $2, $3}'";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Reserved Space Appears Free

The command reads only df's total and used columns, then calculates free space as total - used and utilization as used / total. On filesystems with reserved blocks, this counts reserved capacity as free and reports lower utilization than df itself, so the tile can materially overstate writable space. Read the available column and base both displayed values on used + available.

Knowledge Base Used:

Comment on lines 273 to +277
{isActive && (
<div className="flex items-center gap-2 pt-3 border-t mt-auto flex-wrap">
<ServerDiskUsage
serverId={server.serverId}
/>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Disk Checks Fan Out

Mounting one query per active tile creates an unbounded SSH fan-out whenever this page loads. The server list has no page-size limit, and every query creates a separate SSH client that may remain pending for roughly 100 seconds. Organizations with many or unreachable servers can therefore cause a large simultaneous connection burst. Please bound the concurrency or fetch disk usage through a throttled aggregate path.

Knowledge Base Used: Infrastructure runtime

Comment on lines +403 to +421
const [totalKb = Number.NaN, usedKb = Number.NaN] = result.stdout
.trim()
.split(/\s+/)
.map(Number);

if (!Number.isFinite(totalKb) || totalKb <= 0 || !Number.isFinite(usedKb)) {
throw new Error("Unable to read disk usage");
}

const totalBytes = Math.round(totalKb * 1024);
const usedBytes = Math.min(
totalBytes,
Math.max(0, Math.round(usedKb * 1024)),
);
return {
totalBytes,
usedBytes,
usagePercent: Math.round((usedBytes / totalBytes) * 100),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Disk Parser Lacks Tests

The new shell-output parser and its byte and percentage calculations have no direct or integration test, despite depending on exact df output and malformed-output handling. Extracting and testing the parser with valid, empty, and malformed output would prevent platform or command-output changes from silently reducing the feature to “Unavailable.”

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant