AI Agent Gateway for Unraid. Permission-enforcing REST API that lets AI agents manage your server.
UnraidClaw sits between AI agents and your Unraid servers, providing a unified REST API with fine-grained access control. It combines Unraid's GraphQL API with direct system integration (CLI commands for parity checks, reboot/shutdown, and syslog; filesystem operations for share config editing and notification management; network introspection via ip) to expose capabilities that no single Unraid API covers. Every call is authenticated, authorized against a configurable permission matrix, and logged.
- 43 tools across 11 categories: Docker, VMs, Array, Disks, Shares, System, Notifications, Network, Users, Logs
- 22 permission keys in a resource:action matrix, configurable from the WebGUI
- HTTPS with auto-generated self-signed TLS certificate
- SHA-256 API key authentication
- Activity logging with JSONL format, filter, and search
- OpenClaw plugin available on npm (
openclaw plugins install unraidclaw) - Single-file server, no
node_modulesneeded on Unraid
- Unraid 7.0.0+ (Node.js 22 is built-in)
Search for UnraidClaw in the Unraid CA store and click Install.
# Download and install the plugin
plugin install https://raw.githubusercontent.com/emaspa/unraidclaw/main/packages/unraid-plugin/unraidclaw.plg- Go to Settings > Management Access in the Unraid WebGUI, scroll to the API section, and copy your Unraid API key (must have ADMIN role)
- Go to Settings > UnraidClaw, paste the Unraid API key into the Unraid API Key field
- Generate an UnraidClaw API key (it's hashed with SHA-256; save it, it won't be shown again)
- Configure permissions on the Permissions tab
- Set Service to Enabled and click Apply
The server starts on port 9876 over HTTPS by default. A self-signed TLS certificate is auto-generated on first start.
All endpoints return a consistent envelope:
{
"ok": true,
"data": { ... }
}Authentication via x-api-key: <api-key> header.
| Category | Method | Endpoint | Permission |
|---|---|---|---|
| Health | GET | /api/health |
none |
| Docker | GET | /api/docker/containers |
docker:read |
| GET | /api/docker/containers/:id |
docker:read |
|
| GET | /api/docker/containers/:id/logs |
docker:read |
|
| POST | /api/docker/containers |
docker:create |
|
| POST | /api/docker/containers/:id/:action |
docker:update |
|
| DELETE | /api/docker/containers/:id |
docker:delete |
|
| VMs | GET | /api/vms |
vms:read |
| GET | /api/vms/:id |
vms:read |
|
| POST | /api/vms/:id/:action |
vms:update |
|
| DELETE | /api/vms/:id |
vms:delete |
|
| Array | GET | /api/array/status |
array:read |
| GET | /api/array/parity/status |
array:read |
|
| POST | /api/array/start |
array:update |
|
| POST | /api/array/stop |
array:update |
|
| POST | /api/array/parity/start |
array:update |
|
| POST | /api/array/parity/pause |
array:update |
|
| POST | /api/array/parity/resume |
array:update |
|
| POST | /api/array/parity/cancel |
array:update |
|
| Disks | GET | /api/disks |
disk:read |
| GET | /api/disks/:id |
disk:read |
|
| Shares | GET | /api/shares |
share:read |
| GET | /api/shares/:name |
share:read |
|
| PATCH | /api/shares/:name |
share:update |
|
| System | GET | /api/system/info |
info:read |
| GET | /api/system/metrics |
info:read |
|
| GET | /api/system/services |
services:read |
|
| POST | /api/system/reboot |
os:update |
|
| POST | /api/system/shutdown |
os:update |
|
| Notifications | GET | /api/notifications |
notification:read |
| GET | /api/notifications/overview |
notification:read |
|
| POST | /api/notifications |
notification:create |
|
| POST | /api/notifications/:id/archive |
notification:update |
|
| DELETE | /api/notifications/:id |
notification:delete |
|
| Network | GET | /api/network |
network:read |
| Users | GET | /api/users/me |
me:read |
| Logs | GET | /api/logs/syslog |
logs:read |
POST /api/docker/containers accepts:
{
"image": "vikunja/vikunja:latest",
"name": "vikunja",
"ports": ["3456:3456"],
"volumes": ["/mnt/cache/appdata/vikunja:/app/vikunja/files"],
"env": ["VIKUNJA_SERVICE_TIMEZONE=Europe/London"],
"restart": "unless-stopped",
"network": "bridge",
"icon": "https://example.com/icon.png",
"webui": "http://[IP]:[PORT:3456]/"
}Only image is required. The container is started immediately and an Unraid dockerMan XML template is created so it appears in the Docker tab.
POST /api/docker/containers/:id/:action where action is one of: start, stop, restart, pause, unpause
POST /api/vms/:id/:action where action is one of: start, stop, force-stop, pause, resume, reboot, reset
PATCH /api/shares/:name accepts:
{
"comment": "My share description",
"allocator": "highwater",
"splitLevel": "1",
"floor": "0"
}The OpenClaw plugin exposes all 43 tools to any AI agent that supports the OpenClaw protocol.
npm pack unraidclaw && openclaw plugins install unraidclaw-*.tgz && rm unraidclaw-*.tgzrm -rf ~/.openclaw/extensions/unraidclaw && npm pack unraidclaw && openclaw plugins install unraidclaw-*.tgz && rm unraidclaw-*.tgzEdit ~/.openclaw/openclaw.json:
Single server:
{
"plugins": {
"allow": ["unraidclaw"],
"entries": {
"unraidclaw": {
"config": {
"serverUrl": "https://YOUR_UNRAID_IP:9876",
"apiKey": "YOUR_API_KEY",
"tlsSkipVerify": true
}
}
}
}
}Multiple servers:
{
"plugins": {
"allow": ["unraidclaw"],
"entries": {
"unraidclaw": {
"config": {
"servers": [
{
"name": "home",
"serverUrl": "https://192.168.1.100:9876",
"apiKey": "...",
"tlsSkipVerify": true,
"default": true
},
{
"name": "work",
"serverUrl": "https://10.0.0.50:9876",
"apiKey": "..."
}
]
}
}
}
}
}With multi-server, every tool accepts an optional server parameter (e.g. unraid_docker_list(server: "work")). If omitted, the default server is used.
Set tlsSkipVerify: true when using the auto-generated self-signed certificate.
| Category | Tools |
|---|---|
| Health | unraid_health_check |
| Docker | unraid_docker_list, unraid_docker_inspect, unraid_docker_logs, unraid_docker_create, unraid_docker_start, unraid_docker_stop, unraid_docker_restart, unraid_docker_pause, unraid_docker_unpause, unraid_docker_remove |
| VMs | unraid_vm_list, unraid_vm_inspect, unraid_vm_start, unraid_vm_stop, unraid_vm_pause, unraid_vm_resume, unraid_vm_force_stop, unraid_vm_reboot |
| Array | unraid_array_status, unraid_array_start, unraid_array_stop, unraid_parity_status, unraid_parity_start, unraid_parity_pause, unraid_parity_resume, unraid_parity_cancel |
| Disks | unraid_disk_list, unraid_disk_details |
| Shares | unraid_share_list, unraid_share_details, unraid_share_update |
| System | unraid_system_info, unraid_system_metrics, unraid_service_list, unraid_system_reboot, unraid_system_shutdown |
| Notifications | unraid_notification_list, unraid_notification_create, unraid_notification_archive, unraid_notification_delete |
| Network | unraid_network_info |
| Users | unraid_user_me |
| Logs | unraid_syslog |
Permissions use a resource:action format. Configure them from the WebGUI Permissions tab or edit /boot/config/plugins/unraidclaw/permissions.json directly.
| Category | Permissions |
|---|---|
| Docker | docker:read, docker:create, docker:update, docker:delete |
| VMs | vms:read, vms:update, vms:delete |
| Array & Storage | array:read, array:update, disk:read, share:read, share:update |
| System | info:read, os:update, services:read |
| Notifications | notification:read, notification:create, notification:update, notification:delete |
| Network | network:read |
| Users | me:read |
| Logs | logs:read |
The WebGUI includes presets: Read Only, Docker Manager, VM Manager, Full Admin, and None.
GraphQL ──> Unraid API
/ (list queries, array, disks)
┌─────────────┐ HTTPS ┌──────────────────┐──+
│ AI Agent │ ──────────────> │ UnraidClaw │ \
│ (OpenClaw) │ x-api-key │ (Fastify) │ CLI ──────> docker, virsh, mdcmd,
└─────────────┘ │ │ / reboot, ip, ...
│ - Auth │──+
│ - Permissions │ \
│ - Activity Log │ Filesystem > share configs, syslog,
└──────────────────┘ notifications
This is a pnpm monorepo with three packages:
| Package | Description |
|---|---|
packages/shared |
Shared TypeScript types, permission definitions, API interfaces |
packages/unraid-plugin/server |
Fastify REST API server, bundles to a single CJS file |
packages/openclaw-plugin |
OpenClaw plugin, bundles to a single ESM file, published to npm as unraidclaw |
- API keys are hashed with SHA-256 before storage; the plaintext key is never persisted
- All requests require authentication via
x-api-keyheader - Every API call is checked against the permission matrix before execution
- Activity logging records all requests with timestamps, endpoints, and results
- HTTPS with auto-generated EC (prime256v1) certificates, 10-year validity
- The server runs locally on your Unraid box, no cloud dependencies
MIT
