Files
2026-02-08 20:22:11 -05:00

11 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, user_setup, must_haves
phase plan type wave depends_on files_modified autonomous user_setup must_haves
14-unraid-api-access 01 execute 1
.env.unraid-api
.gitignore
n8n-workflow.json
true
service why env_vars dashboard_config
unraid-api GraphQL API authentication for container update sync
name source
UNRAID_API_KEY Unraid WebGUI -> Settings -> Management Access -> API Keys -> Create, or SSH: unraid-api apikey --create --name 'Docker Manager Bot' --permissions 'DOCKER:UPDATE_ANY' --description 'Container update status sync' --json
name source
UNRAID_HOST User's Unraid WebGUI URL (e.g., http://192.168.1.100 or http://tower.local). If using host.docker.internal, must add '--add-host=host.docker.internal:host-gateway' to n8n container Extra Parameters in Unraid Docker template editor.
task location
Create API key with DOCKER:UPDATE_ANY permission Unraid WebGUI -> Settings -> Management Access -> API Keys, or via SSH
task location
Add --add-host=host.docker.internal:host-gateway to n8n container Extra Parameters (if using host.docker.internal) Unraid WebGUI -> Docker -> n8n container -> Edit -> Extra Parameters
truths artifacts key_links
Credential template file exists with correct variable names matching .env.n8n-api pattern
Credential file is gitignored and will not be committed
n8n workflow contains HTTP Request node configured for Unraid GraphQL API
n8n workflow contains error handling for GraphQL response validation
Test query requests fields needed by downstream phases (id, names, state, isUpdateAvailable)
path provides contains
.env.unraid-api Credential template with UNRAID_HOST and UNRAID_API_KEY UNRAID_HOST
path provides contains
.gitignore Gitignore entry for .env.unraid-api .env.unraid-api
path provides contains
n8n-workflow.json Unraid GraphQL test query nodes in main workflow Unraid
from to via pattern
n8n-workflow.json (HTTP Request node) Unraid GraphQL API POST to UNRAID_HOST/graphql with x-api-key header /graphql
from to via pattern
n8n-workflow.json (Code node) HTTP Request node Response validation and error handling data.docker.containers
Set up credential infrastructure and build Unraid GraphQL API test nodes in the main n8n workflow.

Purpose: Establishes the foundation for Unraid API connectivity — credential storage mirroring the existing .env.n8n-api pattern, gitignore protection, and actual n8n workflow nodes that query the Unraid GraphQL API to validate connectivity, authentication, and container data structure.

Output: .env.unraid-api template file, updated .gitignore, and new nodes in n8n-workflow.json for Unraid API testing.

<execution_context> @/home/luc/.claude/get-shit-done/workflows/execute-plan.md @/home/luc/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/14-unraid-api-access/14-CONTEXT.md @.planning/phases/14-unraid-api-access/14-RESEARCH.md @ARCHITECTURE.md @CLAUDE.md @.gitignore @n8n-workflow.json Task 1: Create credential infrastructure .env.unraid-api, .gitignore 1. Create `.env.unraid-api` file with template values, mirroring the existing `.env.n8n-api` pattern: ``` UNRAID_HOST=http://host.docker.internal UNRAID_API_KEY=your-unraid-api-key-here ```
  1. Add .env.unraid-api to .gitignore on a new line after the existing .env.n8n-api entry. Keep the comment header relevant (update if needed, e.g., "Environment files with sensitive credentials").

  2. Update CLAUDE.md — add a new section "## Unraid API Access" (after the existing "## n8n API Access" section) documenting:

    • Credential file location and structure (.env.unraid-api)
    • Loading pattern: . .env.unraid-api; curl -X POST "${UNRAID_HOST}/graphql" ...
    • GraphQL query pattern for testing
    • Note that this mirrors the n8n API access pattern

Per user decision: Dual storage approach — .env.unraid-api for CLI/deploy scripts, n8n Header Auth credential for workflow nodes. The n8n credential creation is a user setup step (documented in plan's user_setup frontmatter), not automated here.

  • .env.unraid-api exists with UNRAID_HOST and UNRAID_API_KEY variables
  • grep -q ".env.unraid-api" .gitignore returns 0
  • CLAUDE.md contains "Unraid API Access" section Credential template file exists with correct variables, is gitignored, and usage is documented in CLAUDE.md
Task 2: Add Unraid GraphQL test nodes to main workflow n8n-workflow.json Add a new branch to the main workflow's Keyword Router (Switch node) that handles an "unraid" keyword. This creates a test path: user sends "unraid" -> Keyword Router -> Unraid test nodes -> Telegram response.

The branch needs 3 new nodes:

Node 1: HTTP Request node ("Unraid API Test")

  • Method: POST
  • URL: ={{ $env.UNRAID_HOST }}/graphql (reads from n8n environment variable, OR use expression that can be overridden)
  • Authentication: Header Auth
    • Credential name: "Unraid API Key" (Header Auth type, header name: x-api-key)
    • NOTE: The credential must be created manually by the user in n8n. Use credential ID placeholder — the user will need to update this after creating the credential.
  • Body (JSON): { "query": "query { docker { containers { id names state isUpdateAvailable } } }" }
  • Options: "Ignore SSL Issues" = true (handles self-signed certs per research pitfall #2)
  • On Error: "Continue on Error" (so the Code node can handle errors gracefully)

Node 2: Code node ("Validate Unraid Response")

  • Validates the GraphQL response:
    const response = $input.item.json;
    
    // Check for HTTP errors (from continueOnError)
    if (response.error) {
      return {
        json: {
          action: 'send_message',
          text: `❌ <b>Unraid API Error</b>\n\n` +
                `<b>Error:</b> ${response.error.message || JSON.stringify(response.error)}\n\n` +
                `<b>Check:</b>\n` +
                `• Is UNRAID_HOST correct?\n` +
                `• Is the API key valid?\n` +
                `• Can n8n reach the Unraid host? (--add-host flag)\n` +
                `• Is Unraid GraphQL API enabled? (v7.2+ or Connect plugin)`,
          chatId: $('Telegram Trigger').item.json.message.chat.id
        }
      };
    }
    
    // Check for GraphQL errors
    if (response.errors) {
      const errorMsg = response.errors.map(e => e.message).join(', ');
      return {
        json: {
          action: 'send_message',
          text: `❌ <b>Unraid GraphQL Error</b>\n\n${errorMsg}`,
          chatId: $('Telegram Trigger').item.json.message.chat.id
        }
      };
    }
    
    // Validate response structure
    if (!response.data?.docker?.containers) {
      return {
        json: {
          action: 'send_message',
          text: '❌ <b>Unexpected response</b>\n\nNo container data in GraphQL response.',
          chatId: $('Telegram Trigger').item.json.message.chat.id
        }
      };
    }
    
    const containers = response.data.docker.containers;
    const sampleId = containers[0]?.id || 'N/A';
    const updateCount = containers.filter(c => c.isUpdateAvailable).length;
    
    return {
      json: {
        action: 'send_message',
        text: `✅ <b>Unraid API Connected</b>\n\n` +
              `<b>Containers:</b> ${containers.length}\n` +
              `<b>Updates available:</b> ${updateCount}\n` +
              `<b>ID format:</b> <code>${sampleId}</code>\n\n` +
              `Sample:\n` +
              containers.slice(0, 5).map(c =>
                `• ${c.names?.[0] || c.id} (${c.state})${c.isUpdateAvailable ? ' 🔄' : ''}`
              ).join('\n'),
        chatId: $('Telegram Trigger').item.json.message.chat.id
      }
    };
    
  • Uses clear, descriptive error messages per user decision (what failed, why, what to check)
  • Uses existing error logging pattern (structured return, same shape as Docker API errors)

Node 3: Telegram Send Message node ("Send Unraid Test Result")

  • Chat ID: ={{ $json.chatId }}
  • Text: ={{ $json.text }}
  • Parse Mode: HTML
  • Use existing Telegram credential (ID: I0xTTiASl7C1NZhJ)

Wiring:

  • Connect Keyword Router's new "unraid" output -> HTTP Request node -> Code node -> Telegram Send node
  • Add "unraid" as a new contains rule in the Keyword Router Switch node. Place it AFTER existing startsWith rules but the order among contains rules doesn't matter since "unraid" is unique.
  • Update the Keyword Router's rules array and connections accordingly.

Important n8n JSON patterns (from CLAUDE.md):

  • Telegram credential: { "id": "I0xTTiASl7C1NZhJ", "name": "Telegram account" }
  • Node IDs: Generate unique UUIDs for each new node
  • Position: Place nodes visually below/after existing keyword branches (check existing node positions for Y-offset pattern)
  • For the Header Auth credential: Use a placeholder credential reference. The user creates "Unraid API Key" credential in n8n manually and the credential ID gets set. Use name "Unraid API Key" in the node JSON.

Auth check: The "unraid" command goes through the existing Auth IF node (same path as all other text commands), so it's already protected.

  • python3 -c "import json; wf=json.load(open('n8n-workflow.json')); nodes=[n['name'] for n in wf['nodes']]; print('Unraid API Test' in nodes, 'Validate Unraid Response' in nodes, 'Send Unraid Test Result' in nodes)" All three should print True.
  • Keyword Router Switch node contains "unraid" rule.
  • Connections wire: Keyword Router -> Unraid API Test -> Validate Unraid Response -> Send Unraid Test Result.
  • Push workflow to n8n: . .env.n8n-api; ... push recipe from CLAUDE.md. Verify HTTP 200. Main workflow contains a working "unraid" keyword branch with HTTP Request (GraphQL query), validation Code node (error handling with descriptive messages), and Telegram response node. Workflow pushes to n8n successfully.
- `.env.unraid-api` exists with template values - `.gitignore` includes `.env.unraid-api` - `CLAUDE.md` documents Unraid API access pattern - `n8n-workflow.json` contains 3 new nodes: "Unraid API Test", "Validate Unraid Response", "Send Unraid Test Result" - Keyword Router has "unraid" rule - All connections properly wired - Workflow pushes to n8n without errors

<success_criteria>

  • Credential infrastructure mirrors existing .env.n8n-api pattern exactly
  • Test workflow branch is wired into main workflow's existing auth-protected text path
  • Error handling provides clear, actionable feedback (what failed, why, what to check)
  • Test query includes fields needed by Phase 15+: id, names, state, isUpdateAvailable </success_criteria>
After completion, create `.planning/phases/14-unraid-api-access/14-01-SUMMARY.md`