811030cee4
Files: - STACK.md: Socket proxy, n8n API, Telegram keyboards - FEATURES.md: Table stakes, differentiators, MVP scope - ARCHITECTURE.md: Integration points, data flow changes - PITFALLS.md: Top 5 risks with prevention strategies - SUMMARY.md: Executive summary, build order, confidence Key findings: - Stack: LinuxServer socket-proxy, HTTP Request nodes for keyboards - Architecture: TCP curl migration (~15 nodes), new callback routes - Critical pitfall: Socket proxy breaks existing curl commands Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
386 lines
13 KiB
Markdown
386 lines
13 KiB
Markdown
# Stack Research: v1.1 Features
|
|
|
|
**Project:** Unraid Docker Manager
|
|
**Researched:** 2026-02-02
|
|
**Focus:** Stack additions for n8n API, Docker socket security, Telegram keyboards, Unraid integration
|
|
|
|
## n8n API Access
|
|
|
|
### Overview
|
|
|
|
n8n provides a public REST API for programmatic workflow management. This enables Claude Code to read, update, and test workflows without manual UI interaction.
|
|
|
|
### Authentication
|
|
|
|
**Method:** API Key via HTTP header
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Header name | `X-N8N-API-KEY` |
|
|
| Key location | n8n UI: Settings > n8n API > Create an API key |
|
|
| Base path | `/api/v1` |
|
|
|
|
**Environment Variables:**
|
|
- `N8N_PUBLIC_API_DISABLED=false` (default) - API enabled
|
|
- `N8N_PUBLIC_API_SWAGGERUI_DISABLED=false` (default) - Swagger UI enabled
|
|
|
|
The API is **enabled by default** on self-hosted n8n. No additional configuration needed unless it was explicitly disabled.
|
|
|
|
### Key Endpoints
|
|
|
|
| Endpoint | Method | Purpose |
|
|
|----------|--------|---------|
|
|
| `/api/v1/workflows` | GET | List all workflows |
|
|
| `/api/v1/workflows/{id}` | GET | Get workflow JSON |
|
|
| `/api/v1/workflows/{id}` | PUT | Update workflow |
|
|
| `/api/v1/workflows/{id}/activate` | POST | Activate workflow |
|
|
| `/api/v1/workflows/{id}/deactivate` | POST | Deactivate workflow |
|
|
| `/api/v1/executions` | GET | List executions (with logs) |
|
|
| `/api/v1/executions/{id}` | GET | Get execution details |
|
|
|
|
### API Playground
|
|
|
|
Self-hosted n8n includes a built-in Swagger UI at `/api/v1/docs` (or similar path based on configuration). This provides interactive documentation for testing API calls.
|
|
|
|
### Integration with Claude Code
|
|
|
|
To enable Claude Code workflow management:
|
|
|
|
1. Create API key in n8n Settings > n8n API
|
|
2. Store key securely (not in repository)
|
|
3. Use HTTP requests to n8n API endpoints
|
|
4. Example: `curl -H "X-N8N-API-KEY: <key>" http://localhost:5678/api/v1/workflows`
|
|
|
|
**Confidence:** MEDIUM - Official docs confirm API exists and authentication method. Specific endpoint paths verified through multiple sources but not directly tested.
|
|
|
|
**Sources:**
|
|
- [n8n API Authentication](https://docs.n8n.io/api/authentication/)
|
|
- [n8n API Reference](https://docs.n8n.io/api/api-reference/)
|
|
- [Disable Public API](https://docs.n8n.io/hosting/securing/disable-public-api/)
|
|
|
|
---
|
|
|
|
## Docker Socket Security
|
|
|
|
### The Problem
|
|
|
|
Current setup mounts Docker socket directly into internet-exposed n8n container:
|
|
```
|
|
-v /var/run/docker.sock:/var/run/docker.sock
|
|
```
|
|
|
|
This is a security risk: if n8n is compromised, attacker has full Docker (root) access to the host.
|
|
|
|
### Solution: Docker Socket Proxy
|
|
|
|
A socket proxy sits between containers and the Docker socket, filtering API requests to only allow specific operations.
|
|
|
|
### Option Comparison
|
|
|
|
| Feature | Tecnativa | LinuxServer | Wollomatic |
|
|
|---------|-----------|-------------|------------|
|
|
| Base | HAProxy (Alpine) | HAProxy (Alpine) | Go (scratch) |
|
|
| Image size | ~10MB | ~10MB | ~3MB |
|
|
| Config method | Environment variables | Environment variables | Regex allowlists |
|
|
| Granularity | Per-API section | Per-API section | Per-endpoint regex |
|
|
| Active maintenance | Yes | Yes | Yes |
|
|
| Unraid compatibility | Yes | Yes | Yes |
|
|
|
|
### Recommendation: LinuxServer/socket-proxy
|
|
|
|
**Why:** Drop-in replacement for Tecnativa with better documentation and active LinuxServer community support. Familiar to Unraid users.
|
|
|
|
### Configuration for This Project
|
|
|
|
The bot needs these Docker API operations:
|
|
- List containers (`/containers/json`)
|
|
- Inspect container (`/containers/{id}/json`)
|
|
- Start container (`/containers/{id}/start`)
|
|
- Stop container (`/containers/{id}/stop`)
|
|
- Restart container (`/containers/{id}/restart`)
|
|
- Pull image (`/images/create`)
|
|
- Create container (`/containers/create`)
|
|
- Remove container (`/containers/{id}`)
|
|
- Container logs (`/containers/{id}/logs`)
|
|
|
|
**Required Environment Variables:**
|
|
|
|
```bash
|
|
# LinuxServer socket-proxy configuration
|
|
CONTAINERS=1 # Container list/inspect
|
|
IMAGES=1 # Image pull
|
|
POST=1 # Enable POST requests (needed for start/stop/restart/create)
|
|
ALLOW_START=1 # /containers/{id}/start
|
|
ALLOW_STOP=1 # /containers/{id}/stop
|
|
ALLOW_RESTARTS=1 # /containers/{id}/restart (also enables /kill)
|
|
|
|
# Keep defaults (already enabled)
|
|
EVENTS=1 # Default
|
|
PING=1 # Default
|
|
VERSION=1 # Default
|
|
```
|
|
|
|
### Deployment Architecture
|
|
|
|
```
|
|
[Internet]
|
|
|
|
|
[n8n container]
|
|
|
|
|
[socket-proxy] <-- internal network only
|
|
|
|
|
[Docker socket]
|
|
```
|
|
|
|
**n8n container changes:**
|
|
- Remove: `-v /var/run/docker.sock:/var/run/docker.sock`
|
|
- Add: `DOCKER_HOST=tcp://socket-proxy:2375`
|
|
- Add: Connect to same Docker network as socket-proxy
|
|
|
|
**Socket-proxy container:**
|
|
```bash
|
|
docker run -d \
|
|
--name socket-proxy \
|
|
--restart=unless-stopped \
|
|
-v /var/run/docker.sock:/var/run/docker.sock:ro \
|
|
--read-only \
|
|
--tmpfs /run \
|
|
-e CONTAINERS=1 \
|
|
-e IMAGES=1 \
|
|
-e POST=1 \
|
|
-e ALLOW_START=1 \
|
|
-e ALLOW_STOP=1 \
|
|
-e ALLOW_RESTARTS=1 \
|
|
--network internal \
|
|
lscr.io/linuxserver/socket-proxy:latest
|
|
```
|
|
|
|
**CRITICAL:** Never expose socket-proxy port (2375) to external networks. Use internal Docker network only.
|
|
|
|
**Confidence:** HIGH - Official documentation from both Tecnativa and LinuxServer confirms configuration options and security model.
|
|
|
|
**Sources:**
|
|
- [Tecnativa docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy)
|
|
- [LinuxServer socket-proxy](https://docs.linuxserver.io/images/docker-socket-proxy/)
|
|
- [Wollomatic socket-proxy](https://github.com/wollomatic/socket-proxy)
|
|
|
|
---
|
|
|
|
## Telegram Inline Keyboards
|
|
|
|
### The Problem
|
|
|
|
n8n's native Telegram node has limitations with inline keyboards:
|
|
1. Cannot pass dynamic JSON for `reply_markup`
|
|
2. Expressions in keyboard fields cause "The value is not supported!" errors
|
|
3. PR #17258 adding JSON keyboard support has been pending since July 2025
|
|
|
|
### Solution Options
|
|
|
|
| Option | Approach | Pros | Cons |
|
|
|--------|----------|------|------|
|
|
| HTTP Request node | Direct Telegram API calls | Full control, no dependencies | Token in URL, more setup |
|
|
| Custom community node | @topvisor/n8n-nodes-telegram-send-message-custom | Easy JSON support | External dependency |
|
|
| Wait for PR #17258 | Native n8n support | No workarounds needed | Indefinite timeline |
|
|
|
|
### Recommendation: HTTP Request Node
|
|
|
|
**Why:** No external dependencies, full Telegram API access, already proven pattern in similar projects.
|
|
|
|
### Implementation
|
|
|
|
**Send Message with Inline Keyboard:**
|
|
|
|
```json
|
|
// HTTP Request node
|
|
// URL: https://api.telegram.org/bot{{ $credentials.telegramApi.token }}/sendMessage
|
|
// Method: POST
|
|
// Body Type: JSON
|
|
{
|
|
"chat_id": "={{ $json.message.chat.id }}",
|
|
"text": "Select a container:",
|
|
"parse_mode": "HTML",
|
|
"reply_markup": {
|
|
"inline_keyboard": [
|
|
[
|
|
{"text": "plex", "callback_data": "start:plex"},
|
|
{"text": "sonarr", "callback_data": "start:sonarr"}
|
|
],
|
|
[
|
|
{"text": "radarr", "callback_data": "start:radarr"},
|
|
{"text": "Cancel", "callback_data": "cancel"}
|
|
]
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
**Handle Callback Query:**
|
|
|
|
The workflow already handles `callback_query` via the Telegram Trigger node (confirmed in current workflow). The callback_data format `action:container` allows parsing:
|
|
|
|
```javascript
|
|
// In Code node
|
|
const callbackData = $json.callback_query.data;
|
|
const [action, container] = callbackData.split(':');
|
|
return { action, container };
|
|
```
|
|
|
|
**Answer Callback Query (remove loading spinner):**
|
|
|
|
```json
|
|
// HTTP Request node
|
|
// URL: https://api.telegram.org/bot{{ $credentials.telegramApi.token }}/answerCallbackQuery
|
|
// Method: POST
|
|
{
|
|
"callback_query_id": "={{ $json.callback_query.id }}",
|
|
"text": "Processing..."
|
|
}
|
|
```
|
|
|
|
### Callback Data Limits
|
|
|
|
Telegram limits `callback_data` to 64 bytes. Use short encodings:
|
|
- `s:plex` instead of `start:plex`
|
|
- Single char actions: s=start, t=stop, r=restart, u=update, l=logs
|
|
|
|
### Alternative: Custom Community Node
|
|
|
|
If HTTP Request becomes unwieldy, install:
|
|
```
|
|
Settings > Community Nodes > Install
|
|
Package: @topvisor/n8n-nodes-telegram-send-message-custom
|
|
```
|
|
|
|
This allows passing any Telegram API parameters as JSON, including `reply_markup`.
|
|
|
|
**Confidence:** MEDIUM - HTTP Request approach confirmed working by multiple community members. Native node limitations confirmed by open issues and PR #17258.
|
|
|
|
**Sources:**
|
|
- [n8n Telegram Callback Operations](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.telegram/callback-operations/)
|
|
- [PR #17258: JSON Keyboard Support](https://github.com/n8n-io/n8n/pull/17258)
|
|
- [Custom Telegram Node](https://github.com/topvisor/n8n-nodes-telegram-send-message-custom)
|
|
- [Telegram Bot API - Inline Keyboards](https://core.telegram.org/bots/api#inlinekeyboardmarkup)
|
|
|
|
---
|
|
|
|
## Unraid Integration
|
|
|
|
### How Unraid Detects Updates
|
|
|
|
Unraid checks for Docker image updates by comparing local image digests against remote registry digests:
|
|
|
|
1. Local image has digest (e.g., `35049b54ac64`)
|
|
2. Unraid queries registry for `latest` tag digest (e.g., `96c1da19c304`)
|
|
3. If different, shows "Update Available" badge
|
|
|
|
Update status is stored in: `/var/lib/docker/unraid-update-status.json`
|
|
|
|
### The Problem
|
|
|
|
When containers are updated externally (Watchtower, Portainer, or our bot), Unraid doesn't detect the change:
|
|
- Container updates successfully
|
|
- Unraid still shows "Update Available" badge
|
|
- Manual "Check for Updates" doesn't fix it
|
|
- Only deleting `unraid-update-status.json` and re-checking clears it
|
|
|
|
### Root Cause
|
|
|
|
Unraid only checks for **newly available** updates, not for containers that are **no longer** out of date. This is a known regression/limitation in Unraid's Docker management.
|
|
|
|
### Solution Options
|
|
|
|
| Option | Approach | Reliability |
|
|
|--------|----------|-------------|
|
|
| Delete status file | `rm /var/lib/docker/unraid-update-status.json` after update | HIGH - forces full recheck |
|
|
| Trigger recheck | Unraid WebUI "Check for Updates" after file delete | MEDIUM - requires UI or API |
|
|
| Accept mismatch | Document that badge may be stale | LOW - poor UX |
|
|
|
|
### Recommendation: Delete Status File + Document
|
|
|
|
**Approach:**
|
|
1. After bot successfully updates a container, delete the status file
|
|
2. Document that users should click "Check for Updates" in Unraid UI to refresh badges
|
|
3. Future enhancement: investigate if Unraid has an API to trigger update check
|
|
|
|
**Implementation:**
|
|
|
|
Add to update workflow after successful container recreation:
|
|
|
|
```bash
|
|
# In Execute Command node (runs on Unraid host)
|
|
rm -f /var/lib/docker/unraid-update-status.json
|
|
```
|
|
|
|
**Caveat:** This requires the n8n container to have access to `/var/lib/docker/` on the host, which is a security consideration. Alternative: document the manual step.
|
|
|
|
### Integration Points
|
|
|
|
| File/API | Purpose | Access Method |
|
|
|----------|---------|---------------|
|
|
| `/var/lib/docker/unraid-update-status.json` | Update badge status | Host filesystem |
|
|
| Unraid WebUI | Trigger update check | Manual (no API found) |
|
|
|
|
**Confidence:** MEDIUM - File location and behavior confirmed by multiple Unraid forum threads. No official Unraid API documentation found for programmatic update checks.
|
|
|
|
**Sources:**
|
|
- [Unraid Forum: Docker shows "update ready" after updating](https://forums.unraid.net/topic/157820-docker-shows-update-ready-after-updating/)
|
|
- [Watchtower + Unraid Discussion](https://github.com/containrrr/watchtower/discussions/1389)
|
|
- [Unraid Forum: Incorrect docker update notification](https://forums.unraid.net/bug-reports/stable-releases/regression-incorrect-docker-update-notification-r2807/)
|
|
|
|
---
|
|
|
|
## Recommendations Summary
|
|
|
|
### Stack Additions
|
|
|
|
| Component | Recommendation | Confidence |
|
|
|-----------|----------------|------------|
|
|
| n8n API | Use existing public API with API key auth | MEDIUM |
|
|
| Docker security | LinuxServer socket-proxy | HIGH |
|
|
| Telegram keyboards | HTTP Request node to Telegram API | MEDIUM |
|
|
| Unraid sync | Delete status file after update | MEDIUM |
|
|
|
|
### Implementation Order
|
|
|
|
1. **Docker socket proxy** - Security improvement, low risk, well-documented
|
|
2. **Telegram inline keyboards** - UX improvement, proven pattern
|
|
3. **n8n API access** - Developer tooling, not user-facing
|
|
4. **Unraid update sync** - Nice-to-have, requires additional host access
|
|
|
|
### No New Dependencies Required
|
|
|
|
All solutions use existing n8n capabilities:
|
|
- HTTP Request node (Telegram API, Docker via proxy)
|
|
- Execute Command node (Unraid file deletion)
|
|
- n8n public API (existing feature)
|
|
|
|
The only new container is `socket-proxy`, which is infrastructure, not application code.
|
|
|
|
### Key Risks
|
|
|
|
| Risk | Mitigation |
|
|
|------|------------|
|
|
| Socket proxy misconfiguration | Test each Docker operation after setup |
|
|
| Telegram API token exposure | Use n8n credentials, never log full URLs |
|
|
| Unraid status file access | May need additional volume mount or manual step |
|
|
| n8n API key security | Store outside repository, rotate periodically |
|
|
|
|
---
|
|
|
|
## Metadata
|
|
|
|
**Research date:** 2026-02-02
|
|
**Valid until:** 2026-03-02 (30 days)
|
|
|
|
**Confidence breakdown:**
|
|
- n8n API: MEDIUM - Docs confirm existence, specific endpoints need validation
|
|
- Docker socket proxy: HIGH - Official docs, multiple implementations
|
|
- Telegram keyboards: MEDIUM - Community-confirmed workarounds
|
|
- Unraid integration: MEDIUM - Forum-confirmed behavior, no official API
|
|
|
|
**Gaps:**
|
|
- n8n API specific endpoint paths should be validated via Swagger UI
|
|
- Unraid may have undocumented API for update checks (not found)
|
|
- PR #17258 merge timeline unknown
|