Files
Lucas Berger 2cb6f3a689 docs(01): research phase domain
Phase 1: Foundation
- Standard stack identified (n8n Telegram nodes, Bot API)
- Architecture patterns documented (auth, echo, formatting)
- Pitfalls catalogued (webhook SSL, merge deadlock, rate limits)
- Code examples from official sources

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 18:28:17 -05:00

507 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 1: Foundation - Research
**Researched:** 2026-01-28
**Domain:** Telegram Bot + n8n Workflow Automation
**Confidence:** HIGH
## Summary
This phase establishes basic Telegram ↔ n8n communication for a Docker management bot. The research confirms that n8n provides robust, production-ready Telegram integration through dedicated nodes (Telegram Trigger for receiving messages, Telegram node for sending). The standard approach uses Telegram's webhook architecture, which n8n manages automatically, requiring only BotFather token setup and proper environment configuration.
The research revealed critical security patterns for user authentication (verifying `from.id` in message objects), webhook security (secret tokens), and n8n environment variable management. Common pitfalls center around webhook URL configuration, SSL/TLS requirements, and merge node blocking issues.
**Primary recommendation:** Use n8n's Telegram Trigger node (automatic webhook management) + Telegram node (send operations) with environment variable-based user ID authentication. This approach is well-documented, actively maintained, and handles all webhook complexity automatically.
## Standard Stack
The established libraries/tools for Telegram bot development with n8n:
### Core
| Library | Version | Purpose | Why Standard |
|---------|---------|---------|--------------|
| n8n | Latest (2026) | Workflow automation platform | Official Telegram node support, active development, webhook abstraction |
| Telegram Bot API | Current | Message sending/receiving | Official Telegram API, comprehensive documentation |
| n8n Telegram Trigger | Built-in | Receive messages via webhook | Automatic webhook registration, event filtering |
| n8n Telegram Node | Built-in | Send messages and operations | Full Bot API coverage, supports all message types |
### Supporting
| Library | Version | Purpose | When to Use |
|---------|---------|---------|-------------|
| n8n IF Node | Built-in | Conditional branching | User ID verification, message routing |
| n8n Code Node | Built-in | Custom JavaScript/Python | Complex message parsing, timestamp formatting |
| n8n Stop And Error | Built-in | Error workflow triggering | Handle unauthorized access, API failures |
### Alternatives Considered
| Instead of | Could Use | Tradeoff |
|------------|-----------|----------|
| Telegram Trigger | Generic Webhook | Manual webhook management, no automatic registration |
| n8n | python-telegram-bot | More control but requires coding, hosting, maintenance |
| Environment Variables | Hardcoded Values | Less flexible, requires workflow edits to change config |
**Installation:**
n8n already running on Unraid. No additional packages required for Telegram integration.
## Architecture Patterns
### Recommended Workflow Structure
```
Telegram Bot Workflow
├── Telegram Trigger # Entry point - receives all messages
├── IF (User ID Check) # Authentication gate
│ ├── TRUE branch
│ │ └── Code (Echo) # Echo message with timestamp
│ │ └── Telegram (Send) # Send response back
│ └── FALSE branch
│ └── (no nodes) # Silent ignore - workflow ends
```
### Pattern 1: User Authentication via Message Object
**What:** Verify sender identity using Telegram's `from.id` field
**When to use:** Every workflow requiring access control
**Example:**
```javascript
// In IF node expression
// Source: https://core.telegram.org/bots/api#message
{{ $json.message.from.id }} === {{ $env.TELEGRAM_USER_ID }}
```
**Key fields from Message object:**
- `message.from.id` - Unique user identifier (up to 52-bit integer)
- `message.from.username` - User's @username (optional, can change)
- `message.chat.id` - Chat identifier (needed for sending responses)
- `message.text` - Message content
### Pattern 2: Echo with Metadata
**What:** Confirm message processing with timestamp proof
**When to use:** Testing webhook round-trip, debugging message flow
**Example:**
```javascript
// In Code node
// Source: n8n best practices
const message = $input.item.json.message.text;
const timestamp = new Date().toISOString();
const userId = $input.item.json.message.from.id;
return {
chatId: $input.item.json.message.chat.id,
text: `Got: ${message}\n\nProcessed: ${timestamp}\nUser ID: ${userId}`
};
```
### Pattern 3: Environment Variable Configuration
**What:** Store sensitive config (user ID, tokens) in environment variables
**When to use:** All credentials and user-specific configuration
**Example:**
```bash
# In n8n Docker environment
# Source: https://docs.n8n.io/hosting/configuration/environment-variables/
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
TELEGRAM_USER_ID=987654321
```
Access in workflows:
```javascript
{{ $env.TELEGRAM_USER_ID }}
{{ $env.TELEGRAM_BOT_TOKEN }}
```
### Pattern 4: Telegram Message Formatting
**What:** Use HTML or Markdown for rich text formatting
**When to use:** Error messages, status updates, formatted responses
**Example:**
```javascript
// HTML formatting (recommended - more robust)
// Source: https://core.telegram.org/bots/api#html-style
const formatted = `<b>Container Status</b>
<code>Plex:</code> Running
<code>Sonarr:</code> Stopped
<i>Last updated: ${timestamp}</i>`;
// In Telegram node, set Parse Mode to "HTML"
```
**Available formatting:**
- HTML: `<b>bold</b>`, `<i>italic</i>`, `<code>code</code>`, `<pre>block</pre>`
- MarkdownV2: `*bold*`, `_italic_`, `` `code` ``, ` ```block``` `
- Default: HTML (more forgiving of syntax errors)
### Pattern 5: Silent Ignore for Unauthorized Users
**What:** End workflow without response for unauthorized messages
**When to use:** Security pattern - bot appears offline to strangers
**Example:**
```
Telegram Trigger → IF (auth check)
├── TRUE → (process message)
└── FALSE → (no nodes, workflow ends)
```
**Why this works:**
- No error thrown
- No response sent
- No indication bot exists
- Logs optional (can disable execution saving for production)
### Anti-Patterns to Avoid
- **Hardcoded credentials:** Store tokens in credentials manager or env vars, never in workflow JSON
- **Waiting on both merge branches:** IF splits create conditional paths - don't merge both branches if one may not execute
- **Saving execution progress in production:** Causes excessive database writes (3000/day for 30-node × 100 executions)
- **Using username for auth:** Usernames can change; use immutable `from.id` instead
- **Forgetting HTTPS requirement:** Telegram webhooks require TLS 1.2+ on ports 443, 80, 88, or 8443
## Don't Hand-Roll
Problems that look simple but have existing solutions:
| Problem | Don't Build | Use Instead | Why |
|---------|-------------|-------------|-----|
| Webhook management | Custom webhook server | n8n Telegram Trigger | Automatic registration, handles test/prod URLs, manages SSL |
| Message parsing | Custom JSON extraction | n8n's `$json` syntax | Built-in access to all message fields, expression editor |
| User auth validation | Custom middleware | IF node with env variable | Simple, visual, auditable in workflow |
| Telegram formatting | String concatenation | Parse Mode (HTML/Markdown) | Handles escaping, provides rich formatting, less error-prone |
| Retry logic | Custom loops | n8n error workflow + retries | Centralized error handling, exponential backoff, monitoring |
**Key insight:** Telegram's Bot API and n8n's integration layer handle webhook security, message routing, and connection management. Building custom solutions means reimplementing TLS verification, update deduplication, and rate limiting—all of which are already solved.
## Common Pitfalls
### Pitfall 1: Webhook URL Misconfiguration
**What goes wrong:** Telegram Trigger stays in "Test URL" mode, production webhook never registers
**Why it happens:** Missing or incorrect `WEBHOOK_URL` environment variable in n8n
**How to avoid:**
- Set `WEBHOOK_URL=https://your-n8n-domain.com/` (must be HTTPS)
- Set `N8N_PROXY_HOPS=1` if behind reverse proxy
- Verify URL is publicly accessible on ports 443, 80, 88, or 8443
**Warning signs:**
- Workflow only works when manually executed
- Telegram shows "Connection not secure" or no webhook registered
- Messages not triggering workflow automatically
**Source:** https://docs.n8n.io/hosting/configuration/environment-variables/
### Pitfall 2: Certificate/SSL Issues
**What goes wrong:** Webhook registration fails silently or with "certificate verification failed"
**Why it happens:**
- Self-signed certificates not uploaded to Telegram
- Missing intermediate certificates in chain
- Using TLS version < 1.2
- Wrong domain in certificate CN
**How to avoid:**
- Use Let's Encrypt or valid CA certificate
- If self-signed, upload cert when calling `setWebhook`
- Verify cert chain includes all intermediates
- Test with: `curl --tlsv1.2 -v -k https://your-domain:443/`
**Warning signs:**
- `setWebhook` returns error about SSL
- Webhook works locally but not in production
- Certificate warnings in browser
**Source:** https://core.telegram.org/bots/webhooks
### Pitfall 3: Secret Token Not Verified
**What goes wrong:** Webhook accepts spoofed requests from attackers
**Why it happens:** Not checking `X-Telegram-Bot-Api-Secret-Token` header
**How to avoid:**
- Telegram Trigger handles this automatically
- If using custom webhook: verify header matches your secret
- Use long random string for secret token
**Warning signs:**
- Receiving messages you didn't send
- Unexpected workflow executions
- Security audit flags missing token verification
**Note:** n8n Telegram Trigger validates this automatically—only relevant if building custom webhook.
**Source:** https://core.telegram.org/bots/api
### Pitfall 4: Merge Node Deadlock
**What goes wrong:** Workflow hangs indefinitely waiting for data that never arrives
**Why it happens:** IF node creates conditional branch, but Merge waits for both TRUE and FALSE paths
**How to avoid:**
- Don't merge after conditional splits unless both paths always execute
- Use Switch node instead of IF for multiple outcomes that need merging
- Design workflows to avoid needing to merge conditional branches
**Warning signs:**
- Workflow shows "Waiting for input" forever
- Only one branch of IF executes but merge expects two
- Manual execution works, but automated runs hang
**Source:** https://medium.com/@juanm.acebal/7-common-n8n-workflow-mistakes-that-can-break-your-automations-9638903fb076
### Pitfall 5: Rate Limit Exceeded
**What goes wrong:** Telegram returns 429 errors, messages fail to send
**Why it happens:** Sending >30 messages per second to same chat
**How to avoid:**
- Add delay between messages if sending multiple
- Use batch processing with sleep intervals
- For high volume, implement queue-based sending
**Warning signs:**
- `sendMessage` returns HTTP 429
- Messages delivered inconsistently
- Some messages disappear
**Source:** https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.telegram/message-operations.md
### Pitfall 6: Using getUpdates with Active Webhook
**What goes wrong:** Bot stops receiving webhook updates
**Why it happens:** Telegram's API prevents both polling (getUpdates) and webhooks simultaneously
**How to avoid:**
- Choose one method: webhook (for production) or polling (for local dev)
- Delete webhook before using getUpdates: call `deleteWebhook`
- n8n Telegram Trigger uses webhooks—don't mix with polling libraries
**Warning signs:**
- Webhook suddenly stops working after testing with getUpdates
- Messages not delivered despite active workflow
- Telegram API shows "conflict" errors
**Source:** https://core.telegram.org/bots/webhooks
## Code Examples
Verified patterns from official sources:
### Creating Telegram Credential in n8n
```bash
# 1. Get token from BotFather
# Open Telegram, search @BotFather
# Send: /newbot
# Follow prompts for name and username (must end with 'bot')
# Copy the token: 123456789:ABCdefGHIjklMNOpqrsTUVwxyz
# 2. Add to n8n
# UI: Credentials → + → Telegram API
# Paste token in "Access Token" field
# Save
# Source: https://docs.n8n.io/integrations/builtin/credentials/telegram/
```
### Telegram Trigger Configuration
```javascript
// Telegram Trigger Node Settings
{
"credential": "Telegram API",
"updates": "message", // Trigger on new messages
"additionalFields": {
"download": false // Don't auto-download files/photos
}
}
// Output structure ($json):
{
"update_id": 123456789,
"message": {
"message_id": 1,
"from": {
"id": 987654321,
"is_bot": false,
"first_name": "John",
"username": "johndoe"
},
"chat": {
"id": 987654321,
"first_name": "John",
"username": "johndoe",
"type": "private"
},
"date": 1640000000,
"text": "Hello bot!"
}
}
// Source: https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.telegramtrigger/
```
### User ID Authentication Check
```javascript
// IF Node Expression
// Compare incoming user ID with authorized user
{{ $json.message.from.id }} === {{ $('Telegram Trigger').item.json.message.from.id }}
// Or using environment variable (recommended)
{{ $json.message.from.id.toString() }} === {{ $env.TELEGRAM_USER_ID }}
// Note: Ensure TELEGRAM_USER_ID is set in n8n environment:
// Docker: environment variable in docker-compose.yml
// Docker run: -e TELEGRAM_USER_ID=987654321
// Source: https://core.telegram.org/bots/api#message
```
### Echo Message with Timestamp
```javascript
// Code Node (JavaScript)
// Generate echo response with metadata
const message = $input.item.json.message;
const timestamp = new Date().toISOString();
return {
chatId: message.chat.id,
text: `Got: ${message.text}\n\nProcessed at: ${timestamp}\nFrom user: ${message.from.id}`
};
// Source: n8n Code node documentation
```
### Send Formatted Response
```javascript
// Telegram Node Configuration
{
"resource": "message",
"operation": "sendMessage",
"chatId": "={{ $json.chatId }}",
"text": "={{ $json.text }}",
"additionalFields": {
"parse_mode": "HTML",
"disable_notification": false,
"append_attribution": false // Remove "sent with n8n" footer
}
}
// HTML formatting example:
const text = `<b>Echo Test</b>
<code>Message:</code> ${message.text}
<code>Time:</code> ${timestamp}
<i>User ID verified: ${userId}</i>`;
// Available HTML tags:
// <b>bold</b>, <i>italic</i>, <code>inline code</code>
// <pre>code block</pre>, <a href="url">link</a>
// Source: https://core.telegram.org/bots/api#html-style
```
### Environment Variable Setup
```yaml
# docker-compose.yml for n8n
version: '3'
services:
n8n:
image: n8nio/n8n:latest
environment:
- WEBHOOK_URL=https://n8n.example.com/
- N8N_PROXY_HOPS=1
- TELEGRAM_USER_ID=987654321 # Your Telegram user ID
- N8N_ENCRYPTION_KEY=your_encryption_key
ports:
- "5678:5678"
volumes:
- ~/.n8n:/home/node/.n8n
# Get your user ID:
# 1. Message your bot
# 2. Check workflow execution data: message.from.id
# 3. Add to environment variable
# Source: https://docs.n8n.io/hosting/configuration/environment-variables/
```
### Silent Ignore Pattern (No Response)
```javascript
// Workflow structure for unauthorized users
// IF Node (check user ID)
// TRUE branch:
// → Code (process message)
// → Telegram (send response)
// FALSE branch:
// → (empty - workflow just ends)
// No need for error nodes or explicit "ignore" logic
// Simply don't add nodes to the FALSE branch
// Workflow completes, no response sent, appears offline
// Optional: Disable execution saving for production
// Settings → Workflow → Save Execution Progress: OFF
// Source: n8n workflow best practices
```
## State of the Art
| Old Approach | Current Approach | When Changed | Impact |
|--------------|------------------|--------------|--------|
| Long polling (getUpdates) | Webhooks | Always recommended | Real-time delivery, sub-second latency vs polling intervals |
| Hardcoded credentials | Environment variables + _FILE suffix | 2023+ | Docker Secrets/K8s Secrets support, better security |
| Markdown formatting | HTML formatting (default) | Ongoing | HTML more forgiving of syntax errors, same capabilities |
| Manual webhook registration | n8n Telegram Trigger auto-registration | n8n native | No manual setWebhook calls, handles test/prod URLs |
| Username-based auth | User ID-based auth | Always recommended | IDs immutable, usernames can change |
| Custom error handling per node | Centralized error workflow | n8n best practice 2025+ | Single "Mission Control" for all workflow errors |
**Deprecated/outdated:**
- **Markdown (Legacy)**: Use MarkdownV2 or HTML instead—legacy version has parsing inconsistencies
- **SSLv2/3, TLS 1.0/1.1**: Telegram requires TLS 1.2+ for webhook connections
- **HTTP webhooks**: Never supported—HTTPS always required
- **Save Execution Progress in production**: Creates excessive DB load; use only for debugging
- **Hardcoded tokens in workflow JSON**: Use credentials manager or environment variables
## Open Questions
Things that couldn't be fully resolved:
1. **n8n Encryption Key Management**
- What we know: n8n encrypts credentials before database storage using N8N_ENCRYPTION_KEY
- What's unclear: Best practice for key rotation without breaking existing credentials
- Recommendation: Set encryption key in initial setup, back up key securely, avoid rotation unless compromised
2. **Webhook IP Whitelisting in Unraid**
- What we know: Telegram sends webhooks from 149.154.160.0/20 and 91.108.4.0/22
- What's unclear: How to configure IP whitelisting in Unraid firewall/reverse proxy
- Recommendation: Configure at reverse proxy level (nginx/Caddy), not critical for Phase 1 (HTTPS + secret token sufficient)
3. **Multi-User Support Future-Proofing**
- What we know: Current design uses single TELEGRAM_USER_ID env variable
- What's unclear: Best pattern for scaling to multiple authorized users later
- Recommendation: For Phase 1, stick with single user ID; future phases can use array in env var or database lookup
4. **Error Workflow Integration**
- What we know: n8n supports centralized error workflows triggered by failures
- What's unclear: Whether to implement error workflow in Phase 1 or defer to monitoring phase
- Recommendation: Defer to later phase—Phase 1 focus is basic communication; add error workflow when building actual Docker commands
## Sources
### Primary (HIGH confidence)
- `/n8n-io/n8n-docs` (Context7) - Telegram node operations, webhook configuration, environment variables
- https://core.telegram.org/bots/api - Official Bot API, Message object, sendMessage method, formatting
- https://core.telegram.org/bots/webhooks - Official webhook setup guide, security, SSL requirements
- https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.telegram/ - Telegram node documentation
- https://docs.n8n.io/integrations/builtin/credentials/telegram/ - Credential setup with BotFather
### Secondary (MEDIUM confidence)
- https://medium.com/@juanm.acebal/7-common-n8n-workflow-mistakes-that-can-break-your-automations-9638903fb076 - Common workflow mistakes (merge deadlock, execution saving)
- https://michaelitoback.com/n8n-workflow-best-practices/ - n8n best practices for 2026
- https://n8n.io/integrations/telegram/ - Official n8n Telegram integration overview
- https://www.hostinger.com/tutorials/n8n-telegram-integration - Setup tutorial verified against official docs
- https://docs.n8n.io/hosting/configuration/environment-variables/ - Environment variable configuration guide
### Tertiary (LOW confidence)
- https://community.n8n.io/t/problems-with-telegram-webhook/113560 - Community troubleshooting (webhook issues)
- https://dev.to/akshay_kumar_bm/build-a-no-code-ai-telegram-bot-with-n8n-on-premise-free-1cbm - Tutorial (recent, matches official patterns)
## Metadata
**Confidence breakdown:**
- Standard stack: HIGH - Context7 + official docs confirm n8n has native, maintained Telegram support
- Architecture: HIGH - Patterns drawn from official n8n docs and Telegram API documentation
- Pitfalls: HIGH - Verified through official docs (webhook SSL, rate limits) and established community patterns (merge deadlock, execution saving)
**Research date:** 2026-01-28
**Valid until:** ~60 days (stable APIs, but n8n updates monthly—recheck before major version changes)
**Research gaps filled:**
- ✅ Telegram webhook security requirements (secret token, TLS 1.2+, ports)
- ✅ n8n Telegram Trigger automatic webhook management
- ✅ User ID authentication pattern using Message.from.id
- ✅ Environment variable configuration for n8n
- ✅ Message formatting options (HTML recommended over Markdown)
- ✅ Common workflow mistakes (merge deadlock, execution saving)
- ✅ BotFather setup flow for token generation
**Key decisions supported by research:**
- ✅ n8n for orchestration: Native Telegram support confirmed, production-ready
- ✅ User ID auth: from.id is immutable, proper field for authentication
- ✅ Single-user pattern: Simple environment variable approach validated