docs(14): research Unraid GraphQL API access patterns
This commit is contained in:
@@ -0,0 +1,593 @@
|
||||
# Phase 14: Unraid API Access - Research
|
||||
|
||||
**Researched:** 2026-02-08
|
||||
**Domain:** Unraid GraphQL API integration from n8n container
|
||||
**Confidence:** HIGH
|
||||
|
||||
## Summary
|
||||
|
||||
Phase 14 establishes connectivity from the n8n container to Unraid's GraphQL API endpoint and validates authentication, enabling subsequent phases to sync container update status. This phase is pure infrastructure setup — no workflow modifications, no mutations called, no status synchronization implemented yet.
|
||||
|
||||
The Unraid GraphQL API is the official interface for Docker container management, available natively in Unraid 7.2+ or via the Connect plugin for 6.9-7.1. Authentication uses API keys with granular permission scoping. The API endpoint is `http://<unraid-host>/graphql` and uses standard GraphQL over HTTP with x-api-key header authentication.
|
||||
|
||||
Network access from the n8n container to the Unraid host requires either `host.docker.internal` (with `--add-host=host.docker.internal:host-gateway` in container config) or direct IP/hostname access. Container ID format uses Unraid's `PrefixedID` scalar type (e.g., `docker:containername` or server-prefixed format like `123:containername`).
|
||||
|
||||
**Primary recommendation:** Use `host.docker.internal` for network access (standard Docker pattern), store credentials in `.env.unraid-api` file (mirrors existing n8n API pattern), and validate with a simple container list query before planning mutation calls in Phase 15.
|
||||
|
||||
---
|
||||
|
||||
<user_constraints>
|
||||
## User Constraints (from CONTEXT.md)
|
||||
|
||||
### Locked Decisions
|
||||
|
||||
**Credential management**
|
||||
- Dual storage: `.env.unraid-api` file (for CLI/deploy scripts) + n8n credential (for workflow nodes)
|
||||
- `.env.unraid-api` contains both `UNRAID_API_KEY` and `UNRAID_HOST` (mirrors `.env.n8n-api` pattern)
|
||||
- Phase includes documentation for creating the Unraid API key in WebGUI with correct permissions
|
||||
- File is gitignored
|
||||
|
||||
**Network connectivity**
|
||||
- User runs Unraid on default WebGUI ports — GraphQL API assumed on same port
|
||||
- HTTP vs HTTPS and self-signed cert handling needs to be figured out during research/testing
|
||||
- Connectivity verification done purely through n8n workflow nodes — no separate test script
|
||||
- Host URL stored in `UNRAID_HOST` env var — user configures during setup
|
||||
|
||||
**GraphQL query design**
|
||||
- Document only the queries/mutations relevant to update sync — not the full Docker schema
|
||||
- Container ID format mapping needs research — we don't know how Unraid identifies containers in GraphQL yet
|
||||
- GraphQL API contract documented in ARCHITECTURE.md alongside existing Docker API contract
|
||||
|
||||
**Error handling & feedback**
|
||||
- Clear, descriptive error messages on failure (what failed, why, what to check)
|
||||
- Use existing error logging system — same pattern as Docker API errors, not a separate log category
|
||||
- Phase 14 tests connectivity only — permission validation happens naturally in Phase 15 when mutations are attempted
|
||||
- No user-facing Telegram health check command for Unraid API — errors surface naturally during sync failures
|
||||
|
||||
### Claude's Discretion
|
||||
|
||||
- n8n credential type selection (based on Unraid GraphQL API's actual auth mechanism)
|
||||
- Network approach for n8n container reaching Unraid host (host IP, Docker networking, etc.)
|
||||
- What fields to include in the test query (based on what downstream phases need)
|
||||
|
||||
### Deferred Ideas (OUT OF SCOPE)
|
||||
|
||||
None — discussion stayed within phase scope
|
||||
</user_constraints>
|
||||
|
||||
---
|
||||
|
||||
## Standard Stack
|
||||
|
||||
### Core
|
||||
|
||||
| Library | Version | Purpose | Why Standard |
|
||||
|---------|---------|---------|--------------|
|
||||
| Unraid GraphQL API | 7.2+ native, 6.9-7.1 via Connect plugin | Container management and status sync | Official Unraid interface, same mechanism as WebGUI |
|
||||
| n8n HTTP Request node | Built-in (n8n 1.x) | GraphQL client | Standard GraphQL-over-HTTP pattern, no additional dependencies |
|
||||
| Unraid API Key | N/A (credential) | Authentication | Official authentication method, granular permission scoping |
|
||||
|
||||
### Supporting
|
||||
|
||||
| Library | Version | Purpose | When to Use |
|
||||
|---------|---------|---------|-------------|
|
||||
| n8n Credential system | Built-in | Secure credential storage | Store `UNRAID_HOST` and `UNRAID_API_KEY` for workflow access |
|
||||
| `.env.unraid-api` file | N/A (file) | External credential storage | CLI testing, deployment scripts, credential documentation |
|
||||
|
||||
### Alternatives Considered
|
||||
|
||||
| Instead of | Could Use | Tradeoff |
|
||||
|------------|-----------|----------|
|
||||
| GraphQL API | Direct file write to `/var/lib/docker/unraid-update-status.json` | File format undocumented, brittle, no UI refresh trigger |
|
||||
| API key auth | Session cookies | Requires WebGUI login flow, session expiry handling, fragile |
|
||||
| `host.docker.internal` | Hardcoded Unraid IP | Works but not portable, requires manual config changes |
|
||||
|
||||
**Installation:**
|
||||
|
||||
No n8n dependencies required (HTTP Request node is built-in). Requires Unraid API key creation on host:
|
||||
|
||||
```bash
|
||||
# SSH to Unraid:
|
||||
unraid-api apikey --create \
|
||||
--name "Docker Manager Bot" \
|
||||
--permissions "DOCKER:UPDATE_ANY" \
|
||||
--description "Telegram bot container update sync" \
|
||||
--json
|
||||
```
|
||||
|
||||
**Network configuration:**
|
||||
|
||||
If using `host.docker.internal` (recommended), add to n8n container config via Unraid Docker template editor:
|
||||
|
||||
```
|
||||
Extra Parameters: --add-host=host.docker.internal:host-gateway
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architecture Patterns
|
||||
|
||||
### Recommended Credential Storage Pattern
|
||||
|
||||
**Dual storage approach** (mirrors existing `.env.n8n-api` pattern):
|
||||
|
||||
```bash
|
||||
# .env.unraid-api (gitignored)
|
||||
UNRAID_HOST=http://host.docker.internal
|
||||
UNRAID_API_KEY=your-api-key-here
|
||||
```
|
||||
|
||||
**n8n credential configuration:**
|
||||
|
||||
1. Credentials → Add Credential → Header Auth
|
||||
2. Name: `Unraid API Key`
|
||||
3. Header Name: `x-api-key`
|
||||
4. Header Value: Reference environment variable or paste key directly
|
||||
|
||||
**Why dual storage:** CLI scripts (testing, deployment verification) use `.env` file, n8n workflows use n8n credential system. Keeps patterns consistent with existing n8n API access.
|
||||
|
||||
### Network Access Pattern
|
||||
|
||||
**Option 1: host.docker.internal (RECOMMENDED)**
|
||||
|
||||
```javascript
|
||||
// n8n HTTP Request node configuration
|
||||
{
|
||||
url: 'http://host.docker.internal/graphql',
|
||||
method: 'POST',
|
||||
authentication: 'headerAuth',
|
||||
credentialName: 'Unraid API Key',
|
||||
body: {
|
||||
query: 'query { docker { containers { id names state } } }'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Requires:** `--add-host=host.docker.internal:host-gateway` in n8n container config
|
||||
|
||||
**Pros:** Portable (works across different Unraid IPs), standard Docker pattern
|
||||
**Cons:** Requires container reconfiguration (one-time setup)
|
||||
|
||||
**Option 2: Direct IP/Hostname**
|
||||
|
||||
```javascript
|
||||
// Alternative for environments where host.docker.internal doesn't work
|
||||
{
|
||||
url: 'http://192.168.1.100/graphql', // or http://tower.local/graphql
|
||||
// ... rest same as Option 1
|
||||
}
|
||||
```
|
||||
|
||||
**Pros:** No container reconfiguration needed
|
||||
**Cons:** Hardcoded, not portable if Unraid IP changes
|
||||
|
||||
**Recommendation:** Use `host.docker.internal` for primary implementation, document direct IP as fallback.
|
||||
|
||||
### GraphQL Query Pattern for Testing
|
||||
|
||||
**Test connectivity query:**
|
||||
|
||||
```graphql
|
||||
query TestConnectivity {
|
||||
docker {
|
||||
containers {
|
||||
id
|
||||
names
|
||||
state
|
||||
isUpdateAvailable
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**What this validates:**
|
||||
- Network connectivity (can reach `/graphql` endpoint)
|
||||
- Authentication (API key accepted)
|
||||
- Permissions (can read Docker data)
|
||||
- Container ID format (see actual ID structure in response)
|
||||
|
||||
**n8n HTTP Request node body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"query": "query { docker { containers { id names state isUpdateAvailable } } }"
|
||||
}
|
||||
```
|
||||
|
||||
### Container ID Format Documentation Pattern
|
||||
|
||||
**Research finding:** Unraid uses `PrefixedID` scalar type. Format is `<server_id>:<resource_id>` where server_id is stripped on input, added on output.
|
||||
|
||||
**Example observed formats:**
|
||||
- `docker:plex` (name-based, common pattern)
|
||||
- `123:456` (numeric server + resource ID)
|
||||
|
||||
**Critical:** Actual format must be validated during Phase 14 testing. The GraphQL schema defines `PrefixedID` as abstract — implementation details discovered by running test query.
|
||||
|
||||
**Documentation location:** `ARCHITECTURE.md` section "GraphQL API Contract" (to be added in Phase 14).
|
||||
|
||||
### Anti-Patterns to Avoid
|
||||
|
||||
- **Hardcoding credentials in workflow nodes:** Always use n8n credential system or environment variables
|
||||
- **Testing GraphQL mutations in Phase 14:** Only queries, mutations are Phase 15+
|
||||
- **Skipping network connectivity verification:** Must validate HTTP access before assuming GraphQL works
|
||||
- **Using Docker socket proxy for Unraid API calls:** Different security boundary — Unraid API is host-level, not Docker daemon
|
||||
|
||||
---
|
||||
|
||||
## Don't Hand-Roll
|
||||
|
||||
| Problem | Don't Build | Use Instead | Why |
|
||||
|---------|-------------|-------------|-----|
|
||||
| GraphQL client library | Custom HTTP client with schema parsing, error handling, type validation | n8n HTTP Request node with POST method | GraphQL-over-HTTP is standard, no client library needed |
|
||||
| API key rotation system | Automated key lifecycle management, expiry tracking | Manual rotation via `unraid-api apikey --delete` + recreate | Keys don't expire, rotation is infrequent |
|
||||
| Network discovery | Auto-detect Unraid host IP, scan network for GraphQL endpoints | User-configured `UNRAID_HOST` variable | Single-host environment, user knows Unraid IP |
|
||||
| Credential encryption at rest | Custom encryption wrapper for `.env.unraid-api` | n8n's built-in credential encryption (via `N8N_ENCRYPTION_KEY`) | n8n already handles credential security, file is for CLI/testing only |
|
||||
|
||||
**Key insight:** Unraid GraphQL API is designed as a simple HTTP interface. Over-engineering the client side (schema validation, code generation, connection pooling) adds complexity without benefit for this use case.
|
||||
|
||||
---
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
### Pitfall 1: host.docker.internal Not Working on Linux Docker
|
||||
|
||||
**What goes wrong:** `host.docker.internal` is a Docker Desktop feature. On native Linux Docker, it may not resolve, causing "connection refused" or "no such host" errors.
|
||||
|
||||
**Why it happens:** Docker Engine on Linux doesn't automatically create the `host.docker.internal` DNS entry like Docker Desktop does on macOS/Windows.
|
||||
|
||||
**How to avoid:** Add `--add-host=host.docker.internal:host-gateway` to container extra parameters. The `host-gateway` special value resolves to the host's bridge IP (typically `172.17.0.1`).
|
||||
|
||||
**Warning signs:**
|
||||
- n8n HTTP Request node returns `getaddrinfo ENOTFOUND host.docker.internal`
|
||||
- `docker exec -it n8n curl http://host.docker.internal` fails with DNS error
|
||||
|
||||
**Verification:**
|
||||
```bash
|
||||
# From inside n8n container:
|
||||
docker exec -it n8n curl -I http://host.docker.internal/graphql
|
||||
# Should return HTTP 400 (GraphQL needs POST) or 200, NOT connection refused
|
||||
```
|
||||
|
||||
**Source:** [Docker Bridge Network Guide](https://docs.docker.com/engine/network/drivers/bridge/), [Connecting to Host from Container](https://dev.to/iamrj846/connecting-to-the-host-machines-localhost-from-a-docker-container-a-practical-guide-nc4)
|
||||
|
||||
### Pitfall 2: HTTP vs HTTPS Confusion with Self-Signed Certs
|
||||
|
||||
**What goes wrong:** User runs Unraid WebGUI on HTTPS with self-signed cert. HTTP Request node either fails with SSL verification error or connects to HTTP (port 80) when Unraid only listens on HTTPS (port 443).
|
||||
|
||||
**Why it happens:** Unraid defaults to HTTP but many users enable HTTPS via Settings → Management Access → Use SSL/TLS. Self-signed certs fail Node.js default SSL validation.
|
||||
|
||||
**How to avoid:**
|
||||
1. Check Unraid WebGUI URL — if `https://tower.local`, use `https://` in `UNRAID_HOST`
|
||||
2. In n8n HTTP Request node, set "Ignore SSL Issues" to `true` for self-signed certs
|
||||
3. Document both HTTP and HTTPS configs in setup instructions
|
||||
|
||||
**Warning signs:**
|
||||
- `UNABLE_TO_VERIFY_LEAF_SIGNATURE` error
|
||||
- `CERT_HAS_EXPIRED` error
|
||||
- Connection works on port 80 but not 443 (or vice versa)
|
||||
|
||||
**Verification:**
|
||||
```bash
|
||||
# Test which port Unraid listens on:
|
||||
curl -I http://tower.local/graphql # Port 80
|
||||
curl -I https://tower.local/graphql # Port 443
|
||||
```
|
||||
|
||||
**Recommendation:** Default to HTTP in examples (simpler), document HTTPS config as optional enhancement.
|
||||
|
||||
**Source:** Observed behavior in Unraid community forums, standard Node.js HTTPS client behavior
|
||||
|
||||
### Pitfall 3: Container ID Format Mismatch
|
||||
|
||||
**What goes wrong:** Phase 15+ calls `updateContainer(id: "plex")` but Unraid expects `"docker:plex"` or numeric ID. Mutation returns "container not found" error despite container existing.
|
||||
|
||||
**Why it happens:** GraphQL schema defines `PrefixedID` scalar but doesn't document exact format. Implementation may vary by Unraid version or container source (template vs. custom).
|
||||
|
||||
**How to avoid:**
|
||||
1. **Phase 14 MUST document actual ID format** observed in test query response
|
||||
2. Store both `id` (GraphQL format) and `names` (Docker format) during testing
|
||||
3. Phase 15 uses documented format from Phase 14, not assumptions
|
||||
|
||||
**Warning signs:**
|
||||
- Test query returns IDs like `"123:456"` or `"docker:containername"`
|
||||
- Mutation fails with "invalid ID format" or "container not found"
|
||||
|
||||
**Verification pattern:**
|
||||
```graphql
|
||||
# Phase 14 test query:
|
||||
query { docker { containers { id names } } }
|
||||
|
||||
# Response reveals format:
|
||||
{
|
||||
"data": {
|
||||
"docker": {
|
||||
"containers": [
|
||||
{ "id": "docker:plex", "names": ["plex"] } # Format discovered
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Critical:** Do NOT assume format. Let test query reveal truth.
|
||||
|
||||
**Source:** [Unraid API Schema](https://raw.githubusercontent.com/unraid/api/main/api/generated-schema.graphql) (defines PrefixedID as abstract), community client implementations show variation
|
||||
|
||||
### Pitfall 4: API Key Permissions Too Broad or Too Narrow
|
||||
|
||||
**What goes wrong:**
|
||||
- **Too narrow:** API key created without `DOCKER:UPDATE_ANY`, Phase 15 mutations fail with "permission denied"
|
||||
- **Too broad:** API key has `ADMIN` role, excessive permissions violate least privilege
|
||||
|
||||
**Why it happens:** Unraid API key creation supports both role-based (`--roles ADMIN`) and permission-based (`--permissions DOCKER:UPDATE_ANY`) access. Docs show both examples, easy to pick wrong one.
|
||||
|
||||
**How to avoid:**
|
||||
1. Use **permission-based scoping:** `--permissions "DOCKER:UPDATE_ANY"`
|
||||
2. **Do NOT use `--roles ADMIN`** (grants full system access)
|
||||
3. Phase 14 tests read-only query (permissions validation happens in Phase 15)
|
||||
|
||||
**Warning signs:**
|
||||
- API key works for queries but fails for mutations
|
||||
- Unraid logs show "insufficient permissions" for Docker operations
|
||||
|
||||
**Correct command:**
|
||||
```bash
|
||||
unraid-api apikey --create \
|
||||
--name "Docker Manager Bot" \
|
||||
--permissions "DOCKER:UPDATE_ANY" \
|
||||
--description "Container update status sync"
|
||||
```
|
||||
|
||||
**Wrong command (don't use):**
|
||||
```bash
|
||||
unraid-api apikey --create --roles ADMIN # Too broad!
|
||||
```
|
||||
|
||||
**Source:** [Unraid API Key Management](https://docs.unraid.net/API/programmatic-api-key-management/), [Using Unraid API](https://docs.unraid.net/API/how-to-use-the-api/)
|
||||
|
||||
### Pitfall 5: Rate Limiting Surprises
|
||||
|
||||
**What goes wrong:** Phase 16 batch sync calls `updateContainers` for 20+ containers, API returns 429 Too Many Requests or rate limit error.
|
||||
|
||||
**Why it happens:** Unraid API documentation states "The API implements rate limiting to prevent abuse" but doesn't specify thresholds. Actual limits are unknown.
|
||||
|
||||
**How to avoid:**
|
||||
1. Phase 14/15 use single-container queries/mutations (well within any reasonable limit)
|
||||
2. Phase 16 batch operations should use `updateContainers` (plural) mutation for efficiency, not N individual calls
|
||||
3. If rate limiting occurs, implement exponential backoff (standard HTTP pattern)
|
||||
|
||||
**Warning signs:**
|
||||
- HTTP 429 response
|
||||
- GraphQL error: `"message": "rate limit exceeded"`
|
||||
|
||||
**Impact assessment:** LOW for this project (bot updates are infrequent, <10/min even in aggressive batch mode). Rate limiting unlikely to be hit in normal usage.
|
||||
|
||||
**Mitigation:** Document in ARCHITECTURE.md, handle 429 gracefully (retry with backoff), consider it edge case not primary concern.
|
||||
|
||||
**Source:** [Using Unraid API](https://docs.unraid.net/API/how-to-use-the-api/) (confirms rate limiting exists), specific thresholds not documented
|
||||
|
||||
### Pitfall 6: Unraid Version Compatibility (Connect Plugin Missing)
|
||||
|
||||
**What goes wrong:** User runs Unraid 6.11 (pre-7.2), assumes GraphQL API is built-in, gets "404 Not Found" on `/graphql` endpoint.
|
||||
|
||||
**Why it happens:** Native GraphQL API was added in Unraid 7.2. Earlier versions (6.9-7.1) require the Connect plugin to be installed.
|
||||
|
||||
**How to avoid:**
|
||||
1. Phase 14 setup documentation MUST include version check
|
||||
2. If Unraid <7.2, document Connect plugin installation steps
|
||||
3. Test query naturally fails if API unavailable, clear error message guides user to install plugin
|
||||
|
||||
**Warning signs:**
|
||||
- HTTP 404 on `/graphql` endpoint
|
||||
- `curl http://tower.local/graphql` returns "Not Found"
|
||||
|
||||
**Setup instructions pattern:**
|
||||
```bash
|
||||
# Check Unraid version:
|
||||
cat /etc/unraid-version # SSH to Unraid
|
||||
|
||||
# If <7.2: Install Connect plugin
|
||||
# Apps → Search "Unraid Connect" → Install
|
||||
# Settings → Management Access → API → Enable
|
||||
```
|
||||
|
||||
**Verification:**
|
||||
```bash
|
||||
# After setup, this should return HTTP 400 (GraphQL requires POST body):
|
||||
curl -I http://tower.local/graphql
|
||||
```
|
||||
|
||||
**Source:** [Unraid API Documentation](https://docs.unraid.net/API/) (version availability), community forum discussions about Connect plugin
|
||||
|
||||
---
|
||||
|
||||
## Code Examples
|
||||
|
||||
Verified patterns from official sources:
|
||||
|
||||
### Test Connectivity Query (Phase 14)
|
||||
|
||||
```javascript
|
||||
// n8n HTTP Request node configuration
|
||||
// Node name: "Test Unraid API"
|
||||
// Method: POST
|
||||
// URL: http://host.docker.internal/graphql
|
||||
// Authentication: Header Auth (credential: "Unraid API Key")
|
||||
// Body Content Type: JSON
|
||||
|
||||
{
|
||||
"query": "query TestConnectivity { docker { containers { id names state isUpdateAvailable } } }"
|
||||
}
|
||||
|
||||
// Expected response structure:
|
||||
{
|
||||
"data": {
|
||||
"docker": {
|
||||
"containers": [
|
||||
{
|
||||
"id": "docker:plex", // Format may vary — document actual format
|
||||
"names": ["plex"],
|
||||
"state": "running",
|
||||
"isUpdateAvailable": false
|
||||
}
|
||||
// ... more containers
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error handling pattern (n8n Code node after HTTP Request):
|
||||
const response = $input.item.json;
|
||||
|
||||
if (response.errors) {
|
||||
// GraphQL returned errors
|
||||
const errorMsg = response.errors.map(e => e.message).join(', ');
|
||||
throw new Error(`Unraid API error: ${errorMsg}`);
|
||||
}
|
||||
|
||||
if (!response.data || !response.data.docker) {
|
||||
// Unexpected response structure
|
||||
throw new Error('Invalid GraphQL response from Unraid API');
|
||||
}
|
||||
|
||||
// Success — pass container data to next node
|
||||
return {
|
||||
json: {
|
||||
success: true,
|
||||
containers: response.data.docker.containers,
|
||||
containerIdFormat: response.data.docker.containers[0]?.id // Document format
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**Source:** [n8n GraphQL Documentation](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.graphql/), Unraid API schema
|
||||
|
||||
### CLI Testing Pattern (Outside n8n)
|
||||
|
||||
```bash
|
||||
# Source credentials
|
||||
. .env.unraid-api
|
||||
|
||||
# Test query via curl
|
||||
curl -X POST "${UNRAID_HOST}/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: ${UNRAID_API_KEY}" \
|
||||
-d '{
|
||||
"query": "query { docker { containers { id names state isUpdateAvailable } } }"
|
||||
}' \
|
||||
| python3 -c "
|
||||
import sys, json
|
||||
data = json.load(sys.stdin)
|
||||
if 'errors' in data:
|
||||
print('ERROR:', data['errors'])
|
||||
sys.exit(1)
|
||||
containers = data['data']['docker']['containers']
|
||||
print(f'Found {len(containers)} containers')
|
||||
for c in containers[:3]: # Show first 3
|
||||
print(f\" {c['id']} - {c['names'][0]} ({c['state']})\")
|
||||
"
|
||||
```
|
||||
|
||||
**Why CLI testing:** Validates API access outside n8n environment, useful for debugging network issues.
|
||||
|
||||
### Credential Storage Pattern
|
||||
|
||||
```bash
|
||||
# .env.unraid-api (gitignored)
|
||||
UNRAID_HOST=http://host.docker.internal
|
||||
UNRAID_API_KEY=1234567890abcdef
|
||||
|
||||
# Load in bash scripts:
|
||||
. .env.unraid-api
|
||||
curl -H "x-api-key: ${UNRAID_API_KEY}" "${UNRAID_HOST}/graphql" ...
|
||||
|
||||
# Reference in n8n:
|
||||
# Option 1: n8n credential system (recommended for workflows)
|
||||
# Option 2: Environment variables if n8n container has env file mounted
|
||||
```
|
||||
|
||||
**Security note:** Never commit `.env.unraid-api` to git. Already in `.gitignore` (mirrors `.env.n8n-api` pattern).
|
||||
|
||||
**Source:** [n8n Credentials Environment Variables](https://docs.n8n.io/hosting/configuration/environment-variables/credentials/), existing project `.env.n8n-api` pattern
|
||||
|
||||
---
|
||||
|
||||
## State of the Art
|
||||
|
||||
| Old Approach | Current Approach | When Changed | Impact |
|
||||
|--------------|------------------|--------------|--------|
|
||||
| Direct file manipulation (`/var/lib/docker/unraid-update-status.json`) | GraphQL API `updateContainer` mutation | Unraid 6.9 (2020, Connect plugin) | Official interface, version-safe, handles internal state sync |
|
||||
| Session cookie auth | API key with x-api-key header | Unraid 6.9 API introduction | Stateless, no expiry handling, programmatic access |
|
||||
| Unraid CLI scripts (`/usr/local/emhttp/plugins/dynamix.docker.manager/`) | GraphQL API exposure of DockerService | Unraid 7.2 (2023, native API) | No PHP runtime needed, standard HTTP interface |
|
||||
|
||||
**Deprecated/outdated:**
|
||||
- **Direct `/var/lib/docker/unraid-update-status.json` writes:** File format undocumented, no UI refresh trigger, brittle
|
||||
- **Unraid API-RE (community plugin):** Replaced by official Unraid API/Connect plugin, no longer maintained
|
||||
- **WebGUI session scraping:** Fragile, breaks on Unraid updates, security risk
|
||||
|
||||
**Current best practice (2026):** Use official GraphQL API via HTTP Request with API key authentication. Mirrors how Unraid's own WebGUI communicates with backend.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. **Exact container ID format in GraphQL responses**
|
||||
- What we know: Schema defines `PrefixedID` scalar, format is `<server>:<resource>`
|
||||
- What's unclear: Whether it's `"docker:containername"`, numeric like `"123:456"`, or varies by source
|
||||
- Recommendation: Phase 14 test query MUST document actual format observed, used by Phase 15+
|
||||
|
||||
2. **HTTP vs HTTPS default on user's Unraid**
|
||||
- What we know: Unraid defaults to HTTP but many users enable HTTPS
|
||||
- What's unclear: How many users have self-signed certs vs. valid certs vs. HTTP-only
|
||||
- Recommendation: Default to HTTP in examples, document HTTPS + "Ignore SSL" as configuration option
|
||||
|
||||
3. **Rate limiting thresholds**
|
||||
- What we know: API implements rate limiting (confirmed in docs)
|
||||
- What's unclear: Actual request/minute limits, burst allowances
|
||||
- Recommendation: Assume reasonable limits (100+/min), handle 429 gracefully, unlikely to hit in practice
|
||||
|
||||
4. **Unraid version distribution (6.x vs 7.x)**
|
||||
- What we know: 7.2+ has native API, 6.9-7.1 needs Connect plugin, <6.9 unsupported
|
||||
- What's unclear: User's actual Unraid version
|
||||
- Recommendation: Phase 14 setup instructions check version, guide plugin install if needed
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
### Primary (HIGH confidence)
|
||||
- [Unraid GraphQL Schema](https://raw.githubusercontent.com/unraid/api/main/api/generated-schema.graphql) — Container queries, mutation signatures, PrefixedID definition
|
||||
- [Using the Unraid API](https://docs.unraid.net/API/how-to-use-the-api/) — Endpoint URL, authentication header format, rate limiting acknowledgment
|
||||
- [Unraid API Key Management](https://docs.unraid.net/API/programmatic-api-key-management/) — API key creation, permission scoping
|
||||
- [n8n GraphQL Node Documentation](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.graphql/) — HTTP Request node GraphQL patterns
|
||||
- [Docker Bridge Network](https://docs.docker.com/engine/network/drivers/bridge/) — host.docker.internal behavior, bridge IP access
|
||||
|
||||
### Secondary (MEDIUM confidence)
|
||||
- [n8n Security Best Practices](https://docs.n8n.io/hosting/configuration/environment-variables/credentials/) — Credential storage, encryption
|
||||
- [Connecting to Host from Docker Container](https://dev.to/iamrj846/connecting-to-the-host-machines-localhost-from-a-docker-container-a-practical-guide-nc4) — host.docker.internal Linux workarounds
|
||||
- Project `.planning/research/STACK.md` — Prior v1.3 research on Unraid API (same domain, validates findings)
|
||||
- Project `.planning/research/SUMMARY.md` — Architecture patterns for this project
|
||||
|
||||
### Tertiary (LOW confidence)
|
||||
- Community forum posts on Unraid API authentication — Anecdotal troubleshooting examples
|
||||
- GitHub client implementations ([unraid-mcp](https://github.com/jmagar/unraid-mcp), [ha-unraid](https://github.com/domalab/unraid-api-client)) — Reference patterns, not official docs
|
||||
|
||||
---
|
||||
|
||||
## Metadata
|
||||
|
||||
**Confidence breakdown:**
|
||||
- Standard stack: HIGH — GraphQL API is official, HTTP Request node is n8n built-in, well-documented
|
||||
- Architecture: HIGH — Network patterns are standard Docker, credential storage mirrors existing project pattern
|
||||
- Pitfalls: MEDIUM-HIGH — Most are standard HTTP/Docker issues, container ID format needs empirical validation
|
||||
|
||||
**Research date:** 2026-02-08
|
||||
**Valid until:** 60 days (Unraid API is stable, GraphQL schema changes infrequent)
|
||||
|
||||
**Critical dependencies for planning:**
|
||||
- Phase 14 MUST validate container ID format via test query (open question #1)
|
||||
- Phase 14 MUST document HTTP vs HTTPS configuration for user's environment (open question #2)
|
||||
- Setup instructions MUST include Unraid version check and Connect plugin guidance (open question #4)
|
||||
|
||||
**Ready for planning:** YES — Sufficient information to create tasks for API key creation, network configuration, test query implementation, and container ID format documentation.
|
||||
Reference in New Issue
Block a user