docs: complete v1.1 research (4 researchers + synthesis)

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>
This commit is contained in:
Lucas Berger
2026-02-02 22:09:06 -05:00
parent ff289677ab
commit 811030cee4
5 changed files with 1614 additions and 0 deletions
+356
View File
@@ -0,0 +1,356 @@
# Architecture Research: v1.1
**Researched:** 2026-02-02
**Domain:** Integration architecture for v1.1 features
**Confidence:** HIGH (n8n API, Docker socket proxy), MEDIUM (Telegram keyboards), LOW (Unraid update sync)
## Executive Summary
The v1.1 features require careful integration with the existing single-workflow architecture. The key finding is that all four features (n8n API access, Docker socket security, Telegram keyboards, Unraid update sync) can be implemented without major refactoring of the existing workflow structure. However, Docker socket proxy is the most impactful change, requiring container-level infrastructure modifications before workflow changes.
## Current Architecture
```
+-------------------+ +------------------+ +-------------------+
| Telegram User |---->| n8n Workflow |---->| Docker Socket |
| (Webhook) | | (3,200 lines) | | (/var/run/...) |
+-------------------+ +------------------+ +-------------------+
|
v
+------------------+
| Telegram Bot |
| API (Response) |
+------------------+
```
**Current Components:**
| Component | Description | Modification Risk |
|-----------|-------------|-------------------|
| Telegram Trigger | Webhook receiving messages & callbacks | LOW - add callback_query handling |
| Route Update Type | Switch node: message vs callback | LOW - already exists |
| Auth Check | IF nodes checking user ID | NONE - unchanged |
| Keyword Router | Switch node with contains rules | LOW - add new routes |
| Docker operations | Execute Command + curl | HIGH - needs socket proxy changes |
| Response formatting | Code nodes + Telegram send | LOW - extend existing |
## Integration Points
### 1. n8n API Access
**What needs to change:** Enable n8n REST API and create API key for external access.
**Integration approach:** Configuration change only, no workflow modifications needed.
**Configuration required:**
```bash
# n8n container environment variables
N8N_PUBLIC_API_DISABLED=false # Default - API is enabled
# No additional env vars needed for basic API access
```
**How Claude Code can use it:**
```bash
# Get workflow (requires API key)
curl -X GET "http://n8n:5678/api/v1/workflows" \
-H "X-N8N-API-KEY: <api-key>"
# Get specific workflow
curl -X GET "http://n8n:5678/api/v1/workflows/<workflow-id>" \
-H "X-N8N-API-KEY: <api-key>"
# Update workflow
curl -X PUT "http://n8n:5678/api/v1/workflows/<workflow-id>" \
-H "X-N8N-API-KEY: <api-key>" \
-H "Content-Type: application/json" \
-d @workflow.json
# Get execution logs
curl -X GET "http://n8n:5678/api/v1/executions" \
-H "X-N8N-API-KEY: <api-key>"
# Execute workflow manually
curl -X POST "http://n8n:5678/api/v1/workflows/<workflow-id>/activate" \
-H "X-N8N-API-KEY: <api-key>"
```
**Impact on existing workflow:** NONE - this is infrastructure configuration.
**Sources:**
- [n8n public REST API](https://docs.n8n.io/api/)
- [n8n API authentication](https://docs.n8n.io/api/authentication/)
- [Disable the public REST API](https://docs.n8n.io/hosting/securing/disable-public-api/)
### 2. Docker Socket Security (Socket Proxy)
**What needs to change:** Replace direct Docker socket mount with socket proxy container.
**Current architecture (INSECURE):**
```
n8n container ----mount----> /var/run/docker.sock (host)
```
**Target architecture (SECURE):**
```
n8n container ---tcp---> socket-proxy container ---mount---> docker.sock (host)
```
**New container required:** LinuxServer or Tecnativa docker-socket-proxy
**Recommended configuration (LinuxServer):**
```yaml
# docker-compose.yml
services:
socket-proxy:
image: lscr.io/linuxserver/socket-proxy:latest
container_name: socket-proxy
environment:
- CONTAINERS=1 # List containers
- POST=0 # Disable general POST (security)
- ALLOW_START=1 # Allow container start
- ALLOW_STOP=1 # Allow container stop
- ALLOW_RESTARTS=1 # Allow restart/kill
- IMAGES=1 # For image operations (update flow)
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
read_only: true
tmpfs:
- /run
n8n:
# Remove: -v /var/run/docker.sock:/var/run/docker.sock
environment:
- DOCKER_HOST=tcp://socket-proxy:2375
depends_on:
- socket-proxy
```
**Impact on existing workflow:** HIGH - all curl commands must change
| Current Pattern | New Pattern |
|-----------------|-------------|
| `curl --unix-socket /var/run/docker.sock http://localhost/...` | `curl http://socket-proxy:2375/...` |
**Workflow changes needed:**
1. All Execute Command nodes using `--unix-socket` flag need modification
2. Host changes from `localhost` to `socket-proxy`
3. Socket path removed from curl commands
**Search & replace pattern:**
```
FROM: curl -s --unix-socket /var/run/docker.sock 'http://localhost/v1.47/
TO: curl -s 'http://socket-proxy:2375/v1.47/
```
**Node count affected:** ~15 Execute Command nodes (Docker List, Inspect, Start, Stop, etc.)
**Security benefit:**
- n8n no longer has root-equivalent host access
- Socket proxy limits which Docker API endpoints are accessible
- Read-only mount on socket-proxy container
**Sources:**
- [LinuxServer socket-proxy](https://docs.linuxserver.io/images/docker-socket-proxy/)
- [Tecnativa docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy)
### 3. Telegram Inline Keyboards
**What needs to change:** Add persistent menu buttons and expand inline keyboard usage.
**Integration with existing architecture:**
- Existing callback_query handling already in place (suggestions, batch confirmations)
- HTTP Request nodes already used for complex Telegram API calls
- Switch node (Route Callback) handles different callback types
**Current callback flow (already exists):**
```
Telegram Trigger (callback_query)
-> IF Callback Authenticated
-> Parse Callback Data
-> Route Callback (Switch)
-> cancel / expired / batch / single action
```
**Additions needed:**
1. **Persistent keyboard on /start or unknown input:**
```json
{
"reply_markup": {
"keyboard": [
[{"text": "Status"}],
[{"text": "Start"}, {"text": "Stop"}],
[{"text": "Restart"}, {"text": "Update"}],
[{"text": "Logs"}]
],
"is_persistent": true,
"resize_keyboard": true
}
}
```
2. **Container selection keyboards:**
After user sends "start" without container name, show inline keyboard with running/stopped containers.
**Known limitation:** n8n's native Telegram node doesn't support dynamic inline keyboards well. Continue using HTTP Request nodes for complex keyboards (already the pattern in v1.0).
**New callback routing needed:**
| Callback Type | Action Code | Handler |
|---------------|-------------|---------|
| Container selection | `sel:{containerId}` | New route in Route Callback |
| Menu action | `menu:{action}` | New route for keyboard-triggered actions |
**Impact on existing workflow:** MEDIUM
- Add 1-2 new outputs to Route Callback switch
- Add nodes for container selection keyboard generation
- Modify "Show Menu" response to include persistent keyboard
**Sources:**
- [n8n Telegram callback operations](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.telegram/callback-operations/)
- [Telegram Bot API ReplyKeyboardMarkup](https://core.telegram.org/bots/api#replykeyboardmarkup)
- [n8n community: inline keyboard callback query](https://community.n8n.io/t/n8n-telegram-inline-keyboard-callback-query-workflow-example/112588)
### 4. Unraid Update Sync
**What needs to change:** After bot updates a container, clear Unraid's "update available" badge.
**How Unraid tracks updates:**
- File: `/var/lib/docker/unraid-update-status.json`
- Managed by: `/usr/local/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php`
- Update check compares local image digest vs registry digest
**Known issue:** When containers are updated by external tools (Watchtower, our bot), Unraid doesn't automatically clear the "update available" badge. Workaround is deleting the status file.
**Integration approach:**
**Option A: Delete status file (simple but blunt)**
```bash
# After successful container update
rm /var/lib/docker/unraid-update-status.json
```
This forces Unraid to recheck all containers on next "Check for Updates".
**Option B: Trigger Unraid's check (cleaner)**
```bash
# Call Unraid's update check endpoint (if exposed)
# Requires research into Unraid API
```
**Option C: Modify status file directly**
```bash
# Update the specific container's entry in the JSON
# Requires understanding the JSON schema
```
**Challenges:**
1. Status file is on host, not in n8n container
2. n8n doesn't have host filesystem access
3. Socket proxy won't help (not a Docker API operation)
**Possible solutions:**
1. **Mount status file into n8n:** `-v /var/lib/docker/unraid-update-status.json:/unraid-status.json`
2. **Create helper script on host:** Cron job that monitors for updates
3. **Use Unraid API:** If Unraid exposes an endpoint to trigger update checks
**Confidence:** LOW - This requires host-level access that may not be available via Docker. Needs further investigation with actual Unraid system access.
**Sources:**
- [Unraid forums: incorrect docker update notification](https://forums.unraid.net/bug-reports/stable-releases/regression-incorrect-docker-update-notification-r2807/)
- [Unraid Docker management docs](https://docs.unraid.net/unraid-os/manual/docker-management/)
## Component Changes Summary
| Component | Change Type | Description | Effort |
|-----------|-------------|-------------|--------|
| socket-proxy | NEW | Docker socket proxy container | Medium |
| n8n container | MODIFY | Remove socket mount, add DOCKER_HOST env | Low |
| n8n API key | NEW | Create API key in n8n settings | Low |
| Execute Command nodes | MODIFY | Change curl commands to use proxy | Medium |
| Show Menu node | MODIFY | Add persistent keyboard | Low |
| Route Callback switch | MODIFY | Add new callback types | Low |
| Container selection | NEW | Generate dynamic keyboards | Medium |
| Unraid sync | NEW | Status file update mechanism | High (uncertain) |
## Data Flow Changes
### Before v1.1 (current)
```
User -> Telegram -> n8n webhook -> curl -> docker.sock -> Docker Engine
```
### After v1.1
```
User -> Telegram -> n8n webhook -> curl -> socket-proxy:2375 -> docker.sock -> Docker Engine
^
|
Claude Code -> n8n API --+
```
## Suggested Build Order
Based on dependencies and risk:
### Phase 1: Infrastructure (no workflow changes)
1. **n8n API enablement** - Configuration only, enables faster iteration
2. **Socket proxy setup** - Container deployment, test connectivity
**Rationale:** API access first means Claude Code can more easily modify the workflow for subsequent phases. Socket proxy is infrastructure that must exist before workflow changes.
### Phase 2: Workflow Migration
3. **Update all curl commands** - Migrate from socket to proxy
4. **Test all existing functionality** - Verify no regressions
**Rationale:** This is the highest-risk change. Must be completed and tested before adding new features.
### Phase 3: UX Enhancements
5. **Persistent keyboard** - Quick win, minimal integration
6. **Container selection keyboards** - Depends on callback routing
**Rationale:** UX improvements can proceed once core functionality is stable.
### Phase 4: Advanced Integration
7. **Unraid update sync** - Requires further research, may need host access
**Rationale:** Most uncertain feature, defer until other features are stable.
## Risk Assessment
| Feature | Risk Level | Mitigation |
|---------|------------|------------|
| n8n API | LOW | Configuration only, easy rollback |
| Socket proxy | MEDIUM | Test in isolation before workflow changes |
| Curl migration | MEDIUM | Use search/replace, comprehensive testing |
| Persistent keyboard | LOW | Additive change, no existing code modified |
| Inline container selection | LOW | Extends existing callback pattern |
| Unraid sync | HIGH | May require host access not available |
## Open Questions
1. **Unraid API:** Does Unraid expose an API endpoint to trigger "Check for Updates"?
2. **Status file format:** What is the exact JSON structure of `unraid-update-status.json`?
3. **Socket proxy port:** Should socket-proxy be exposed only on internal Docker network (recommended) or also externally?
4. **n8n API network:** Should n8n API be exposed on LAN or only via Tailscale/VPN?
## Recommendations
1. **Start with n8n API enablement** - Low risk, high value for development velocity
2. **Deploy socket proxy as sidecar** - Same Docker network as n8n, not exposed externally
3. **Use HTTP Request nodes for keyboards** - Native Telegram node has limitations with dynamic keyboards
4. **Defer Unraid sync** - Needs host access investigation, may not be feasible via Docker alone
5. **Test socket proxy thoroughly** - All container operations (start, stop, restart, update, logs) before proceeding
## Sources Summary
**HIGH confidence (official docs):**
- [n8n public REST API](https://docs.n8n.io/api/)
- [n8n API authentication](https://docs.n8n.io/api/authentication/)
- [LinuxServer socket-proxy](https://docs.linuxserver.io/images/docker-socket-proxy/)
- [Telegram Bot API](https://core.telegram.org/bots/api)
**MEDIUM confidence (verified patterns):**
- [Tecnativa docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy)
- [n8n Telegram callback operations](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.telegram/callback-operations/)
**LOW confidence (community reports):**
- [Unraid forums: docker update notification](https://forums.unraid.net/bug-reports/stable-releases/regression-incorrect-docker-update-notification-r2807/)
- [Unraid Docker management](https://docs.unraid.net/unraid-os/manual/docker-management/)
+381
View File
@@ -0,0 +1,381 @@
# Features Research: v1.1
**Domain:** Telegram Bot for Docker Container Management
**Researched:** 2026-02-02
**Confidence:** MEDIUM-HIGH (WebSearch verified with official docs where available)
## Telegram Inline Keyboards
### Table Stakes
| Feature | Why Expected | Complexity | Dependencies |
|---------|--------------|------------|--------------|
| Callback button handling | Core inline keyboard functionality - buttons must trigger actions | Low | Telegram Trigger already handles callback_query |
| answerCallbackQuery response | Required by Telegram - clients show loading animation until answered (up to 1 minute) | Low | None |
| Edit message after button press | Standard pattern - update existing message rather than send new one to reduce clutter | Low | None |
| Container action buttons | Users expect tap-to-action for start/stop/restart without typing | Medium | Existing container matching logic |
| Status view with action buttons | Show container list with inline buttons for each container | Medium | Existing status command |
### Differentiators
| Feature | Value Proposition | Complexity | Dependencies |
|---------|-------------------|------------|--------------|
| Confirmation dialogs for dangerous actions | "Are you sure?" before stop/restart/update prevents accidental actions | Low | None - edit message with Yes/No buttons |
| Contextual button removal | Remove buttons after action completes (prevents double-tap issues) | Low | None |
| Dynamic container list keyboards | Generate buttons based on actual running containers | Medium | Container listing logic |
| Progress indicators via message edit | Update message with "Updating..." then "Complete" states | Low | None |
| Pagination for many containers | "Next page" button when >8-10 containers | Medium | None |
### Anti-features
| Anti-Feature | Why Avoid | What to Do Instead |
|--------------|-----------|-------------------|
| Reply keyboards for actions | Takes over user keyboard space, sends visible messages to chat | Use inline keyboards attached to bot messages |
| More than 5 buttons per row | Wraps poorly on mobile/desktop, breaks muscle memory | Max 3-4 buttons per row for container actions |
| Complex callback_data structures | 64-byte limit, easy to exceed with JSON | Use short action codes: `start_plex`, `stop_sonarr` |
| Buttons without feedback | Users think tap didn't work, tap again | Always answerCallbackQuery, even for errors |
| Auto-refreshing keyboards | High API traffic, rate limiting risk | Refresh on explicit user action only |
### Implementation Notes
**Critical constraint:** callback_data is limited to 64 bytes. Use short codes like `action:containername` rather than JSON structures.
**n8n native node limitation:** The Telegram node doesn't support dynamic inline keyboards well. Workaround is HTTP Request node calling Telegram Bot API directly for `sendMessage` with `reply_markup` parameter.
**Pattern for confirmations:**
1. User taps "Stop plex"
2. Edit message: "Stop plex container?" with [Yes] [Cancel] buttons
3. User taps Yes -> perform action, edit message with result, remove buttons
4. User taps Cancel -> edit message back to original state
**Sources:**
- [Telegram Bot Features](https://core.telegram.org/bots/features) (HIGH confidence)
- [Telegram Bot API Buttons](https://core.telegram.org/api/bots/buttons) (HIGH confidence)
- [n8n Telegram Callback Operations](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.telegram/callback-operations/) (HIGH confidence)
- [n8n Community: Dynamic Inline Keyboard](https://community.n8n.io/t/dynamic-inline-keyboard-for-telegram-bot/86568) (MEDIUM confidence)
---
## Batch Operations
### Table Stakes
| Feature | Why Expected | Complexity | Dependencies |
|---------|--------------|------------|--------------|
| Update multiple specified containers | Core batch use case - `update plex sonarr radarr` | Medium | Existing update logic, loop handling |
| Sequential execution | Process one at a time to avoid resource contention | Low | None |
| Per-container status feedback | "Updated plex... Updated sonarr..." progress | Low | Existing message sending |
| Error handling per container | One failure shouldn't abort the batch | Low | Try-catch per iteration |
| Final summary message | "3 updated, 1 failed: jellyfin" | Low | Accumulator pattern |
### Differentiators
| Feature | Value Proposition | Complexity | Dependencies |
|---------|-------------------|------------|--------------|
| "Update all" command | Single command to update everything (with confirmation) | Medium | Container listing |
| "Update all except X" | Exclude specific containers from batch | Medium | Exclusion pattern |
| Parallel status checks | Check which containers have updates available first | Medium | None |
| Batch operation confirmation | Show what will happen before doing it | Low | Keyboard buttons |
| Cancel mid-batch | Stop processing remaining containers | High | State management |
### Anti-features
| Anti-Feature | Why Avoid | What to Do Instead |
|--------------|-----------|-------------------|
| Parallel container updates | Resource contention, disk I/O saturation, network bandwidth | Sequential with progress feedback |
| Silent batch operations | User thinks bot is frozen during long batch | Send progress message per container |
| Update without checking first | Wastes time on already-updated containers | Check for updates, report "3 containers have updates" |
| Auto-update on schedule | Out of scope - user might be using system when update causes downtime | User-initiated only, this is reactive tool |
### Implementation Notes
**Existing update flow:** Current implementation pulls image, recreates container, cleans up old image. Batch needs to wrap this in a loop.
**Progress pattern:**
```
User: update all
Bot: Found 5 containers with updates. Update now? [Yes] [Cancel]
User: Yes
Bot: Updating plex (1/5)...
Bot: (edit) Updated plex. Updating sonarr (2/5)...
...
Bot: (edit) Batch complete: 5 updated, 0 failed.
```
**Watchtower-style options (NOT recommended for this bot):**
- Watchtower does automatic updates on schedule
- This bot is intentionally reactive (user asks, bot does)
- Automation can cause downtime at bad times
**Sources:**
- [Watchtower Documentation](https://containrrr.dev/watchtower/) (HIGH confidence)
- [Docker Multi-Container Apps](https://docs.docker.com/get-started/docker-concepts/running-containers/multi-container-applications/) (HIGH confidence)
- [How to Update Docker Containers](https://phoenixnap.com/kb/update-docker-image-container) (MEDIUM confidence)
---
## Development API Workflow
### Table Stakes
| Feature | Why Expected | Complexity | Dependencies |
|---------|--------------|------------|--------------|
| API key authentication | Standard n8n API auth method | Low | n8n configuration |
| Get workflow by ID | Read current workflow JSON | Low | n8n REST API |
| Update workflow | Push modified workflow back | Low | n8n REST API |
| Activate/deactivate workflow | Turn workflow on/off programmatically | Low | n8n REST API |
| Get execution list | See recent runs | Low | n8n REST API |
| Get execution details/logs | Debug failed executions | Low | n8n REST API |
### Differentiators
| Feature | Value Proposition | Complexity | Dependencies |
|---------|-------------------|------------|--------------|
| Execute workflow on demand | Trigger test run via API | Medium | n8n REST API with test data |
| Version comparison | Diff local vs deployed workflow | High | JSON diff tooling |
| Backup before update | Save current version before pushing changes | Low | File system or git |
| Rollback capability | Restore previous version on failure | Medium | Version history |
| MCP integration | Claude Code can manage workflows via MCP | High | MCP server setup |
### Anti-features
| Anti-Feature | Why Avoid | What to Do Instead |
|--------------|-----------|-------------------|
| Direct n8n database access | Bypasses API, can corrupt state | Use REST API only |
| Credential exposure via API | API returns credential IDs, not values | Never try to extract credential values |
| Auto-deploy on git push | Adds CI/CD complexity, not needed for single-user | Manual deploy via API call |
| Real-time workflow editing | n8n UI is better for this | API for read/bulk operations only |
### Implementation Notes
**n8n REST API key endpoints:**
| Operation | Method | Endpoint |
|-----------|--------|----------|
| List workflows | GET | `/api/v1/workflows` |
| Get workflow | GET | `/api/v1/workflows/{id}` |
| Update workflow | PUT | `/api/v1/workflows/{id}` |
| Activate | POST | `/api/v1/workflows/{id}/activate` |
| Deactivate | POST | `/api/v1/workflows/{id}/deactivate` |
| List executions | GET | `/api/v1/executions` |
| Get execution | GET | `/api/v1/executions/{id}` |
| Execute workflow | POST | `/rest/workflows/{id}/run` |
**Authentication:** Header `X-N8N-API-KEY: your_api_key`
**Workflow structure:** n8n workflows are JSON documents (~3,200 lines for this bot). Key sections:
- `nodes[]` - Array of workflow nodes
- `connections` - How nodes connect
- `settings` - Workflow-level settings
**MCP option:** There's an unofficial n8n MCP server (makafeli/n8n-workflow-builder) that could enable Claude Code to manage workflows directly, but this adds complexity. Standard REST API is simpler for v1.1.
**Sources:**
- [n8n API Documentation](https://docs.n8n.io/api/) (HIGH confidence)
- [n8n API Reference](https://docs.n8n.io/api/api-reference/) (HIGH confidence)
- [n8n Workflow Manager API Template](https://n8n.io/workflows/4166-n8n-workflow-manager-api/) (MEDIUM confidence)
- [Python n8n API Guide](https://martinuke0.github.io/posts/2025-12-10-a-detailed-guide-to-using-the-n8n-api-with-python/) (MEDIUM confidence)
---
## Update Notification Sync
### Table Stakes
| Feature | Why Expected | Complexity | Dependencies |
|---------|--------------|------------|--------------|
| Update clears bot's "update available" state | Bot should know container is now current | Low | Already works - re-check after update |
| Accurate update status reporting | Status command shows which have updates | Medium | Image digest comparison |
### Differentiators
| Feature | Value Proposition | Complexity | Dependencies |
|---------|-------------------|------------|--------------|
| Sync with Unraid UI | Clear "update available" badge in Unraid web UI | High | Unraid API or file manipulation |
| Pre-update check | Show what version you're on, what version available | Medium | Image tag inspection |
| Update notification to user | "3 containers have updates available" proactive message | Medium | Scheduled check, notification logic |
### Anti-features
| Anti-Feature | Why Avoid | What to Do Instead |
|--------------|-----------|-------------------|
| Taking over Unraid notifications | Explicitly out of scope per PROJECT.md | Keep Unraid notifications, bot is for control |
| Proactive monitoring | Bot is reactive per PROJECT.md | User checks status manually |
| Blocking Unraid auto-updates | User may want both systems | Coexist with Unraid's own update mechanism |
### Implementation Notes
**The core problem:** When you update a container via the bot (or Watchtower), Unraid's web UI may still show "update available" because it has its own tracking.
**Unraid update status file:** `/var/lib/docker/unraid-update-status.json`
- This file tracks which containers have updates
- Deleting it forces Unraid to recheck
- Can also trigger recheck via: Settings > Docker > Check for Updates
**Unraid API (v7.2+):**
- GraphQL API for Docker containers
- Can query container status
- Mutations for notifications exist
- API key auth: `x-api-key` header
**Practical approach for v1.1:**
1. **Minimum:** Document that Unraid UI may lag behind - user can click "Check for Updates" in Unraid
2. **Better:** After bot update, delete `/var/lib/docker/unraid-update-status.json` to force Unraid recheck
3. **Best (requires Unraid 7.2+):** Use Unraid GraphQL API to clear notification state
**Known issue:** Users report Unraid shows "update ready" even after container is updated. This is a known Unraid bug where it only checks for new updates, not whether containers are now current.
**Sources:**
- [Unraid API Documentation](https://docs.unraid.net/API/how-to-use-the-api/) (HIGH confidence)
- [Unraid Docker Integration DeepWiki](https://deepwiki.com/unraid/api/2.4.1-docker-integration) (MEDIUM confidence)
- [Watchtower + Unraid Discussion](https://github.com/containrrr/watchtower/discussions/1389) (MEDIUM confidence)
- [Unraid Forum: Update Badge Issues](https://forums.unraid.net/topic/157820-docker-shows-update-ready-after-updating/) (MEDIUM confidence)
---
## Docker Socket Security
### Table Stakes
| Feature | Why Expected | Complexity | Dependencies |
|---------|--------------|------------|--------------|
| Remove direct socket from internet-exposed n8n | Security requirement per PROJECT.md scope | Medium | Socket proxy setup |
| Maintain all existing functionality | Bot should work identically after security change | Medium | API compatibility |
| Container start/stop/restart/update | Core actions must still work | Low | Proxy allows these APIs |
| Container list/inspect | Status command must still work | Low | Proxy allows read APIs |
| Image pull | Update command needs this | Low | Proxy configuration |
### Differentiators
| Feature | Value Proposition | Complexity | Dependencies |
|---------|-------------------|------------|--------------|
| Granular API restrictions | Only allow APIs the bot actually uses | Low | Socket proxy env vars |
| Block dangerous APIs | Prevent exec, create, system commands | Low | Socket proxy defaults |
| Audit logging | Log all Docker API calls through proxy | Medium | Proxy logging config |
### Anti-features
| Anti-Feature | Why Avoid | What to Do Instead |
|--------------|-----------|-------------------|
| Read-only socket mount (:ro) | Doesn't actually protect - socket as pipe stays writable | Use proper socket proxy |
| Direct socket access from internet-facing container | Full root access if n8n is compromised | Socket proxy isolates access |
| Allowing exec API | Enables arbitrary command execution in containers | Block exec in proxy |
| Allowing create/network APIs | Bot doesn't need to create containers | Block creation APIs |
### Implementation Notes
**Recommended: Tecnativa/docker-socket-proxy or LinuxServer.io/docker-socket-proxy**
Both provide HAProxy-based filtering of Docker API requests.
**Minimal proxy configuration for this bot:**
```yaml
# docker-compose.yml
services:
socket-proxy:
image: tecnativa/docker-socket-proxy
environment:
- CONTAINERS=1 # List/inspect containers
- IMAGES=1 # Pull images
- POST=1 # Allow write operations
- SERVICES=0 # Swarm services (not needed)
- TASKS=0 # Swarm tasks (not needed)
- NETWORKS=0 # Network management (not needed)
- VOLUMES=0 # Volume management (not needed)
- EXEC=0 # CRITICAL: Block exec
- BUILD=0 # CRITICAL: Block build
- COMMIT=0 # CRITICAL: Block commit
- SECRETS=0 # CRITICAL: Block secrets
- CONFIGS=0 # CRITICAL: Block configs
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- docker-proxy
n8n:
# ... existing config ...
environment:
- DOCKER_HOST=tcp://socket-proxy:2375
networks:
- docker-proxy
# Plus existing networks
```
**Key security benefits:**
1. n8n no longer has direct socket access
2. Only whitelisted API categories are available
3. EXEC=0 prevents arbitrary command execution
4. Proxy is on internal network only, not internet-exposed
**Migration path:**
1. Deploy socket-proxy container
2. Update n8n to use `DOCKER_HOST=tcp://socket-proxy:2375`
3. Remove direct socket mount from n8n
4. Test all bot commands still work
**Sources:**
- [Tecnativa docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) (HIGH confidence)
- [LinuxServer.io docker-socket-proxy](https://docs.linuxserver.io/images/docker-socket-proxy/) (HIGH confidence)
- [Docker Socket Security Guide](https://www.paulsblog.dev/how-to-secure-your-docker-environment-by-using-a-docker-socket-proxy/) (MEDIUM confidence)
---
## Feature Summary Table
| Feature | Complexity | Dependencies | Priority | Notes |
|---------|------------|--------------|----------|-------|
| **Inline Keyboards** | | | | |
| Basic callback handling | Low | Existing trigger | Must Have | Foundation for all buttons |
| Container action buttons | Medium | Container matching | Must Have | Core UX improvement |
| Confirmation dialogs | Low | None | Should Have | Prevents accidents |
| Dynamic keyboard generation | Medium | HTTP Request node | Must Have | n8n native node limitation workaround |
| **Batch Operations** | | | | |
| Update multiple containers | Medium | Existing update | Must Have | Sequential with progress |
| "Update all" command | Medium | Container listing | Should Have | With confirmation |
| Per-container feedback | Low | None | Must Have | Progress visibility |
| **n8n API** | | | | |
| API key setup | Low | n8n config | Must Have | Enable programmatic access |
| Read workflow | Low | REST API | Must Have | Development workflow |
| Update workflow | Low | REST API | Must Have | Development workflow |
| Activate/deactivate | Low | REST API | Should Have | Testing workflow |
| **Update Sync** | | | | |
| Delete status file | Low | SSH/exec access | Should Have | Simple Unraid sync |
| Unraid GraphQL API | High | Unraid 7.2+, API key | Nice to Have | Requires version check |
| **Security** | | | | |
| Socket proxy deployment | Medium | New container | Must Have | Security requirement |
| API restriction config | Low | Proxy env vars | Must Have | Minimize attack surface |
| Migration testing | Low | All commands | Must Have | Verify no regression |
## MVP Recommendation for v1.1
**Phase 1: Foundation (Must Have)**
1. Docker socket security via proxy - security first
2. n8n API access setup - enables faster development
3. Basic inline keyboard infrastructure - callback handling
**Phase 2: UX Improvements (Should Have)**
4. Container action buttons from status view
5. Confirmation dialogs for stop/update actions
6. Batch update with progress feedback
**Phase 3: Polish (Nice to Have)**
7. Unraid update status sync (file deletion method)
8. "Update all" convenience command
## Confidence Assessment
| Area | Confidence | Reason |
|------|------------|--------|
| Telegram Inline Keyboards | HIGH | Official Telegram docs + n8n docs verified |
| Batch Operations | MEDIUM-HIGH | Standard Docker patterns, well-documented |
| n8n API | MEDIUM | API exists but detailed endpoint docs required fetching |
| Unraid Update Sync | MEDIUM | Community knowledge, API docs limited |
| Docker Socket Security | HIGH | Well-documented proxy solutions |
## Gaps to Address in Phase Planning
1. **Exact n8n API endpoints** - Need to verify full endpoint list during implementation
2. **Unraid version compatibility** - GraphQL API requires Unraid 7.2+, need version check
3. **n8n Telegram node workarounds** - HTTP Request approach needs testing
4. **Socket proxy on Unraid** - Deployment specifics for Unraid environment
+224
View File
@@ -0,0 +1,224 @@
# Pitfalls Research: v1.1
**Project:** Unraid Docker Manager
**Milestone:** v1.1 - n8n Integration & Polish
**Researched:** 2026-02-02
**Confidence:** MEDIUM-HIGH (verified with official docs where possible)
## Context
This research identifies pitfalls specific to **adding** these features to an existing working system:
- n8n API access (programmatic workflow read/update/test/logs)
- Docker socket proxy (security hardening)
- Telegram inline keyboards (UX improvements)
- Unraid update sync (clear "update available" badge)
**Risk focus:** Breaking existing functionality while adding new features.
---
## n8n API Access Pitfalls
| Pitfall | Warning Signs | Prevention | Phase |
|---------|---------------|------------|-------|
| **API key with full access** | API key created without scopes; all workflows accessible | Enterprise: use scoped API keys (read-only for Claude Code initially). Non-enterprise: accept risk, rotate keys every 6-12 months | API Setup |
| **Missing X-N8N-API-KEY header** | 401 Unauthorized errors on all API calls | Store API key in Claude Code MCP config; always send as `X-N8N-API-KEY` header, not Bearer token | API Setup |
| **Workflow ID mismatch after import** | API calls return 404; workflow actions fail | Workflow IDs change on import; query `/api/v1/workflows` first to get current IDs, don't hardcode | API Setup |
| **Editing active workflow via API** | Production workflow changes unexpectedly; users see partial updates | n8n 2.0: Save vs Publish are separate actions. Use API to read only; manual publish via UI | API Setup |
| **N8N_BLOCK_ENV_ACCESS_IN_NODE default** | Code nodes can't access env vars; returns undefined | n8n 2.0+ blocks env vars by default. Use credentials system instead, or explicitly set `N8N_BLOCK_ENV_ACCESS_IN_NODE=false` | API Setup |
| **API not enabled on instance** | Connection refused on /api/v1 endpoints | Self-hosted: API is available by default. Cloud trial: API not available. Verify with `curl http://localhost:5678/api/v1/workflows` | API Setup |
| **Rate limiting on rapid API calls** | 429 errors when reading workflow repeatedly | Add delay between API calls (1-2 seconds); use caching for workflow data that doesn't change frequently | API Usage |
**Sources:**
- [n8n API Authentication](https://docs.n8n.io/api/authentication/)
- [n8n API Reference](https://docs.n8n.io/api/)
- [n8n v2.0 Breaking Changes](https://docs.n8n.io/2-0-breaking-changes/)
---
## Docker Socket Security Pitfalls
| Pitfall | Warning Signs | Prevention | Phase |
|---------|---------------|------------|-------|
| **Proxy exposes POST by default** | Container can create/delete containers; security scan flags | Set `POST=0` on socket proxy; most read operations work with GET only | Socket Proxy |
| **Using `--privileged` unnecessarily** | Security audit fails; container has excessive permissions | Remove `--privileged` flag; Tecnativa proxy works without it on standard Docker | Socket Proxy |
| **Outdated socket proxy image** | Using `latest` tag which is 3+ years old | Pin to specific version: `tecnativa/docker-socket-proxy:0.2.0` or use `linuxserver/socket-proxy` | Socket Proxy |
| **Proxy port exposed publicly** | Port 2375 accessible from network; security scan fails | Never expose proxy port; run on internal Docker network only | Socket Proxy |
| **Insufficient permissions for n8n** | "Permission denied" or empty responses from Docker API | Enable minimum required: `CONTAINERS=1`, `ALLOW_START=1`, `ALLOW_STOP=1`, `ALLOW_RESTARTS=1` for actions | Socket Proxy |
| **Breaking existing curl commands** | Existing workflow fails after adding proxy; commands timeout | Socket proxy uses TCP, not Unix socket. Update curl commands: `curl http://socket-proxy:2375/...` instead of `--unix-socket` | Socket Proxy |
| **Network isolation breaks connectivity** | n8n can't reach proxy; "connection refused" errors | Both containers must be on same Docker network; verify with `docker network inspect` | Socket Proxy |
| **Permissions too restrictive** | Container list works but start/stop fails | Must explicitly enable action endpoints: `ALLOW_START=1`, `ALLOW_STOP=1`, `ALLOW_RESTARTS=1` (separate from `CONTAINERS=1`) | Socket Proxy |
| **Missing INFO or VERSION permissions** | Some Docker API calls fail unexpectedly | `VERSION=1` and `PING=1` are enabled by default; may need `INFO=1` for system queries | Socket Proxy |
**Minimum safe configuration for this project:**
```yaml
environment:
- CONTAINERS=1 # Read container info
- ALLOW_START=1 # Start containers
- ALLOW_STOP=1 # Stop containers
- ALLOW_RESTARTS=1 # Restart containers
- IMAGES=1 # Pull images (for updates)
- POST=1 # Required for start/stop/restart actions
- NETWORKS=0 # Not needed
- VOLUMES=0 # Not needed
- BUILD=0 # Not needed
- COMMIT=0 # Not needed
- CONFIGS=0 # Not needed
- SECRETS=0 # Security critical - keep disabled
- EXEC=0 # Security critical - keep disabled
- AUTH=0 # Security critical - keep disabled
```
**Sources:**
- [Tecnativa docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy)
- [LinuxServer socket-proxy](https://docs.linuxserver.io/images/docker-socket-proxy/)
- [Docker Community Forums - Socket Proxy Security](https://forums.docker.com/t/does-a-docker-socket-proxy-improve-security/136305)
---
## Telegram Keyboard Pitfalls
| Pitfall | Warning Signs | Prevention | Phase |
|---------|---------------|------------|-------|
| **Native node rejects dynamic keyboards** | Error: "The value '[[...]]' is not supported!" | Use HTTP Request node for inline keyboards instead of native Telegram node; this is a known n8n limitation | Keyboards |
| **callback_data exceeds 64 bytes** | Buttons don't respond; no callback_query received; 400 BUTTON_DATA_INVALID | Use short codes: `s:plex` not `start_container:plex-media-server`. Hash long names to 8-char IDs | Keyboards |
| **Callback auth path missing** | Keyboard clicks ignored; no response to button press | Existing workflow already handles callback_query (line 56-74 in workflow). Ensure new keyboards use same auth flow | Keyboards |
| **Multiple additional fields ignored** | Button has both callback_data and URL; only URL works | n8n Telegram node limitation - can't use both. Choose one per button: either action (callback) or link (URL) | Keyboards |
| **Keyboard flickers on every message** | Visual glitches; keyboard re-renders constantly | Send `reply_markup` only on /start or menu requests; omit from action responses (keyboard persists) | Keyboards |
| **Inline vs Reply keyboard confusion** | Wrong keyboard type appears; buttons don't trigger callbacks | Inline keyboards (InlineKeyboardMarkup) for callbacks; Reply keyboards (ReplyKeyboardMarkup) for persistent menus. Use inline for container actions | Keyboards |
| **answerCallbackQuery not called** | "Loading..." spinner persists after button click; Telegram shows timeout | Must call `answerCallbackQuery` within 10 seconds of receiving callback_query, even if just to acknowledge | Keyboards |
| **Button layout exceeds limits** | Buttons don't appear; API error | Bot API 7.0: max 100 buttons total per message. For container lists, paginate or limit to 8-10 buttons | Keyboards |
**Recommended keyboard structure for container actions:**
```javascript
// Short callback_data pattern: action:container_short_id
// Example: "s:abc123" for start, "x:abc123" for stop
{
"inline_keyboard": [
[
{"text": "Start", "callback_data": "s:" + containerId.slice(0,8)},
{"text": "Stop", "callback_data": "x:" + containerId.slice(0,8)}
],
[
{"text": "Restart", "callback_data": "r:" + containerId.slice(0,8)},
{"text": "Logs", "callback_data": "l:" + containerId.slice(0,8)}
]
]
}
```
**Sources:**
- [n8n GitHub Issue #19955 - Inline Keyboard Expression](https://github.com/n8n-io/n8n/issues/19955)
- [n8n Telegram Callback Operations](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.telegram/callback-operations/)
- [Telegram Bot API - InlineKeyboardButton](https://core.telegram.org/bots/api#inlinekeyboardbutton)
---
## Unraid Integration Pitfalls
| Pitfall | Warning Signs | Prevention | Phase |
|---------|---------------|------------|-------|
| **Update badge persists after bot update** | Unraid UI shows "update available" after container updated via bot | Delete `/var/lib/docker/unraid-update-status.json` to force recheck; or trigger Unraid's check mechanism | Unraid Sync |
| **unraid-update-status.json format unknown** | Attempted to modify file directly; broke Unraid Docker tab | File format is undocumented. Safest approach: delete file and let Unraid regenerate. Don't modify directly | Unraid Sync |
| **Unraid only checks for new updates** | Badge never clears; only sees new updates, not cleared updates | This is known Unraid behavior. Deletion of status file is current workaround per Unraid forums | Unraid Sync |
| **Race condition on status file** | Status file deleted but badge still shows; file regenerated too fast | Wait for Unraid's update check interval, or manually trigger "Check for Updates" from Unraid UI after deletion | Unraid Sync |
| **Bot can't access Unraid filesystem** | Permission denied when accessing /var/lib/docker/ | n8n container needs additional volume mount: `/var/lib/docker:/var/lib/docker` or execute via SSH | Unraid Sync |
| **Breaking Unraid's Docker management** | Unraid Docker tab shows errors; containers appear in wrong state | Never modify Unraid's internal files (in /boot/config/docker or /var/lib/docker) except update-status.json deletion | Unraid Sync |
**Unraid sync approach (safest):**
1. After bot successfully updates container
2. Execute: `rm -f /var/lib/docker/unraid-update-status.json`
3. Unraid will regenerate on next "Check for Updates" or automatically
**Sources:**
- [Unraid Forums - Update notification regression](https://forums.unraid.net/bug-reports/stable-releases/regression-incorrect-docker-update-notification-r2807/)
- [Unraid Forums - Update badge persists](https://forums.unraid.net/topic/157820-docker-shows-update-ready-after-updating/)
- [Unraid Forums - Containers show update available incorrectly](https://forums.unraid.net/topic/142238-containers-show-update-available-even-when-it-is-up-to-date/)
---
## Integration Pitfalls (Breaking Existing Functionality)
| Pitfall | Warning Signs | Prevention | Phase |
|---------|---------------|------------|-------|
| **Socket proxy breaks existing curl** | All Docker commands fail after adding proxy | Existing workflow uses `--unix-socket`. Migrate curl commands to use proxy TCP endpoint: `http://socket-proxy:2375` | Socket Proxy |
| **Auth flow bypassed on new paths** | New keyboard handlers skip user ID check; anyone can click buttons | Existing workflow has auth at lines 92-122 and 126-155. Copy same pattern for any new callback handlers | All |
| **Workflow test vs production mismatch** | Works in test mode; fails when activated | Test with actual Telegram messages, not just manual execution. Production triggers differ from manual runs | All |
| **n8n 2.0 upgrade breaks workflow** | After n8n update, workflow stops working; nodes missing | n8n 2.0 has breaking changes: Execute Command disabled by default, Start node removed, env vars blocked. Check [migration guide](https://docs.n8n.io/2-0-breaking-changes/) before upgrading | All |
| **Credential reference breaks after import** | Imported workflow can't decrypt credentials; all nodes fail | n8n uses N8N_ENCRYPTION_KEY. After import, must recreate credentials manually in n8n UI | All |
| **HTTP Request node vs Execute Command** | HTTP Request can't reach Docker socket; timeout errors | HTTP Request node doesn't support Unix sockets. Keep using Execute Command with curl for Docker API (or migrate to TCP proxy) | Socket Proxy |
| **Parallel execution race conditions** | Two button clicks cause conflicting container states | Add debounce logic: ignore rapid duplicate callbacks within 2-3 seconds. Store last action timestamp | Keyboards |
| **Error workflow doesn't fire** | Errors occur but no notification; silent failures | Error Trigger only fires on automatic executions, not manual test runs. Test by triggering via Telegram with intentional failure | All |
| **Save vs Publish confusion (n8n 2.0)** | Edited workflow but production still uses old version | n8n 2.0 separates Save (preserves edits) from Publish (updates production). Must explicitly publish changes | All |
**Pre-migration checklist:**
- [ ] Export current workflow JSON as backup
- [ ] Document current curl commands and endpoints
- [ ] Test each existing command works after changes
- [ ] Verify auth flow applies to new handlers
- [ ] Test error handling triggers correctly
**Sources:**
- [n8n v2.0 Breaking Changes](https://docs.n8n.io/2-0-breaking-changes/)
- [n8n Manual vs Production Executions](https://docs.n8n.io/workflows/executions/manual-partial-and-production-executions/)
- [n8n Community - Test vs Production Behavior](https://community.n8n.io/t/workflow-behaves-differently-in-test-vs-production/139973)
---
## Summary: Top 5 Risks
Ranked by likelihood x impact for this specific milestone:
### 1. Socket Proxy Breaks Existing Commands (HIGH likelihood, HIGH impact)
**Why:** Current workflow uses `--unix-socket` flag. Socket proxy uses TCP. All existing functionality breaks if not migrated correctly.
**Prevention:**
1. Add socket proxy container first (don't remove direct socket yet)
2. Update curl commands one-by-one to use proxy
3. Test each command works via proxy
4. Only then remove direct socket mount
### 2. Native Telegram Node Rejects Dynamic Keyboards (HIGH likelihood, MEDIUM impact)
**Why:** n8n's native Telegram node has a known bug (Issue #19955) where it rejects array expressions for inline keyboards.
**Prevention:** Use HTTP Request node to call Telegram API directly for any dynamic keyboard generation. Keep native node for simple text responses only.
### 3. Unraid Update Badge Never Clears (HIGH likelihood, LOW impact)
**Why:** Unraid doesn't check for "no longer outdated" containers - only new updates. Documented behavior, not a bug.
**Prevention:** Delete `/var/lib/docker/unraid-update-status.json` after successful bot update. Requires additional volume mount or SSH access.
### 4. n8n 2.0 Breaking Changes on Upgrade (MEDIUM likelihood, HIGH impact)
**Why:** n8n 2.0 (released Dec 2025) has multiple breaking changes: Execute Command disabled by default, env vars blocked, Save/Publish separation.
**Prevention:**
1. Check current n8n version before starting
2. If upgrading, run Migration Report first (Settings > Migration Report)
3. Don't upgrade n8n during this milestone unless necessary
### 5. callback_data Exceeds 64 Bytes (MEDIUM likelihood, MEDIUM impact)
**Why:** Container names can be long (e.g., `linuxserver-plex-media-server`). Adding action prefix easily exceeds 64 bytes.
**Prevention:** Use short action codes (`s:`, `x:`, `r:`, `l:`) and container ID prefix (8 chars) instead of full names. Map back via lookup.
---
## Phase Assignment Summary
| Phase | Pitfalls to Address |
|-------|---------------------|
| **API Setup** | API key scoping, header format, workflow ID discovery, env var blocking |
| **Socket Proxy** | Proxy configuration, permission settings, curl command migration, network setup |
| **Keyboards** | HTTP Request node for keyboards, callback_data limits, answerCallbackQuery |
| **Unraid Sync** | Update status file deletion, volume mount for access |
| **All Phases** | Auth flow consistency, test vs production, error workflow testing |
---
## Confidence Assessment
| Area | Confidence | Rationale |
|------|------------|-----------|
| n8n API | HIGH | Official docs verified, known breaking changes documented |
| Docker Socket Proxy | HIGH | Official Tecnativa docs, community best practices verified |
| Telegram Keyboards | MEDIUM-HIGH | n8n GitHub issues confirm limitations, Telegram API docs verified |
| Unraid Integration | MEDIUM | Forum posts describe workaround, but file format undocumented |
| Integration Risks | MEDIUM | Based on existing v1.0 codebase analysis and general patterns |
**Research date:** 2026-02-02
**Valid until:** 2026-03-02 (30 days - n8n and Telegram APIs stable)
+385
View File
@@ -0,0 +1,385 @@
# 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
+268
View File
@@ -0,0 +1,268 @@
# Research Summary: v1.1 n8n Integration & Polish
**Project:** Unraid Docker Manager
**Domain:** Telegram Bot Enhancement / Security Hardening
**Researched:** 2026-02-02
**Confidence:** MEDIUM-HIGH
## Executive Summary
The v1.1 milestone focuses on four areas: Docker socket security (critical), Telegram UX improvements (inline keyboards), n8n API access (development workflow), and Unraid update sync (nice-to-have). Research confirms all features are achievable with existing n8n capabilities and no new application dependencies beyond a Docker socket proxy container.
The recommended approach is security-first: deploy the Docker socket proxy before any workflow changes, then migrate existing curl commands to use TCP instead of Unix socket. This order minimizes risk and provides a clean foundation. Telegram inline keyboards require HTTP Request nodes due to n8n native node limitations with dynamic keyboards. The n8n API is enabled by default on self-hosted instances and requires only an API key for Claude Code access.
Key risk is breaking existing functionality during socket proxy migration. All 15+ Execute Command nodes using `--unix-socket` must be updated simultaneously. The mitigation is incremental migration with comprehensive testing before removing direct socket access. Unraid update sync has the lowest confidence - it works via file deletion but requires additional volume mounts.
---
## Stack Additions
| Component | Purpose | Why This Choice |
|-----------|---------|-----------------|
| **LinuxServer socket-proxy** | Docker socket security | HAProxy-based filtering, active maintenance, Unraid community familiarity |
| **n8n REST API** | Programmatic workflow management | Already enabled by default, no new dependencies |
| **HTTP Request nodes** | Dynamic Telegram keyboards | Workaround for n8n native node limitations with inline keyboards |
**No new application dependencies** - all solutions use existing n8n capabilities:
- HTTP Request node for Telegram API and Docker via proxy
- Execute Command node for Unraid file operations
- n8n public API for Claude Code workflow management
**Socket proxy environment variables (minimum required):**
```bash
CONTAINERS=1 # List/inspect containers
IMAGES=1 # Pull images for updates
POST=1 # Enable write operations
ALLOW_START=1 # Container start
ALLOW_STOP=1 # Container stop
ALLOW_RESTARTS=1 # Container restart/kill
```
---
## Feature Table Stakes
### Must Have
| Feature | Rationale |
|---------|-----------|
| **Docker socket proxy** | Security requirement - remove root-equivalent access from internet-exposed n8n |
| **Inline keyboard callback handling** | Already partially implemented; must complete for button responses |
| **answerCallbackQuery responses** | Telegram requirement - loading spinner persists up to 1 minute without it |
| **n8n API key setup** | Enables programmatic workflow management for Claude Code |
| **Batch update with progress** | Core batch use case - `update plex sonarr radarr` with per-container feedback |
### Should Have
| Feature | Rationale |
|---------|-----------|
| **Container action buttons** | Tap-to-action UX improvement over typing commands |
| **Confirmation dialogs** | "Are you sure?" before stop/restart/update prevents accidents |
| **"Update all" command** | Convenience feature with mandatory confirmation |
| **Unraid status file sync** | Clear "update available" badge after bot updates (file deletion method) |
### Defer to v2+
| Feature | Rationale |
|---------|-----------|
| **Unraid GraphQL API integration** | Requires Unraid 7.2+, adds complexity |
| **MCP integration for n8n** | Unofficial server exists but adds significant complexity |
| **Cancel mid-batch** | Requires state management complexity |
| **Pagination for containers** | Only needed if >10 containers common |
---
## Architecture Changes
### Target Architecture
```
User -> Telegram -> n8n webhook -> curl -> socket-proxy:2375 -> docker.sock -> Docker Engine
^
|
Claude Code -> n8n API --+
```
### Key Integration Points
| Component | Change | Impact |
|-----------|--------|--------|
| **socket-proxy container** | NEW - sidecar on internal network | Infrastructure |
| **n8n container** | MODIFY - `DOCKER_HOST=tcp://socket-proxy:2375`, remove socket mount | Medium |
| **Execute Command nodes** | MODIFY - change curl from `--unix-socket` to TCP | ~15 nodes |
| **Route Callback switch** | MODIFY - add new callback types for keyboards | Low |
| **HTTP Request nodes** | NEW - for dynamic inline keyboard generation | Medium |
### Curl Migration Pattern
```
FROM: curl -s --unix-socket /var/run/docker.sock 'http://localhost/v1.47/...'
TO: curl -s 'http://socket-proxy:2375/v1.47/...'
```
---
## Top Risks
### 1. Socket Proxy Breaks Existing Commands (CRITICAL)
**Risk:** All Docker commands fail after migration
**Prevention:**
1. Deploy socket-proxy first without removing direct socket
2. Update curl commands one-by-one to use proxy
3. Test each command via proxy before removing direct socket
4. Maintain rollback capability throughout
### 2. n8n Native Telegram Node Rejects Dynamic Keyboards (HIGH)
**Risk:** Error "The value is not supported!" when using expressions in keyboard fields
**Prevention:** Use HTTP Request node to call Telegram Bot API directly for any dynamic keyboard. Keep native node for simple text responses only.
### 3. callback_data Exceeds 64 Bytes (MEDIUM)
**Risk:** Buttons silently fail when callback_data is too long
**Prevention:** Use short codes: `s:abc12345` (action:container_id_prefix) instead of full names. Map back via container ID lookup.
### 4. n8n 2.0 Breaking Changes (MEDIUM)
**Risk:** Execute Command disabled by default, env vars blocked, Save/Publish separation
**Prevention:** Check n8n version before starting. If 2.0+, verify Execute Command is enabled in settings. Don't upgrade n8n during this milestone.
### 5. Unraid Update Badge Never Clears (LOW impact but HIGH likelihood)
**Risk:** Unraid UI shows "update available" even after bot updates container
**Prevention:** Delete `/var/lib/docker/unraid-update-status.json` after successful bot update. Document that user may need to click "Check for Updates" in Unraid UI.
---
## Recommended Build Order
Based on dependencies and risk mitigation:
### Phase 1: Socket Security Foundation
**Delivers:** Secure Docker socket access via proxy
**What:**
1. Deploy socket-proxy container on internal network
2. Configure minimum required permissions
3. Migrate all curl commands to use TCP endpoint
4. Test all existing functionality
5. Remove direct socket mount from n8n
**Rationale:** Security is the primary v1.1 goal. Must complete before adding any new features to avoid compounding risk.
**Pitfalls to avoid:**
- Proxy port exposed publicly (keep internal only)
- Insufficient permissions (test each operation)
- Breaking existing curl commands (migrate incrementally)
### Phase 2: n8n API Access
**Delivers:** Claude Code can read/update/test workflows programmatically
**What:**
1. Create API key in n8n Settings
2. Document API endpoints for workflow management
3. Test basic operations (list, get, update workflow)
**Rationale:** Low risk, high value. Enables faster iteration for subsequent phases.
**Pitfalls to avoid:**
- API key committed to repository (use environment/secrets)
- Workflow ID hardcoded (query API to discover)
### Phase 3: Inline Keyboard Infrastructure
**Delivers:** Foundation for button-based UX
**What:**
1. HTTP Request node pattern for dynamic keyboards
2. Callback routing for new action types
3. answerCallbackQuery integration
4. Short callback_data encoding scheme
**Rationale:** Foundation needed before adding specific button features.
**Pitfalls to avoid:**
- Using native Telegram node for keyboards (use HTTP Request)
- callback_data exceeding 64 bytes (use short codes)
### Phase 4: UX Improvements
**Delivers:** Button-based container management
**What:**
1. Container selection keyboards from commands
2. Confirmation dialogs for dangerous actions
3. Message editing for progress/results
4. Batch update with progress feedback
**Rationale:** User-facing improvements built on Phase 3 foundation.
### Phase 5: Unraid Sync (Optional)
**Delivers:** Clear update badges after bot updates
**What:**
1. Add volume mount for status file access
2. Delete status file after successful updates
3. Document user step to refresh Unraid UI
**Rationale:** Lowest confidence, most uncertain. May require additional host access. Defer if other phases take longer than expected.
---
## Open Questions
1. **Socket proxy network:** Should socket-proxy be on a dedicated internal network or share n8n's network? (Recommendation: dedicated internal network)
2. **n8n API exposure:** Should n8n API be accessible only via Tailscale/VPN or also on LAN? (Recommendation: Tailscale only for security)
3. **Unraid status file access:** Does n8n already have `/var/lib/docker` mounted, or is a new volume mount needed? (Needs verification)
4. **Batch size limits:** Should "update all" have a maximum container limit or always require confirmation? (Recommendation: always confirm, no limit)
---
## Ready for Requirements
Research is complete. All four research files provide sufficient detail for roadmap creation:
- **STACK.md:** Socket proxy configuration, n8n API setup, Telegram keyboard patterns
- **FEATURES.md:** Table stakes vs differentiators, complexity estimates, MVP recommendations
- **ARCHITECTURE.md:** Integration points, data flow changes, component modifications
- **PITFALLS.md:** Top 5 risks ranked, prevention strategies, phase-specific warnings
**Recommended phase count:** 4-5 phases
**Estimated complexity:** Medium (infrastructure change + UX improvements)
**Confidence for planning:** HIGH for Phases 1-4, MEDIUM for Phase 5 (Unraid sync)
---
## Confidence Assessment
| Area | Confidence | Notes |
|------|------------|-------|
| Stack | HIGH | Official docs for socket-proxy and n8n API verified |
| Features | MEDIUM-HIGH | Telegram API well-documented; n8n limitations confirmed via GitHub issues |
| Architecture | HIGH | Clear integration points, existing workflow well understood |
| Pitfalls | MEDIUM-HIGH | Based on official docs + community experience; Unraid behavior forum-confirmed |
**Overall confidence:** MEDIUM-HIGH
### Gaps to Address
1. **n8n version check** - Verify current n8n version before starting (2.0 has breaking changes)
2. **Unraid volume mounts** - Verify existing mounts or plan for new ones
3. **Telegram keyboard testing** - HTTP Request pattern needs validation with actual workflow
---
## Sources
### Primary (HIGH confidence)
- [n8n API Documentation](https://docs.n8n.io/api/) - Authentication, endpoints
- [LinuxServer socket-proxy](https://docs.linuxserver.io/images/docker-socket-proxy/) - Configuration options
- [Telegram Bot API](https://core.telegram.org/bots/api) - Inline keyboards, callback queries
### Secondary (MEDIUM confidence)
- [n8n GitHub Issue #19955](https://github.com/n8n-io/n8n/issues/19955) - Native node keyboard limitations
- [Tecnativa docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) - Alternative proxy option
### Tertiary (LOW confidence)
- [Unraid Forums](https://forums.unraid.net/bug-reports/stable-releases/regression-incorrect-docker-update-notification-r2807/) - Update badge behavior workarounds
---
*Research completed: 2026-02-02*
*Ready for roadmap: yes*