Files
homelab/n8n/N8N-SETUP-PLAN.md
Jordan Ramos c16d521070 docs(n8n): correct architecture for Debian 12 and Nginx Proxy Manager
Real-world deployment feedback revealed documentation mismatches:
- OS: Ubuntu references → Debian 12 (actual deployment)
- Reverse Proxy: Standalone nginx → Nginx Proxy Manager (NPM)

Changes Applied (30+ corrections in 4 batches):

Batch 1 - OS Corrections:
- Update OS template and PostgreSQL repo references to Debian 12

Batch 2 - NPM Terminology (10 updates):
- Update CT 102 specs (2 cores, 4GB RAM, 10GB disk)
- Rename nginx → nginx-proxy-mgr throughout
- Add NPM admin UI port 81 to diagrams
- Remove nginx-light/certbot from prerequisites

Batch 3 - Major Rewrites:
- Section VI-A: Complete NPM architecture overview
- Phase 7: Rewrite for NPM web UI (20min → 10min)
  * Replace SSH/manual config with browser-based setup
  * Add step-by-step proxy host creation guide
  * Include NPM-specific troubleshooting

Batch 4 - Minor Updates (15+ changes):
- Update troubleshooting sections for NPM
- Update architecture diagrams
- Update deployment workflows

Impact:
- Deployment time reduced (Phase 7: 20min → 10min)
- Complexity reduced (GUI vs manual nginx config)
- Accuracy improved (matches actual Debian 12 + NPM deployment)

Validated-by: Lab-Operator
Real-world-tested: PostgreSQL installation, NPM configuration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 17:37:00 -07:00

76 KiB
Raw Blame History

N8N Workflow Automation Server - Setup Plan

Document Created: 2025-11-29 Infrastructure Survey Date: 2025-11-29 14:13:39 Proxmox Node: serviceslab Author: The Scribe (Steve's Architecture Module)


Executive Summary

This document provides a comprehensive plan for deploying n8n (a powerful workflow automation platform) in your Proxmox homelab. After analyzing your current infrastructure, I recommend deploying n8n as an LXC container with PostgreSQL database backing, reverse-proxied through your existing Nginx Proxy Manager (NPM) container for SSL termination and secure external access.


I. Current Infrastructure Overview

Proxmox Host Specifications

╔════════════════════════════════════════════════════════════════╗
║                    PROXMOX NODE: serviceslab                   ║
╠════════════════════════════════════════════════════════════════╣
║  Version:        Proxmox VE 8.3.3                              ║
║  Architecture:   Single-node cluster                           ║
║  CPU:            Dual Intel Xeon X5670 @ 2.93GHz               ║
║                  (2 sockets × 6 cores × 2 threads = 24 vCPUs)  ║
║  RAM:            173 GB total                                  ║
║                  - Used: 92 GB                                 ║
║                  - Available: 80 GB                            ║
║  Management IP:  192.168.2.100/24                              ║
╚════════════════════════════════════════════════════════════════╝

Storage Infrastructure

┌─────────────────────────────────────────────────────────────────┐
│ Storage Pool              Size    Used    Free    Usage  Type   │
├─────────────────────────────────────────────────────────────────┤
│ local                     43.9G   6.4G    35G     16%    ext4   │
│   Purpose: ISOs, templates, backups                             │
│                                                                 │
│ local-lvm                 65.8G   N/A     N/A     N/A    LVM    │
│   Purpose: VM disk images (thin provisioned)                    │
│                                                                 │
│ Vault (ZFS)               4.36T   124G    4.24T   2%     ZFS    │
│   Purpose: Primary VM/LXC storage                               │
│   Health: ONLINE                                                │
│   Compression: Enabled                                          │
│                                                                 │
│ PBS-Backups               Remote storage at 192.168.2.151       │
│   Purpose: Proxmox Backup Server repository                     │
│                                                                 │
│ iso-share (NFS)           3.1T at 192.168.2.150                 │
│   Purpose: Shared ISO library                                   │
└─────────────────────────────────────────────────────────────────┘

Network Configuration

┌──────────────────────────────────────────────────────────────────┐
│                       Network Topology                           │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Physical NIC: eno1 (f0:4d:a2:04:0c:17)                          │
│        │                                                         │
│        └──► vmbr0 (Primary Bridge)                               │
│               │                                                  │
│               ├─ IP: 192.168.2.100/24                            │
│               ├─ Gateway: 192.168.2.1                            │
│               ├─ VLAN-aware: yes                                 │
│               └─ VLAN range: 2-4094                              │
│                                                                  │
│  vmbr1 (Isolated Network)                                        │
│    └─ IP: 192.168.3.0/24                                         │
│       Purpose: Internal services network                         │
│                                                                  │
│  VLAN 5: Used for web servers and ansible control                │
└──────────────────────────────────────────────────────────────────┘

Existing Virtual Machines (QEMU/KVM)

┌────────┬─────────────────────┬───────┬──────────┬──────────┬────────────┐
│ VM ID  │ Name                │ vCPU  │ RAM (GB) │ Disk     │ Network    │
├────────┼─────────────────────┼───────┼──────────┼──────────┼────────────┤
│ 100    │ docker-hub          │ 4     │ 8.2      │ 100G     │ vmbr0      │
│ 101    │ gitlab              │ 4     │ 17.0     │ 50G      │ vmbr0      │
│ 104    │ ubuntu-dev          │ N/A   │ N/A      │ N/A      │ vmbr0      │
│ 105    │ dev                 │ N/A   │ N/A      │ N/A      │ vmbr0      │
│ 106    │ Ansible-Control     │ 2     │ 4.0      │ 32G      │ vmbr0.5    │
│ 107    │ ubuntu-docker       │ 2     │ 4.0      │ 50G      │ vmbr0      │
│        │ (Template)          │       │          │          │            │
│ 108    │ CML                 │ N/A   │ N/A      │ N/A      │ vmbr0      │
│ 109    │ web-server-01       │ 1     │ 2.0      │ 32G      │ vmbr0.5    │
│ 110    │ web-server-02       │ N/A   │ N/A      │ 32G      │ vmbr0.5    │
│ 111    │ db-server-01        │ 1     │ 4.0      │ 32G      │ vmbr0.5    │
└────────┴─────────────────────┴───────┴──────────┴──────────┴────────────┘

Total VM Resources: ~11 vCPUs, ~40 GB RAM

Existing LXC Containers

┌────────┬─────────────────────┬───────┬──────────┬──────────┬────────────┐
│ CT ID  │ Name                │ Cores │ RAM (GB) │ Disk     │ IP Address │
├────────┼─────────────────────┼───────┼──────────┼──────────┼────────────┤
│ 102    │ nginx-proxy-mgr     │ 2     │ 4.0      │ 10G      │ 192.168.   │
│        │ (NPM - Reverse Proxy)│      │          │          │ 2.101/24   │
│        │                     │       │          │          │            │
│ 103    │ netbox              │ N/A   │ N/A      │ N/A      │ DHCP       │
│        │ (IPAM/Docs)         │       │          │          │            │
│        │                     │       │          │          │            │
│ 112    │ Anytype             │ 2     │ 4.0      │ 25G      │ DHCP       │
│        │ (Knowledge Mgmt)    │       │          │          │            │
└────────┴─────────────────────┴───────┴──────────┴──────────┴────────────┘

Features: All containers have nesting=1 (Docker support)

Resource Availability Assessment

╔═══════════════════════════════════════════════════════════════╗
║                   AVAILABLE RESOURCES                         ║
╠═══════════════════════════════════════════════════════════════╣
║  CPU:     ~13 vCPUs available (24 total - ~11 allocated)      ║
║  RAM:     ~80 GB available                                    ║
║  Disk:    4.12 TB available on Vault ZFS pool                 ║
║                                                               ║
║  Verdict: EXCELLENT capacity for n8n deployment               ║
╚═══════════════════════════════════════════════════════════════╝

II. N8N Architecture Decision: LXC vs VM

┌─────────────────────────────────────────────────────────────────┐
│                    LXC vs VM Comparison                         │
├──────────────────┬──────────────────────┬───────────────────────┤
│ Factor           │ LXC Container        │ Virtual Machine       │
├──────────────────┼──────────────────────┼───────────────────────┤
│ Boot Time        │ < 5 seconds          │ 30-60 seconds         │
│ RAM Overhead     │ ~100 MB              │ ~500 MB               │
│ Disk Space       │ ~2-5 GB              │ ~10-15 GB             │
│ Performance      │ Near-native          │ Slight overhead       │
│ Snapshot Speed   │ Instant (ZFS)        │ 5-30 seconds          │
│ Backup Size      │ Smaller              │ Larger                │
│ Docker Support   │ Yes (with nesting)   │ Native                │
│ Resource Isol.   │ Good                 │ Excellent             │
│ Complexity       │ Simple               │ Moderate              │
└──────────────────┴──────────────────────┴───────────────────────┘

Why LXC for n8n?

Advantages:

  1. Efficiency: n8n is a Node.js application with modest requirements. LXC provides near-native performance with minimal overhead.
  2. Fast Deployment: Container creation takes seconds vs minutes for VMs.
  3. Resource Conservation: Uses ~500 MB less RAM than a VM, leaving more resources for workflows.
  4. ZFS Snapshots: Instant snapshots before updates or configuration changes.
  5. Consistency: Your existing Nginx Proxy Manager (CT 102) is already an LXC container.
  6. Docker Compatibility: With nesting=1 feature, the container can run Docker if needed for custom nodes.

Considerations:

  • n8n doesn't require kernel-level isolation that VMs provide
  • No exotic hardware requirements
  • Perfectly suited for containerized deployment

When to Use a VM Instead:

You would only need a VM if:

  • Running n8n with Windows-specific integrations
  • Requiring complete kernel isolation for security
  • Testing multiple OS environments simultaneously
  • Planning to run heavy compute workloads within workflows

For typical n8n workflow automation: LXC is the superior choice.


III. N8N Server Specifications

┌─────────────────────────────────────────────────────────────────┐
│                    N8N LXC Container Specs                      │
├─────────────────────────────────────────────────────────────────┤
│  Container ID:      113 (next available)                        │
│  Hostname:          n8n                                         │
│  OS Template:       Debian 12 (bookworm)                        │
│                                                                 │
│  vCPU Cores:        2 (scalable to 4 if needed)                 │
│  RAM:               4096 MB (4 GB)                              │
│  Swap:              2048 MB (2 GB)                              │
│                                                                 │
│  Root Disk:         20 GB (Vault ZFS pool)                      │
│    - OS: ~2 GB                                                  │
│    - n8n: ~1 GB                                                 │
│    - PostgreSQL: ~2 GB                                          │
│    - Workflow data: ~5 GB                                       │
│    - Growth buffer: ~10 GB                                      │
│                                                                 │
│  Network:           vmbr0 (Primary bridge)                      │
│  IP Address:        192.168.2.113/24 (static)                   │
│  Gateway:           192.168.2.1                                 │
│  DNS:               8.8.8.8, 8.8.4.4                            │
│                                                                 │
│  Features:          nesting=1 (Docker support)                  │
│  Start on Boot:     Yes (onboot: 1)                             │
│  Unprivileged:      Yes (security best practice)                │
│  Firewall:          Yes (Proxmox firewall enabled)              │
└─────────────────────────────────────────────────────────────────┘

Performance Scaling Guide

Usage Level          vCPU    RAM     Disk    Notes
───────────────────────────────────────────────────────────────
Light (< 10 workflows)   2    4 GB    20 GB   Recommended start
Medium (10-50)           2    6 GB    30 GB   Most homelabs
Heavy (50-100)           4    8 GB    50 GB   Power users
Enterprise (100+)        4    12 GB   100 GB  Consider VM/K8s

IV. Network Architecture & Integration

Network Diagram

                          Internet
                             │
                             ▼
                    ┌─────────────────┐
                    │  Router/Firewall │
                    │  192.168.2.1     │
                    └────────┬─────────┘
                             │
                  ┌──────────┴───────────┐
                  │   vmbr0 Bridge       │
                  │   192.168.2.0/24     │
                  └──────────┬───────────┘
                             │
          ┌──────────────────┼──────────────────────┐
          │                  │                      │
          ▼                  ▼                      ▼
    ┌──────────┐      ┌──────────┐          ┌──────────┐
    │   NPM    │      │   n8n    │          │ GitLab   │
    │ CT: 102  │      │ CT: 113  │          │ VM: 101  │
    │ .101:80  │◄─────┤ .113:5678│          │ DHCP     │
    │ .101:443 │      └──────────┘          └──────────┘
    └──────────┘            │
         │                  ▼
         │           ┌──────────────┐
         │           │ PostgreSQL   │
         │           │ (in CT 113)  │
         │           │ localhost:   │
         │           │ 5432         │
         │           └──────────────┘
         │
         ▼
    SSL Termination
    n8n.yourdomain.com ──► https://192.168.2.113:5678

IP Address Allocation

┌──────────────────┬────────────────────┬──────────────────────┐
│ IP Address       │ Hostname           │ Service              │
├──────────────────┼────────────────────┼──────────────────────┤
│ 192.168.2.1      │ router             │ Gateway              │
│ 192.168.2.100    │ serviceslab        │ Proxmox Host         │
│ 192.168.2.101    │ Nginx Proxy Manager│ Reverse Proxy        │
│ 192.168.2.113    │ n8n                │ N8N Server (NEW)     │
│ 192.168.2.150    │ NAS                │ NFS Storage          │
│ 192.168.2.151    │ PBS                │ Backup Server        │
└──────────────────┴────────────────────┴──────────────────────┘

Port Mapping Strategy

┌────────────────────────────────────────────────────────────────┐
│                    Port Configuration                          │
├────────────────────────────────────────────────────────────────┤
│  Internal n8n Container:                                       │
│    5678/tcp  ──► n8n Web Interface (HTTP)                      │
│    5432/tcp  ──► PostgreSQL (localhost only)                   │
│                                                                │
│  Nginx Proxy Manager (CT 102):                                 │
│    443/tcp   ──► HTTPS (proxies to n8n:5678)                   │
│    80/tcp    ──► HTTP (redirects to HTTPS)                     │
│    81/tcp    ──► NPM Admin UI (LAN only)                       │
│                                                                │
│  External Access:                                              │
│    https://n8n.yourdomain.com ──► NPM:443 ──► n8n:5678         │
└────────────────────────────────────────────────────────────────┘

Firewall Rules

# Proxmox Firewall Configuration for CT 113 (n8n)

Direction  Protocol  Source          Dest Port   Action  Comment
─────────────────────────────────────────────────────────────────
IN         TCP       192.168.2.101   5678        ACCEPT  NPM proxy
IN         TCP       192.168.2.0/24  22          ACCEPT  SSH admin
IN         TCP       0.0.0.0/0       5678        DROP    Block direct
OUT        TCP       any             80,443      ACCEPT  Updates/webhooks
OUT        TCP       any             25,587      ACCEPT  Email (SMTP)
OUT        UDP       any             53          ACCEPT  DNS

V. Database Architecture

PostgreSQL vs SQLite Decision Matrix

┌───────────────────┬─────────────────────┬─────────────────────┐
│ Factor            │ PostgreSQL (Rec.)   │ SQLite              │
├───────────────────┼─────────────────────┼─────────────────────┤
│ Performance       │ Excellent           │ Good                │
│ Concurrent Access │ Full support        │ Limited             │
│ Data Integrity    │ ACID compliant      │ ACID compliant      │
│ Backup/Restore    │ Standard tools      │ File copy           │
│ Scaling           │ Unlimited           │ Limited to 1-2 GB   │
│ HA/Clustering     │ Yes                 │ No                  │
│ Setup Complexity  │ Moderate            │ Zero config         │
│ Production Ready  │ Yes                 │ For small setups    │
└───────────────────┴─────────────────────┴─────────────────────┘

Recommendation: PostgreSQL for production reliability and future growth.

PostgreSQL Configuration

┌─────────────────────────────────────────────────────────────────┐
│              PostgreSQL Database Specifications                 │
├─────────────────────────────────────────────────────────────────┤
│  Version:           PostgreSQL 16 (latest stable)               │
│  Installation:      Same container as n8n (CT 113)              │
│  Database Name:     n8n_db                                      │
│  Database User:     n8n_user                                    │
│  Listen Address:    127.0.0.1 (localhost only)                  │
│  Port:              5432                                        │
│  Max Connections:   20                                          │
│  Shared Buffers:    512 MB                                      │
│  Maintenance Work:  128 MB                                      │
│  WAL Level:         replica (for backups)                       │
│                                                                 │
│  Backup Strategy:                                               │
│    - Daily pg_dump to /var/backups/n8n/                         │
│    - Proxmox container backup to PBS (weekly)                   │
│    - ZFS snapshots before updates (manual)                      │
└─────────────────────────────────────────────────────────────────┘

VI. Integration with Existing Services

A. Nginx Proxy Manager (CT 102)

Your existing Nginx Proxy Manager container will handle:

  1. SSL/TLS Termination - Let's Encrypt certificates (via NPM UI)
  2. HTTPS Enforcement - HTTP to HTTPS redirect
  3. Security Headers - HSTS, CSP, X-Frame-Options
  4. Rate Limiting - Prevent abuse
  5. Access Logging - Centralized logging
  6. Web-based Management - No manual config file editing required

Nginx Proxy Manager Overview:

Nginx Proxy Manager (NPM) is a Docker-based reverse proxy management tool that provides:

  • Web UI: Accessible at http://192.168.2.101:81
  • Let's Encrypt Integration: One-click SSL certificate generation and renewal
  • GUI Configuration: Point-and-click proxy host creation
  • Built-in Access Control: IP whitelisting and basic authentication
  • Real-time Monitoring: View proxy status and logs through dashboard

GitHub: https://github.com/NginxProxyManager/nginx-proxy-manager

Configuration for n8n (via NPM Web UI):

Instead of manually editing nginx configuration files, you'll configure the n8n proxy through NPM's web interface in Phase 7. Basic setup:

  1. Access NPM Admin UI: http://192.168.2.101:81
  2. Create Proxy Host with these settings:
    • Domain: n8n.yourdomain.com
    • Forward to: 192.168.2.113:5678
    • Enable WebSockets support
  3. Configure SSL: Request Let's Encrypt certificate via UI
  4. Advanced Settings (optional custom nginx config):
# Custom Nginx directives for n8n (added via NPM Advanced tab)
client_max_body_size 50M;

# Extended timeouts for long-running workflows
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;

# Additional security headers
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;

# WebSocket keep-alive
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

NPM Architecture:

  • Admin UI: Port 81 (LAN access only)
  • Proxy Traffic: Ports 80/443
  • Docker-based: Runs in containers on CT 102
  • Auto-renewal: Let's Encrypt certificates renew automatically

B. GitLab Integration (VM 101)

N8N can automate GitLab workflows:

  • CI/CD Triggers - Start pipelines on external events
  • Issue Management - Auto-create/update issues from tickets
  • Merge Request Automation - Code review workflows
  • Repository Monitoring - Track commits, tags, releases
  • Deployment Notifications - Slack/email on deployments

Connection:

  • GitLab API available at VM 101's IP (configure in n8n)
  • Create Personal Access Token in GitLab with API scope
  • Store token in n8n credentials manager

C. Docker Hub (VM 100)

Integration possibilities:

  • Image Update Notifications - Alert on new image versions
  • Automated Pulls - Trigger container updates
  • Build Monitoring - Track image builds

D. Ansible Control (VM 106)

N8N can trigger Ansible playbooks:

  • Infrastructure Automation - Run playbooks via webhook
  • Configuration Management - Scheduled config updates
  • Orchestration - Multi-system deployment workflows

Setup Method:

  • n8n HTTP Request node → Ansible AWX/Tower REST API
  • Or: n8n Execute Command node via SSH to Ansible Control VM

VII. Step-by-Step Setup Plan

Phase 1: Container Creation (15 minutes)

┌─────────────────────────────────────────────────────────────────┐
│                    Create LXC Container                         │
└─────────────────────────────────────────────────────────────────┘

Option A: Proxmox Web UI Method
─────────────────────────────────
1. Login to Proxmox at https://192.168.2.100:8006
2. Click "Create CT" button
3. Configure container:

   General:
   ├─ Node: serviceslab
   ├─ CT ID: 113
   ├─ Hostname: n8n
   ├─ Unprivileged: ☑ (checked)
   └─ Password: [Set strong password]

   Template:
   └─ Storage: local
      Template: debian-12-standard (or ubuntu-24.04-standard)

   Disks:
   ├─ Storage: Vault
   └─ Disk size: 20 GB

   CPU:
   └─ Cores: 2

   Memory:
   ├─ Memory: 4096 MB
   └─ Swap: 2048 MB

   Network:
   ├─ Bridge: vmbr0
   ├─ IPv4: Static
   ├─ IPv4/CIDR: 192.168.2.113/24
   ├─ Gateway: 192.168.2.1
   └─ IPv6: SLAAC (or disable)

   DNS:
   ├─ DNS domain: apophisnetworking.net
   └─ DNS servers: 8.8.8.8 8.8.4.4

4. Click "Confirm" then "Finish"
5. Enable features:
   ├─ Right-click CT 113 → Options
   ├─ Features → Edit
   └─ Check: "nesting" ☑

6. Start container


Option B: CLI Method (Proxmox SSH)
──────────────────────────────────
# SSH to Proxmox host
ssh root@192.168.2.100

# Download template (if not present)
pveam update
pveam download local debian-12-standard_12.7-1_amd64.tar.zst

# Create container
pct create 113 local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst \
  --hostname n8n \
  --cores 2 \
  --memory 4096 \
  --swap 2048 \
  --rootfs Vault:20 \
  --net0 name=eth0,bridge=vmbr0,ip=192.168.2.113/24,gw=192.168.2.1 \
  --nameserver 8.8.8.8 \
  --features nesting=1 \
  --unprivileged 1 \
  --onboot 1

# Start container
pct start 113

# Enter container
pct enter 113

Phase 2: System Preparation (10 minutes)

# Inside CT 113 (after pct enter 113)

# Update system
apt update && apt upgrade -y

# Install basic prerequisites
apt install -y \
  curl \
  wget \
  git \
  gnupg2 \
  ca-certificates \
  lsb-release \
  ufw

# Add PostgreSQL Official Repository
# Note: PostgreSQL 16 is not in standard Debian repositories
echo "Setting up PostgreSQL 16 from official repository..."

# Add PostgreSQL GPG key
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | \
  gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg

# Add PostgreSQL APT repository
sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

# Update package list with new repository
apt update

# Install PostgreSQL 16
apt install -y postgresql-16 postgresql-contrib-16

# Verify installation
psql --version

# Configure timezone
timedatectl set-timezone America/New_York  # Adjust to your TZ

Phase 3: PostgreSQL Setup (10 minutes)

# Switch to postgres user
sudo -u postgres psql

-- Execute these SQL commands:
CREATE DATABASE n8n_db;
CREATE USER n8n_user WITH ENCRYPTED PASSWORD 'YourSecurePassword123!';
GRANT ALL PRIVILEGES ON DATABASE n8n_db TO n8n_user;
\q

# Configure PostgreSQL
cat >> /etc/postgresql/16/main/postgresql.conf << 'EOF'

# N8N Optimizations
max_connections = 20
shared_buffers = 512MB
effective_cache_size = 2GB
maintenance_work_mem = 128MB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 200
work_mem = 26214kB
min_wal_size = 1GB
max_wal_size = 4GB
EOF

# Restart PostgreSQL
systemctl restart postgresql
systemctl enable postgresql

# Test connection
PGPASSWORD='YourSecurePassword123!' psql -U n8n_user -d n8n_db -h localhost -c "SELECT version();"

Phase 4: Node.js & n8n Installation (15 minutes)

# Install Node.js 20.x (LTS - recommended for n8n)
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs

# Verify Node.js installation
node --version  # Should show v20.x.x
npm --version   # Should show 10.x.x

# Install n8n globally
npm install -g n8n

# Create n8n system user
useradd -r -m -d /opt/n8n -s /bin/bash n8n

# Create directory structure
mkdir -p /opt/n8n/{.n8n,backups,logs}
chown -R n8n:n8n /opt/n8n

Phase 5: N8N Configuration (10 minutes)

# Create environment configuration
cat > /opt/n8n/.env << 'EOF'
# Database Configuration
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=localhost
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n_db
DB_POSTGRESDB_USER=n8n_user
DB_POSTGRESDB_PASSWORD=YourSecurePassword123!

# n8n Configuration
N8N_PROTOCOL=https
N8N_HOST=n8n.yourdomain.com
N8N_PORT=5678
N8N_PATH=/
WEBHOOK_URL=https://n8n.yourdomain.com/

# Execution
EXECUTIONS_DATA_SAVE_ON_ERROR=all
EXECUTIONS_DATA_SAVE_ON_SUCCESS=all
EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=true

# Performance
N8N_PAYLOAD_SIZE_MAX=16
EXECUTIONS_TIMEOUT=300
EXECUTIONS_TIMEOUT_MAX=3600

# Timezone
GENERIC_TIMEZONE=America/New_York

# Security
N8N_BASIC_AUTH_ACTIVE=false
N8N_JWT_AUTH_ACTIVE=true
N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)

# Paths
N8N_USER_FOLDER=/opt/n8n/.n8n
N8N_LOG_LOCATION=/opt/n8n/logs/
N8N_LOG_LEVEL=info
EOF

# Secure environment file
chown n8n:n8n /opt/n8n/.env
chmod 600 /opt/n8n/.env

Phase 6: Systemd Service Creation (5 minutes)

# Create systemd service
cat > /etc/systemd/system/n8n.service << 'EOF'
[Unit]
Description=n8n - Workflow Automation
Documentation=https://docs.n8n.io
After=network.target postgresql.service
Wants=postgresql.service

[Service]
Type=simple
User=n8n
Group=n8n
WorkingDirectory=/opt/n8n
EnvironmentFile=/opt/n8n/.env
ExecStart=/usr/bin/n8n start

# Restart configuration
Restart=always
RestartSec=10
StartLimitInterval=60
StartLimitBurst=5

# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=/opt/n8n
ProtectHome=true

# Logging
StandardOutput=append:/opt/n8n/logs/n8n.log
StandardError=append:/opt/n8n/logs/n8n-error.log

[Install]
WantedBy=multi-user.target
EOF

# Reload systemd and start n8n
systemctl daemon-reload
systemctl enable n8n
systemctl start n8n

# Check status
systemctl status n8n

# View logs
journalctl -u n8n -f

Phase 7: Nginx Proxy Manager Configuration (10 minutes)

Unlike traditional nginx configuration, NPM uses a web-based GUI for all proxy management. No SSH required.

Prerequisites:

  • NPM is installed and running on CT 102
  • NPM admin UI accessible at http://192.168.2.101:81
  • DNS A record for n8n.yourdomain.com pointing to your public IP

Step 1: Access NPM Admin Interface

From your workstation browser:

  • Navigate to: http://192.168.2.101:81
  • First-time login credentials:
    • Email: admin@example.com
    • Password: changeme
  • IMPORTANT: You will be prompted to change these immediately

Step 2: Create Proxy Host for n8n

  1. Navigate to Proxy Hosts:

    • Click "Hosts" → "Proxy Hosts" in the NPM dashboard
    • Click "Add Proxy Host" button
  2. Configure Details Tab:

    Domain Names:          n8n.yourdomain.com
    Scheme:                http
    Forward Hostname/IP:   192.168.2.113
    Forward Port:          5678
    
    Options:
    ☑ Cache Assets
    ☑ Block Common Exploits
    ☑ Websockets Support  (CRITICAL for n8n!)
    ☐ Access List (optional - configure if needed)
    
  3. Configure SSL Tab:

    SSL Certificate:       Request a new SSL Certificate
    
    ☑ Force SSL
    ☑ HTTP/2 Support
    ☑ HSTS Enabled
    ☐ HSTS Subdomains (not needed for n8n)
    
    Email Address:         your-email@domain.com
    ☑ I Agree to the Let's Encrypt Terms of Service
    
  4. Configure Advanced Tab (Optional):

    # Custom Nginx Configuration
    # Paste the following for optimal n8n performance:
    
    client_max_body_size 50M;
    
    # Extended timeouts for long-running workflows
    proxy_connect_timeout 300;
    proxy_send_timeout 300;
    proxy_read_timeout 300;
    send_timeout 300;
    
    # Additional security headers
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    
    # WebSocket keep-alive
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
  5. Save Configuration:

    • Click "Save" button
    • NPM will automatically:
      • Generate nginx configuration
      • Request Let's Encrypt certificate
      • Configure SSL settings
      • Reload nginx
      • Enable automatic certificate renewal (every 60 days)

Step 3: Verify Configuration

# Test n8n accessibility through NPM
curl -I https://n8n.yourdomain.com

# Expected response:
HTTP/2 200
server: nginx
content-type: text/html; charset=utf-8
strict-transport-security: max-age=31536000
x-frame-options: SAMEORIGIN
...

Step 4: Verify DNS and Port Forwarding

DNS Configuration: Ensure your domain's DNS has an A record pointing to your public IP:

Type: A
Host: n8n
Points to: <your-public-ip>
TTL: 3600

Router Port Forwarding (if behind NAT):

External Port 80  → 192.168.2.101:80
External Port 443 → 192.168.2.101:443

NPM Monitoring & Management

View Logs:

  • Click on proxy host → "Actions" → "View Logs"
  • Real-time request logging and error tracking

Certificate Renewal:

  • Automatic renewal via NPM (every 60 days)
  • Manual renewal: Edit proxy host → SSL tab → "Renew Certificate"

Disable/Enable Proxy:

  • Toggle switch next to proxy host name
  • No need to restart services

Troubleshooting NPM

Issue: NPM Web UI not accessible

# Check NPM container status on CT 102
pct enter 102
docker ps | grep nginx-proxy-manager
docker logs nginx-proxy-manager

# Restart NPM if needed
docker restart nginx-proxy-manager

Issue: SSL certificate generation fails

  • Verify DNS propagation: nslookup n8n.yourdomain.com
  • Check port 80/443 accessibility from internet
  • Review Let's Encrypt rate limits (5 certs/week per domain)
  • Check NPM logs for specific error messages

Issue: n8n not accessible through NPM

  • Verify n8n is running: curl http://192.168.2.113:5678
  • Check NPM proxy host configuration (correct IP/port)
  • Verify firewall allows 192.168.2.101 → 192.168.2.113:5678
  • Review NPM access logs for 502/504 errors

Phase 8: Firewall Configuration (5 minutes)

# On n8n container (CT 113)
ufw default deny incoming
ufw default allow outgoing
ufw allow from 192.168.2.0/24 to any port 22 comment 'SSH from LAN'
ufw allow from 192.168.2.101 to any port 5678 comment 'NPM reverse proxy'
ufw enable

# On Proxmox host (configure Proxmox firewall)
# Via Web UI:
# Datacenter → Firewall → Add rules for CT 113
# Or via CLI:
cat >> /etc/pve/firewall/113.fw << 'EOF'
[OPTIONS]
enable: 1

[RULES]
IN ACCEPT -source 192.168.2.101 -dport 5678 -proto tcp -log nolog
IN ACCEPT -source 192.168.2.0/24 -dport 22 -proto tcp -log nolog
IN DROP -dport 5678 -proto tcp -log warning
EOF

# Apply firewall
pve-firewall compile

Phase 9: Initial n8n Setup (10 minutes)

┌─────────────────────────────────────────────────────────────────┐
│                    First-Time Access                            │
└─────────────────────────────────────────────────────────────────┘

1. Open browser to: https://n8n.yourdomain.com

2. Create owner account:
   ├─ Email: your@email.com
   ├─ First Name: [Your Name]
   ├─ Last Name: [Your Last Name]
   └─ Password: [Strong password]

3. Setup tour will guide you through:
   ├─ Creating your first workflow
   ├─ Adding credentials
   └─ Testing a simple automation

4. Configure critical settings:
   Settings → General:
   ├─ Timezone: Match your location
   ├─ Execution timeout: 300 seconds (default)
   └─ Save data: All executions (for debugging)

5. Setup credentials for integrations:
   Credentials → Add Credential:
   ├─ GitLab API (for VM 101)
   ├─ SMTP (for email notifications)
   ├─ Webhook authentication
   └─ Any other services you use

Phase 10: Backup Configuration (15 minutes)

# On n8n container (CT 113)

# Create backup script
cat > /opt/n8n/backup.sh << 'EOF'
#!/bin/bash
# N8N Backup Script

BACKUP_DIR="/opt/n8n/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="n8n_backup_${DATE}"

# Create backup directory
mkdir -p ${BACKUP_DIR}/${BACKUP_NAME}

# Backup PostgreSQL database
PGPASSWORD='YourSecurePassword123!' pg_dump \
  -U n8n_user \
  -h localhost \
  -d n8n_db \
  -F c \
  -f ${BACKUP_DIR}/${BACKUP_NAME}/n8n_db.dump

# Backup n8n user folder
tar -czf ${BACKUP_DIR}/${BACKUP_NAME}/n8n_data.tar.gz \
  -C /opt/n8n/.n8n .

# Backup environment file
cp /opt/n8n/.env ${BACKUP_DIR}/${BACKUP_NAME}/

# Create backup manifest
cat > ${BACKUP_DIR}/${BACKUP_NAME}/MANIFEST.txt << MANIFEST
N8N Backup
Date: $(date)
Database: n8n_db.dump
User Data: n8n_data.tar.gz
Environment: .env
MANIFEST

# Compress backup
cd ${BACKUP_DIR}
tar -czf ${BACKUP_NAME}.tar.gz ${BACKUP_NAME}
rm -rf ${BACKUP_NAME}

# Keep last 7 daily backups
find ${BACKUP_DIR} -name "n8n_backup_*.tar.gz" -mtime +7 -delete

echo "Backup completed: ${BACKUP_DIR}/${BACKUP_NAME}.tar.gz"
EOF

chmod +x /opt/n8n/backup.sh

# Create daily backup cron job
cat > /etc/cron.d/n8n-backup << 'EOF'
# Daily n8n backup at 2 AM
0 2 * * * n8n /opt/n8n/backup.sh >> /opt/n8n/logs/backup.log 2>&1
EOF

# Test backup
sudo -u n8n /opt/n8n/backup.sh

# Configure Proxmox container backup
# On Proxmox host:
# Datacenter → Backup → Add
# Schedule: Weekly, Sunday 1:00 AM
# Storage: PBS-Backups
# Mode: Snapshot
# Compression: ZSTD
# Include: CT 113

VIII. Post-Installation Checklist

┌─────────────────────────────────────────────────────────────────┐
│                    Verification Checklist                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  □  Container CT 113 created and running                        │
│  □  Static IP 192.168.2.113 configured                          │
│  □  PostgreSQL installed and accessible                         │
│  □  n8n service running (systemctl status n8n)                  │
│  □  n8n accessible at https://n8n.yourdomain.com                │
│  □  SSL certificate valid and auto-renewing                     │
│  □  Nginx reverse proxy forwarding correctly                    │
│  □  Firewall rules in place                                     │
│  □  Owner account created in n8n                                │
│  □  Daily database backups configured                           │
│  □  Proxmox container backups scheduled                         │
│  □  Can create and execute test workflow                        │
│  □  Webhook URL working (test with curl)                        │
│  □  Email notifications configured (optional)                   │
│  □  GitLab integration tested (optional)                        │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

IX. Testing & Validation

Test 1: Basic Connectivity

# From any machine on 192.168.2.0/24 network
curl -I http://192.168.2.113:5678
# Expected: HTTP/1.1 200 OK

# HTTPS through NPM
curl -I https://n8n.yourdomain.com
# Expected: HTTP/2 200 (or 301 → 200)

Test 2: Create Sample Workflow

1. Login to n8n web interface
2. Click "+ Add workflow"
3. Add nodes:
   ├─ Schedule Trigger (every 1 hour)
   ├─ HTTP Request (GET https://api.github.com/zen)
   └─ Send Email (to your address)
4. Configure email credentials
5. Execute workflow manually
6. Check email received
7. Enable workflow
8. Monitor executions tab

Test 3: GitLab Integration

1. In GitLab (VM 101):
   └─ Settings → Access Tokens
      Create token with 'api' scope

2. In n8n:
   └─ Credentials → Add → GitLab API
      Enter: GitLab URL and Access Token

3. Create workflow:
   ├─ Webhook Trigger (on /webhook/gitlab)
   ├─ GitLab node (Get issue details)
   └─ Log to file

4. Configure GitLab webhook:
   └─ Project → Settings → Webhooks
      URL: https://n8n.yourdomain.com/webhook/gitlab
      Events: Issues

5. Test: Create issue in GitLab
6. Verify: Check n8n execution log

Test 4: Database Performance

# On CT 113
sudo -u postgres psql -d n8n_db -c "
SELECT
    schemaname,
    tablename,
    pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
LIMIT 10;
"

Test 5: Backup & Restore

# Test backup
sudo -u n8n /opt/n8n/backup.sh

# Simulate disaster: Stop n8n, drop database
systemctl stop n8n
sudo -u postgres psql -c "DROP DATABASE n8n_db;"

# Restore from backup
sudo -u postgres psql -c "CREATE DATABASE n8n_db OWNER n8n_user;"
LATEST_BACKUP=$(ls -t /opt/n8n/backups/*.tar.gz | head -1)
tar -xzf $LATEST_BACKUP -C /tmp/
PGPASSWORD='YourSecurePassword123!' pg_restore \
  -U n8n_user \
  -d n8n_db \
  /tmp/*/n8n_db.dump

# Restart n8n
systemctl start n8n
# Verify workflows still exist

X. Monitoring & Maintenance

Health Monitoring

# Create monitoring script
cat > /usr/local/bin/n8n-health-check << 'EOF'
#!/bin/bash
# N8N Health Check Script

# Check if n8n service is running
if ! systemctl is-active --quiet n8n; then
    echo "CRITICAL: n8n service is not running"
    exit 2
fi

# Check if n8n responds to HTTP
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:5678/healthz)
if [ "$HTTP_CODE" != "200" ]; then
    echo "WARNING: n8n healthcheck returned $HTTP_CODE"
    exit 1
fi

# Check PostgreSQL
if ! PGPASSWORD='YourSecurePassword123!' psql -U n8n_user -d n8n_db -h localhost -c "SELECT 1;" > /dev/null 2>&1; then
    echo "CRITICAL: PostgreSQL connection failed"
    exit 2
fi

# Check disk space
DISK_USAGE=$(df -h /opt/n8n | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$DISK_USAGE" -gt 80 ]; then
    echo "WARNING: Disk usage at ${DISK_USAGE}%"
    exit 1
fi

echo "OK: All checks passed"
exit 0
EOF

chmod +x /usr/local/bin/n8n-health-check

# Schedule health check every 5 minutes
cat > /etc/cron.d/n8n-health << 'EOF'
*/5 * * * * root /usr/local/bin/n8n-health-check >> /var/log/n8n-health.log 2>&1
EOF

Log Rotation

# Configure logrotate
cat > /etc/logrotate.d/n8n << 'EOF'
/opt/n8n/logs/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 n8n n8n
    sharedscripts
    postrotate
        systemctl reload n8n > /dev/null 2>&1 || true
    endscript
}
EOF

Update Procedure

# Create update script
cat > /opt/n8n/update-n8n.sh << 'EOF'
#!/bin/bash
# N8N Update Script

set -e

echo "Starting n8n update process..."

# Backup before update
echo "Creating backup..."
/opt/n8n/backup.sh

# Stop n8n service
echo "Stopping n8n..."
systemctl stop n8n

# Update n8n
echo "Updating n8n..."
npm update -g n8n

# Clear npm cache
npm cache clean --force

# Start n8n service
echo "Starting n8n..."
systemctl start n8n

# Wait for service to be ready
sleep 10

# Check health
if /usr/local/bin/n8n-health-check; then
    echo "Update completed successfully!"
    n8n --version
else
    echo "ERROR: Health check failed after update!"
    echo "Restoring from backup may be necessary"
    exit 1
fi
EOF

chmod +x /opt/n8n/update-n8n.sh

Maintenance Schedule

┌────────────────────────────────────────────────────────────────┐
│                    Maintenance Calendar                        │
├────────────────────────────────────────────────────────────────┤
│                                                                 │
│  Daily:                                                         │
│    └─ 02:00 AM - Database backup                              │
│                                                                 │
│  Weekly:                                                        │
│    └─ Sunday 01:00 AM - Proxmox container backup              │
│                                                                 │
│  Monthly:                                                       │
│    ├─ Review execution logs                                    │
│    ├─ Check disk space usage                                   │
│    ├─ Update n8n to latest version                            │
│    ├─ Review and optimize workflows                            │
│    └─ Test backup restoration                                  │
│                                                                 │
│  Quarterly:                                                     │
│    ├─ Review security headers                                  │
│    ├─ Update SSL certificates (automatic via Let's Encrypt)    │
│    ├─ Audit user access                                        │
│    └─ PostgreSQL VACUUM ANALYZE                                │
│                                                                 │
└────────────────────────────────────────────────────────────────┘

XI. Troubleshooting Guide

Common Issues & Solutions

Issue 1: n8n Won't Start

# Check service status
systemctl status n8n

# Check logs
journalctl -u n8n -n 50 --no-pager

# Common causes:
# 1. PostgreSQL not running
systemctl status postgresql
systemctl start postgresql

# 2. Database connection error
PGPASSWORD='YourSecurePassword123!' psql -U n8n_user -d n8n_db -h localhost

# 3. Port already in use
ss -tulpn | grep 5678

# 4. Permission issues
chown -R n8n:n8n /opt/n8n

Issue 2: Can't Access via HTTPS

# Check NPM status (on CT 102)
pct enter 102
docker ps | grep nginx-proxy-manager
docker logs nginx-proxy-manager

# View NPM proxy host configuration
# Access http://192.168.2.101:81 and check proxy host settings

# Check SSL certificate
# NPM Admin UI → SSL Certificates tab shows all certs and expiry dates

# Renew if needed (NPM auto-renews, but can manually trigger)
# NPM UI → Proxy Host → Edit → SSL → Renew Certificate button

# Check firewall
ufw status
# Ensure 443 is open on NPM container (CT 102)

# Test backend connectivity
curl http://192.168.2.113:5678

Issue 3: Workflows Timeout

# Increase timeout in /opt/n8n/.env
EXECUTIONS_TIMEOUT=600
EXECUTIONS_TIMEOUT_MAX=7200

# Restart n8n
systemctl restart n8n

# Also check NPM timeout in proxy host Advanced settings
# proxy_read_timeout 600;

Issue 4: Database Connection Pool Exhausted

# Edit /etc/postgresql/16/main/postgresql.conf
max_connections = 50

# Restart PostgreSQL
systemctl restart postgresql

# Monitor connections
sudo -u postgres psql -c "
SELECT count(*)
FROM pg_stat_activity
WHERE datname = 'n8n_db';
"

Issue 5: High Memory Usage

# Check memory usage
free -h
top -o %MEM

# Reduce n8n memory if needed in /opt/n8n/.env
N8N_PAYLOAD_SIZE_MAX=8

# Restart n8n
systemctl restart n8n

# Consider increasing container RAM
# On Proxmox: pct set 113 -memory 6144

XII. Security Hardening

Security Checklist

┌─────────────────────────────────────────────────────────────────┐
│                    Security Hardening Checklist                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  □  Use strong, unique passwords (20+ characters)               │
│  □  Enable HTTPS only (HTTP → HTTPS redirect)                  │
│  □  Configure HSTS header (max-age=31536000)                    │
│  □  Implement rate limiting in NPM (if available)               │
│  □  Use unprivileged LXC container                              │
│  □  Firewall blocks direct access to port 5678                  │
│  □  PostgreSQL listens on localhost only                        │
│  □  Regular security updates (apt update && upgrade)            │
│  □  Backup encryption for sensitive workflows                   │
│  □  Multi-factor authentication (n8n Cloud feature)             │
│  □  IP whitelist for admin access (optional)                    │
│  □  Credential encryption enabled (N8N_ENCRYPTION_KEY)          │
│  □  Audit logs enabled and monitored                            │
│  □  Fail2ban for SSH brute-force protection                     │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Additional Security Measures

# Install fail2ban (on CT 113)
apt install -y fail2ban

# Configure fail2ban for SSH
cat > /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
EOF

systemctl enable fail2ban
systemctl start fail2ban

# Implement NPM rate limiting
# Navigate to NPM Admin UI → Proxy Host → n8n → Advanced tab
# Add custom configuration:

limit_req_zone $binary_remote_addr zone=n8n_limit:10m rate=10r/s;

# In location block (Advanced config):
limit_req zone=n8n_limit burst=20 nodelay;

# Save configuration (NPM auto-reloads)

XIII. Advanced Configurations

High Availability Setup (Future Expansion)

If you need HA in the future:

┌─────────────────────────────────────────────────────────────────┐
│              High Availability Architecture                     │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│         Load Balancer (HAProxy/Keepalived)                      │
│                    │                                             │
│        ┌───────────┴───────────┐                                │
│        │                       │                                │
│   ┌────▼─────┐          ┌─────▼────┐                           │
│   │  n8n-01  │          │  n8n-02  │                           │
│   │ CT: 113  │          │ CT: 114  │                           │
│   └────┬─────┘          └─────┬────┘                           │
│        │                       │                                │
│        └───────────┬───────────┘                                │
│                    │                                             │
│           ┌────────▼────────┐                                   │
│           │  PostgreSQL HA  │                                   │
│           │  (Replication)  │                                   │
│           └─────────────────┘                                   │
│                                                                  │
│  Requirements:                                                   │
│  - Shared PostgreSQL with streaming replication                 │
│  - Queue mode enabled (requires Redis)                          │
│  - Session persistence at load balancer                         │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Custom Node Development

# Setup development environment
# On CT 113 or separate dev container

# Install n8n development tools
npm install -g n8n-node-dev

# Create custom node
n8n-node-dev new

# Follow prompts to create node
# Test node locally
# Package and install to production n8n

XIV. Integration Examples

Example 1: GitLab CI/CD Automation

Workflow: "GitLab Deploy Notification"

Trigger: GitLab Webhook (on pipeline completion)
  │
  ├─ Filter: status == "success"
  │
  ├─ Get Deployment Details (GitLab API)
  │
  ├─ Update Netbox (HTTP Request to VM 103)
  │
  ├─ Send Slack Notification
  │
  └─ Create Jira Ticket (if production deploy)

Example 2: Infrastructure Monitoring

Workflow: "Service Health Monitor"

Trigger: Schedule (every 5 minutes)
  │
  ├─ Check GitLab Health (HTTP Request)
  │
  ├─ Check NPM Status (http://192.168.2.101:81)
  │
  ├─ Check Docker Hub (HTTP Request to VM 100)
  │
  ├─ Query Netbox for Status (HTTP Request)
  │
  ├─ Aggregate Results
  │
  └─ If any failed:
      ├─ Send Email Alert
      ├─ Post to Slack
      └─ Create PagerDuty Incident

Example 3: Automated Backups

Workflow: "Backup Verification"

Trigger: Schedule (daily at 3 AM)
  │
  ├─ SSH to each VM/CT
  │
  ├─ Run backup script
  │
  ├─ Verify backup file exists
  │
  ├─ Check backup size (ensure not 0 bytes)
  │
  ├─ Update Google Sheets log
  │
  └─ Send summary email

XV. Performance Optimization

Tuning PostgreSQL for n8n

-- Run these on PostgreSQL for better performance

-- Increase work memory for complex queries
ALTER SYSTEM SET work_mem = '50MB';

-- Optimize for SSD (ZFS)
ALTER SYSTEM SET random_page_cost = 1.1;

-- Enable parallel query execution
ALTER SYSTEM SET max_parallel_workers_per_gather = 2;
ALTER SYSTEM SET max_parallel_workers = 4;

-- Reload configuration
SELECT pg_reload_conf();

-- Create indexes for common queries
CREATE INDEX IF NOT EXISTS idx_execution_data_workflow_id
ON public.execution_entity (workflow_id);

CREATE INDEX IF NOT EXISTS idx_execution_data_finished
ON public.execution_entity (finished);

-- Vacuum and analyze
VACUUM ANALYZE;

n8n Performance Settings

# Edit /opt/n8n/.env

# Increase concurrent executions
EXECUTIONS_PROCESS=main
EXECUTIONS_MODE=regular

# Queue mode for high throughput (requires Redis)
# EXECUTIONS_MODE=queue
# QUEUE_BULL_REDIS_HOST=localhost
# QUEUE_BULL_REDIS_PORT=6379

# Increase payload limits
N8N_PAYLOAD_SIZE_MAX=32

# Cache settings
CACHE_TTL=3600

XVI. Cost Analysis & Resource Planning

Resource Usage Projection

┌─────────────────────────────────────────────────────────────────┐
│                    Resource Usage Forecast                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Current (0-10 workflows):                                       │
│    ├─ CPU: 5-10% avg (0.1-0.2 vCPU)                            │
│    ├─ RAM: 600-800 MB                                           │
│    └─ Disk: 5 GB                                                │
│                                                                  │
│  Growth (10-50 workflows):                                       │
│    ├─ CPU: 15-25% avg (0.3-0.5 vCPU)                           │
│    ├─ RAM: 1.5-2 GB                                             │
│    └─ Disk: 15 GB                                               │
│                                                                  │
│  Heavy Use (50-100 workflows):                                   │
│    ├─ CPU: 30-50% avg (0.6-1.0 vCPU)                           │
│    ├─ RAM: 3-4 GB                                               │
│    └─ Disk: 30 GB                                               │
│                                                                  │
│  Scaling Recommendations:                                        │
│  - At 50 workflows: Increase RAM to 6 GB                        │
│  - At 100 workflows: Increase vCPU to 4 cores                   │
│  - At 200 workflows: Consider queue mode + Redis               │
│  - At 500+ workflows: Migrate to dedicated VM or HA setup      │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

XVII. Documentation & Knowledge Base

Essential Resources

┌─────────────────────────────────────────────────────────────────┐
│                    N8N Documentation Links                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Official Documentation:                                         │
│  └─ https://docs.n8n.io/                                        │
│                                                                  │
│  Community Forum:                                                │
│  └─ https://community.n8n.io/                                   │
│                                                                  │
│  GitHub Repository:                                              │
│  └─ https://github.com/n8n-io/n8n                              │
│                                                                  │
│  Workflow Templates:                                             │
│  └─ https://n8n.io/workflows                                    │
│                                                                  │
│  YouTube Channel:                                                │
│  └─ https://www.youtube.com/@n8n-io                            │
│                                                                  │
│  Integration Nodes:                                              │
│  └─ https://docs.n8n.io/integrations/                          │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Internal Documentation

Create these documents in your homelab repo:

  1. /home/jramos/homelab/docs/n8n-workflows.md

    • Document all active workflows
    • Purpose, trigger, dependencies
    • Maintenance notes
  2. /home/jramos/homelab/docs/n8n-credentials.md (encrypted)

    • Credential inventory
    • Service API endpoints
    • Renewal/rotation schedule
  3. /home/jramos/homelab/docs/n8n-runbook.md

    • Emergency procedures
    • Escalation contacts
    • Restore procedures

XVIII. Migration Path from SQLite (If Needed)

If you start with SQLite and later migrate to PostgreSQL:

# Export from SQLite
n8n export:workflow --all --output=/tmp/workflows.json
n8n export:credentials --all --output=/tmp/credentials.json

# Stop n8n
systemctl stop n8n

# Update .env to use PostgreSQL
# (already configured in Phase 5)

# Import to PostgreSQL
n8n import:workflow --input=/tmp/workflows.json
n8n import:credentials --input=/tmp/credentials.json

# Start n8n
systemctl start n8n

XIX. Final Architecture Diagram

╔══════════════════════════════════════════════════════════════════╗
║                                                                  ║
║              N8N HOMELAB INFRASTRUCTURE - FINAL STATE            ║
║                                                                  ║
╠══════════════════════════════════════════════════════════════════╣
║                                                                  ║
║                          Internet                                ║
║                             │                                    ║
║                             ▼                                    ║
║                   ┌──────────────────┐                           ║
║                   │  Router/Firewall │                           ║
║                   │  192.168.2.1     │                           ║
║                   │  Port 443 → 101  │                           ║
║                   └────────┬─────────┘                           ║
║                            │                                     ║
║    ┌───────────────────────┼─────────────────────────┐           ║
║    │         Proxmox Node: serviceslab               │           ║
║    │         192.168.2.100/24 (vmbr0)                │           ║
║    │                       │                         │           ║
║    │   ┌───────────────────┼───────────────────────┐ │           ║
║    │   │                   │                       │ │           ║
║    │   │  ┌────────────────▼──────┐   ┌──────────▼┐  │           ║
║    │   │  │  NPM (CT 102)         │   │ n8n       │  │           ║
║    │   │  │  192.168.2.101        │   │ (CT 113)  │  │           ║
║    │   │  ├───────────────────────┤   │ .113      │  │           ║
║    │   │  │ - SSL Termination     │   │           │  │           ║
║    │   │  │ - Reverse Proxy       │───┤ n8n App   │  │           ║
║    │   │  │ - Let's Encrypt       │   │ :5678     │  │           ║
║    │   │  │ - Rate Limiting       │   │           │  │           ║
║    │   │  └───────────────────────┘   │ Postgres  │  │           ║
║    │   │                              │ :5432     │  │           ║
║    │   │                              └─────┬─────┘  │           ║
║    │   │                                    │        │           ║
║    │   │  ┌─────────────────────────────────┼─────┐  │           ║
║    │   │  │     Integration Services        │     │  │           ║
║    │   │  │                                 │     │  │           ║
║    │   │  │  ┌──────────┐  ┌──────────┐     │     │  │           ║
║    │   │  │  │ GitLab   │  │ Docker   │     │     │  │           ║
║    │   │  │  │ VM 101   │  │ Hub      │     │     │  │           ║
║    │   │  │  │ 17GB RAM │  │ VM 100   │     │     │  │           ║
║    │   │  │  └────┬─────┘  └────┬─────┘     │     │  │           ║
║    │   │  │       │             │           │     │  │           ║
║    │   │  │  ┌────▼─────┐  ┌────▼─────┐     │     │  │           ║
║    │   │  │  │ Netbox   │  │ Ansible  │     │     │  │           ║
║    │   │  │  │ CT 103   │  │ VM 106   │◄── ─┼─────┘  │           ║
║    │   │  │  │ IPAM     │  │ Control  │     │        │           ║
║    │   │  │  └──────────┘  └──────────┘     │        │           ║
║    │   │  └───────────────────────────────────────┘  │           ║
║    │   │                                             │           ║
║    │   │  ┌──────────────────────────────────────┐   │           ║
║    │   │  │     Storage: Vault (ZFS)             │   │           ║
║    │   │  │     4.36 TB Total / 124 GB Used      │   │           ║
║    │   │  └──────────────────────────────────────┘   │           ║
║    │   │                                             │           ║
║    │   └─────────────────────────────────────────────┘           ║
║    │                                                             ║
║    │  Backups: PBS (192.168.2.151)                               ║
║    └───────────────────────────────────────────────────────────  ║
║                                                                  ║
╚══════════════════════════════════════════════════════════════════╝

Workflow Examples:
─────────────────
• GitLab Pipeline → n8n → Slack Notification
• Schedule → n8n → Ansible Playbook → Email Report
• Webhook → n8n → Update Netbox → GitLab Issue
• Cron → n8n → Backup Verification → Dashboard Update

XX. Conclusion & Next Steps

Summary

You now have a comprehensive blueprint for deploying n8n in your Proxmox homelab. The LXC container approach provides:

  • Efficiency: Minimal resource overhead (~600 MB RAM, < 5 GB disk)
  • Performance: Near-native execution speed
  • Reliability: PostgreSQL backend with automated backups
  • Security: Reverse proxy with SSL, firewall rules, unprivileged container
  • Scalability: Easy to upgrade resources as workflow count grows
  • Integration: Seamless connection to your existing infrastructure

Immediate Next Steps

  1. Create CT 113 using Phase 1 instructions
  2. Install PostgreSQL (Phase 3)
  3. Deploy n8n (Phase 4-6)
  4. Configure NPM proxy (Phase 7)
  5. Test connectivity (Phase 9)
  6. Setup backups (Phase 10)

Week 1 Goals

  • Complete installation (Phases 1-7)
  • Create first workflow (scheduled health check)
  • Integrate with GitLab
  • Configure backups
  • Test disaster recovery

Month 1 Goals

  • Deploy 5-10 production workflows
  • Setup monitoring and alerting
  • Document all workflows
  • Optimize PostgreSQL performance
  • Implement advanced security measures

Future Considerations

3 Months:

  • Evaluate workflow performance
  • Consider queue mode if > 50 workflows
  • Implement custom nodes if needed

6 Months:

  • Review HA requirements
  • Integrate with additional services
  • Expand automation scope

1 Year:

  • Consider n8n Cloud migration (if needed)
  • Evaluate container→VM migration
  • Implement disaster recovery testing

Appendix A: Quick Reference Commands

# Container Management
pct list                           # List all containers
pct start 113                      # Start n8n container
pct stop 113                       # Stop n8n container
pct enter 113                      # Enter container shell

# Service Management
systemctl status n8n               # Check n8n status
systemctl restart n8n              # Restart n8n
journalctl -u n8n -f              # Follow n8n logs

# Database
sudo -u postgres psql -d n8n_db    # Connect to database
/opt/n8n/backup.sh                 # Run backup

# Health Checks
/usr/local/bin/n8n-health-check    # Run health check
curl http://localhost:5678/healthz # Test n8n API

# Updates
/opt/n8n/update-n8n.sh             # Update n8n
apt update && apt upgrade -y        # Update system packages

# Backups
ls -lh /opt/n8n/backups/           # List backups
tar -tzf backup.tar.gz | head      # View backup contents

Appendix B: Environment Variables Reference

# Core Configuration
DB_TYPE=postgresdb                 # Database type
N8N_PROTOCOL=https                 # Protocol (http/https)
N8N_HOST=n8n.yourdomain.com       # Public hostname
N8N_PORT=5678                      # n8n listen port
WEBHOOK_URL=https://...            # Webhook base URL

# Database
DB_POSTGRESDB_HOST=localhost
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n_db
DB_POSTGRESDB_USER=n8n_user
DB_POSTGRESDB_PASSWORD=...

# Execution
EXECUTIONS_TIMEOUT=300             # Default timeout (seconds)
EXECUTIONS_TIMEOUT_MAX=3600        # Maximum timeout
EXECUTIONS_DATA_SAVE_ON_ERROR=all  # Save failed executions
EXECUTIONS_DATA_SAVE_ON_SUCCESS=all # Save successful

# Performance
N8N_PAYLOAD_SIZE_MAX=16            # Max payload size (MB)
EXECUTIONS_PROCESS=main            # Execution mode

# Timezone
GENERIC_TIMEZONE=America/New_York

# Security
N8N_ENCRYPTION_KEY=...             # Credential encryption key
N8N_JWT_AUTH_ACTIVE=true           # Use JWT auth

Appendix C: Support & Contact

Getting Help

  1. N8N Community Forum: https://community.n8n.io/
  2. GitHub Issues: https://github.com/n8n-io/n8n/issues
  3. Discord: https://discord.gg/n8n
  4. Documentation: https://docs.n8n.io/

This Document

  • Location: /home/jramos/homelab/N8N-SETUP-PLAN.md
  • Version: 1.0
  • Created: 2025-11-29
  • Last Updated: 2025-11-29
  • Author: The Scribe (Homelab Infrastructure)

Remember: This is a living document. Update it as your infrastructure evolves, workflows expand, and requirements change. Good infrastructure documentation is your future self's best friend.

Now, let's build something remarkable with n8n.

— The Scribe