368 lines
14 KiB
Markdown
368 lines
14 KiB
Markdown
# Homelable
|
||
|
||
Homelable is a self-hosted infrastructure visualization solution. It provides a network/zigbee scanning feature to accelerate the identification of machines, devices and services deployed on your local infrastructure.
|
||
|
||
Homelable also offers a healthcheck system through multiple methods (ping/TCP, /health API, etc.) to get a global overview of online/offline services.
|
||
|
||
You can also select some pre-built design styles, or personalize each device in your diagram.
|
||
|
||
If you just like the design, you can only run the frontend and export your design as PNG.
|
||
|
||
If you are running <img width="22" height="22" align="top" alt="New_Home_Assistant_logo" src="https://github.com/user-attachments/assets/3bb17686-c706-40ce-a2d3-57e02378f37c" /> Homeassistant, check the [Homelable HA version](https://github.com/Pouzor/homelable-hacs) (via HACS)
|
||
|
||
<a href="https://trendshift.io/repositories/24461?utm_source=trendshift-badge&utm_medium=badge&utm_campaign=badge-trendshift-24461" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/24461/daily?language=TypeScript" alt="Pouzor%2Fhomelable | Trendshift" width="250" height="55"/></a>
|
||
---
|
||
|
||
## Screenshots
|
||
|
||
<p align="center">
|
||
<img src="docs/homelable1.png" alt="Homelable canvas overview" width="100%" />
|
||
<img alt="Homelable Device inventory" src="https://github.com/user-attachments/assets/f3903ac8-354d-4873-81ba-1914971890ed" />
|
||
<img width="49.5%" alt="Homelable Custom node" src="https://github.com/user-attachments/assets/813725b1-376b-4bad-bb1f-0985f3bc7546" />
|
||
<img width="49.5%" alt="Homelable Zigbee Network" src="https://github.com/user-attachments/assets/35e18d11-8363-498d-ae3d-642685cac76d" />
|
||
|
||
</p>
|
||
|
||
---
|
||
|
||
## Features
|
||
|
||
From one-click **network scans** and **Proxmox / Zigbee / Z-Wave** imports to **live status monitoring**, floor plans, multi-canvas layouts and an **MCP server** for AI assistants — Homelable maps and watches your whole homelab.
|
||
|
||
Every feature, with how to turn it on and use it, is described in **[FEATURES.md](./FEATURES.md)**.
|
||
|
||
---
|
||
|
||
## Installation
|
||
|
||
Docker, Proxmox LXC, build from source, configuration, and development setup are all covered in **[INSTALLATION.md](./INSTALLATION.md)**.
|
||
|
||
---
|
||
|
||
## Network Scanner
|
||
|
||
The scanner runs `nmap -sV --open` on your configured CIDR ranges and populates a **Pending Devices** queue. From the sidebar you can then approve (adds a node to the canvas), hide, or ignore each discovered device.
|
||
|
||
### Triggering a scan
|
||
|
||
To save you time when mapping your infrastructure, Homlable can scan your network and report all the services it detects. It can also identify them, saving you even more time.
|
||
Click **Scan Network** in the sidebar. The Scan History tab opens automatically and refreshes every 3 seconds until the scan completes.
|
||
|
||
### Deep scan (custom ports)
|
||
|
||
By default the scanner only probes nmap's standard port set. To fingerprint services on non-standard ports, enable the deep scan via `.env` (all options are overridable per-scan from the scan dialog):
|
||
|
||
```env
|
||
# JSON array of port specs — each entry is a single port "N" or an inclusive
|
||
# range "N-M" (1–65535, N <= M). These are ports, not CIDRs or bare integers.
|
||
SCANNER_HTTP_RANGES=["8080","9000-9100"]
|
||
SCANNER_HTTP_PROBE_ENABLED=true # send an HTTP probe to those ports for service ID
|
||
SCANNER_HTTP_VERIFY_TLS=false # verify TLS certs on the HTTP probe
|
||
```
|
||
|
||
The listed ports are appended to nmap's `-p` spec. Invalid entries (out-of-range, malformed, or reversed ranges) are silently skipped.
|
||
|
||
### macOS / root privileges
|
||
|
||
Some nmap scan types (SYN scan, OS detection) require root. If the scan fails with a permissions error, run it manually with sudo using the included script:
|
||
|
||
```bash
|
||
cd backend
|
||
sudo python ../scripts/run_scan.py 192.168.1.0/24
|
||
|
||
# Multiple ranges:
|
||
sudo python ../scripts/run_scan.py 192.168.1.0/24 10.0.0.0/24
|
||
```
|
||
|
||
Results are written directly to the database and appear as Pending Devices in the UI without restarting the backend.
|
||
|
||
> On Linux the backend process itself can be given the `NET_RAW` capability instead of running as root:
|
||
> ```bash
|
||
> sudo setcap cap_net_raw+ep $(which nmap)
|
||
> ```
|
||
|
||
---
|
||
|
||
## Node Check Methods
|
||
|
||
Homelable continuously monitors your nodes and displays their live status (online / offline / unknown) directly on the canvas. Each node can be configured with an independent check method suited to the service it runs.
|
||
|
||
| Method | Description |
|
||
|--------|-------------|
|
||
| `ping` | ICMP ping |
|
||
| `http` | GET request, success if status < 500 |
|
||
| `https` | GET with TLS verify |
|
||
| `tcp` | TCP connect (target: `host:port`) |
|
||
| `ssh` | TCP connect to port 22 |
|
||
| `prometheus` | GET `/metrics` |
|
||
| `health` | GET `/health` |
|
||
|
||
---
|
||
|
||
## Zigbee2MQTT Import
|
||
|
||
Homelable can connect directly to your MQTT broker and import your Zigbee network topology from **Zigbee2MQTT**, placing each device on the canvas as a typed node.
|
||
|
||
### Prerequisites
|
||
|
||
- A running **MQTT broker** (e.g. Mosquitto) accessible from the Homelable host
|
||
- **Zigbee2MQTT** connected to the broker with at least one device paired
|
||
|
||
### Usage
|
||
|
||
1. Click **Zigbee Import** in the left sidebar (below "Scan Network")
|
||
2. Enter your broker host, port (default `1883`), optional credentials, and base topic (default `zigbee2mqtt`)
|
||
3. Click **Test Connection** to verify reachability, then **Fetch Devices**
|
||
4. Select the devices you want from the grouped list (Coordinator / Router / End Device)
|
||
5. Click **Add N to Canvas** — devices are placed in a grid with IoT edges
|
||
|
||
### Node Types
|
||
|
||
| Type | Z2M Device | Icon |
|
||
|------|-----------|------|
|
||
| `zigbee_coordinator` | Coordinator | Network hub |
|
||
| `zigbee_router` | Router (mains-powered) | Radio |
|
||
| `zigbee_enddevice` | End Device (battery) | Antenna |
|
||
|
||
Hierarchy is set automatically: coordinator → routers → end devices (`parent_id`).
|
||
LQI (Link Quality Indicator) is stored as a node property.
|
||
|
||
> **Full documentation:** [docs/zigbee-import.md](./docs/zigbee-import.md)
|
||
|
||
---
|
||
|
||
## Z-Wave Import
|
||
|
||
Homelable can also import your **Z-Wave** network from **Z-Wave JS UI** (formerly `zwavejs2mqtt`) over the same MQTT broker, dropping each node on the canvas as a typed node.
|
||
|
||
### Prerequisites
|
||
|
||
- A running **MQTT broker** (e.g. Mosquitto) accessible from the Homelable host
|
||
- **Z-Wave JS UI** connected to the broker with its MQTT gateway enabled and at least one node included
|
||
|
||
### Usage
|
||
|
||
1. Click **Z-Wave Import** in the left sidebar (below "Zigbee Import")
|
||
2. Enter your broker host, port (default `1883`), optional credentials, MQTT prefix (default `zwave`), and gateway name (default `zwavejs2mqtt`)
|
||
3. Click **Test Connection** to verify reachability
|
||
4. Choose a target — **Pending section** or **Canvas directly** — then **Import to Pending** / **Fetch Devices**
|
||
5. Select the devices you want from the grouped list (Controller / Router / End Device) and click **Add N to Canvas**
|
||
|
||
### Node Types
|
||
|
||
| Type | Z-Wave Role | Icon |
|
||
|------|-------------|------|
|
||
| `zwave_coordinator` | Controller | Network hub |
|
||
| `zwave_router` | Routing (mains-powered) node | Radio |
|
||
| `zwave_enddevice` | End Device (battery) | Antenna |
|
||
|
||
Hierarchy is set automatically: controller → routers → end devices (`parent_id`), derived from each node's neighbor list. Z-Wave has no LQI, so that property is omitted.
|
||
|
||
> **Full documentation:** [docs/zwave-import.md](./docs/zwave-import.md)
|
||
|
||
---
|
||
|
||
## Proxmox VE Import
|
||
|
||
Homelable can import your **Proxmox VE** inventory over the Proxmox REST API — hosts, VMs and LXC containers arrive as typed, named nodes with run state and hardware specs, and can auto-sync on a schedule. Guest IPs that were already found by a network scan are merged in place (no duplicates).
|
||
|
||
### Prerequisites
|
||
|
||
- A reachable **Proxmox VE** host (default API port `8006`)
|
||
- A **Proxmox API token** with the read-only **`PVEAuditor`** role (Datacenter → Permissions → API Tokens)
|
||
|
||
### Usage
|
||
|
||
1. Click **Proxmox Import** in the left sidebar (below "Z-Wave Import")
|
||
2. Enter the host, port (default `8006`), and API token (`user@realm!tokenid` + secret) — or leave the token blank to use the server-configured one
|
||
3. Click **Test Connection** to verify reachability + token
|
||
4. Choose a target — **Pending section** or **Canvas directly** — then **Import to Pending** / **Fetch Inventory**
|
||
5. Select the devices from the grouped list (Hosts / Virtual Machines / LXC Containers) and click **Add N to Canvas**
|
||
|
||
### Node Types
|
||
|
||
| Type | Proxmox object | Icon |
|
||
|------|----------------|------|
|
||
| `proxmox` | Host / cluster member | Layers |
|
||
| `vm` | QEMU virtual machine | Box |
|
||
| `lxc` | LXC container | Container |
|
||
|
||
Each host is linked to its guests with a `virtual` edge. vCPU / RAM / disk are imported as node properties (hidden by default). Enable **auto-sync** from Settings once a server token is configured (`PROXMOX_TOKEN_ID` / `PROXMOX_TOKEN_SECRET`).
|
||
|
||
> **Full documentation:** [docs/proxmox-import.md](./docs/proxmox-import.md)
|
||
|
||
---
|
||
|
||
## Live View (read-only public canvas)
|
||
|
||
Live View lets you share a read-only snapshot of your canvas with anyone on your network — no login required. It is disabled by default.
|
||
|
||
### Activation
|
||
|
||
Add LIVEVIEW_KEY to your .env:
|
||
|
||
`LIVEVIEW_KEY=your-secret-key`
|
||
|
||
|
||
Then restart the backend:
|
||
|
||
`docker compose restart backend`
|
||
|
||
### Usage
|
||
|
||
Use this URL to view your canvas:
|
||
|
||
http://<your-homelab-ip>/view?key=your-secret-key
|
||
|
||
The page shows your canvas in pan/zoom-only mode — no editing, no credentials needed. Clicking a node that has an IP opens it in a new tab.
|
||
|
||
---
|
||
|
||
## Gethomepage Widget (read-only stats)
|
||
|
||
Homelable can expose a small JSON stats endpoint that [gethomepage](https://gethomepage.dev) consumes through its built-in `customapi` widget. Disabled by default.
|
||
|
||
### Activation
|
||
|
||
Add `HOMEPAGE_API_KEY` to your `.env`:
|
||
|
||
`HOMEPAGE_API_KEY=your-secret-key`
|
||
|
||
Restart the backend (`docker compose restart backend`).
|
||
|
||
### Endpoint
|
||
|
||
`GET /api/v1/stats/summary` — requires header `X-API-Key: your-secret-key`. Returns:
|
||
|
||
```json
|
||
{
|
||
"nodes": 12,
|
||
"online": 9,
|
||
"offline": 2,
|
||
"unknown": 1,
|
||
"pending_devices": 3,
|
||
"zigbee_devices": 5,
|
||
"last_scan_at": "2026-05-14T10:00:00+00:00"
|
||
}
|
||
```
|
||
|
||
### gethomepage `services.yaml` snippet
|
||
|
||
```yaml
|
||
- Homelab:
|
||
- Homelable:
|
||
icon: mdi-lan
|
||
href: http://homelable.local:3000
|
||
widget:
|
||
type: customapi
|
||
url: http://homelable.local:8000/api/v1/stats/summary
|
||
method: GET
|
||
headers:
|
||
X-API-Key: your-secret-key
|
||
mappings:
|
||
- field: nodes ; label: Nodes
|
||
- field: online ; label: Online
|
||
- field: offline ; label: Offline
|
||
- field: pending_devices ; label: Pending
|
||
- field: zigbee_devices ; label: Zigbee
|
||
- field: last_scan_at ; label: Last scan
|
||
```
|
||
|
||
The backend port (`8000`) must be reachable from your gethomepage container.
|
||
|
||
---
|
||
|
||
## MCP Server (AI Integration) (optional)
|
||
|
||
Homelable can exposes a [Model Context Protocol](https://modelcontextprotocol.io) server so any MCP-compatible AI client (Claude Code, Claude Desktop, Open WebUI…) can read your homelab topology and act on it.
|
||
|
||
### What the AI can do
|
||
|
||
| | Action |
|
||
|---|---|
|
||
| **Read** | List all nodes, edges, full canvas, pending devices, scan history |
|
||
| **Write** | Add / update / delete nodes and edges, trigger a network scan, approve or hide discovered devices |
|
||
|
||
### Setup
|
||
|
||
**1. Add the keys to your `.env`:**
|
||
|
||
```env
|
||
# Authenticates AI clients (Claude Code, etc.) → MCP server
|
||
MCP_API_KEY=mcp_sk_changeme
|
||
|
||
# Authenticates MCP server → backend (internal Docker network only, never exposed)
|
||
MCP_SERVICE_KEY=svc_changeme
|
||
|
||
# Generate both with:
|
||
# python3 -c "import secrets; print(secrets.token_hex(32))"
|
||
```
|
||
|
||
No plain-text passwords involved — `AUTH_PASSWORD_HASH` is only used for the web UI login.
|
||
|
||
**2. Start the MCP service:**
|
||
|
||
```bash
|
||
docker compose up -d mcp
|
||
# MCP server is now listening on http://<your-homelab-ip>:8001
|
||
```
|
||
|
||
> **Proxmox LXC / bare-metal (no Docker):** create the LXC via
|
||
> [community-scripts/ProxmoxVE](https://github.com/community-scripts/ProxmoxVE) (or any
|
||
> Debian/Ubuntu LXC), then inside it run `sudo bash scripts/lxc-mcp-install.sh`.
|
||
> Installs a `homelable-mcp` systemd service, prompts for `MCP_API_KEY` / `MCP_SERVICE_KEY`
|
||
> (auto-generated if you press Enter), and skips prompts if `mcp/.env` already exists.
|
||
|
||
**3. Configure your AI client:**
|
||
|
||
**Claude Code** — run this command in your terminal:
|
||
```bash
|
||
claude mcp add --transport sse homelable http://<your-homelab-ip>:8001/mcp \
|
||
--header "X-API-Key: mcp_sk_yourkey"
|
||
```
|
||
|
||
Or add it manually to `~/.claude.json`:
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"homelable": {
|
||
"type": "sse",
|
||
"url": "http://<your-homelab-ip>:8001/mcp",
|
||
"headers": {
|
||
"X-API-Key": "mcp_sk_yourkey"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**Claude Desktop** — edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"homelable": {
|
||
"type": "sse",
|
||
"url": "http://<your-homelab-ip>:8001/mcp",
|
||
"headers": {
|
||
"X-API-Key": "mcp_sk_yourkey"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Example prompts
|
||
|
||
- *"What nodes are currently offline?"*
|
||
- *"Add a new LXC container named `pihole` at 192.168.1.5, connected to my switch."*
|
||
- *"Trigger a network scan on 192.168.1.0/24 and show me the pending devices."*
|
||
- *"Show me the full canvas topology."*
|
||
|
||
### Security
|
||
|
||
- The MCP server is **not** intended to be exposed to the internet — keep port 8001 firewalled to your LAN.
|
||
- Rotate the key any time by updating `MCP_API_KEY` in `.env` and restarting: `docker compose restart mcp`.
|
||
- The MCP server communicates with the backend over the internal Docker network — the backend API is never directly exposed to MCP clients.
|
||
|
||
---
|