---
name: homelab-infrastructure-review
description: >
  Performs a 3-way infrastructure reconciliation audit: homelab_Infra.md
  documentation (including Nginx Proxy Route mappings) vs. live Docker container
  states vs. homelable MCP canvas topology. Also audits the Homepage Dashboard
  services configuration to ensure newly proxied services are accessible.
  Triggers ONLY on explicit user command. No automation or cron.
version: 1.4.0
author: wompmacho
date: 2026-05-30
platforms: [linux, macos, windows]
metadata:
  hermes:
    tags: [homelab, infrastructure, audit, reconciliation, mcp, docker, nginx, homepage]
    related_skills: [docker-workflows, workflow-management]
---

# Homelab Infrastructure Review

This skill has been refactored into an intelligent, context-aware auditing engine. It uses a YAML configuration (`scripts/audit_config.yaml`) to understand architectural conventions (aliases, ignored containers) and employs a robust, incremental development workflow. **Always test changes in small, atomic steps** (`syntax check -> run`) to avoid complex debugging cycles. The core logic now uses a Python helper (`scripts/load_config.py`) for configuration and `docker inspect` for accurate health checks.

## 1. Core Objectives

This skill provides a highly-disciplined auditing workflow that:
1. **Identifies all live services** on the host.
2. **Identifies all active proxies and domains** for services by parsing Nginx Proxy Manager config files.
3. **Cross-references** them against the source of truth documentation (`homelab_Infra.md`).
4. **Cross-references** them against the `homelable-mcp` visual canvas topology.
5. **Audits the Homepage Dashboard services configuration** (`/srv/configs/docker_compose/homepage/config/services.yaml`) to ensure all proxied services are accessible.
6. **Generates exact proposed changes** to:
   - The markdown documentation (`homelab_Infra.md`)
   - The `homelable-mcp` visual canvas nodes and edges
   - The Homepage Dashboard services config (`services.yaml`), with services correctly split into their relevant hosts/categories.

---

## 2. Trigger Conditions

This skill is invoked **only on explicit, manual user command** — never automatically or periodically.
Acceptable trigger phrases: "review homelab", "infrastructure audit", "reconcile homelab", "homelab review", "check infrastructure".

No cron, no automated polling, and no silent background execution.

---

## 3. Source Inventory and Boundary Map

| Source Component | Path / Port / Endpoint | Permission Boundaries |
|---|---|---|
| **Infra Document** | `/srv/docs/public/projects/homelab/homelab_Infra.md` | Read: ✅ Write: ❌ (requires explicit user confirmation, never run git commands without auth) |
| **Live Docker State** | Host session via `docker ps` | Read: ✅ Write: ❌ (no automated container lifecycle modifications allowed) |
| **Nginx Proxy Configs** | `/app/nginxproxy/data/nginx/proxy_host/*.conf` | Read: ✅ Write: ❌ (read-only proxy blocks mapping) |
| **Homelable Backend API** | `http://localhost:9445/api/v1` | Read: ✅ Write: ❌ (node/edge canvas edits require explicit confirmation) |
| **Homepage Config** | `/srv/configs/docker_compose/homepage/config/services.yaml` | Read: ✅ Write: ❌ (requires explicit user confirmation) |
| **Homepage Layout** | `/srv/configs/docker_compose/homepage/config/settings.yaml` | Read: ✅ Write: ❌ (requires explicit user confirmation) |
| **Workspace Dir** | `/srv/configs/ai/` | Read: ✅ Write: ✅ (agent state and proposed drafts) |

---

## 4. Reconciliation Logic & Execution Steps

### Step 1: Pre-Flight Safety Checks
Run **in order** before beginning any audit cycle. If any check fails, **simply inform the user directly in the session** and abort (do NOT log failures to a local `errors.log` file):
- **Lock Check:** Verify no concurrent audit process holds `/srv/configs/ai/.audit.lock`.
- **Backend Port Check:** Verify port `9445` is actively listening.
- **Backend API Check:** Verify backend returns `HTTP 200` on `/api/v1/health` using the parsed `MCP_SERVICE_KEY` from `/srv/configs/docker_compose/homelabel/.env`.
- **Source Files Check:** Verify both `/srv/configs/.bash_aliases` and `homelab_Infra.md` exist.

### Step 2: Nginx Proxy Parsing
Parse every proxy configuration file `/app/nginxproxy/data/nginx/proxy_host/*.conf` for:
- `server_name` (Proxy Domain name / Route)
- `set $port` (Forwarded Container Port)

Keep an internal lookup dictionary of `Forwarded Port -> Proxy Domain` for comparison.

### Step 3: Homepage Dashboard Audit
Read `/srv/configs/docker_compose/homepage/config/services.yaml` and compare the list of active proxy routes against the dashboard items. Propose adding newly proxied services so the user can navigate to them.

Homepage services must be strictly split into three distinct categories:
1. **Physical Devices & Networking related** (e.g. Proxmox, TrueNAS, Router, Pi-Hole, Moonlight streaming)
2. **Docker Host Containers** (e.g. nginx-proxy-manager, portainer, immich, vaultwarden, paperless-ngx, slopsmith-web)
3. **TrueNAS Host Containers** (e.g. radarr, sonarr, readarr, bazarr, prowlarr, calibre)

### Step 4: Documentation Formatting Standardization

Both the **`## Docker services`** and the **`## Truenas Services`** markdown tables inside `homelab_Infra.md` must strictly maintain this exact 5-column layout:

`| Container Name | Mapped Ports | Access | Proxy Route / Domain | Description / Role |`

Always parse and print matching columns when proposing or applying documentation edits.

### Step 5: Proxmox LXC/VM Auditing
Proxmox host virtualization represents nodes (containers/VMs) that communicate on the LAN subnet `10.0.0.0/16`. 
- Parse the Proxmox Node Table under `### Proxmox node (laptop-proxmox)` in `homelab_Infra.md`.
- Retrieve all network canvas nodes from `http://localhost:9445/api/v1/nodes` matching types `vm`, `lxc`, or direct hosts.
- Compare and verify that active virtualization nodes on your network (such as `invidious` on `10.0.0.217` or `pterodactyl` on `10.0.0.110`) exist inside the documentation table. Propose additions for any unregistered LXCs or VMs.

### Step 6: Homelable MCP Canvas Styling Standards

When registering new Docker containers on the visual canvas using the `POST` endpoint at `/api/v1/nodes`, you must strictly match the styling of other standard services (use `gitea_runner` as reference):

- `"type"` must be `"docker_container"`
- `"hostname"` must be `"docker"`
- `"ip"` must be `""` (empty string, as they reside behind parent container networking)
- `"width"` must be `140.0`
- `"height"` must be `50.0`
- `"bottom_handles"` must be `1`
- `"custom_colors"` must be `{"show_services": false}`
- `"parent_id"` must be set to the Docker parent host node UUID (e.g. `ee61411a-018a-4471-8a76-bcd4a1f5579a`)

---

## 5. Safety and Guardrails

> [!IMPORTANT]
> 1. **No silent writes:** All modifications to `homelab_Infra.md`, the `homelable-mcp` canvas, or `services.yaml` must be presented as a clear diff block and receive explicit, manual user validation.
> 2. **NO UNAUTHORIZED GIT COMMANDS:** Never execute any Git commands (such as `git add`, `git commit`, `git status`, `git diff`, etc.) without the user's explicit, per-action authorization.
> 3. **Preserve Comments:** Do not remove, alter, or strip existing documentation comments or section text blocks.
> 4. **No Errors Log File:** Do not append failures to a local `errors.log` file. Output error details directly to the active console stream to keep workspace logs clean.

---

## 6. Technical Pitfalls & Workarounds

> [!WARNING]
> - **Windows CRLF line endings (`\r\n`):** The Homepage dashboard's `services.yaml` contains Windows CRLF terminators. Traditional bash/unix line-ending regex matches (such as `$`) will **silently fail** to match titles or categories. Always run `tr -d '\r'` to sanitize lines before attempting pattern matches.
> - **Direct REST API bypass:** Querying `homelable-mcp` on `8001` via SSE requires an async JSON-RPC transport negotiation which is fragile and slow. Instead, bypass the MCP layer entirely and query the `homelable-backend` REST API directly on port `9445` at `/api/v1/nodes`. Pass the header `"X-MCP-Service-Key"` parsed from `/srv/configs/docker_compose/homelabel/.env` for instant, authenticated, and robust network nodes lookup.
- **Active Port Verification (Stale Config Filter):** Nginx Proxy Manager configuration files on disk can be stale/leftover (e.g. Moonlight). To completely prevent reporting decommissioned configs, always verify that the port associated with any Nginx config is **actively listening on the host** (or mapped in active docker container port-mappings) before reporting it as an active proxy. If the port is inactive, ignore the proxy block completely.
- **TrueNAS SCALE Node Socket Verification:** Rather than setting up fragile credentials or SSH logins, TrueNAS SCALE container port verification is achieved securely and in milliseconds using lightweight, non-destructive `/dev/tcp/10.0.0.2/[port]` network socket connection handshakes.
- **Proxmox VE API Live Verification:** To verify running LXCs and VMs, query `https://10.0.0.142:8006/api2/json/cluster/resources?type=vm` directly. Load `HOMEPAGE_VAR_proxmox_password` dynamically from `/srv/configs/docker_compose/homepage/.env` at runtime and strip outer double quotes before passing to the Authorization headers. Never hardcode credentials in codebase or transcripts.
- **Homepage Settings Layout Syncing:** When renaming category names in `/srv/configs/docker_compose/homepage/config/services.yaml` (such as `Arr` -> `Truenas Containers`, and `Containers` -> `Docker Containers`), the layout block names inside `/srv/configs/docker_compose/homepage/config/settings.yaml` under `layout:` **must be updated identically** or the cards will fail to render on the dashboard.
- **Do NOT Invent Public Proxies:** Do not invent public proxy domains or automatically propose changing local/VPN hrefs (such as `http://radarr/` or `http://calibre/`) to public domains (like `radarr.wompmacho.com`) in homepage configurations. They must remain as local/VPN URLs exactly as currently configured to preserve network isolation and security.
- **Multi-Alias Substring Matcher:** Nginx Proxy configs often specify multiple space-separated aliases (e.g. `server_name vaultwarden vaultwarden.wompmacho.com;`). When searching for these in `services.yaml` to detect missing cards, token-split the domains and verify if *any* alias matches as a substring within the homepage card `href` or name (case-insensitively). This prevents false-positives (such as flagging Vaultwarden or Gitea as missing).

---

## 7. Skill File Structure

All scripts and files associated with this skill are stored in this self-contained directory:
- `SKILL.md` — Custom skill documentation and procedures.
- `scripts/homelab-infrastructure-review.sh` — Bash shell auditing script.
- `scripts/mcp_client.py` — Python client for direct database and API queries.
- `errors.log` — Legacy log file (decommissioned per safety rules — errors print straight to console).
- `.audit.lock` — Legitimate lock file preventing concurrent executions.

