From 7e73e0de71d20fdff6a49cbfab28a5962bdaa74a Mon Sep 17 00:00:00 2001 From: jason Date: Sat, 9 May 2026 23:31:14 -0500 Subject: [PATCH] update docs --- INSTALL-UNRAID.md | 64 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/INSTALL-UNRAID.md b/INSTALL-UNRAID.md index 93dfc7c..690ef04 100644 --- a/INSTALL-UNRAID.md +++ b/INSTALL-UNRAID.md @@ -40,6 +40,22 @@ chown -R 99:100 /mnt/user/appdata/totalmcp (99:100 = `nobody:users`, the standard Unraid container ownership.) +### Gather your tokens + +Have these in a scratch file before starting — easier than tab-switching during the GUI install. + +| Token | Where to get it | +|---|---| +| **`AGENT_TOKENS`** | Generate fresh: `openssl rand -hex 32` (run 3× — one per agent: claude-code, antigravity, codex). Save them — you'll paste the same values into agent configs after install. | +| **`GITEA_TOKEN`** | `git.alwisp.com` → your avatar → **Settings** → **Applications** → **Generate New Token**. Scopes: `repo`, `issue`, `read:user`. Copy the token immediately (Gitea won't show it again). | +| **`UNRAID_API_KEY`** | On the Unraid host: `unraid-api start`, then `unraid-api key` to print the key. (Requires the unraid-api plugin from Apps.) | +| **`OPENCLAW_HOST`** | Already known: `http://10.2.0.26:18789` (NOVA). No token — LAN-only. | +| **`UNIFI_API_KEY`** | UniFi Access UI → **Settings** → **Security** → **API Tokens** → **Create**. Scopes: read all, plus the writes you want. | +| **`UNIFI_SITE_ID`** | UniFi Access UI URL contains it (`/locations/`). Optional. | +| **`CODEX_DB_PATH`** | Container path is `/app/codex/db.sqlite` (after the volume mount). Host file: `/mnt/user/appdata/codex/db.sqlite`. | +| **`RACKMAPPER_TOKEN`** | RackMapper UI → API tokens. Optional if RackMapper has no auth. | +| **`STREAMVAULT_*`** | Skip — service not deployed yet. | + --- ## 1. Add Container — top-level fields @@ -54,7 +70,7 @@ chown -R 99:100 /mnt/user/appdata/totalmcp | **Docker Hub URL** | (leave blank — private registry) | | **Icon URL** | (optional — set later) | | **WebUI** | `http://[IP]:[PORT:8811]/health` | -| **Extra Parameters** | `--pids-limit=2048` | +| **Extra Parameters** | `--pids-limit=2048 --user 0:0` (the `--user 0:0` is needed for the `docker` plugin — see §3) | | **Post Arguments** | (leave blank) | | **Network Type** | `Custom: br0` | | **Use IPv4 only** | ☑ checked | @@ -98,6 +114,8 @@ Click **Add Path** for each row. > Read-only is enough for `docker_list_containers`/`get_logs`/`get_stats`, but `start`/`stop`/`restart` require RW. +> ⚠️ **Permission gotcha:** the container runs as the unprivileged `mcp` user, but Unraid's `/var/run/docker.sock` is owned by `root:root` (mode 660). The `mcp` user has no access by default — `docker_list_containers` will return `EACCES`. The simplest fix is to add `--user 0:0` to the **Extra Parameters** field at the top of the Add Container form (run the container as root). For a LAN-only gateway behind bearer auth on a single-tenant box, this tradeoff is acceptable. See troubleshooting §7 for stricter alternatives. + ### Required if `codex-mrp` plugin is enabled (Phase 3) | Container Path | Host Path | Access Mode | Description | @@ -215,6 +233,31 @@ claude mcp add --scope user --transport http totalmcp http://10.2.0.35:8811/mcp Then run `/mcp` inside Claude Code — the totalmcp tools should appear in the catalog. +### Per-plugin smoke tests + +Run these from Claude Code in order of risk (lowest first). Each row = the safest first call to confirm a plugin actually works end-to-end. + +| Plugin | First call | Expected on success | Likely failure mode | +|---|---|---|---| +| **gitea** | `gitea_list_repos` | `{ repos: [...] }` including the `totalmcp` repo | 401 → `GITEA_TOKEN` missing/wrong scopes | +| **unraid** | `unraid_host_summary` | `{ host, os, uptime, cpu, memory, array }` | GraphQL field shape mismatch — adjust queries in `src/plugins/unraid/index.ts` to match your unraid-api version | +| **docker** | `docker_list_containers` | ~35 containers from your Unraid stack | `EACCES` on `/var/run/docker.sock` — confirm `--user 0:0` is in Extra Parameters | +| **openclaw** | `openclaw_list_models` | List of models on NOVA | Connection timeout → confirm NOVA at `10.2.0.26:18789` is reachable from `10.2.0.35` | +| **unifi** | `unifi_list_sites` | List of UniFi Access locations | 404 on `/api/v1/developer/locations` — UniFi Access REST paths vary by version; adjust the plugin's endpoint paths | +| **codex-mrp** | `codex_list_work_orders` | `{ workOrders: [...] }` | `no such table: work_orders` — **expected.** Run `sqlite3 /mnt/user/appdata/codex/db.sqlite ".schema"`, then update the SQL in `src/plugins/codex-mrp/index.ts` to match real CODEX table names | +| **streamvault** | (skip) | n/a | Service not deployed — `onLoad` will warn at startup, tool calls return connection error. Disable by removing from `ENABLED_PLUGINS` until ready. | +| **rackmapper** | `rackmapper_list_racks` | `{ racks: [...] }` | 404 — RackMapper API path may differ; adjust | + +### What to expect on first run + +- **gitea**, **openclaw**, **docker** are highest-confidence. Built against well-documented APIs that haven't drifted. +- **unraid**, **unifi** are medium-confidence. APIs evolve between versions; field shapes may need adjustment. +- **codex-mrp** is low-confidence. Placeholder SQL by design — needs the real CODEX schema before it works. +- **streamvault** will be in failure state until the service exists. Disable for now. +- **rackmapper** depends on whether RackMapper has a JSON API; adjust if not. + +Capture each plugin's failure (if any) and we'll fix the schemas/paths in a follow-up pass. + --- ## 6. Updates @@ -248,9 +291,22 @@ Common causes: - **`Invalid environment configuration`** — `AGENT_TOKENS` malformed or `PORT` not a number. Fix the Variable in the Unraid GUI and the container will auto-restart. - **`Cannot find module ...`** — image was built without one of the new deps (e.g., `dockerode` or `better-sqlite3`). Force-update to pull the latest image. -### `docker` plugin: `docker_connect_failed` +### `docker` plugin: `docker_connect_failed` or `EACCES` on socket -Confirm the path mapping is `/var/run/docker.sock → /var/run/docker.sock` with **Read/Write** access mode. +Most common cause: the container is running as the unprivileged `mcp` user but `/var/run/docker.sock` is owned by `root:root` on the host. + +**Quickest fix:** add `--user 0:0` to **Extra Parameters** on the container (run as root inside the container). + +**Stricter alternatives** if you don't want root in the container: +1. Find the docker GID on the host: `stat -c '%g' /var/run/docker.sock` (commonly `281` on Unraid). +2. Either: + - Override the container's group with `--group-add ` in Extra Parameters, **or** + - Rebuild the image with that GID baked in (modify the Dockerfile's `addgroup` step). +3. Or run a [docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) in front and point `dockerode` at the proxy URL via a `socketPath` override. + +For a LAN-only gateway behind bearer auth on a single-tenant Unraid box, `--user 0:0` is the pragmatic choice. + +Also confirm the path mapping is `/var/run/docker.sock → /var/run/docker.sock` with **Read/Write** access mode. ### `codex-mrp` plugin: `codex_mrp_connect_failed` @@ -292,3 +348,5 @@ If you just want the gateway running with **only the Gitea plugin** to start: | Variable `GITEA_TOKEN` | *(your PAT)* | Apply, verify with `curl /health`, then expand by adding more variables and updating `ENABLED_PLUGINS` as each phase comes online. + +> **Note:** even the minimal install does **not** need `--user 0:0` since the `docker` plugin isn't enabled. Add `--user 0:0` only when you turn `docker` on.