server-inventory
Add and scan remote Linux servers via SSH, collect system facts, and view fleet health in a React dashboard.
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
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/server-inventory/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How server-inventory Compares
| Feature / Agent | server-inventory | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/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
Use mcp-server-builder to create, test, and export MCP server configurations through the REST API.
Skill: seed-inventory
## Purpose
Skill: Uptime Monitoring
## Overview
Skill: Status Page
## Overview
Skill: unit-conversion
## Overview
Skill: recipe-scaler
## Overview
reading-list
Operate the reading-list API to save, manage, tag, search, and export articles.
email-digest
Configure, test, and troubleshoot the reading-list daily email digest delivered via nodemailer.
websocket-realtime
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
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
## Overview
Skill: csv-import
## Overview