n8n Worker 모드와 PostgreSQL, Redis를 활용한 Docker Compose 통합 운영 가이드
핵심 키워드: n8n Docker Compose, n8n Worker 모드, n8n PostgreSQL 설정, n8n Redis 큐, 워크플로우 자동화 확장, n8n 프로덕션 배포
이 글에서 사용되는 Docker 이미지 버전 및 문서 정보는 다음과 같습니다.
- n8n 버전: 2.0.0 (2025-12-05 출시)
- PostgreSQL 버전: 18-alpine (2025-09 출시)
- Redis 버전: 8-alpine (2025-11 GA 출시)
- Docker Compose 버전: v2.x
- 대상 독자: n8n을 프로덕션 환경에서 운영하려는 개발자 및 시스템 관리자
| Database Stack(PostgreSQL, Redis)과 n8n Stack(n8n-main, n8n-worker)으로 구성된 프로덕션 환경을 구성합니다. |
|
[ 차례 ]
|
1. 개요: n8n Worker 모드란 무엇인가
n8n은 기본적으로 단일 프로세스에서 웹훅 수신과 워크플로우 실행을 모두 처리합니다. 하지만 업무 자동화 규모가 커지면 하나의 프로세스만으로는 처리 능력에 한계가 발생하게 됩니다. Worker 모드는 이러한 문제를 해결하기 위해 n8n의 역할을 메인 인스턴스와 워커 인스턴스로 분리하는 아키텍처입니다. 메인 인스턴스는 웹훅 수신, UI 제공, 워크플로우 관리를 담당하고, 워커 인스턴스는 실제 워크플로우 실행만을 전담합니다.
이 구조에서 Redis는 메인과 워커 사이의 작업 큐(Queue) 역할을 수행합니다. 메인 인스턴스가 실행해야 할 워크플로우를 Redis 큐에 등록하면, 워커 인스턴스가 이를 가져와 실행하는 방식입니다. PostgreSQL은 워크플로우 정의, 실행 이력, 자격 증명 등 모든 데이터를 영구적으로 저장하는 데이터베이스로 활용됩니다. SQLite 대신 PostgreSQL을 사용하면 여러 인스턴스가 동시에 데이터베이스에 접근할 수 있어 Worker 모드 운영에 필수적입니다.
Worker 모드의 가장 큰 장점은 수평적 확장(Horizontal Scaling)이 가능하다는 점입니다. 워크플로우 처리량이 증가하면 워커 인스턴스의 수를 늘려서 대응할 수 있습니다. 또한 무거운 워크플로우가 실행되더라도 메인 인스턴스의 웹훅 수신이나 UI 응답성에 영향을 주지 않아 시스템 전체의 안정성이 향상됩니다.
Worker 모드가 필요한 상황
• 동시에 많은 워크플로우가 실행되어야 할 때
• 실행 시간이 긴 워크플로우가 다른 작업을 지연시킬 때
• 웹훅 응답 속도가 중요한 서비스를 운영할 때
• 고가용성(High Availability)이 요구되는 환경에서

2. 아키텍처 구성도
Worker 모드의 전체 아키텍처를 이해하면 각 컴포넌트의 역할과 데이터 흐름을 명확하게 파악할 수 있습니다. 아래 다이어그램은 외부 요청이 들어와서 처리되기까지의 전체 과정을 보여줍니다. 사용자의 웹훅 요청은 먼저 메인 인스턴스에 도달하고, 메인 인스턴스는 해당 작업을 Redis 큐에 등록합니다. 워커 인스턴스들은 Redis 큐를 지속적으로 모니터링하다가 새로운 작업이 들어오면 이를 가져와 실행합니다.

각 컴포넌트의 역할을 정리하면 다음과 같습니다.
- n8n Main은 시스템의 진입점으로서 모든 외부 요청을 받아들이고, 사용자에게 워크플로우 편집 인터페이스를 제공합니다.
- Redis는 인메모리 데이터 스토어로서 작업 큐의 역할을 수행하며, 메인과 워커 사이의 통신을 중개합니다.
- PostgreSQL은 관계형 데이터베이스로서 워크플로우 정의, 실행 로그, 암호화된 자격 증명 등 모든 영구 데이터를 저장합니다.
- n8n Worker는 실제 워크플로우 로직을 실행하는 역할을 담당하며, 필요에 따라 여러 인스턴스를 운영할 수 있습니다.
3. 사전 준비사항
Docker & Docker Compose
Docker Compose를 이용한 n8n Worker 모드 구성을 시작하기 전에 몇 가지 사전 준비가 필요합니다. 먼저 Docker와 Docker Compose가 시스템에 설치되어 있어야 합니다. MacOS에서는 Docker Desktop을 설치하면 Docker Compose가 함께 포함되어 있으므로 별도의 설치가 필요하지 않습니다. Linux 서버 환경에서는 Docker Engine과 Docker Compose 플러그인을 각각 설치해야 할 수 있습니다.
하드웨어 요구사항
시스템 요구사항으로는 최소 4GB 이상의 RAM과 10GB 이상의 여유 디스크 공간을 권장합니다. Worker 인스턴스를 여러 개 운영하거나 복잡한 워크플로우를 실행한다면 더 많은 리소스가 필요할 수 있습니다. 또한 외부에서 웹훅을 수신하려면 해당 포트(기본 5678)가 방화벽에서 열려 있어야 하며, 도메인과 SSL 인증서 설정도 프로덕션 환경에서는 필수적입니다.
# Docker 버전 확인
docker --version
# 출력 예시: Docker version 24.0.7, build afdd53b
# Docker Compose 버전 확인
docker compose version
# 출력 예시: Docker Compose version v2.23.3
# 시스템 리소스 확인 (MacOS)
system_profiler SPHardwareDataType | grep "Memory"
# 시스템 리소스 확인 (Linux)
free -h
df -h
N8N_ENCRYPTION_KEY
n8n Worker 모드를 안전하게 운영하기 위해서는 몇 가지 보안 관련 값들을 미리 생성해 두어야 합니다. N8N_ENCRYPTION_KEY는 데이터베이스에 저장되는 자격 증명을 암호화하는 데 사용되므로 반드시 안전한 곳에 백업해야 합니다. 이 키를 분실하면 저장된 모든 자격 증명을 복구할 수 없게 됩니다. 아래 명령어를 사용하여 필요한 보안 키들을 생성할 수 있습니다.
# N8N_ENCRYPTION_KEY 생성 (32자 이상 권장)
openssl rand -hex 24
# 출력 예시: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
# PostgreSQL 비밀번호 생성
openssl rand -base64 32
# 출력 예시: xK9mN2pL5qR8sT1uV4wX7yZ0aB3cD6eF
# Redis 비밀번호 생성 (선택사항이지만 권장)
openssl rand -base64 24
# 출력 예시: hG7jK2lM5nP8qR1sT4uV
4. 디렉토리 구조 설정
체계적인 디렉토리 구조는 시스템 관리와 백업을 용이하게 만들어 줍니다. 아래와 같은 구조를 권장하며, 각 디렉토리는 특정 목적을 가지고 있습니다. data 디렉토리 아래에 각 서비스별 데이터를 저장하면 백업 시 해당 폴더만 복사하면 되므로 관리가 편리합니다. config 디렉토리에는 각 서비스의 설정 파일을 저장하고, logs 디렉토리에는 로그 파일을 모아서 관리합니다.
PostgreSQL과 Redis 컨테이너가 별도로 운영되고, 이 리소스를 공유하는 형태라면 10. 외부 공유 자원 활용 아키텍처를 참조하세요.
n8n-worker-stack/
├── docker-compose.yml # Docker Compose 메인 설정 파일
├── .env # 환경 변수 파일 (비밀번호, 키 등)
├── .env.example # 환경 변수 예시 파일 (버전 관리용)
├── data/ # 영구 데이터 저장 디렉토리
│ ├── postgres/ # PostgreSQL 데이터
│ ├── redis/ # Redis 데이터 (AOF/RDB)
│ └── n8n/ # n8n 로컬 파일 (업로드된 파일 등)
├── config/ # 설정 파일 디렉토리
│ ├── redis/ # Redis 설정
│ │ └── redis.conf # Redis 커스텀 설정
│ └── postgres/ # PostgreSQL 설정
│ └── init.sql # 초기화 SQL 스크립트
├── logs/ # 로그 파일 디렉토리
│ ├── n8n/ # n8n 로그
│ └── postgres/ # PostgreSQL 로그
├── backups/ # 백업 파일 저장 디렉토리
└── scripts/ # 유틸리티 스크립트
├── backup.sh # 백업 스크립트
└── restore.sh # 복원 스크립트
아래 명령어를 실행하여 필요한 디렉토리 구조를 한 번에 생성할 수 있습니다. mkdir -p 옵션은 상위 디렉토리가 없으면 함께 생성해 주므로 편리합니다. 디렉토리 생성 후에는 적절한 권한을 설정하여 Docker 컨테이너가 해당 디렉토리에 읽고 쓸 수 있도록 해야 합니다. 특히 PostgreSQL 데이터 디렉토리는 보안상 제한된 권한을 가져야 합니다.
# 프로젝트 루트 디렉토리 생성 및 이동
mkdir -p ~/n8n-worker-stack && cd ~/n8n-worker-stack
# 전체 디렉토리 구조 생성
mkdir -p data/{postgres,redis,n8n}
mkdir -p config/{redis,postgres}
mkdir -p logs/{n8n,postgres}
mkdir -p backups scripts
# 디렉토리 권한 설정 (Docker 컨테이너 접근용)
# PostgreSQL은 UID 999(postgres user)로 실행됨
sudo chown -R 999:999 data/postgres
# Redis는 UID 999(redis user)로 실행됨
sudo chown -R 999:999 data/redis
# n8n은 UID 1000(node user)로 실행됨
sudo chown -R 1000:1000 data/n8n
# 생성된 구조 확인
tree -L 2 ~/n8n-worker-stack
# tree가 없다면: ls -laR ~/n8n-worker-stack
5. 환경 변수 파일 구성
환경 변수 파일 | .env
환경 변수 파일(.env)은 비밀번호, API 키, 설정 값 등 민감한 정보를 Docker Compose 파일과 분리하여 관리하는 데 사용됩니다. 이렇게 분리하면 docker-compose.yml 파일은 버전 관리 시스템(Git)에 포함시키면서도 .env 파일은 .gitignore에 추가하여 보안을 유지할 수 있습니다. 또한 개발, 스테이징, 프로덕션 환경별로 다른 .env 파일을 사용하여 환경에 맞는 설정을 적용할 수 있습니다.
아래는 n8n Worker 모드 운영에 필요한 모든 환경 변수를 포함한 .env 파일의 예시입니다. 각 변수에는 상세한 설명을 주석으로 달아 두었으니 참고하시기 바랍니다. 특히 N8N_ENCRYPTION_KEY와 각종 비밀번호는 반드시 안전한 값으로 변경하고, 별도로 백업해 두어야 합니다. 이 파일을 분실하면 암호화된 자격 증명을 복구할 수 없습니다.
# =============================================================================
# n8n Worker Mode - Environment Variables
# =============================================================================
# 이 파일을 .env로 저장하고, 실제 값으로 변경하세요.
# 중요: 이 파일은 절대 Git에 커밋하지 마세요! (.gitignore에 추가)
# =============================================================================
# -----------------------------------------------------------------------------
# 기본 설정 (Basic Configuration)
# -----------------------------------------------------------------------------
# 타임존 설정 - 스케줄러와 로그 시간에 영향
TZ=Asia/Seoul
# n8n 인스턴스 식별자 (여러 환경 구분용)
ENVIRONMENT=production
# -----------------------------------------------------------------------------
# n8n 핵심 설정 (n8n Core Settings)
# -----------------------------------------------------------------------------
# n8n 버전 - 특정 버전 고정 권장 (latest 사용 시 예기치 않은 변경 가능)
# Latest : n8n 2.0: 2025-12-05 출시, 보안 강화 및 Save/Publish 분리
N8N_VERSION=2.0.0
# N8N_VERSION=1.94.1 # 이전 안정 버전 (1.x 마지막)
# 외부 접속 URL - 웹훅 URL 생성에 사용됨
# 실제 도메인으로 변경 필요 (예: https://n8n.yourdomain.com)
N8N_HOST=localhost
N8N_PORT=5678
N8N_PROTOCOL=http
WEBHOOK_URL=http://localhost:5678
# 에디터 기본 URL (UI 접근용)
N8N_EDITOR_BASE_URL=http://localhost:5678
# 암호화 키 - 자격 증명 암호화에 사용 (필수 백업!)
# 생성 명령: openssl rand -hex 24
N8N_ENCRYPTION_KEY=your-encryption-key-change-this-immediately
# -----------------------------------------------------------------------------
# 데이터베이스 설정 (PostgreSQL)
# -----------------------------------------------------------------------------
# PostgreSQL 버전
# Latest : PostgreSQL 18: 2025-09 출시, Vacuum 개선, 고동시성 최적화
POSTGRES_VERSION=18-alpine
# POSTGRES_VERSION=17-alpine # 이전 안정 버전
# POSTGRES_VERSION=16-alpine # LTS 버전 (2028년까지 지원)
# 데이터베이스 연결 정보
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=n8n
POSTGRES_USER=n8n
POSTGRES_PASSWORD=your-secure-postgres-password-change-this
# PostgreSQL 비연결 타임아웃 (초)
POSTGRES_IDLE_TIMEOUT=10000
# PostgreSQL 최대 연결 수
POSTGRES_MAX_CONNECTIONS=100
# n8n 데이터베이스 설정
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=your-secure-postgres-password-change-this
# -----------------------------------------------------------------------------
# Redis 설정 (Queue)
# -----------------------------------------------------------------------------
# Redis 버전
# Latest : Redis 8: 2025-11 GA 출시, I/O Threading 30%+ 성능 향상, JSON 메모리 92% 절감
REDIS_VERSION=8-alpine
# REDIS_VERSION=7-alpine # 이전 안정 버전 (7.4까지 지원)
# Redis 연결 정보
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=your-secure-redis-password-change-this
# Redis 메모리 제한 (권장: 시스템 메모리의 25% 이하)
REDIS_MAXMEMORY=256mb
# 큐 설정
QUEUE_BULL_REDIS_HOST=redis
QUEUE_BULL_REDIS_PORT=6379
QUEUE_BULL_REDIS_PASSWORD=your-secure-redis-password-change-this
QUEUE_BULL_REDIS_DB=0
# 큐 헬스체크 활성화
QUEUE_HEALTH_CHECK_ACTIVE=true
# -----------------------------------------------------------------------------
# Worker 모드 설정 (Queue Mode)
# -----------------------------------------------------------------------------
# 실행 모드: queue (Worker 모드 활성화)
EXECUTIONS_MODE=queue
# 실행 프로세스: main (메인에서), own (워커에서)
# main: 메인 인스턴스에서 웹훅 직접 처리 가능
EXECUTIONS_PROCESS=main
# 워커 동시 처리 수 (CPU 코어 수에 맞게 조정)
N8N_CONCURRENCY_PRODUCTION_LIMIT=10
# 워커당 최대 동시 실행 수
WORKER_CONCURRENCY=5
# -----------------------------------------------------------------------------
# 보안 설정 (Security)
# -----------------------------------------------------------------------------
# 기본 인증 활성화 (프로덕션에서 필수)
N8N_BASIC_AUTH_ACTIVE=true
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=your-secure-admin-password-change-this
# JWT 시크릿 (세션 관리용)
N8N_JWT_SECRET=your-jwt-secret-key-change-this
# 보안 쿠키 (HTTPS 사용 시 true로 설정)
N8N_SECURE_COOKIE=false
# -----------------------------------------------------------------------------
# Latest : n8n 2.0 보안 설정 (Secure by Default)
# -----------------------------------------------------------------------------
# !!중요: n8n 2.0에서는 보안이 기본적으로 강화되었습니다.
# 기존 1.x 워크플로우가 있다면 아래 설정을 검토하세요.
# Task Runner 활성화 - Code 노드를 격리된 환경에서 실행
# 2.0 기본값: true (권장)
# 1.x 동작으로 되돌리려면: false (보안상 비권장)
N8N_RUNNERS_ENABLED=true
# Code 노드에서 환경 변수 접근 차단
# 2.0 기본값: true (권장)
# 환경 변수 접근이 필요한 워크플로우가 있다면: false
N8N_BLOCK_ENV_ACCESS_IN_NODE=true
# 위험한 노드 활성화 (Execute Command, SSH 등)
# 2.0에서는 기본적으로 비활성화됨
# 필요한 경우에만 명시적으로 활성화 (쉼표로 구분)
# N8N_NODES_INCLUDE=n8n-nodes-base.executeCommand,n8n-nodes-base.ssh
N8N_NODES_INCLUDE=
# -----------------------------------------------------------------------------
# 실행 데이터 설정 (Execution Data)
# -----------------------------------------------------------------------------
# 실행 데이터 저장 기간 (시간 단위, 720 = 30일)
EXECUTIONS_DATA_MAX_AGE=720
# 완료된 실행 데이터 저장 여부
EXECUTIONS_DATA_SAVE_ON_SUCCESS=all
EXECUTIONS_DATA_SAVE_ON_ERROR=all
EXECUTIONS_DATA_SAVE_ON_PROGRESS=true
EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=true
# 실행 데이터 정리 활성화
EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_PRUNE_MAX_COUNT=50000
# -----------------------------------------------------------------------------
# 로깅 설정 (Logging)
# -----------------------------------------------------------------------------
# 로그 레벨: error, warn, info, verbose, debug
N8N_LOG_LEVEL=info
# 로그 출력 형식: text, json
N8N_LOG_OUTPUT=console,file
# 파일 로그 설정
N8N_LOG_FILE_LOCATION=/home/node/logs/n8n.log
N8N_LOG_FILE_SIZE_MAX=50
N8N_LOG_FILE_COUNT_MAX=10
# -----------------------------------------------------------------------------
# 성능 설정 (Performance)
# -----------------------------------------------------------------------------
# Node.js 메모리 제한 (MB)
NODE_OPTIONS=--max-old-space-size=2048
# 페이로드 크기 제한 (MB)
N8N_PAYLOAD_SIZE_MAX=64
# 워크플로우 타임아웃 (초, 0 = 무제한)
N8N_WORKFLOW_TIMEOUT=3600
# -----------------------------------------------------------------------------
# 기타 설정 (Miscellaneous)
# -----------------------------------------------------------------------------
# 템플릿 활성화
N8N_TEMPLATES_ENABLED=true
# 버전 알림
N8N_VERSION_NOTIFICATIONS_ENABLED=true
# 진단 데이터 수집 (익명)
N8N_DIAGNOSTICS_ENABLED=false
# 커뮤니티 노드 설치 허용
N8N_COMMUNITY_PACKAGES_ENABLED=true
# 외부 npm 패키지 허용 (Code 노드용)
NODE_FUNCTION_ALLOW_EXTERNAL=*
샘플 환경변수 파일 생성 | .env.example
.env.example 파일도 함께 생성하여 팀원들이 필요한 환경 변수를 확인할 수 있도록 합니다. 이 파일에는 실제 값 대신 예시 값이나 설명을 넣어두고, Git 저장소에 포함시킵니다. 새로운 팀원이 프로젝트에 참여할 때 이 파일을 복사하여 .env로 만들고 실제 값을 채워 넣으면 됩니다. 아래 명령어로 현재 .env 파일에서 값을 제거한 예시 파일을 생성할 수 있습니다.
# .env 파일에서 값을 제거하고 .env.example 생성
sed 's/=.*/=/' .env > .env.example
# .gitignore 파일 생성
cat > .gitignore << 'EOF'
# 환경 변수 파일 (민감한 정보 포함)
.env
.env.local
.env.*.local
# 데이터 디렉토리
data/
# 로그 파일
logs/
*.log
# 백업 파일
backups/
# OS 생성 파일
.DS_Store
Thumbs.db
# IDE 설정
.idea/
.vscode/
*.swp
*.swo
EOF
6. Docker Compose 파일 작성
docker-compose.yml
이제 핵심이 되는 docker-compose.yml 파일을 작성합니다. 이 파일은 PostgreSQL, Redis, n8n Main, n8n Worker 네 가지 서비스를 정의하고 있으며, 각 서비스 간의 의존성과 네트워크 연결을 설정합니다. 모든 서비스는 n8n-network라는 내부 네트워크를 통해 통신하며, 외부에서는 n8n Main의 5678 포트만 접근 가능합니다. 보안을 위해 PostgreSQL과 Redis 포트는 외부에 노출하지 않는 것이 Best Practice입니다.
# =============================================================================
# n8n Worker Mode - Docker Compose Configuration
# =============================================================================
# 파일명: docker-compose.yml
# 설명: n8n을 Worker 모드로 운영하기 위한 통합 Docker Compose 설정
# 구성: PostgreSQL + Redis + n8n Main + n8n Worker
# =============================================================================
services:
# ===========================================================================
# PostgreSQL Database
# ===========================================================================
# 역할: 워크플로우 정의, 실행 이력, 자격 증명 등 모든 영구 데이터 저장
# 중요: 정기적인 백업 필수, POSTGRES_PASSWORD 변경 필수
# Latest : PostgreSQL 18: Vacuum 메모리 관리 개선, 고동시성 워크로드 최적화
# ===========================================================================
postgres:
# Latest : 최신 버전 (2025-12 기준)
image: postgres:${POSTGRES_VERSION:-18-alpine}
# image: postgres:${POSTGRES_VERSION:-17-alpine} # 이전 안정 버전
# image: postgres:${POSTGRES_VERSION:-16-alpine} # LTS 버전 (2028년까지 지원)
container_name: n8n-postgres
restart: unless-stopped
# 환경 변수
environment:
POSTGRES_USER: ${POSTGRES_USER:-n8n}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
POSTGRES_DB: ${POSTGRES_DB:-n8n}
# PostgreSQL 성능 튜닝
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C"
# 타임존 설정
TZ: ${TZ:-Asia/Seoul}
# 볼륨 마운트
volumes:
# 데이터 영구 저장
- ./data/postgres:/var/lib/postgresql/data
# 초기화 스크립트 (최초 실행 시에만 적용)
- ./config/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
# 네트워크 설정
networks:
- n8n-network
# 헬스체크 - PostgreSQL이 준비되었는지 확인
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-n8n} -d ${POSTGRES_DB:-n8n}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
# 리소스 제한 (필요에 따라 조정)
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
# 로깅 설정
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
# ===========================================================================
# Redis Queue
# ===========================================================================
# 역할: 메인과 워커 간의 작업 큐(Job Queue) 관리
# 중요: 메모리 기반이므로 persistence 설정으로 데이터 보존
# Latest : Redis 8: I/O Threading으로 30%+ 처리량 향상, JSON 메모리 92% 절감
# ===========================================================================
redis:
# Latest : 최신 버전 (2025-12 기준)
image: redis:${REDIS_VERSION:-8-alpine}
# image: redis:${REDIS_VERSION:-7-alpine} # 이전 안정 버전
container_name: n8n-redis
restart: unless-stopped
# Redis 서버 시작 명령
# --requirepass: 비밀번호 인증 활성화
# --appendonly yes: AOF(Append Only File) 영구 저장 활성화
# --maxmemory: 최대 메모리 사용량 제한
# --maxmemory-policy: 메모리 초과 시 정책 (noeviction: 새 쓰기 거부)
# Latest : Redis 8: --io-threads 옵션으로 I/O 멀티스레딩 활성화 가능
command: >
redis-server
--requirepass ${REDIS_PASSWORD:?REDIS_PASSWORD is required}
--appendonly yes
--appendfsync everysec
--maxmemory ${REDIS_MAXMEMORY:-256mb}
--maxmemory-policy noeviction
--tcp-keepalive 300
--timeout 0
--io-threads 4
--io-threads-do-reads yes
# Redis 7 이하 버전 사용 시 아래 command로 교체 (io-threads 미지원)
# command: >
# redis-server
# --requirepass ${REDIS_PASSWORD:?REDIS_PASSWORD is required}
# --appendonly yes
# --appendfsync everysec
# --maxmemory ${REDIS_MAXMEMORY:-256mb}
# --maxmemory-policy noeviction
# --tcp-keepalive 300
# --timeout 0
# 환경 변수
environment:
TZ: ${TZ:-Asia/Seoul}
# 볼륨 마운트
volumes:
# Redis 데이터 영구 저장 (AOF, RDB)
- ./data/redis:/data
# 네트워크 설정
networks:
- n8n-network
# 헬스체크 - Redis 연결 확인
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
# 리소스 제한
deploy:
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
# 로깅 설정
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
# ===========================================================================
# n8n Main Instance
# ===========================================================================
# 역할: 웹훅 수신, 웹 UI 제공, 워크플로우 관리, 스케줄러
# 중요: 외부 접근이 필요한 유일한 서비스
# Latest : n8n 2.0: Secure by Default, Task Runner 기본 활성화, Save/Publish 분리
# ===========================================================================
n8n-main:
# Latest :최신 버전 (2025-12 기준)
image: n8nio/n8n:${N8N_VERSION:-2.0.0}
# image: n8nio/n8n:${N8N_VERSION:-1.94.1} # 이전 안정 버전 (1.x 마지막)
container_name: n8n-main
restart: unless-stopped
# PostgreSQL, Redis가 준비된 후 시작
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
# 포트 매핑 - 외부에서 접근 가능
ports:
- "${N8N_PORT:-5678}:5678"
# 환경 변수
environment:
# 기본 설정
TZ: ${TZ:-Asia/Seoul}
GENERIC_TIMEZONE: ${TZ:-Asia/Seoul}
# n8n 호스트 설정
N8N_HOST: ${N8N_HOST:-localhost}
N8N_PORT: 5678
N8N_PROTOCOL: ${N8N_PROTOCOL:-http}
WEBHOOK_URL: ${WEBHOOK_URL:-http://localhost:5678}
N8N_EDITOR_BASE_URL: ${N8N_EDITOR_BASE_URL:-http://localhost:5678}
# 암호화 키 (필수)
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY:?N8N_ENCRYPTION_KEY is required}
# 데이터베이스 설정
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB:-n8n}
DB_POSTGRESDB_USER: ${POSTGRES_USER:-n8n}
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
# Queue Mode 설정 (Worker 모드 활성화)
EXECUTIONS_MODE: queue
EXECUTIONS_PROCESS: main
# Redis 큐 설정
QUEUE_BULL_REDIS_HOST: redis
QUEUE_BULL_REDIS_PORT: 6379
QUEUE_BULL_REDIS_PASSWORD: ${REDIS_PASSWORD}
QUEUE_BULL_REDIS_DB: 0
QUEUE_HEALTH_CHECK_ACTIVE: "true"
# ===========================================
# Latest : n8n 2.0 신규 보안 설정 (Secure by Default)
# ===========================================
# Task Runner: Code 노드를 격리된 환경에서 실행 (2.0 기본값: true)
N8N_RUNNERS_ENABLED: ${N8N_RUNNERS_ENABLED:-true}
# N8N_RUNNERS_ENABLED: "false" # 1.x 동작 방식으로 되돌리기 (비권장)
# Code 노드에서 환경 변수 접근 차단 (2.0 기본값: true)
N8N_BLOCK_ENV_ACCESS_IN_NODE: ${N8N_BLOCK_ENV_ACCESS_IN_NODE:-true}
# N8N_BLOCK_ENV_ACCESS_IN_NODE: "false" # 환경 변수 접근 허용 (보안 주의)
# Execute Command 노드 비활성화 (2.0 기본값: false)
N8N_NODES_INCLUDE: ${N8N_NODES_INCLUDE:-}
# 위험한 노드 명시적 활성화 필요 시:
# N8N_NODES_INCLUDE: "n8n-nodes-base.executeCommand,n8n-nodes-base.ssh"
# ===========================================
# 인증 설정
# ===========================================
N8N_BASIC_AUTH_ACTIVE: ${N8N_BASIC_AUTH_ACTIVE:-true}
N8N_BASIC_AUTH_USER: ${N8N_BASIC_AUTH_USER:-admin}
N8N_BASIC_AUTH_PASSWORD: ${N8N_BASIC_AUTH_PASSWORD:-changeme}
# 실행 데이터 설정
EXECUTIONS_DATA_MAX_AGE: ${EXECUTIONS_DATA_MAX_AGE:-720}
EXECUTIONS_DATA_SAVE_ON_SUCCESS: ${EXECUTIONS_DATA_SAVE_ON_SUCCESS:-all}
EXECUTIONS_DATA_SAVE_ON_ERROR: ${EXECUTIONS_DATA_SAVE_ON_ERROR:-all}
EXECUTIONS_DATA_SAVE_ON_PROGRESS: ${EXECUTIONS_DATA_SAVE_ON_PROGRESS:-true}
EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS: ${EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS:-true}
EXECUTIONS_DATA_PRUNE: ${EXECUTIONS_DATA_PRUNE:-true}
EXECUTIONS_DATA_PRUNE_MAX_COUNT: ${EXECUTIONS_DATA_PRUNE_MAX_COUNT:-50000}
# 로깅 설정
N8N_LOG_LEVEL: ${N8N_LOG_LEVEL:-info}
N8N_LOG_OUTPUT: ${N8N_LOG_OUTPUT:-console}
# 성능 설정
NODE_OPTIONS: ${NODE_OPTIONS:---max-old-space-size=2048}
N8N_PAYLOAD_SIZE_MAX: ${N8N_PAYLOAD_SIZE_MAX:-64}
# 기타 설정
N8N_TEMPLATES_ENABLED: ${N8N_TEMPLATES_ENABLED:-true}
N8N_VERSION_NOTIFICATIONS_ENABLED: ${N8N_VERSION_NOTIFICATIONS_ENABLED:-true}
N8N_DIAGNOSTICS_ENABLED: ${N8N_DIAGNOSTICS_ENABLED:-false}
N8N_COMMUNITY_PACKAGES_ENABLED: ${N8N_COMMUNITY_PACKAGES_ENABLED:-true}
NODE_FUNCTION_ALLOW_EXTERNAL: ${NODE_FUNCTION_ALLOW_EXTERNAL:-*}
# 볼륨 마운트
volumes:
# n8n 로컬 파일 저장 (업로드된 파일 등)
- ./data/n8n:/home/node/.n8n
# 로그 파일 저장 (선택적)
- ./logs/n8n:/home/node/logs
# 네트워크 설정
networks:
- n8n-network
# 헬스체크 - n8n API 응답 확인
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:5678/healthz || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# 리소스 제한
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
# 로깅 설정
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
# ===========================================================================
# n8n Worker Instance
# ===========================================================================
# 역할: 워크플로우 실제 실행 담당
# 중요: 필요에 따라 여러 인스턴스로 스케일 아웃 가능
# Latest : n8n 2.0: Task Runner 기본 활성화로 Code 노드 격리 실행
# ===========================================================================
n8n-worker:
# Latest : 최신 버전 (2025-12 기준)
image: n8nio/n8n:${N8N_VERSION:-2.0.0}
# image: n8nio/n8n:${N8N_VERSION:-1.94.1} # 이전 안정 버전 (1.x 마지막)
container_name: n8n-worker
restart: unless-stopped
# Worker 모드로 실행
command: worker
# PostgreSQL, Redis, Main이 준비된 후 시작
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
n8n-main:
condition: service_healthy
# 환경 변수 (Main과 대부분 동일해야 함)
environment:
# 기본 설정
TZ: ${TZ:-Asia/Seoul}
GENERIC_TIMEZONE: ${TZ:-Asia/Seoul}
# 암호화 키 (Main과 동일해야 함 - 필수!)
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
# 데이터베이스 설정 (Main과 동일)
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB:-n8n}
DB_POSTGRESDB_USER: ${POSTGRES_USER:-n8n}
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
# Queue Mode 설정
EXECUTIONS_MODE: queue
# Redis 큐 설정 (Main과 동일)
QUEUE_BULL_REDIS_HOST: redis
QUEUE_BULL_REDIS_PORT: 6379
QUEUE_BULL_REDIS_PASSWORD: ${REDIS_PASSWORD}
QUEUE_BULL_REDIS_DB: 0
QUEUE_HEALTH_CHECK_ACTIVE: "true"
# ===========================================
# Latest : n8n 2.0 신규 보안 설정 (Main과 동일하게 설정)
# ===========================================
N8N_RUNNERS_ENABLED: ${N8N_RUNNERS_ENABLED:-true}
N8N_BLOCK_ENV_ACCESS_IN_NODE: ${N8N_BLOCK_ENV_ACCESS_IN_NODE:-true}
N8N_NODES_INCLUDE: ${N8N_NODES_INCLUDE:-}
# Worker 동시성 설정
N8N_CONCURRENCY_PRODUCTION_LIMIT: ${N8N_CONCURRENCY_PRODUCTION_LIMIT:-10}
# 로깅 설정
N8N_LOG_LEVEL: ${N8N_LOG_LEVEL:-info}
N8N_LOG_OUTPUT: ${N8N_LOG_OUTPUT:-console}
# 성능 설정
NODE_OPTIONS: ${NODE_OPTIONS:---max-old-space-size=2048}
N8N_PAYLOAD_SIZE_MAX: ${N8N_PAYLOAD_SIZE_MAX:-64}
# 기타 설정
NODE_FUNCTION_ALLOW_EXTERNAL: ${NODE_FUNCTION_ALLOW_EXTERNAL:-*}
# 볼륨 마운트 (Main과 동일한 n8n 데이터 공유)
volumes:
- ./data/n8n:/home/node/.n8n
- ./logs/n8n:/home/node/logs
# 네트워크 설정
networks:
- n8n-network
# 리소스 제한
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
# 워커 복제본 수 (스케일 아웃 시 조정)
replicas: 1
# 로깅 설정
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
# =============================================================================
# Networks
# =============================================================================
networks:
n8n-network:
driver: bridge
name: n8n-network
ipam:
config:
- subnet: 172.28.0.0/16
# =============================================================================
# Volumes (명시적 선언 - 선택적)
# =============================================================================
# 바인드 마운트를 사용하므로 별도의 볼륨 선언은 필요하지 않음
# Docker 볼륨을 사용하려면 아래 주석을 해제하고 서비스의 volumes 섹션도 수정
# =============================================================================
# volumes:
# postgres-data:
# redis-data:
# n8n-data:
PostgreSQL 초기화 스크립트도 함께 생성합니다. 이 스크립트는 PostgreSQL 컨테이너가 최초로 시작될 때 한 번만 실행되며, 필요한 확장 기능을 설치하고 데이터베이스 설정을 최적화합니다. 이미 데이터가 있는 상태에서는 실행되지 않으므로 안심하고 사용할 수 있습니다. n8n이 사용하는 UUID 확장 기능을 미리 설치해 두면 워크플로우 실행 시 성능이 향상됩니다.
-- =============================================================================
-- PostgreSQL 초기화 스크립트
-- =============================================================================
-- 파일명: config/postgres/init.sql
-- 설명: n8n 데이터베이스 초기화 및 최적화 설정
-- 실행 시점: PostgreSQL 컨테이너 최초 시작 시 (data 디렉토리가 비어있을 때만)
-- =============================================================================
-- UUID 확장 기능 설치 (n8n에서 사용)
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- pg_trgm 확장 (텍스트 검색 성능 향상)
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
-- 연결 타임아웃 설정
ALTER SYSTEM SET idle_in_transaction_session_timeout = '10min';
-- 로그 설정
ALTER SYSTEM SET log_statement = 'ddl';
ALTER SYSTEM SET log_min_duration_statement = 1000;
-- 메모리 설정 (컨테이너 환경에 최적화)
-- 주의: 실제 가용 메모리에 맞게 조정 필요
ALTER SYSTEM SET shared_buffers = '256MB';
ALTER SYSTEM SET effective_cache_size = '768MB';
ALTER SYSTEM SET maintenance_work_mem = '64MB';
ALTER SYSTEM SET work_mem = '16MB';
-- 연결 설정
ALTER SYSTEM SET max_connections = 100;
-- 설정 적용 알림 (실제 적용은 재시작 필요)
SELECT pg_reload_conf();
-- 완료 메시지
DO $$
BEGIN
RAISE NOTICE '======================================';
RAISE NOTICE 'n8n PostgreSQL 초기화 완료';
RAISE NOTICE '======================================';
END $$;
7. 서비스별 상세 설명
PostgreSQL 서비스
PostgreSQL은 n8n의 모든 영구 데이터를 저장하는 핵심 데이터베이스입니다.
Worker 모드에서는 메인 인스턴스와 워커 인스턴스가 동시에 데이터베이스에 접근해야 하므로 SQLite 대신 PostgreSQL을 사용해야 합니다. Alpine 기반 이미지를 사용하면 이미지 크기가 작아 다운로드와 시작 시간이 빨라집니다. 버전은 안정성이 검증된 16 버전을 권장하며, 특별한 이유가 없다면 latest 태그 사용은 피하는 것이 좋습니다. 저는 최신 버전 사용하는 것을 좋아하는 성격이라서 18 버전으로 설정할 예정입니다.
PostgreSQL 설정에서 주목할 점은 헬스체크 설정입니다.
pg_isready 명령어를 사용하여 데이터베이스가 실제로 연결을 받을 준비가 되었는지 확인합니다. 이 헬스체크가 통과해야만 n8n 서비스들이 시작되므로, 시작 순서 문제로 인한 연결 오류를 방지할 수 있습니다. $start_period는 컨테이너가 처음 시작될 때 초기화에 필요한 시간을 고려한 대기 시간입니다.
# PostgreSQL 헬스체크 상세 설명
healthcheck:
# 실행할 명령어: PostgreSQL 연결 준비 상태 확인
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-n8n} -d ${POSTGRES_DB:-n8n}"]
# 헬스체크 실행 간격 (10초마다 확인)
interval: 10s
# 명령어 타임아웃 (5초 내에 응답해야 함)
timeout: 5s
# 연속 실패 허용 횟수 (5번 실패하면 unhealthy)
retries: 5
# 초기 대기 시간 (컨테이너 시작 후 30초 후부터 체크 시작)
start_period: 30s
Redis 서비스
Redis는 메인 인스턴스와 워커 인스턴스 사이의 작업 큐 역할을 수행합니다.
메인에서 워크플로우 실행 요청이 들어오면 Redis 큐에 작업을 등록하고, 워커는 이 큐를 모니터링하다가 작업을 가져가 실행합니다. n8n은 내부적으로 Bull 라이브러리를 사용하여 Redis 기반 큐를 관리합니다. Bull은 작업 재시도, 지연 실행, 우선순위 처리 등 다양한 기능을 제공하는 검증된 큐 라이브러리입니다.
Redis의 영구 저장(Persistence) 설정은 시스템 안정성에 매우 중요합니다.
--appendonly yes 옵션은 AOF(Append Only File) 방식으로 모든 쓰기 명령을 파일에 기록하여 데이터 손실을 최소화합니다. --appendfsync everysec 설정은 1초마다 디스크에 동기화하여 성능과 안정성의 균형을 맞춥니다. 메모리 정책으로 $noeviction을 사용하면 메모리가 가득 찼을 때 기존 데이터를 삭제하지 않고 새로운 쓰기를 거부하므로, 큐 데이터가 예기치 않게 사라지는 것을 방지할 수 있습니다.
# Redis 시작 명령어 상세 설명
command: >
redis-server
--requirepass ${REDIS_PASSWORD} # 비밀번호 인증 필수
--appendonly yes # AOF 영구 저장 활성화
--appendfsync everysec # 1초마다 디스크 동기화
--maxmemory 256mb # 최대 메모리 사용량
--maxmemory-policy noeviction # 메모리 초과 시 쓰기 거부
--tcp-keepalive 300 # TCP 연결 유지 (5분)
--timeout 0 # 클라이언트 타임아웃 없음
n8n Main 서비스
n8n Main은 시스템의 진입점으로서 웹훅 수신, 웹 UI 제공, 워크플로우 편집 및 관리, 스케줄러(Cron 트리거) 실행을 담당합니다.
외부에서 접근해야 하므로 포트 매핑이 설정되어 있으며, 이 포트를 통해 사용자는 웹 브라우저로 n8n UI에 접속할 수 있습니다. 프로덕션 환경에서는 이 포트 앞에 Nginx 같은 리버스 프록시를 두어 SSL/TLS 암호화를 적용하는 것이 권장됩니다.
EXECUTIONS_MODE=queue 설정이 Worker 모드를 활성화하는 핵심 옵션입니다.
이 설정이 없으면 n8n은 기본 모드(regular)로 실행되어 모든 워크플로우를 메인 프로세스에서 직접 처리합니다. EXECUTIONS_PROCESS=main 설정은 웹훅으로 트리거된 워크플로우의 첫 번째 노드를 메인에서 실행할지 워커에서 실행할지를 결정합니다. main으로 설정하면 웹훅 응답 속도가 빨라지지만 메인의 부하가 증가하고, own으로 설정하면 모든 처리를 워커에게 위임합니다.
# Worker 모드 핵심 환경 변수
environment:
# 실행 모드: queue = Worker 모드 활성화
EXECUTIONS_MODE: queue
# 실행 프로세스 위치
# main: 웹훅의 첫 노드는 메인에서 실행 (빠른 응답)
# own: 모든 실행을 워커에게 위임 (메인 부하 감소)
EXECUTIONS_PROCESS: main
# 큐 헬스체크 활성화 (워커 상태 모니터링)
QUEUE_HEALTH_CHECK_ACTIVE: "true"
n8n Worker 서비스
n8n Worker는 실제 워크플로우 로직을 실행하는 역할을 전담합니다. command: worker 옵션으로 n8n을 워커 모드로 시작하며, 이 모드에서는 웹 UI를 제공하지 않고 큐에서 작업을 가져와 실행하는 것에만 집중합니다. 워커는 메인과 동일한 데이터베이스와 암호화 키를 사용해야 하므로 환경 변수 설정에 주의가 필요합니다. 특히 N8N_ENCRYPTION_KEY가 메인과 다르면 자격 증명을 복호화할 수 없어 워크플로우 실행이 실패합니다.
N8N_CONCURRENCY_PRODUCTION_LIMIT 환경 변수는 워커가 동시에 처리할 수 있는 최대 워크플로우 수를 설정합니다. 이 값은 서버의 CPU 코어 수와 메모리를 고려하여 설정해야 합니다. 너무 높게 설정하면 리소스 부족으로 전체 시스템이 느려질 수 있고, 너무 낮게 설정하면 큐에 작업이 쌓여 처리 지연이 발생합니다. 일반적으로 CPU 코어 수의 2~3배 정도로 시작하여 모니터링하면서 조정하는 것이 좋습니다.
# Worker 전용 환경 변수
environment:
# 동시 실행 제한 (CPU 코어 수 × 2~3 권장)
N8N_CONCURRENCY_PRODUCTION_LIMIT: 10
# 암호화 키 (Main과 반드시 동일해야 함!)
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
# 데이터베이스 설정 (Main과 동일)
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
# ... (나머지 DB 설정도 Main과 동일)
8. 실행 및 검증
서비스 시작
모든 설정 파일이 준비되었으면 Docker Compose를 사용하여 서비스를 시작합니다. -d 옵션은 백그라운드(detached) 모드로 실행하여 터미널을 계속 사용할 수 있게 합니다. 처음 시작할 때는 이미지 다운로드와 컨테이너 초기화에 시간이 걸릴 수 있으며, PostgreSQL과 Redis가 준비된 후에 n8n 서비스들이 순차적으로 시작됩니다. --build 옵션은 커스텀 이미지를 빌드할 때 사용하지만, 공식 이미지를 사용하는 경우에는 필요하지 않습니다.
# 프로젝트 디렉토리로 이동
cd ~/n8n-worker-stack
# 환경 변수 파일 확인
cat .env | grep -v "^#" | grep -v "^$"
# 서비스 시작 (백그라운드 모드)
docker compose up -d
# 또는 로그를 실시간으로 보면서 시작 (디버깅용)
docker compose up
# 특정 서비스만 시작
docker compose up -d postgres redis
# 모든 서비스 재시작
docker compose restart
# 특정 서비스만 재시작
docker compose restart n8n-main n8n-worker
상태 확인
서비스가 정상적으로 실행되고 있는지 확인하는 방법은 여러 가지가 있습니다. docker compose ps 명령어는 각 서비스의 상태, 포트 매핑, 헬스체크 결과를 한눈에 보여줍니다. 모든 서비스가 running 상태이고 헬스체크가 healthy로 표시되어야 정상입니다. 만약 unhealthy나 starting 상태가 지속된다면 로그를 확인하여 문제를 파악해야 합니다.
# 전체 서비스 상태 확인
docker compose ps
# 예상 출력:
# NAME IMAGE STATUS PORTS
# n8n-main n8nio/n8n:1.94.1 Up 2 minutes (healthy) 0.0.0.0:5678->5678/tcp
# n8n-postgres postgres:16-alpine Up 3 minutes (healthy) 5432/tcp
# n8n-redis redis:7-alpine Up 3 minutes (healthy) 6379/tcp
# n8n-worker n8nio/n8n:1.94.1 Up 2 minutes
# 실시간 로그 확인 (모든 서비스)
docker compose logs -f
# 특정 서비스 로그만 확인
docker compose logs -f n8n-main
docker compose logs -f n8n-worker
# 최근 100줄 로그 확인
docker compose logs --tail 100 n8n-main
# 리소스 사용량 확인
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"
연결 테스트
각 서비스가 올바르게 연결되어 있는지 확인하기 위해 개별 연결 테스트를 수행합니다. PostgreSQL과 Redis에 직접 연결하여 응답을 확인하고, n8n API 엔드포인트를 호출하여 시스템이 정상 작동하는지 검증합니다. 이러한 테스트는 문제가 발생했을 때 어느 컴포넌트에서 문제가 생겼는지 빠르게 파악하는 데 도움이 됩니다.
# PostgreSQL 연결 테스트
docker compose exec postgres psql -U n8n -d n8n -c "SELECT version();"
# 예상 출력: PostgreSQL 16.x ...
# Redis 연결 테스트
docker compose exec redis redis-cli -a "${REDIS_PASSWORD}" ping
# 예상 출력: PONG
# Redis 큐 상태 확인
docker compose exec redis redis-cli -a "${REDIS_PASSWORD}" keys "bull:*"
# 예상 출력: bull:jobs:* 형태의 키들
# n8n 헬스체크 API 호출
curl -s http://localhost:5678/healthz
# 예상 출력: {"status":"ok"}
# n8n 버전 확인
curl -s http://localhost:5678/api/v1/versions | jq
# 예상 출력: 현재 및 최신 버전 정보
# Worker 상태 확인 (n8n Main 로그에서)
docker compose logs n8n-main | grep -i "worker"
# 예상 출력: Worker connected 메시지
웹 UI 접속
모든 테스트가 통과하면 웹 브라우저에서 n8n UI에 접속할 수 있습니다. 기본 설정에서는 http://localhost:5678로 접속하며, 처음 접속 시 계정 생성 화면이 나타납니다. 외부에서 접속하려면 .env 파일의 N8N_HOST와 WEBHOOK_URL을 실제 도메인이나 IP 주소로 변경해야 합니다. 보안을 위해 프로덕션 환경에서는 반드시 HTTPS를 사용하고, 강력한 비밀번호를 설정해야 합니다.
n8n 웹 UI 접속 정보
1. 접속 URL: http://localhost:5678
2. 최초 접속 시:
- 이메일과 비밀번호로 Owner 계정 생성
- 이 계정이 관리자 권한을 가짐
- 추가 사용자는 Settings > Users에서 초대
3. Basic Auth 설정 시 (.env):
- 사용자명: N8N_BASIC_AUTH_USER
- 비밀번호: N8N_BASIC_AUTH_PASSWORD
4. Worker 연결 확인:
- Settings > Execution > Queue Mode가 활성화되어 있어야 함
9. 스케일링 전략
Worker 수평 확장
Worker 모드의 가장 큰 장점은 워크플로우 처리량이 증가할 때 워커 인스턴스를 추가하여 대응할 수 있다는 점입니다. Docker Compose --scale 옵션을 사용하면 간단하게 워커 수를 늘릴 수 있습니다. 각 워커는 독립적으로 Redis 큐에서 작업을 가져와 실행하므로, 워커 수를 늘리면 동시에 처리할 수 있는 워크플로우 수가 비례하여 증가합니다.
# Worker를 3개로 확장
docker compose up -d --scale n8n-worker=3
# 확장된 Worker 상태 확인
docker compose ps
# 예상 출력:
# NAME STATUS
# n8n-worker-1 Up (healthy)
# n8n-worker-2 Up (healthy)
# n8n-worker-3 Up (healthy)
# 특정 Worker 로그 확인
docker compose logs -f n8n-worker-1
# Worker 수 줄이기
docker compose up -d --scale n8n-worker=1
스케일링할 때 주의해야 할 점이 있습니다.
- 서버 리소스를 확인해야 합니다. 각 워커는 환경 변수에 설정된 메모리(기본 2GB)를 사용하므로, 워커 3개를 실행하려면 최소 6GB 이상의 여유 메모리가 필요합니다.
- Redis 연결 수도 고려해야 합니다. 각 워커는 Redis에 여러 연결을 유지하므로, 워커 수가 많아지면 Redis의 maxclients 설정을 조정해야 할 수 있습니다.
- PostgreSQL 연결 풀도 확인해야 합니다. 기본 설정으로는 100개의 연결을 허용하지만, 워커 수가 많아지면 이 제한에 도달할 수 있습니다.
운영 환경별 설정
개발, 스테이징, 프로덕션 환경에 따라 다른 설정을 적용할 수 있습니다. Docker Compose의 extends 기능이나 여러 Compose 파일을 조합하는 방식을 사용하면 환경별 설정을 효율적으로 관리할 수 있습니다. 아래는 프로덕션 환경에서 추가로 적용할 수 있는 오버라이드 설정의 예시입니다.
# docker-compose.prod.yml
# 사용법: docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
services:
n8n-main:
environment:
# 프로덕션 URL 설정
N8N_HOST: n8n.yourdomain.com
N8N_PROTOCOL: https
WEBHOOK_URL: https://n8n.yourdomain.com
N8N_EDITOR_BASE_URL: https://n8n.yourdomain.com
# 보안 쿠키 활성화 (HTTPS 필수)
N8N_SECURE_COOKIE: "true"
# 로그 레벨 조정
N8N_LOG_LEVEL: warn
# 리소스 제한 강화
deploy:
resources:
limits:
cpus: '4'
memory: 4G
n8n-worker:
deploy:
replicas: 3 # 프로덕션에서 워커 3개 운영
resources:
limits:
cpus: '2'
memory: 2G
postgres:
deploy:
resources:
limits:
cpus: '4'
memory: 4G
10. 외부 공유 자원 활용 아키텍처
실제 운영 환경에서는 PostgreSQL이나 Redis를 n8n 전용으로 구성하지 않고, 이미 운영 중인 데이터베이스 서버나 클라우드 관리형 서비스를 활용하는 경우가 많습니다. 이러한 구성은 리소스 효율성을 높이고 중앙 집중식 관리를 가능하게 하며, 특히 여러 애플리케이션이 공존하는 환경에서 효과적입니다. 이 섹션에서는 외부 PostgreSQL과 Redis를 활용하는 다양한 아키텍처 패턴과 그에 맞는 Docker Compose 설정을 살펴봅니다.
공유 자원 아키텍처 유형
외부 데이터베이스와 캐시 서버를 활용하는 방식은 크게 세 가지 유형으로 나눌 수 있습니다.
- 첫 번째는 동일 호스트 내 별도 컨테이너 방식으로, 같은 서버에서 Docker Compose로 관리되지만 별도의 스택으로 운영되는 경우입니다.
- 두 번째는 네트워크 내 별도 서버 방식으로, NAS나 전용 데이터베이스 서버처럼 동일 네트워크 내의 다른 물리적/가상 서버에서 운영되는 경우입니다.
- 세 번째는 클라우드 관리형 서비스 방식으로, AWS RDS, ElastiCache, Azure Database 같은 완전 관리형 서비스를 사용하는 경우입니다.

각 유형은 운영 환경과 요구사항에 따라 선택해야 합니다. 소규모 팀이나 개인 프로젝트에서는 유형 1이 간단하고 효율적입니다. Synology NAS처럼 이미 데이터베이스가 운영되고 있는 환경에서는 유형 2가 리소스를 효과적으로 활용할 수 있습니다. 엔터프라이즈 환경이나 고가용성이 중요한 서비스에서는 유형 3의 클라우드 관리형 서비스가 운영 부담을 크게 줄여줍니다.
외부 PostgreSQL 활용 시 고려사항
외부 PostgreSQL 서버를 사용할 때는 몇 가지 중요한 설정과 고려사항이 있습니다. 먼저 네트워크 접근 설정이 필요합니다. PostgreSQL의 pg_hba.conf 파일에서 n8n 서버의 IP 주소를 허용해야 하며, 방화벽에서도 5432 포트(또는 사용 중인 포트)가 열려 있어야 합니다. 또한 전용 데이터베이스와 사용자를 생성하여 다른 애플리케이션의 데이터와 분리하는 것이 보안상 권장됩니다.
-- =============================================================================
-- 외부 PostgreSQL 서버에서 n8n용 데이터베이스 및 사용자 생성
-- =============================================================================
-- 실행 위치: 외부 PostgreSQL 서버 (psql 또는 pgAdmin)
-- 권한: superuser 또는 CREATE DATABASE, CREATE USER 권한 필요
-- =============================================================================
-- 1. n8n 전용 사용자 생성
CREATE USER n8n_user WITH
LOGIN
PASSWORD 'your-secure-password-here'
NOSUPERUSER
NOCREATEDB
NOCREATEROLE;
-- 2. n8n 전용 데이터베이스 생성
CREATE DATABASE n8n_production
WITH
OWNER = n8n_user
ENCODING = 'UTF8'
LC_COLLATE = 'C'
LC_CTYPE = 'C'
TEMPLATE = template0;
-- 3. 데이터베이스 연결 후 확장 기능 설치
\c n8n_production
-- UUID 확장 (n8n에서 사용)
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- 텍스트 검색 성능 향상
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
-- 4. 스키마 권한 부여
GRANT ALL PRIVILEGES ON DATABASE n8n_production TO n8n_user;
GRANT ALL PRIVILEGES ON SCHEMA public TO n8n_user;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO n8n_user;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO n8n_user;
-- 향후 생성될 객체에 대한 기본 권한 설정
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT ALL PRIVILEGES ON TABLES TO n8n_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT ALL PRIVILEGES ON SEQUENCES TO n8n_user;
-- 5. 연결 테스트용 쿼리
SELECT version();
SELECT current_database(), current_user;
Synology NAS의 PostgreSQL을 사용하는 경우, Container Manager나 Docker를 통해 PostgreSQL을 설치했다면 해당 컨테이너의 네트워크 설정을 확인해야 합니다. DSM의 패키지 센터에서 설치한 MariaDB 대신 PostgreSQL을 사용하려면 Docker 기반으로 별도 설치가 필요합니다. NAS의 내부 IP 주소(예: 192.168.1.100)와 포트를 확인하고, 방화벽 설정에서 해당 포트가 열려 있는지 확인하세요.
# Synology NAS에서 PostgreSQL 컨테이너 IP 확인
# SSH로 NAS 접속 후 실행
docker inspect synology-postgres | grep IPAddress
# 또는 host 네트워크 모드 사용 시 NAS IP 사용
# NAS 제어판 > 네트워크 > 네트워크 인터페이스에서 IP 확인
# 외부에서 PostgreSQL 연결 테스트
psql -h 192.168.1.100 -p 5432 -U n8n_user -d n8n_production
# 연결 문제 시 포트 열림 확인
nc -zv 192.168.1.100 5432
외부 Redis 활용 시 고려사항
Redis를 외부 서버에서 운영할 때는 보안 설정이 특히 중요합니다. Redis는 기본적으로 인증 없이 모든 명령을 실행할 수 있으므로, 반드시 비밀번호를 설정하고 불필요한 명령을 비활성화해야 합니다. 또한 Redis는 인메모리 데이터베이스이므로 서버 재시작 시 데이터 손실을 방지하기 위한 영구 저장(Persistence) 설정도 필수입니다.
# =============================================================================
# 외부 Redis 서버 권장 설정 (redis.conf)
# =============================================================================
# 바인딩 주소 - 특정 IP만 허용 (0.0.0.0은 모든 IP 허용, 보안상 비권장)
bind 192.168.1.100 127.0.0.1
# 포트 설정
port 6379
# 비밀번호 설정 (필수!)
requirepass your-secure-redis-password
# 보호 모드 (외부 접근 시 비밀번호 필수)
protected-mode yes
# 최대 메모리 설정
maxmemory 512mb
# 메모리 정책 - n8n 큐 데이터 보존을 위해 noeviction 권장
maxmemory-policy noeviction
# 영구 저장 설정 (AOF)
appendonly yes
appendfsync everysec
# 위험한 명령어 비활성화 (보안)
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
rename-command CONFIG ""
# 클라이언트 타임아웃 (0 = 무제한)
timeout 0
# TCP keepalive
tcp-keepalive 300
# 최대 클라이언트 연결 수
maxclients 1000
여러 애플리케이션이 동일한 Redis 서버를 공유할 때는 데이터베이스 번호를 분리하여 사용하는 것이 좋습니다. Redis는 기본적으로 16개의 논리적 데이터베이스(0-15)를 제공하며, 각 애플리케이션마다 다른 번호를 할당하면 키 충돌을 방지할 수 있습니다. n8n Worker 모드에서는 QUEUE_BULL_REDIS_DB 환경 변수로 사용할 데이터베이스 번호를 지정합니다.
## Redis 데이터베이스 분리 전략
Redis Server (192.168.1.100:6379)
├── DB 0: n8n Worker Queue (Bull Queue)
├── DB 1: n8n Session Cache (선택적)
├── DB 2: 다른 애플리케이션 A
├── DB 3: 다른 애플리케이션 B
└── DB 4-15: 예약 / 미사용
### n8n 환경 변수 설정:
QUEUE_BULL_REDIS_DB=0
### 다른 애플리케이션 설정 예시:
App A: REDIS_DB=2
App B: REDIS_DB=3
외부 자원 연결용 Docker Compose (n8n 전용)
외부 PostgreSQL과 Redis를 사용하는 경우의 Docker Compose 파일입니다. 이 구성에서는 n8n Main과 Worker만 컨테이너로 실행하고, 데이터베이스와 캐시는 외부 서버를 참조합니다. depends_on 설정이 제거되고 대신 연결 재시도 로직이 환경 변수로 설정됩니다. 외부 서비스의 가용성에 따라 n8n 시작이 실패할 수 있으므로, 적절한 재시작 정책과 헬스체크가 중요합니다.
# =============================================================================
# n8n Worker Mode - 외부 PostgreSQL/Redis 연결 구성
# =============================================================================
# 파일명: docker-compose.external.yml
# 설명: 외부 데이터베이스/캐시 서버를 사용하는 n8n 전용 Docker Compose
# 사용 사례:
# - Synology NAS의 PostgreSQL/Redis 활용
# - 별도 DB 서버가 있는 환경
# - 클라우드 관리형 서비스(RDS, ElastiCache) 사용
# Latest: 2025-12 기준: n8n 2.0, PostgreSQL 18, Redis 8 지원
# =============================================================================
services:
# ===========================================================================
# n8n Main Instance
# ===========================================================================
n8n-main:
# Latest: 최신 버전 (2025-12 기준)
image: n8nio/n8n:${N8N_VERSION:-2.0.0}
# image: n8nio/n8n:${N8N_VERSION:-1.94.1} # 이전 안정 버전
container_name: n8n-main
restart: unless-stopped
# 외부 서비스 사용 시 depends_on 없음
# 대신 연결 재시도 로직에 의존
ports:
- "${N8N_PORT:-5678}:5678"
environment:
# 기본 설정
TZ: ${TZ:-Asia/Seoul}
GENERIC_TIMEZONE: ${TZ:-Asia/Seoul}
# n8n 호스트 설정
N8N_HOST: ${N8N_HOST:-localhost}
N8N_PORT: 5678
N8N_PROTOCOL: ${N8N_PROTOCOL:-http}
WEBHOOK_URL: ${WEBHOOK_URL:-http://localhost:5678}
N8N_EDITOR_BASE_URL: ${N8N_EDITOR_BASE_URL:-http://localhost:5678}
# 암호화 키 (필수)
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY:?N8N_ENCRYPTION_KEY is required}
# =========================================
# 외부 PostgreSQL 연결 설정
# =========================================
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: ${EXTERNAL_POSTGRES_HOST:?EXTERNAL_POSTGRES_HOST is required}
DB_POSTGRESDB_PORT: ${EXTERNAL_POSTGRES_PORT:-5432}
DB_POSTGRESDB_DATABASE: ${EXTERNAL_POSTGRES_DB:-n8n}
DB_POSTGRESDB_USER: ${EXTERNAL_POSTGRES_USER:-n8n}
DB_POSTGRESDB_PASSWORD: ${EXTERNAL_POSTGRES_PASSWORD:?EXTERNAL_POSTGRES_PASSWORD is required}
# PostgreSQL SSL 설정 (클라우드 서비스 사용 시)
DB_POSTGRESDB_SSL_ENABLED: ${EXTERNAL_POSTGRES_SSL:-false}
DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED: ${EXTERNAL_POSTGRES_SSL_REJECT_UNAUTHORIZED:-true}
# 연결 풀 설정
DB_POSTGRESDB_CONNECTION_POOL_SIZE: ${EXTERNAL_POSTGRES_POOL_SIZE:-10}
# =========================================
# 외부 Redis 연결 설정
# =========================================
EXECUTIONS_MODE: queue
EXECUTIONS_PROCESS: main
QUEUE_BULL_REDIS_HOST: ${EXTERNAL_REDIS_HOST:?EXTERNAL_REDIS_HOST is required}
QUEUE_BULL_REDIS_PORT: ${EXTERNAL_REDIS_PORT:-6379}
QUEUE_BULL_REDIS_PASSWORD: ${EXTERNAL_REDIS_PASSWORD:-}
QUEUE_BULL_REDIS_DB: ${EXTERNAL_REDIS_DB:-0}
# Redis TLS 설정 (클라우드 서비스 사용 시)
QUEUE_BULL_REDIS_TLS: ${EXTERNAL_REDIS_TLS:-false}
QUEUE_HEALTH_CHECK_ACTIVE: "true"
# =========================================
# 🆕 n8n 2.0 보안 설정
# =========================================
N8N_RUNNERS_ENABLED: ${N8N_RUNNERS_ENABLED:-true}
N8N_BLOCK_ENV_ACCESS_IN_NODE: ${N8N_BLOCK_ENV_ACCESS_IN_NODE:-true}
N8N_NODES_INCLUDE: ${N8N_NODES_INCLUDE:-}
# 인증 설정
N8N_BASIC_AUTH_ACTIVE: ${N8N_BASIC_AUTH_ACTIVE:-true}
N8N_BASIC_AUTH_USER: ${N8N_BASIC_AUTH_USER:-admin}
N8N_BASIC_AUTH_PASSWORD: ${N8N_BASIC_AUTH_PASSWORD:-changeme}
# 실행 데이터 설정
EXECUTIONS_DATA_MAX_AGE: ${EXECUTIONS_DATA_MAX_AGE:-720}
EXECUTIONS_DATA_SAVE_ON_SUCCESS: all
EXECUTIONS_DATA_SAVE_ON_ERROR: all
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_PRUNE_MAX_COUNT: 50000
# 로깅
N8N_LOG_LEVEL: ${N8N_LOG_LEVEL:-info}
# 성능
NODE_OPTIONS: ${NODE_OPTIONS:---max-old-space-size=2048}
volumes:
- ./data/n8n:/home/node/.n8n
- ./logs/n8n:/home/node/logs
networks:
- n8n-network
# 외부 서비스 연결 헬스체크
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:5678/healthz || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s # 외부 연결 대기 시간 고려하여 증가
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
# ===========================================================================
# n8n Worker Instance
# ===========================================================================
n8n-worker:
# Latest: 최신 버전 (2025-12 기준)
image: n8nio/n8n:${N8N_VERSION:-2.0.0}
# image: n8nio/n8n:${N8N_VERSION:-1.94.1} # 이전 안정 버전
container_name: n8n-worker
restart: unless-stopped
command: worker
# Main이 시작된 후 Worker 시작
depends_on:
n8n-main:
condition: service_healthy
environment:
# 기본 설정
TZ: ${TZ:-Asia/Seoul}
GENERIC_TIMEZONE: ${TZ:-Asia/Seoul}
# 암호화 키 (Main과 동일 필수)
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
# 외부 PostgreSQL 연결 (Main과 동일)
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: ${EXTERNAL_POSTGRES_HOST}
DB_POSTGRESDB_PORT: ${EXTERNAL_POSTGRES_PORT:-5432}
DB_POSTGRESDB_DATABASE: ${EXTERNAL_POSTGRES_DB:-n8n}
DB_POSTGRESDB_USER: ${EXTERNAL_POSTGRES_USER:-n8n}
DB_POSTGRESDB_PASSWORD: ${EXTERNAL_POSTGRES_PASSWORD}
DB_POSTGRESDB_SSL_ENABLED: ${EXTERNAL_POSTGRES_SSL:-false}
# 외부 Redis 연결 (Main과 동일)
EXECUTIONS_MODE: queue
QUEUE_BULL_REDIS_HOST: ${EXTERNAL_REDIS_HOST}
QUEUE_BULL_REDIS_PORT: ${EXTERNAL_REDIS_PORT:-6379}
QUEUE_BULL_REDIS_PASSWORD: ${EXTERNAL_REDIS_PASSWORD:-}
QUEUE_BULL_REDIS_DB: ${EXTERNAL_REDIS_DB:-0}
QUEUE_BULL_REDIS_TLS: ${EXTERNAL_REDIS_TLS:-false}
QUEUE_HEALTH_CHECK_ACTIVE: "true"
# Latest: n8n 2.0 보안 설정 (Main과 동일)
N8N_RUNNERS_ENABLED: ${N8N_RUNNERS_ENABLED:-true}
N8N_BLOCK_ENV_ACCESS_IN_NODE: ${N8N_BLOCK_ENV_ACCESS_IN_NODE:-true}
N8N_NODES_INCLUDE: ${N8N_NODES_INCLUDE:-}
# Worker 동시성
N8N_CONCURRENCY_PRODUCTION_LIMIT: ${N8N_CONCURRENCY_PRODUCTION_LIMIT:-10}
# 로깅
N8N_LOG_LEVEL: ${N8N_LOG_LEVEL:-info}
# 성능
NODE_OPTIONS: ${NODE_OPTIONS:---max-old-space-size=2048}
volumes:
- ./data/n8n:/home/node/.n8n
- ./logs/n8n:/home/node/logs
networks:
- n8n-network
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
replicas: 1
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
networks:
n8n-network:
driver: bridge
name: n8n-external-network
외부 자원용 환경 변수 파일
외부 PostgreSQL과 Redis를 사용할 때의 환경 변수 파일입니다. 내부 컨테이너를 사용할 때와 달리 외부 서버의 호스트 주소, 포트, 인증 정보를 명시적으로 설정해야 합니다. 클라우드 관리형 서비스를 사용하는 경우 SSL/TLS 설정도 함께 구성해야 합니다.
# =============================================================================
# n8n Worker Mode - 외부 자원 연결용 환경 변수
# =============================================================================
# 파일명: .env.external
# 설명: 외부 PostgreSQL/Redis 서버를 사용할 때의 환경 변수 설정
# Latest: 2025-12 기준: n8n 2.0, PostgreSQL 18, Redis 8 지원
# =============================================================================
# -----------------------------------------------------------------------------
# 기본 설정
# -----------------------------------------------------------------------------
TZ=Asia/Seoul
# Latest: 최신 버전 (2025-12 기준)
N8N_VERSION=2.0.0
# N8N_VERSION=1.94.1 # 이전 안정 버전
# -----------------------------------------------------------------------------
# n8n 호스트 설정
# -----------------------------------------------------------------------------
N8N_HOST=localhost
N8N_PORT=5678
N8N_PROTOCOL=http
WEBHOOK_URL=http://localhost:5678
N8N_EDITOR_BASE_URL=http://localhost:5678
# 암호화 키 (필수 백업!)
N8N_ENCRYPTION_KEY=your-encryption-key-change-this
# -----------------------------------------------------------------------------
# Latest: n8n 2.0 보안 설정
# -----------------------------------------------------------------------------
N8N_RUNNERS_ENABLED=true
N8N_BLOCK_ENV_ACCESS_IN_NODE=true
N8N_NODES_INCLUDE=
# -----------------------------------------------------------------------------
# 외부 PostgreSQL 연결 설정
# -----------------------------------------------------------------------------
# Synology NAS 예시 (PostgreSQL 18 권장)
EXTERNAL_POSTGRES_HOST=192.168.1.100
EXTERNAL_POSTGRES_PORT=5432
EXTERNAL_POSTGRES_DB=n8n_production
EXTERNAL_POSTGRES_USER=n8n_user
EXTERNAL_POSTGRES_PASSWORD=your-postgres-password
# 연결 풀 크기 (동시 연결 수)
EXTERNAL_POSTGRES_POOL_SIZE=10
# SSL 설정 (로컬 네트워크에서는 보통 false)
EXTERNAL_POSTGRES_SSL=false
# -----------------------------------------------------------------------------
# 외부 PostgreSQL - 클라우드 서비스 예시 (AWS RDS)
# -----------------------------------------------------------------------------
# EXTERNAL_POSTGRES_HOST=your-instance.xxxx.region.rds.amazonaws.com
# EXTERNAL_POSTGRES_PORT=5432
# EXTERNAL_POSTGRES_DB=n8n
# EXTERNAL_POSTGRES_USER=n8n_admin
# EXTERNAL_POSTGRES_PASSWORD=your-rds-password
# EXTERNAL_POSTGRES_SSL=true
# EXTERNAL_POSTGRES_SSL_REJECT_UNAUTHORIZED=true
# -----------------------------------------------------------------------------
# 외부 Redis 연결 설정
# -----------------------------------------------------------------------------
# Synology NAS 예시 (Redis 8 권장)
EXTERNAL_REDIS_HOST=192.168.1.100
EXTERNAL_REDIS_PORT=6379
EXTERNAL_REDIS_PASSWORD=your-redis-password
EXTERNAL_REDIS_DB=0
# TLS 설정 (로컬 네트워크에서는 보통 false)
EXTERNAL_REDIS_TLS=false
# -----------------------------------------------------------------------------
# 외부 Redis - 클라우드 서비스 예시 (AWS ElastiCache)
# -----------------------------------------------------------------------------
# EXTERNAL_REDIS_HOST=your-cluster.xxxx.cache.amazonaws.com
# EXTERNAL_REDIS_PORT=6379
# EXTERNAL_REDIS_PASSWORD=your-elasticache-password
# EXTERNAL_REDIS_DB=0
# EXTERNAL_REDIS_TLS=true
# -----------------------------------------------------------------------------
# 인증 설정
# -----------------------------------------------------------------------------
N8N_BASIC_AUTH_ACTIVE=true
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=your-admin-password
# -----------------------------------------------------------------------------
# Worker 설정
# -----------------------------------------------------------------------------
N8N_CONCURRENCY_PRODUCTION_LIMIT=10
# -----------------------------------------------------------------------------
# 로깅 및 성능
# -----------------------------------------------------------------------------
N8N_LOG_LEVEL=info
NODE_OPTIONS=--max-old-space-size=2048
EXECUTIONS_DATA_MAX_AGE=720
Synology NAS 통합 구성 예시
Synology NAS에서 PostgreSQL과 Redis를 운영하고, 별도의 서버(예: MacOS Mini)에서 n8n을 실행하는 실제 구성 예시입니다. 이 구성은 NAS의 안정적인 스토리지와 백업 기능을 활용하면서, 연산 집약적인 워크플로우 실행은 더 강력한 하드웨어에서 처리할 수 있어 효율적입니다. NAS와 애플리케이션 서버가 같은 네트워크에 있어야 하며, 방화벽 설정에서 필요한 포트가 열려 있어야 합니다.

Synology NAS에서 PostgreSQL과 Redis 컨테이너를 설정하는 방법입니다. Container Manager(구 Docker) 패키지를 통해 GUI로 설정하거나, SSH로 접속하여 docker-compose로 설정할 수 있습니다. 아래는 NAS에서 실행할 데이터베이스 스택의 docker-compose 파일입니다.
# =============================================================================
# Synology NAS - 공유 데이터베이스 스택
# =============================================================================
# 파일명: docker-compose.nas-db.yml
# 위치: Synology NAS의 /volume1/docker/database-stack/
# 설명: 여러 애플리케이션이 공유하는 PostgreSQL + Redis 스택
# Latest: 2025-12 기준: PostgreSQL 18, Redis 8 지원
# =============================================================================
services:
postgres:
# Latest: 최신 버전 (2025-12 기준)
image: postgres:18-alpine
# image: postgres:17-alpine # 이전 안정 버전
# image: postgres:16-alpine # LTS 버전
container_name: shared-postgres
restart: unless-stopped
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_ADMIN_PASSWORD}
TZ: Asia/Seoul
volumes:
# Synology 볼륨에 데이터 저장
- /volume1/docker/postgres/data:/var/lib/postgresql/data
# 초기화 스크립트
- /volume1/docker/postgres/init:/docker-entrypoint-initdb.d:ro
ports:
# 내부 네트워크에서 접근 가능하도록 포트 노출
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
# Synology에서는 리소스 제한을 Container Manager GUI에서 설정 가능
deploy:
resources:
limits:
memory: 2G
redis:
# Latest: 최신 버전 (2025-12 기준)
image: redis:8-alpine
# image: redis:7-alpine # 이전 안정 버전
container_name: shared-redis
restart: unless-stopped
# Latest: Redis 8: I/O Threading 지원
command: >
redis-server
--requirepass ${REDIS_PASSWORD}
--appendonly yes
--appendfsync everysec
--maxmemory 512mb
--maxmemory-policy noeviction
--io-threads 4
--io-threads-do-reads yes
# 🔧 Redis 7 이하 버전 사용 시 (io-threads 제거)
# command: >
# redis-server
# --requirepass ${REDIS_PASSWORD}
# --appendonly yes
# --appendfsync everysec
# --maxmemory 512mb
# --maxmemory-policy noeviction
volumes:
- /volume1/docker/redis/data:/data
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
memory: 512M
# 외부 네트워크로 구성하여 다른 스택에서 접근 가능
networks:
default:
name: shared-database-network
driver: bridge
연결 테스트 및 문제 해결
외부 자원을 사용할 때 발생할 수 있는 연결 문제를 진단하고 해결하는 방법입니다. 네트워크 연결, 인증, 권한 문제가 가장 흔하게 발생하며, 아래 명령어들을 순서대로 실행하여 문제 지점을 파악할 수 있습니다.
# =============================================================================
# 외부 자원 연결 테스트 스크립트
# =============================================================================
#!/bin/bash
echo "=============================================="
echo "외부 자원 연결 테스트"
echo "=============================================="
# 환경 변수 로드
source .env.external
echo ""
echo "# 1. 네트워크 연결 테스트"
echo "----------------------------------------------"
# PostgreSQL 포트 연결 테스트
echo -n "PostgreSQL ($EXTERNAL_POSTGRES_HOST:$EXTERNAL_POSTGRES_PORT): "
if nc -zv $EXTERNAL_POSTGRES_HOST $EXTERNAL_POSTGRES_PORT 2>/dev/null; then
echo "연결 가능"
else
echo "연결 실패 - 방화벽 또는 서비스 상태 확인 필요"
fi
# Redis 포트 연결 테스트
echo -n "Redis ($EXTERNAL_REDIS_HOST:$EXTERNAL_REDIS_PORT): "
if nc -zv $EXTERNAL_REDIS_HOST $EXTERNAL_REDIS_PORT 2>/dev/null; then
echo "연결 가능"
else
echo "연결 실패 - 방화벽 또는 서비스 상태 확인 필요"
fi
echo ""
echo "# 2. PostgreSQL 인증 테스트"
echo "----------------------------------------------"
# PostgreSQL 연결 및 쿼리 테스트
PGPASSWORD=$EXTERNAL_POSTGRES_PASSWORD psql \
-h $EXTERNAL_POSTGRES_HOST \
-p $EXTERNAL_POSTGRES_PORT \
-U $EXTERNAL_POSTGRES_USER \
-d $EXTERNAL_POSTGRES_DB \
-c "SELECT version();" 2>/dev/null
if [ $? -eq 0 ]; then
echo "PostgreSQL 인증 성공"
else
echo "PostgreSQL 인증 실패"
echo " 확인사항:"
echo " - 사용자명/비밀번호 확인"
echo " - pg_hba.conf에서 IP 허용 확인"
echo " - 데이터베이스 존재 여부 확인"
fi
echo ""
echo "# 3. Redis 인증 테스트"
echo "----------------------------------------------"
# Redis 연결 및 PING 테스트
REDIS_RESULT=$(redis-cli \
-h $EXTERNAL_REDIS_HOST \
-p $EXTERNAL_REDIS_PORT \
-a $EXTERNAL_REDIS_PASSWORD \
ping 2>/dev/null)
if [ "$REDIS_RESULT" = "PONG" ]; then
echo "Redis 인증 성공"
else
echo "Redis 인증 실패"
echo " 확인사항:"
echo " - 비밀번호 확인"
echo " - Redis protected-mode 설정 확인"
echo " - bind 주소 설정 확인"
fi
echo ""
echo "# 4. 상세 연결 정보"
echo "----------------------------------------------"
echo "PostgreSQL: $EXTERNAL_POSTGRES_USER@$EXTERNAL_POSTGRES_HOST:$EXTERNAL_POSTGRES_PORT/$EXTERNAL_POSTGRES_DB"
echo "Redis: $EXTERNAL_REDIS_HOST:$EXTERNAL_REDIS_PORT (DB: $EXTERNAL_REDIS_DB)"
echo ""
echo "=============================================="
echo "테스트 완료"
echo "=============================================="
외부 자원 사용 시 자주 발생하는 문제와 해결 방법을 정리했습니다. 대부분의 문제는 네트워크 설정이나 인증 관련이며, 로그를 확인하면 정확한 원인을 파악할 수 있습니다.
외부 자원 연결 문제 해결 가이드
문제 1: "connection refused" 오류
원인: 서비스가 실행 중이 아니거나 포트가 열려있지 않음
해결:
1. 외부 서버에서 서비스 실행 상태 확인:
docker ps | grep postgres
docker ps | grep redis
2. 방화벽 설정 확인:
# Synology: 제어판 > 보안 > 방화벽
# Linux: sudo ufw status
3. 서비스가 외부 IP에 바인딩되어 있는지 확인:
netstat -tlnp | grep 5432
문제 2: "authentication failed" 오류
원인: 사용자명, 비밀번호, 또는 접근 권한 문제
해결:
1. PostgreSQL pg_hba.conf 확인:
# n8n 서버 IP 추가
host n8n n8n_user 192.168.1.101/32 scram-sha-256
2. Redis requirepass 설정 확인
3. .env 파일의 비밀번호에 특수문자가 있으면 따옴표로 감싸기:
EXTERNAL_POSTGRES_PASSWORD="p@ss'w0rd"
문제 3: "SSL connection required" 오류 (클라우드)
원인: 클라우드 서비스에서 SSL 연결을 강제하는 경우
해결:
1. PostgreSQL SSL 활성화:
EXTERNAL_POSTGRES_SSL=true
2. Redis TLS 활성화:
EXTERNAL_REDIS_TLS=true
문제 4: 연결이 간헐적으로 끊김
원인: 네트워크 불안정, 연결 타임아웃, 또는 리소스 부족
해결:
1. PostgreSQL 연결 풀 크기 조정:
EXTERNAL_POSTGRES_POOL_SIZE=20
2. Redis tcp-keepalive 설정 확인
3. 외부 서버의 max_connections 설정 확인
11. 모니터링 및 유지보수
로그 관리
효과적인 로그 관리는 시스템 문제를 빠르게 파악하고 해결하는 데 필수적입니다. Docker Compose에서 설정한 로깅 드라이버는 각 컨테이너의 로그를 JSON 파일로 저장하며, 파일 크기와 보관 개수를 제한하여 디스크 공간을 관리합니다. 운영 환경에서는 ELK 스택(Elasticsearch, Logstash, Kibana)이나 Grafana Loki 같은 중앙 집중식 로그 관리 시스템을 도입하는 것이 좋습니다.
# 로그 파일 위치 확인 (Docker 기본)
docker inspect n8n-main --format='{{.LogPath}}'
# 실시간 로그 모니터링 (에러만 필터링)
docker compose logs -f 2>&1 | grep -i "error\|fail\|exception"
# 특정 시간 범위 로그 확인
docker compose logs --since "2024-01-01T00:00:00" --until "2024-01-01T23:59:59"
# 로그 파일 직접 확인 (n8n 내부 로그)
docker compose exec n8n-main cat /home/node/logs/n8n.log | tail -100
# 로그 로테이션 상태 확인
ls -la /var/lib/docker/containers/*/
백업 전략
데이터 백업은 시스템 운영에서 가장 중요한 작업 중 하나입니다. n8n Worker 모드에서는 PostgreSQL 데이터베이스와 n8n 로컬 파일이 백업 대상입니다. PostgreSQL에는 워크플로우 정의, 자격 증명(암호화됨), 실행 이력이 저장되어 있고, n8n 로컬 파일에는 바이너리 데이터나 업로드된 파일이 저장됩니다. Redis 데이터는 임시 큐 데이터이므로 백업이 필수는 아니지만, 진행 중인 작업 복구가 필요하다면 함께 백업할 수 있습니다.
#!/bin/bash
# =============================================================================
# n8n 백업 스크립트
# =============================================================================
# 파일명: scripts/backup.sh
# 사용법: ./scripts/backup.sh
# =============================================================================
set -e
# 설정
BACKUP_DIR="./backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="n8n_backup_${DATE}"
# 백업 디렉토리 생성
mkdir -p "${BACKUP_DIR}/${BACKUP_NAME}"
echo "n8n 백업 시작: ${BACKUP_NAME}"
# 1. PostgreSQL 백업
echo "PostgreSQL 데이터베이스 백업 중..."
docker compose exec -T postgres pg_dump \
-U n8n \
-d n8n \
-F custom \
-f /tmp/n8n_db.dump
docker compose cp postgres:/tmp/n8n_db.dump \
"${BACKUP_DIR}/${BACKUP_NAME}/n8n_database.dump"
# 2. n8n 로컬 파일 백업
echo "n8n 로컬 파일 백업 중..."
tar -czf "${BACKUP_DIR}/${BACKUP_NAME}/n8n_files.tar.gz" \
-C ./data/n8n .
# 3. 환경 변수 파일 백업 (선택적)
echo "⚙설정 파일 백업 중..."
cp .env "${BACKUP_DIR}/${BACKUP_NAME}/.env.backup"
# 4. 전체 압축
echo "최종 압축 중..."
tar -czf "${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" \
-C "${BACKUP_DIR}" "${BACKUP_NAME}"
# 임시 디렉토리 정리
rm -rf "${BACKUP_DIR}/${BACKUP_NAME}"
# 오래된 백업 정리 (30일 이상)
find "${BACKUP_DIR}" -name "n8n_backup_*.tar.gz" -mtime +30 -delete
echo "백업 완료: ${BACKUP_DIR}/${BACKUP_NAME}.tar.gz"
echo "백업 크기: $(du -h "${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" | cut -f1)"
복원 절차
백업에서 데이터를 복원하는 절차는 신중하게 진행해야 합니다. 복원 전에 현재 데이터를 백업해 두고, 가능하다면 별도의 테스트 환경에서 먼저 복원을 테스트하는 것이 좋습니다. 아래 스크립트는 백업 파일에서 PostgreSQL 데이터베이스와 n8n 로컬 파일을 복원합니다.
#!/bin/bash
# =============================================================================
# n8n 복원 스크립트
# =============================================================================
# 파일명: scripts/restore.sh
# 사용법: ./scripts/restore.sh <백업파일명>
# 예시: ./scripts/restore.sh n8n_backup_20240101_120000.tar.gz
# =============================================================================
set -e
BACKUP_FILE=$1
if [ -z "$BACKUP_FILE" ]; then
echo "사용법: $0 <백업파일명>"
echo " 예시: $0 backups/n8n_backup_20240101_120000.tar.gz"
exit 1
fi
if [ ! -f "$BACKUP_FILE" ]; then
echo "백업 파일을 찾을 수 없습니다: $BACKUP_FILE"
exit 1
fi
echo "주의: 이 작업은 현재 데이터를 덮어씁니다!"
read -p "계속하시겠습니까? (yes/no): " CONFIRM
if [ "$CONFIRM" != "yes" ]; then
echo "복원이 취소되었습니다."
exit 0
fi
# 임시 디렉토리 생성
TEMP_DIR=$(mktemp -d)
echo "📂 임시 디렉토리: $TEMP_DIR"
# 백업 파일 압축 해제
echo "🗜️ 백업 파일 압축 해제 중..."
tar -xzf "$BACKUP_FILE" -C "$TEMP_DIR"
BACKUP_NAME=$(ls "$TEMP_DIR")
# 서비스 중지 (Worker 먼저)
echo "서비스 중지 중..."
docker compose stop n8n-worker n8n-main
# PostgreSQL 복원
echo "PostgreSQL 데이터베이스 복원 중..."
docker compose cp "${TEMP_DIR}/${BACKUP_NAME}/n8n_database.dump" \
postgres:/tmp/n8n_db.dump
docker compose exec -T postgres pg_restore \
-U n8n \
-d n8n \
-c \
/tmp/n8n_db.dump || true # 일부 에러 무시
# n8n 로컬 파일 복원
echo "n8n 로컬 파일 복원 중..."
rm -rf ./data/n8n/*
tar -xzf "${TEMP_DIR}/${BACKUP_NAME}/n8n_files.tar.gz" \
-C ./data/n8n
# 권한 복구
sudo chown -R 1000:1000 ./data/n8n
# 임시 디렉토리 정리
rm -rf "$TEMP_DIR"
# 서비스 시작
echo "서비스 시작 중..."
docker compose up -d
echo "복원 완료!"
echo "서비스 상태를 확인하세요: docker compose ps"
12. n8n 2.0 마이그레이션 가이드
n8n 2.0은 2025년 12월 5일에 출시된 메이저 버전으로, "Secure by Default" 철학을 바탕으로 보안이 크게 강화되었습니다. 기존 1.x 버전에서 운영 중인 워크플로우가 있다면, 업그레이드 전에 몇 가지 중요한 변경사항을 확인해야 합니다. 이 섹션에서는 n8n 1.x에서 2.0으로 안전하게 마이그레이션하는 방법과 주의사항을 설명합니다.
n8n 2.0 주요 변경사항
n8n 2.0은 새로운 기능보다는 보안 강화와 안정성 개선에 초점을 맞춘 릴리스입니다. 시맨틱 버저닝을 따르는 n8n은 1.0 출시 이후 2년 넘게 Breaking Change를 축적해왔고, 이번 2.0에서 한꺼번에 적용했습니다. 주요 변경사항은 다음과 같습니다.
## n8n 2.0 주요 변경사항 요약
1. 보안 강화 (Secure by Default)
• Task Runner 기본 활성화: Code 노드가 격리된 환경에서 실행
• 환경 변수 접근 차단: Code 노드에서 process.env 접근 불가
• 위험 노드 비활성화: Execute Command, SSH 등 기본 비활성화
2. Save vs Publish 분리
• 1.x: Save 버튼 클릭 시 즉시 프로덕션에 반영
• 2.0: Save는 편집만 저장, Publish 버튼으로 명시적 배포
• Autosave 기능 2026년 1월 추가 예정
3. UI/UX 개선
• 워크플로우 에디터 캔버스 디자인 개선
• 사이드바 네비게이션 재구성
• 업그레이드 체크 도구 제공
4. 레거시 옵션 제거
• 일부 deprecated 설정 제거
• 엣지 케이스 버그를 유발하던 옵션들 정리
마이그레이션 전 체크리스트
n8n 2.0으로 업그레이드하기 전에 기존 워크플로우를 검토해야 합니다. 특히 Code 노드를 사용하거나 시스템 명령을 실행하는 워크플로우가 있다면 주의가 필요합니다. 아래 체크리스트를 통해 업그레이드 영향을 사전에 파악할 수 있습니다.
## n8n 2.0 마이그레이션 체크리스트
1. Code 노드 환경 변수 사용 확인
• 검색: 워크플로우에서 process.env 또는 $env 사용 여부
• 영향: 2.0에서 기본 차단됨
• 대응: N8N_BLOCK_ENV_ACCESS_IN_NODE=false 설정 또는 코드 수정
2. Execute Command 노드 사용 확인
• 검색: Execute Command, SSH 노드 사용 워크플로우
• 영향: 2.0에서 기본 비활성화됨
• 대응: N8N_NODES_INCLUDE 설정으로 명시적 활성화
3. 외부 npm 패키지 사용 확인
• 검색: Code 노드에서 require() 또는 import 사용
• 영향: Task Runner 환경에서 제한될 수 있음
• 대응: NODE_FUNCTION_ALLOW_EXTERNAL 설정 확인
4. 워크플로우 배포 프로세스 검토
• 변경: Save와 Publish가 분리됨
• 영향: 자동화된 배포 스크립트 수정 필요할 수 있음
• 대응: API 호출 시 publish 엔드포인트 추가 확인
5. 데이터베이스 백업
• 필수: 업그레이드 전 PostgreSQL 전체 백업
• 명령: pg_dump -U n8n -d n8n -F custom -f n8n_backup_pre_v2.dump
6. 테스트 환경에서 먼저 검증
• 권장: 프로덕션 업그레이드 전 스테이징 환경에서 테스트
• 방법: docker-compose.test.yml로 별도 환경 구성
단계별 마이그레이션 절차
n8n 1.x에서 2.0으로 업그레이드하는 단계별 절차입니다. 프로덕션 환경에서는 반드시 백업을 먼저 수행하고, 가능하면 테스트 환경에서 먼저 검증한 후 진행하세요. 업그레이드 중 문제가 발생하면 백업에서 빠르게 복구할 수 있도록 롤백 계획도 준비해 두어야 합니다.
#!/bin/bash
# =============================================================================
# n8n 1.x → 2.0 마이그레이션 스크립트
# =============================================================================
set -e
echo "=============================================="
echo "n8n 2.0 마이그레이션 시작"
echo "=============================================="
# -----------------------------------------------------------------------------
# 1단계: 현재 상태 백업
# -----------------------------------------------------------------------------
echo ""
echo "# 1단계: 데이터베이스 백업"
echo "----------------------------------------------"
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="n8n_backup_pre_v2_${BACKUP_DATE}.dump"
# PostgreSQL 백업
docker compose exec -T postgres pg_dump \
-U n8n \
-d n8n \
-F custom \
-f /tmp/${BACKUP_FILE}
docker compose cp postgres:/tmp/${BACKUP_FILE} ./backups/${BACKUP_FILE}
echo "백업 완료: ./backups/${BACKUP_FILE}"
# -----------------------------------------------------------------------------
# 2단계: 서비스 중지
# -----------------------------------------------------------------------------
echo ""
echo "# 2단계: 서비스 중지"
echo "----------------------------------------------"
docker compose stop n8n-worker n8n-main
echo "n8n 서비스 중지됨"
# -----------------------------------------------------------------------------
# 3단계: .env 파일 업데이트
# -----------------------------------------------------------------------------
echo ""
echo "# 3단계: 환경 변수 업데이트"
echo "----------------------------------------------"
# 버전 업데이트
sed -i 's/N8N_VERSION=1\.[0-9.]*/N8N_VERSION=2.0.0/' .env
# n8n 2.0 보안 설정 추가 (없으면 추가)
if ! grep -q "N8N_RUNNERS_ENABLED" .env; then
echo "" >> .env
echo "# n8n 2.0 보안 설정" >> .env
echo "N8N_RUNNERS_ENABLED=true" >> .env
echo "N8N_BLOCK_ENV_ACCESS_IN_NODE=true" >> .env
echo "N8N_NODES_INCLUDE=" >> .env
fi
echo ".env 파일 업데이트됨"
# -----------------------------------------------------------------------------
# 4단계: 새 이미지 Pull
# -----------------------------------------------------------------------------
echo ""
echo "# 4단계: n8n 2.0 이미지 다운로드"
echo "----------------------------------------------"
docker compose pull n8n-main n8n-worker
echo "이미지 다운로드 완료"
# -----------------------------------------------------------------------------
# 5단계: 서비스 시작
# -----------------------------------------------------------------------------
echo ""
echo "# 5단계: 서비스 시작"
echo "----------------------------------------------"
docker compose up -d n8n-main
echo "n8n Main 시작 대기 (60초)..."
sleep 60
docker compose up -d n8n-worker
echo "n8n Worker 시작 대기 (30초)..."
sleep 30
# -----------------------------------------------------------------------------
# 6단계: 상태 확인
# -----------------------------------------------------------------------------
echo ""
echo "# 6단계: 서비스 상태 확인"
echo "----------------------------------------------"
docker compose ps
# 헬스체크
echo ""
echo "헬스체크 실행..."
curl -s http://localhost:5678/healthz && echo " - n8n 정상"
echo ""
echo "=============================================="
echo "n8n 2.0 마이그레이션 완료!"
echo "=============================================="
echo ""
echo "다음 단계:"
echo " 1. 웹 UI에 접속하여 워크플로우 정상 동작 확인"
echo " 2. Save/Publish 동작 변경 숙지"
echo " 3. 문제 발생 시 롤백: ./scripts/rollback.sh"
echo ""
1.x 호환 모드 설정
기존 1.x 워크플로우와의 호환성이 필요한 경우, 아래 환경 변수를 설정하여 2.0의 일부 보안 기능을 비활성화할 수 있습니다. 단, 이는 임시 조치로만 사용하고, 가능한 빨리 워크플로우를 수정하여 2.0 기본 설정으로 전환하는 것을 권장합니다.
# =============================================================================
# n8n 2.0 - 1.x 호환 모드 설정 (임시 사용 권장)
# =============================================================================
# 경고: 아래 설정은 보안을 약화시킵니다. 임시로만 사용하세요.
# =============================================================================
# Task Runner 비활성화 (1.x 동작)
# Code 노드가 메인 프로세스에서 실행됨
N8N_RUNNERS_ENABLED=false
# Code 노드에서 환경 변수 접근 허용
N8N_BLOCK_ENV_ACCESS_IN_NODE=false
# 위험 노드 활성화
N8N_NODES_INCLUDE=n8n-nodes-base.executeCommand,n8n-nodes-base.ssh,n8n-nodes-base.readWriteFile
# =============================================================================
# 위 설정 사용 시 추가 보안 조치 권장:
# - 방화벽으로 n8n 접근 IP 제한
# - 강력한 인증 설정 (SSO, 2FA)
# - 정기적인 워크플로우 감사
# =============================================================================
롤백 절차
업그레이드 후 문제가 발생하면 빠르게 1.x 버전으로 롤백할 수 있습니다. 백업 파일이 있다면 데이터 손실 없이 이전 상태로 복구할 수 있습니다. 롤백 시에는 2.0에서 생성된 워크플로우나 변경사항은 손실될 수 있으니 주의하세요.
#!/bin/bash
# =============================================================================
# n8n 2.0 → 1.x 롤백 스크립트
# =============================================================================
set -e
echo "=============================================="
echo "n8n 1.x 롤백 시작"
echo "=============================================="
# 백업 파일 확인
BACKUP_FILE=$(ls -t ./backups/n8n_backup_pre_v2_*.dump 2>/dev/null | head -1)
if [ -z "$BACKUP_FILE" ]; then
echo "백업 파일을 찾을 수 없습니다."
exit 1
fi
echo "사용할 백업 파일: $BACKUP_FILE"
read -p "계속하시겠습니까? (yes/no): " CONFIRM
if [ "$CONFIRM" != "yes" ]; then
echo "롤백이 취소되었습니다."
exit 0
fi
# 서비스 중지
echo "서비스 중지..."
docker compose down
# .env 버전 롤백
sed -i 's/N8N_VERSION=2\.[0-9.]*/N8N_VERSION=1.94.1/' .env
# 2.0 전용 설정 주석 처리
sed -i 's/^N8N_RUNNERS_ENABLED/#N8N_RUNNERS_ENABLED/' .env
sed -i 's/^N8N_BLOCK_ENV_ACCESS_IN_NODE/#N8N_BLOCK_ENV_ACCESS_IN_NODE/' .env
# 데이터베이스 복원
echo "데이터베이스 복원..."
docker compose up -d postgres
sleep 10
docker compose cp "$BACKUP_FILE" postgres:/tmp/restore.dump
docker compose exec -T postgres pg_restore \
-U n8n \
-d n8n \
-c \
/tmp/restore.dump || true
# 서비스 시작
echo "서비스 시작..."
docker compose up -d
echo ""
echo "롤백 완료! n8n 1.94.1로 복원되었습니다."
13. 문제 해결 가이드
일반적인 문제와 해결 방법
n8n Worker 모드를 운영하면서 발생할 수 있는 일반적인 문제들과 그 해결 방법을 정리했습니다. 대부분의 문제는 환경 변수 설정 오류, 네트워크 연결 문제, 또는 리소스 부족으로 인해 발생합니다. 문제가 발생하면 먼저 로그를 확인하고, 아래 체크리스트를 따라 원인을 파악하는 것이 좋습니다.
문제 1: Worker가 연결되지 않음
1. Redis 연결 확인:
docker compose exec redis redis-cli -a $REDIS_PASSWORD ping
2. 환경 변수 확인 (Main과 Worker의 Redis 설정이 동일한지):
- QUEUE_BULL_REDIS_HOST
- QUEUE_BULL_REDIS_PORT
- QUEUE_BULL_REDIS_PASSWORD
3. Worker 로그 확인:
docker compose logs n8n-worker
문제2 : 자격 증명 복호화 실패
1. N8N_ENCRYPTION_KEY가 Main과 Worker에서 동일한지 확인
2. .env 파일에 오타나 공백이 없는지 확인
3. 키가 변경되었다면 자격 증명 재설정 필요
문제 3 : PostgreSQL 연결 거부
1. PostgreSQL 컨테이너 상태 확인:
docker compose ps postgres
2. 연결 테스트:
docker compose exec postgres pg_isready -U n8n
3. 로그 확인:
docker compose logs postgres
4. 연결 수 확인:
SELECT count(*) FROM pg_stat_activity;
문제 4: 메모리 부족 (OOM)
1. 컨테이너 메모리 제한 확인:
docker stats
2. deploy.resources.limits.memory 값 조정
3. NODE_OPTIONS의 max-old-space-size 조정
4. Worker 수 줄이기:
docker compose up -d --scale n8n-worker=1
문제 5: 웹훅이 작동하지 않음
1. WEBHOOK_URL이 외부에서 접근 가능한 URL인지 확인
2. 방화벽에서 포트가 열려있는지 확인
3. SSL/TLS 설정 확인 (HTTPS 사용 시)
4. 워크플로우가 활성화되어 있는지 확인
디버깅 명령어 모음
시스템 문제를 진단할 때 유용한 명령어들을 모아두었습니다. 이 명령어들을 사용하면 각 서비스의 상태, 네트워크 연결, 리소스 사용량 등을 상세하게 확인할 수 있습니다. 문제가 발생했을 때 이 명령어들의 출력을 수집해 두면 원인 분석에 큰 도움이 됩니다.
# =============================================================================
# 종합 디버깅 스크립트
# =============================================================================
echo "=== 1. 컨테이너 상태 ==="
docker compose ps -a
echo -e "\n=== 2. 리소스 사용량 ==="
docker stats --no-stream
echo -e "\n=== 3. 네트워크 상태 ==="
docker network inspect n8n-network
echo -e "\n=== 4. PostgreSQL 연결 수 ==="
docker compose exec -T postgres psql -U n8n -d n8n -c \
"SELECT count(*) as connections FROM pg_stat_activity;"
echo -e "\n=== 5. Redis 정보 ==="
docker compose exec -T redis redis-cli -a "${REDIS_PASSWORD}" info stats | \
grep -E "connected_clients|used_memory_human|total_commands"
echo -e "\n=== 6. Redis 큐 상태 ==="
docker compose exec -T redis redis-cli -a "${REDIS_PASSWORD}" \
eval "return #redis.call('keys', 'bull:*')" 0
echo -e "\n=== 7. n8n Main 최근 에러 ==="
docker compose logs --tail 50 n8n-main 2>&1 | grep -i "error" | tail -10
echo -e "\n=== 8. n8n Worker 최근 에러 ==="
docker compose logs --tail 50 n8n-worker 2>&1 | grep -i "error" | tail -10
echo -e "\n=== 9. 디스크 사용량 ==="
du -sh ./data/*
echo -e "\n=== 10. 환경 변수 검증 ==="
docker compose exec n8n-main printenv | grep -E "^(N8N_|DB_|QUEUE_|REDIS_)" | \
sed 's/PASSWORD=.*/PASSWORD=***HIDDEN***/'
14. 보안 강화 체크리스트
프로덕션 환경에서 n8n을 안전하게 운영하기 위해 반드시 확인해야 할 보안 항목들입니다. 각 항목을 순서대로 점검하고, 미흡한 부분은 즉시 보완해야 합니다. 보안은 한 번 설정하고 끝나는 것이 아니라 지속적으로 관리하고 업데이트해야 하는 영역입니다. 정기적으로 이 체크리스트를 검토하고, 새로운 보안 위협에 대응하는 것이 중요합니다.
## 보안 강화 체크리스트
1. 인증 및 접근 제어
□ 강력한 비밀번호 사용 (최소 16자, 특수문자 포함)
□ N8N_BASIC_AUTH 활성화 및 강력한 비밀번호 설정
□ 기본 계정명(admin) 대신 고유한 사용자명 사용
□ 불필요한 사용자 계정 비활성화 또는 삭제
□ 정기적인 비밀번호 변경 정책 수립
2. 네트워크 보안
□ HTTPS 적용 (SSL/TLS 인증서 설정)
□ N8N_SECURE_COOKIE=true 설정 (HTTPS 사용 시)
□ PostgreSQL, Redis 포트 외부 노출 차단
□ 방화벽에서 필요한 포트만 허용
□ 리버스 프록시(Nginx) 적용 및 보안 헤더 설정
□ IP 화이트리스트 적용 (가능한 경우)
3. 암호화 및 키 관리
□ N8N_ENCRYPTION_KEY 안전하게 생성 및 백업
□ 환경 변수 파일(.env) 접근 권한 제한 (chmod 600)
□ .env 파일 버전 관리에서 제외 (.gitignore)
□ 비밀번호 및 키를 코드에 하드코딩하지 않음
□ 정기적인 키 로테이션 계획 수립
4. 컨테이너 보안
□ 최신 이미지 버전 사용 (보안 패치 적용)
□ root가 아닌 사용자로 컨테이너 실행
□ 불필요한 권한(capabilities) 제거
□ 읽기 전용 파일시스템 사용 (가능한 경우)
□ 리소스 제한 설정 (CPU, 메모리)
5. 로깅 및 감사
□ 접근 로그 활성화 및 모니터링
□ 실패한 로그인 시도 모니터링
□ 로그 파일 정기 백업
□ 비정상적인 활동 알림 설정
6. 유지보수 및 업데이트
□ 정기적인 보안 업데이트 적용
□ n8n 버전 업데이트 알림 확인
□ 의존성 취약점 스캔 (Trivy, Snyk 등)
□ 정기적인 백업 및 복원 테스트
□ 재해 복구 계획 수립
이 가이드에서는 n8n을 Worker 모드로 운영하기 위한 Docker Compose 구성을 상세히 살펴보았습니다. PostgreSQL은 안정적인 데이터 저장소로, Redis는 효율적인 작업 큐로, 그리고 메인과 워커의 역할 분리를 통해 확장 가능하고 안정적인 워크플로우 자동화 시스템을 구축할 수 있습니다. 초기 설정이 다소 복잡해 보일 수 있지만, 한 번 구성해 두면 시스템의 안정성과 확장성이 크게 향상됩니다.
운영 환경에 맞게 환경 변수를 조정하고, 정기적인 백업과 모니터링을 통해 시스템을 안정적으로 유지하시기 바랍니다. 문제가 발생하면 로그를 확인하고 이 가이드의 문제 해결 섹션을 참고하여 원인을 파악할 수 있습니다. n8n 공식 문서와 커뮤니티 포럼도 훌륭한 참고 자료이니 함께 활용하시면 도움이 됩니다.
참고 자료
- n8n 공식 문서 - Queue Mode
- n8n 공식 문서 - Docker Compose
- n8n 2.0 릴리스 노트
- n8n 2.0 공식 블로그
- PostgreSQL 18 릴리스 노트
- Redis 8 릴리스 노트
- PostgreSQL Docker Hub
- Redis Docker Hub
- Docker Compose 공식 문서
'AI 활용' 카테고리의 다른 글
| n8n Queue mode 고가용성 서비스 모니터링 구축 (1) | 2025.12.20 |
|---|---|
| n8n 로드밸런싱 및 고가용성 서비스 설정 및 운영 가이드 (0) | 2025.12.19 |
| Docker 컨테이너 운영 가이드 (0) | 2025.12.17 |
| MacOS에서 n8n SSL/HTTPS 구축하기 (1) | 2025.12.16 |
| Synology NAS Container Manager에 n8n설치하기 (1) | 2025.12.16 |