server-inventory

Add and scan remote Linux servers via SSH, collect system facts, and view fleet health in a React dashboard.

7 stars

Best use case

server-inventory is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Add and scan remote Linux servers via SSH, collect system facts, and view fleet health in a React dashboard.

Teams using server-inventory should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/server-inventory/SKILL.md --create-dirs "https://raw.githubusercontent.com/heldernoid/agentic-build-templates/main/projects/devops-infrastructure/server-inventory/skills/server-inventory/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/server-inventory/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How server-inventory Compares

Feature / Agentserver-inventoryStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Add and scan remote Linux servers via SSH, collect system facts, and view fleet health in a React dashboard.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

## When to use this skill

Use this skill when working on the server-inventory application: adding SSH targets, triggering scans, interpreting collected data, configuring groups, or troubleshooting connection errors.

## Prerequisites

- Docker and Docker Compose installed
- SSH private key accessible on the host machine
- Target servers running Linux with SSH enabled
- User account on each target with read access to `/proc`, `/etc/os-release`, and `df`

## Quick Start

### Development

```bash
pnpm install
# Terminal 1
cd backend && pnpm dev
# Terminal 2
cd frontend && pnpm dev
```

### Docker

```bash
cp .env.example .env
# Edit .env to set SSH key path and other options
docker compose up
```

Dashboard: http://localhost:8080
API: http://localhost:3000

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `PORT` | `3000` | Express server port |
| `DB_PATH` | `./data/inventory.db` | SQLite database path |
| `SCAN_INTERVAL_MINUTES` | `60` | Scheduled fleet scan interval |
| `SCAN_CONCURRENCY` | `5` | Max parallel SSH connections |
| `SSH_TIMEOUT_MS` | `10000` | SSH connection timeout in ms |
| `CORS_ORIGIN` | `http://localhost:5173` | Allowed CORS origin |
| `VITE_API_URL` | `http://localhost:3000` | API base URL for frontend |

## Adding Servers

### Via the dashboard

Click "Add Server" in the top bar. Fill in label, host, port, username, auth method, and key path.

### Via the API

```bash
curl -X POST http://localhost:3000/api/servers \
  -H "Content-Type: application/json" \
  -d '{
    "label": "web-01",
    "host": "192.168.1.10",
    "port": 22,
    "username": "ubuntu",
    "authMethod": "key",
    "keyPath": "/root/.ssh/id_rsa",
    "groupId": null
  }'
```

The `keyPath` must be the path inside the server-inventory container (e.g., `/root/.ssh/id_rsa` when `~/.ssh` is mounted at `/root/.ssh`).

## Triggering Scans

```bash
# Scan all servers
curl -X POST http://localhost:3000/api/scan-all

# Scan a single server (replace 1 with server id)
curl -X POST http://localhost:3000/api/servers/1/scan
```

Scan results appear immediately in the dashboard. Each scan inserts a snapshot row and a scan_log row.

## API Reference

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/api/health` | Health check |
| `GET` | `/api/servers` | List all servers with latest snapshot |
| `POST` | `/api/servers` | Add a server |
| `PUT` | `/api/servers/:id` | Update server config |
| `DELETE` | `/api/servers/:id` | Remove server |
| `POST` | `/api/servers/:id/scan` | On-demand scan |
| `GET` | `/api/servers/:id` | Server detail with latest snapshot |
| `GET` | `/api/servers/:id/snapshots` | Snapshot history (last 90) |
| `GET` | `/api/servers/:id/scan-log` | Recent scan log entries for server |
| `POST` | `/api/scan-all` | Scan all servers |
| `GET` | `/api/groups` | List groups |
| `POST` | `/api/groups` | Create group |
| `PUT` | `/api/groups/:id` | Update group |
| `DELETE` | `/api/groups/:id` | Delete group |
| `GET` | `/api/scan-log` | Recent scan log (all servers) |
| `GET` | `/api/settings` | Current settings |
| `POST` | `/api/settings` | Update settings |

## Collected Facts

Each scan runs these read-only SSH commands and stores the results:

| Fact | Command |
|------|---------|
| Hostname | `hostname -f` |
| OS name | `cat /etc/os-release` |
| Kernel | `uname -r` |
| Architecture | `uname -m` |
| Uptime | `cat /proc/uptime` |
| CPU model | `cat /proc/cpuinfo` (first model name) |
| CPU cores | `nproc` |
| Memory | `free -m` |
| Disk mounts | `df -m --output=source,target,size,used,pcent` |
| Load average | `cat /proc/loadavg` |

## Groups

Groups organize servers in the sidebar and allow fleet-filtered views.

```bash
# Create a group
curl -X POST http://localhost:3000/api/groups \
  -H "Content-Type: application/json" \
  -d '{ "name": "web", "color": "#0891b2" }'

# Assign server to group (use the group id from the response)
curl -X PUT http://localhost:3000/api/servers/1 \
  -H "Content-Type: application/json" \
  -d '{ "groupId": 1 }'
```

Deleting a group sets `group_id` to null for all member servers; servers are not deleted.

## Snapshot Retention

Snapshots older than `RETENTION_DAYS` (default 90) are pruned at the start of each scheduled scan cycle. On-demand scans do not trigger pruning. To change retention, update `RETENTION_DAYS` in Settings or via `POST /api/settings`.

## Troubleshooting

### connect ETIMEDOUT

The server is not reachable on the configured port. Check:
1. The server is powered on and on the network
2. No firewall is blocking TCP port 22 from the server-inventory container
3. Try increasing `SSH_TIMEOUT_MS` in Settings for slow connections

### All configured authentication methods failed

SSH key authentication is failing. Check:
1. The public key is in `~username/.ssh/authorized_keys` on the target server
2. The private key at `keyPath` is correctly mounted in the container
3. Key file permissions are `600` (run `chmod 600 ~/.ssh/id_rsa` on the host)
4. The username is correct

### No snapshots after scan

The scan succeeded (scan_log shows `success`) but snapshot data is missing. Check:
1. The SSH user has read access to `/proc/meminfo`, `/proc/loadavg`, and `df`
2. `/etc/os-release` exists on the target (required for OS detection)
3. Review `raw_output` in the snapshots table for parse errors

### SSH key not found in container

The key path is wrong or the mount is missing. Verify the Docker Compose volume mount:
```yaml
volumes:
  - ~/.ssh:/root/.ssh:ro
```
The `keyPath` field should use the in-container path: `/root/.ssh/id_rsa`.

Related Skills

Skill: mcp-server-builder

7
from heldernoid/agentic-build-templates

Use mcp-server-builder to create, test, and export MCP server configurations through the REST API.

Skill: seed-inventory

7
from heldernoid/agentic-build-templates

## Purpose

Skill: Uptime Monitoring

7
from heldernoid/agentic-build-templates

## Overview

Skill: Status Page

7
from heldernoid/agentic-build-templates

## Overview

Skill: unit-conversion

7
from heldernoid/agentic-build-templates

## Overview

Skill: recipe-scaler

7
from heldernoid/agentic-build-templates

## Overview

reading-list

7
from heldernoid/agentic-build-templates

Operate the reading-list API to save, manage, tag, search, and export articles.

email-digest

7
from heldernoid/agentic-build-templates

Configure, test, and troubleshoot the reading-list daily email digest delivered via nodemailer.

websocket-realtime

7
from heldernoid/agentic-build-templates

Use the WebSocket connection in poll-builder to receive live vote updates. Use when you need to stream real-time poll results, monitor a poll for new votes, or build a live dashboard. Triggers include "live results", "real-time updates", "stream votes", "watch poll", or "WebSocket".

poll-builder

7
from heldernoid/agentic-build-templates

Self-hosted poll creation tool with real-time results. Use when you need to create a poll, check vote counts, close a poll, export results, or get the shareable link for a poll. Triggers include "create poll", "vote", "poll results", "survey", "collect votes", "share poll", or any task involving polling or voting.

Skill: personal-finance

7
from heldernoid/agentic-build-templates

## Overview

Skill: csv-import

7
from heldernoid/agentic-build-templates

## Overview