---
title: "n8n Platform Context"
description: "Complete technical documentation for the self-hosted n8n workflow automation platform on LXC 210. Covers architecture, Docker deployment, PostgreSQL backend, Nginx Proxy Manager config, active workflows (Ko-fi, Claude agent notifications), and operational procedures."
type: context
domain: productivity
tags: [n8n, automation, workflow, docker, postgresql, webhook, lxc, nginx-proxy-manager]
---

# n8n Workflow Automation Platform

Self-hosted workflow automation platform for building integrations and automating tasks across your homelab infrastructure.

## Overview

n8n is a fair-code licensed workflow automation tool that allows you to connect various services and automate complex processes through a visual workflow editor.

**Deployment Date:** 2025-11-13
**Version:** Latest (auto-updating via Docker)
**License:** Fair-code (free for self-hosted)

## Architecture

### Infrastructure

**LXC Container:**
- **VMID:** 210
- **Hostname:** docker-n8n-lxc
- **IP Address:** 10.10.0.210
- **CPU:** 4 cores
- **RAM:** 8GB
- **Disk:** 128GB
- **OS:** Ubuntu 20.04 LTS

**Services:**
```
┌─────────────────────────────────────┐
│  https://n8n.manticorum.com         │
│  (Nginx Proxy Manager)              │
└──────────────┬──────────────────────┘
               │ SSL Termination
               ↓
┌─────────────────────────────────────┐
│  LXC 210 (10.10.0.210)              │
│                                     │
│  ┌──────────────┐  ┌─────────────┐ │
│  │   n8n        │  │ PostgreSQL  │ │
│  │   :5678      │→ │   :5432     │ │
│  │              │  │             │ │
│  │ - Workflows  │  │ - Database  │ │
│  │ - Webhooks   │  │ - Creds     │ │
│  │ - Executions │  │ - History   │ │
│  └──────────────┘  └─────────────┘ │
└─────────────────────────────────────┘
```

### Data Persistence

**Docker Volumes:**
- `n8n_data` - Workflow files, credentials, settings
- `n8n_postgres_data` - PostgreSQL database

**Configuration:**
- `/opt/n8n/docker-compose.yml` - Container orchestration
- `/opt/n8n/.env` - Environment variables and secrets

## Access & Authentication

### External Access (Production)
```
URL: https://n8n.manticorum.com/
Username: admin
Password: [stored in .env file]
Protocol: HTTPS (via NPM with Let's Encrypt)
```

### Internal Access (Development/Testing)
```
URL: http://10.10.0.210:5678
Username: admin
Password: [same as above]
Protocol: HTTP (direct to container)
```

### SSH Access
```bash
# Using homelab SSH key
ssh -i ~/.ssh/homelab_rsa root@10.10.0.210

# Or with SSH config alias
ssh n8n
```

## Configuration

### Environment Variables

Key configuration settings in `/opt/n8n/.env`:

**Database:**
```bash
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=[secure-random-password]
```

**n8n Settings:**
```bash
N8N_HOST=n8n.manticorum.com
N8N_PROTOCOL=https
WEBHOOK_URL=https://n8n.manticorum.com/
GENERIC_TIMEZONE=America/Los_Angeles
```

**Security:**
```bash
N8N_ENCRYPTION_KEY=[64-char-hex-key]  # NEVER CHANGE AFTER FIRST RUN
N8N_BASIC_AUTH_ACTIVE=true
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=[secure-random-password]
```

**Performance:**
```bash
NODE_ENV=production
EXECUTIONS_PROCESS=main
EXECUTIONS_MODE=regular
```

### Nginx Proxy Manager Configuration

**Proxy Host Settings:**
- **Domain:** n8n.manticorum.com
- **Scheme:** http
- **Forward Host:** 10.10.0.210
- **Forward Port:** 5678
- **Websockets:** ✅ Enabled (REQUIRED)
- **Block Common Exploits:** ✅ Enabled
- **SSL:** Let's Encrypt with HTTP/2 and HSTS

**Custom Nginx Config:**
```nginx
# Increase timeout for long-running workflows
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;

# WebSocket support for real-time workflow updates
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

# Headers for n8n
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
```

## Operations

### Starting/Stopping Services

**Start n8n:**
```bash
ssh root@10.10.0.210 "cd /opt/n8n && docker compose up -d"
```

**Stop n8n:**
```bash
ssh root@10.10.0.210 "cd /opt/n8n && docker compose down"
```

**Restart n8n (apply configuration changes):**
```bash
ssh root@10.10.0.210 "cd /opt/n8n && docker compose restart n8n"
```

**View logs:**
```bash
ssh root@10.10.0.210 "cd /opt/n8n && docker compose logs -f"

# Just n8n logs
ssh root@10.10.0.210 "cd /opt/n8n && docker compose logs -f n8n"

# Just PostgreSQL logs
ssh root@10.10.0.210 "cd /opt/n8n && docker compose logs -f postgres"
```

**Check status:**
```bash
ssh root@10.10.0.210 "cd /opt/n8n && docker compose ps"
```

### Updates

**Update to latest n8n version:**
```bash
ssh root@10.10.0.210 "cd /opt/n8n && docker compose pull && docker compose up -d"
```

**Note:** n8n handles database migrations automatically on startup.

### Backups

**Database Backup:**
```bash
# Create timestamped backup
ssh root@10.10.0.210 "cd /opt/n8n && docker compose exec -T postgres pg_dump -U n8n n8n > /root/n8n-backup-\$(date +%Y%m%d-%H%M%S).sql"

# Download backup locally
scp -i ~/.ssh/homelab_rsa root@10.10.0.210:/root/n8n-backup-*.sql ~/backups/n8n/
```

**Full Backup (including volumes):**
```bash
ssh root@10.10.0.210 "
cd /opt/n8n
docker compose down
tar -czf /root/n8n-full-backup-\$(date +%Y%m%d-%H%M%S).tar.gz \
  /opt/n8n \
  /var/lib/docker/volumes/n8n_data \
  /var/lib/docker/volumes/n8n_postgres_data
docker compose up -d
"
```

**Restore from Backup:**
```bash
# Restore database only
cat n8n-backup-20251113.sql | ssh root@10.10.0.210 "docker compose exec -T postgres psql -U n8n n8n"

# Full restore (requires downtime)
ssh root@10.10.0.210 "
cd /opt/n8n
docker compose down
tar -xzf /root/n8n-full-backup-20251113.tar.gz -C /
docker compose up -d
"
```

### Monitoring

**Health Check:**
```bash
# Check if n8n is responding
curl -s -o /dev/null -w "%{http_code}" http://10.10.0.210:5678
# Expected: 200

# Check container health
ssh root@10.10.0.210 "docker ps --filter name=n8n --format '{{.Status}}'"
```

**Resource Usage:**
```bash
ssh root@10.10.0.210 "docker stats --no-stream n8n n8n-postgres"
```

## Security Considerations

### Encryption Key
- **Critical:** The `N8N_ENCRYPTION_KEY` encrypts all stored credentials
- **Never change** this key after initial setup - it will make existing credentials unreadable
- **Backup securely** - store this key in a password manager or secrets vault

### Credentials Storage
- All workflow credentials are encrypted in the PostgreSQL database
- Credentials are never exposed in workflow definitions
- Use environment variables for sensitive data when possible

### Network Security
- Port 5678 exposed on container for internal access
- External access only via NPM (HTTPS with SSL)
- Consider using NPM's built-in access lists for IP whitelisting

### Authentication
- Basic auth enabled by default
- Consider integrating with SSO for multi-user scenarios
- Regularly rotate admin password

## Active Workflows

### Claude Agent Done → Discord

**Purpose:** Discord notification when a Claude Code subagent finishes (for long-running pipelines)

**Documentation:** `workflows/claude-agent-notifications.md`

**Workflow Features:**
- Receives `SubagentStop` HTTP hook from Claude Code
- Extracts agent name from payload (`subagent_name` or `session_id` prefix)
- Posts `🏁 Claude agent **{name}** has finished.` to Discord
- Discord webhook URL stored as n8n variable (not in local config)

**Webhook URL:**
- Production: `http://10.10.0.210:5678/webhook/claude-agent-done`
- Test: `http://10.10.0.210:5678/webhook-test/claude-agent-done`

**Related Files:**
- `workflows/claude-agent-notifications.md` - Setup guide
- `workflows/claude-agent-done.json` - Importable n8n workflow

**Hook Config:** The `SubagentStop` HTTP hook should be configured in the `.claude/settings.json` of whichever Claude Code instance runs long-running subagents (e.g. `claude-runner` CT 302), not in `claude-home`.

**Custom Variables:**
- `DISCORD_CLAUDE_ALERTS_WEBHOOK` - Discord webhook URL for the target channel

---

### Ko-fi → Paper Dynasty Integration

**Purpose:** Automated pack distribution when users purchase on Ko-fi

**Documentation:** `workflows/kofi-paper-dynasty.md`

**Workflow Features:**
- Receives Ko-fi shop order webhooks
- Multi-method user identification (discord_userid or team abbrev)
- Product mapping via custom variables
- Paper Dynasty API integration for pack grants
- Discord notifications for success/errors/manual review
- Comprehensive error handling and retry logic

**Webhook URLs:**
- Test: `https://n8n.manticorum.com/webhook-test/kofi-paperdy`
- Production: `https://n8n.manticorum.com/webhook/kofi-paperdy`

**Related Files:**
- `workflows/kofi-paper-dynasty.md` - Complete setup guide
- `workflows/kofi-product-mapping-template.json` - Product configuration template
- `workflows/kofi-testing-guide.md` - Testing procedures and sample payloads

**Credentials Required:**
- Ko-fi Verification Token
- Paper Dynasty API Key
- Discord Webhook URL

**Custom Variables:**
- `KOFI_PRODUCT_MAP` - JSON mapping of Ko-fi products to PD packs

---

## Integration Patterns

### Common Use Cases

**Homelab Automation:**
- Monitor system health and send alerts
- Backup automation workflows
- Service restart orchestration
- Log aggregation and analysis

**Infrastructure Integration:**
- Proxmox API automation
- Docker container management
- Network device configuration
- DNS record management

**Notification Workflows:**
- Discord/Slack alerts
- Email notifications
- SMS via Twilio
- Push notifications

**Data Processing:**
- API data collection and transformation
- Scheduled report generation
- Database sync operations
- File processing and organization

**E-commerce Integration:**
- Ko-fi payment processing (Paper Dynasty packs)
- Automated product fulfillment
- Customer notification workflows
- Transaction logging and analytics

### Webhook Configuration

**Webhook URLs follow this pattern:**
```
https://n8n.manticorum.com/webhook/{webhook-path}
https://n8n.manticorum.com/webhook-test/{webhook-path}
```

**Test webhooks before production:**
- Use `/webhook-test/` for development
- Switch to `/webhook/` for production
- Configure URL in n8n workflow webhook node

## Performance Tuning

### Resource Allocation

Current allocation is suitable for:
- Up to 50 concurrent workflow executions
- 100+ saved workflows
- Moderate webhook traffic (<100 req/min)

**If experiencing performance issues:**
- Increase LXC RAM allocation
- Add more CPU cores
- Monitor PostgreSQL query performance
- Consider workflow optimization

### Execution Modes

**Current:** `EXECUTIONS_MODE=regular` (main process)

**Alternative:** `EXECUTIONS_MODE=queue` (separate worker)
- Better for high-volume workflows
- Requires Redis
- More complex setup

## Troubleshooting

See [troubleshooting.md](troubleshooting.md) for common issues and solutions.

## Related Documentation

- [Troubleshooting Guide](troubleshooting.md) - Common issues and fixes
- [Examples](examples/) - Configuration examples and templates
- [Docker Context](/docker/CONTEXT.md) - Container infrastructure patterns
- [Networking Context](/networking/CONTEXT.md) - NPM and reverse proxy setup

## References

- **Official Documentation:** https://docs.n8n.io/
- **Community Forum:** https://community.n8n.io/
- **GitHub Repository:** https://github.com/n8n-io/n8n
- **Docker Hub:** https://hub.docker.com/r/n8nio/n8n

## Change Log

### 2025-11-13 - Initial Deployment
- Created LXC 210 (docker-n8n-lxc) with 4 cores, 8GB RAM, 128GB disk
- Deployed n8n with PostgreSQL 15 backend
- Configured domain: n8n.manticorum.com
- Integrated with Nginx Proxy Manager for HTTPS access
- Enabled basic authentication
- Set timezone to America/Los_Angeles
