feat: v1.3 Unraid Update Status Sync
Unraid GraphQL API foundation — connectivity, authentication, and
container ID format verified for native Unraid API integration.
Phase 14: Unraid API Access (2 plans, 4 tasks)
- Established Unraid GraphQL API connectivity via myunraid.net cloud relay
- Dual credential storage (.env.unraid-api + n8n env vars)
- Container ID format: {server_hash}:{container_hash} (128-char SHA256 pair)
- Complete API contract documented in ARCHITECTURE.md
- "unraid" test command added to Telegram bot
Phases 15-16 dropped (superseded by v1.4 Unraid API Native).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+118
@@ -33,6 +33,124 @@ Docker Engine
|
||||
|
||||
**Total:** 287 nodes (166 main + 121 across 7 sub-workflows)
|
||||
|
||||
## Unraid GraphQL API
|
||||
|
||||
The Unraid GraphQL API is used to sync container update status back to Unraid after bot-initiated updates, resolving the "apply update" badge issue (see Known Limitations).
|
||||
|
||||
### API Overview
|
||||
|
||||
- **Endpoint:** `{UNRAID_HOST}/graphql` (POST)
|
||||
- **Authentication:** `x-api-key` header with Unraid API key
|
||||
- **Available in:** Unraid 7.2+ (native) or 6.9-7.1 (Connect plugin)
|
||||
- **Purpose:** Sync container update status back to Unraid after bot-initiated updates
|
||||
|
||||
### Authentication
|
||||
|
||||
- **Header:** `x-api-key: {api_key}`
|
||||
- **Credential:** n8n Header Auth credential named "Unraid API Key" - Header Name: `x-api-key`
|
||||
- Header Value: Unraid API key
|
||||
- **Permission required:** `DOCKER:UPDATE_ANY`
|
||||
- **Key creation:** `unraid-api apikey --create --name "Docker Manager Bot" --permissions "DOCKER:UPDATE_ANY"`
|
||||
|
||||
Alternative: Unraid WebGUI -> Settings -> Management Access -> API Keys -> Create key with DOCKER:UPDATE_ANY permission.
|
||||
|
||||
### Network Access
|
||||
|
||||
**Critical findings:**
|
||||
- Direct LAN IP (http://192.168.90.103) does NOT work — nginx redirects HTTP to HTTPS, stripping auth headers on redirect
|
||||
- Direct HTTPS with standard port (https://192.168.90.103:8443) does NOT have /graphql endpoint
|
||||
- **Working approach:** Use Unraid's myunraid.net cloud relay URL
|
||||
|
||||
**Working configuration:**
|
||||
- **URL format:** `https://{ip-dashed}.{hash}.myunraid.net:8443/graphql`
|
||||
- Example: `https://192-168-90-103.abc123def456.myunraid.net:8443/graphql`
|
||||
- **Environment variable:** Set `UNRAID_HOST` on n8n container (without /graphql suffix)
|
||||
- **SSL:** Valid certs via myunraid.net — no SSL ignore needed
|
||||
- **Authentication:** n8n Header Auth credential
|
||||
**Why this works:**
|
||||
- myunraid.net cloud relay properly handles GraphQL endpoint routing
|
||||
- Auth headers preserved through the cloud relay
|
||||
- No nginx redirect issues
|
||||
- GraphQL sandbox mode NOT required for API access
|
||||
|
||||
**Note:** The `host.docker.internal` and direct IP approaches documented in Phase 14 Plan 01 research did not work in production testing. The myunraid.net relay is the verified working solution for Unraid 7.2.
|
||||
|
||||
### Container Query (Phase 14 — read-only)
|
||||
|
||||
```graphql
|
||||
query { docker { containers { id names state } } }
|
||||
```
|
||||
|
||||
**Expected response structure:**
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"docker": {
|
||||
"containers": [
|
||||
{
|
||||
"id": "1639d2f04f44841bc62fec38d18e1869a558d85071fa23e0a8bf64d374b317fa:8a9907a245766012741662a5840cefdec67af6b70e4c6f1629af7ef8f1ee2925",
|
||||
"names": ["/n8n"],
|
||||
"state": "RUNNING"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Important field behaviors:**
|
||||
- `state` values are **UPPERCASE** (`RUNNING`, not `running`)
|
||||
- `names` array entries are **prefixed with `/`** (e.g., `/n8n` not `n8n`)
|
||||
- `isUpdateAvailable` field does **NOT exist** in Unraid 7.2 schema (research was incorrect)
|
||||
|
||||
**Schema differences from research:**
|
||||
- Phase 14 research incorrectly documented `isUpdateAvailable` field
|
||||
- Actual schema introspection shows this field is not present in DockerContainer type
|
||||
- Phase 15 will need to determine correct field for update status tracking
|
||||
|
||||
### Container ID Format
|
||||
|
||||
- **Type:** `PrefixedID` scalar
|
||||
- **Format:** `{server_hash}:{container_hash}` — two 64-character SHA256 hex strings joined by colon
|
||||
- **Example:** `1639d2f04f44841bc62fec38d18e1869a558d85071fa23e0a8bf64d374b317fa:8a9907a245766012741662a5840cefdec67af6b70e4c6f1629af7ef8f1ee2925`
|
||||
- **Components:**
|
||||
- First part (server hash): Same for all containers on a given Unraid server
|
||||
- Second part (container hash): Unique per container
|
||||
- **Note:** Discovered during Phase 14 verification testing. Phase 15 mutations use this format.
|
||||
|
||||
### n8n Container Configuration
|
||||
|
||||
**Required environment variable:**
|
||||
- `UNRAID_HOST` — Unraid myunraid.net URL (without /graphql suffix)
|
||||
- Example: `https://192-168-90-103.abc123def456.myunraid.net:8443`
|
||||
- Set via Unraid WebGUI -> Docker -> n8n container -> Edit -> Add Variable
|
||||
|
||||
**Required n8n credential:**
|
||||
- **Type:** Header Auth
|
||||
- **Name:** "Unraid API Key"
|
||||
- **Header Name:** `x-api-key`
|
||||
- **Header Value:** Unraid API key (from `unraid-api apikey --create`)
|
||||
|
||||
**HTTP Request node configuration:**
|
||||
- **Authentication:** `genericCredentialType` with `httpHeaderAuth`
|
||||
- **Credential:** "Unraid API Key"- **URL:** `{{ $env.UNRAID_HOST }}/graphql`
|
||||
|
||||
### Update Mutation (Phase 15 — planned, not yet implemented)
|
||||
|
||||
```graphql
|
||||
mutation { docker { updateContainer(id: "<PrefixedID>") { id } } }
|
||||
```
|
||||
|
||||
**Status:** Planned for Phase 15 — not yet implemented per phase boundary.
|
||||
**Note:** Update tracking field needs discovery via schema introspection (isUpdateAvailable does not exist).
|
||||
|
||||
### Error Patterns
|
||||
|
||||
- **HTTP errors:** Connection refused (network), 401 (bad API key), 404 (API not available)
|
||||
- **GraphQL errors:** `response.errors[]` array with message field
|
||||
- **Error handling:** Same pattern as Docker API errors (structured return, descriptive messages)
|
||||
|
||||
## Workflow Files
|
||||
|
||||
| File | n8n ID | Purpose | Nodes |
|
||||
|
||||
Reference in New Issue
Block a user