Tropic Host

n8n이란 무엇이며 Docker Compose로 VPS에 설치하는 방법

읽는 데 16분
Tropic
n8n이란 무엇이며 Docker Compose로 VPS에 설치하는 방법

VPS의 n8n: 수작업 반복 업무를 없애는 나만의 자동화 플랫폼

웹사이트에서 신청이 들어옵니다. n8n은 데이터를 확인하고, 중복을 찾고, 거래를 생성하고, AI로 답변 초안을 만든 뒤 Telegram으로 담당자에게 알립니다. 사람은 브라우저 탭 사이에서 데이터를 옮기는 일이 아니라 판단이 필요한 지점에만 개입합니다.

아래에서는 n8n의 작동 방식과 PostgreSQL, HTTPS, 격리된 코드 실행을 포함해 Docker Compose로 VPS에 설치하는 방법을 살펴보겠습니다.

7단계로 시작하는 n8n

최소 실행 계획은 다음과 같습니다.

  1. VPS를 만들고 n8n.example.com과 같은 서브도메인을 연결합니다.
  2. Docker와 Docker Compose를 설치합니다.
  3. PostgreSQL, 외부 태스크 러너, Caddy와 함께 n8n을 실행합니다.
  4. HTTPS로 인터페이스를 열고 소유자 계정을 생성합니다.
  5. Telegram, CRM, 이메일 또는 원하는 외부 API를 연결합니다.
  6. 오류 처리와 실행 기록 보존 기간을 설정합니다.
  7. 데이터베이스, 데이터, 암호화 키의 백업을 자동화합니다.

소규모 운영 환경이라면 2 vCPU와 4 GB RAM으로 시작하는 것이 합리적입니다. 테스트에는 2 GB로 충분한 경우가 많지만 PostgreSQL, Docker, 병렬 프로세스가 여유 자원을 빠르게 사용합니다.

n8n이란 무엇이며 어떻게 작동하는가

n8n은 워크플로 자동화 플랫폼입니다. 시나리오는 여러 노드로 구성됩니다. 첫 번째 노드가 프로세스를 시작하고, 다음 노드들이 데이터를 가져와 변환하며, 마지막 노드가 작업을 수행합니다.

간단한 워크플로는 다음과 같습니다.

Webhook → 데이터 확인 → CRM → Telegram → 웹사이트 응답

워크플로는 webhook, 일정, 이메일, 메시지 또는 외부 서비스의 이벤트로 시작할 수 있습니다. 노드 사이에는 조건, 반복, 필터, 대기, 오류 처리를 사용할 수 있습니다.

n8n의 강점은 자동화가 준비된 연동 기능에만 제한되지 않는다는 점입니다. API가 있는 서비스라면 HTTP Request로 호출할 수 있고, 특수한 로직은 Code node에서 JavaScript나 Python으로 작성할 수 있습니다. 따라서 n8n은 간단한 노코드 빌더와 직접 작성한 서버 코드의 중간에 위치합니다.

단순한 데이터 전달 그 이상인 이유

n8n은 프로세스가 여러 시스템을 거치고 판단이 필요할 때 유용합니다.

양식 → 확인 → 중복 검색 → AI 평가 → 담당자 승인 → CRM

사람은 확인 지점에만 남겨둘 수 있습니다. 예를 들어 AI가 답변을 준비하지만 직원이 승인한 뒤에만 고객에게 메시지가 전송되도록 할 수 있습니다.

대표적인 사용 사례:

  • 영업 및 지원: 신청 수집, 리드 배정, 거래 생성;
  • 콘텐츠 및 AI: 초안 작성, 문의 분류, 승인 후 게시;
  • DevOps: 장애 알림, Git webhook, API 점검;
  • 내부 운영: 스프레드시트, 이메일, 캘린더, 사내 시스템 동기화.

Self-hosted 설치는 프로세스와 데이터베이스를 직접 제어하게 해 주지만 외부 서비스를 로컬로 바꾸지는 않습니다. Telegram, CRM 또는 클라우드 AI 모델로 전송한 데이터는 VPS 밖으로 나갑니다.

n8n Cloud와 자체 서버 비교

항목n8n CloudVPS의 n8n
시작서버 설정 불필요도메인, Docker, HTTPS 필요
업데이트n8n이 수행소유자가 수행
데이터베이스와 파일서비스 인프라에 저장선택한 서버에 저장
확장클라우드 요금제 조건에 따름직접 구성
책임관리 작업이 적음백업, 보안, 모니터링은 소유자 책임
적합한 경우DevOps 없이 빠르게 시작제어, 사용자 지정, 상시 실행 프로세스

Community Edition은 무료로 직접 호스팅해 개인 및 사내 업무에 사용할 수 있습니다. 하지만 n8n은 일반적인 오픈 소스 라이선스가 아니라 fair-code 방식의 Sustainable Use License로 배포됩니다. 내부 사용과 수정은 허용하지만 n8n을 그대로 배포하고 자체 로고를 붙여 별도의 SaaS로 접근 권한을 판매하는 것은 허용하지 않습니다. 이런 제품을 만들려면 라이선스 조건을 별도로 확인해야 합니다.

n8n 서버 요구 사항

부하는 데이터 양, 동시 실행 수, 작업의 성격에 따라 달라집니다. 파일, 긴 목록, Code node, AI 워크플로는 API 사이에서 작은 JSON을 전달하는 작업보다 더 많은 메모리를 필요로 합니다.

시나리오시작 구성
테스트 및 개인용 텍스트 워크플로1 vCPU, 2 GB RAM, 20 GB NVMe
소규모 운영 환경2 vCPU, 4 GB RAM, 25–40 GB NVMe
병렬 프로세스, AI 또는 파일4 vCPU, 8 GB RAM 이상
queue mode의 여러 worker 프로세스실행 수에 맞춰 산정

SQLite는 학습이나 소규모 단일 인스턴스에 적합합니다. 운영 환경에는 PostgreSQL이 더 편리합니다. 백업이 쉽고 나중에 queue mode로 전환하기도 수월합니다.

VPS에 n8n을 설치하는 방법

이 예제에서는 Ubuntu 24.04, PostgreSQL, Caddy, 외부 태스크 러너를 사용합니다. n8n.example.com과 시간대를 자신의 값으로 바꾸세요.

1. DNS를 설정하고 서버 준비하기

VPS의 IPv4 주소를 가리키는 DNS A 레코드를 만든 다음 SSH로 접속합니다.

ssh root@SERVER_IP
apt update && apt upgrade -y
apt install -y ca-certificates curl ufw openssl

공식 저장소에서 Docker Engine과 Compose 플러그인을 설치합니다.

install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

cat > /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

apt update
apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin
docker compose version

SSH, HTTP, HTTPS만 허용합니다.

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

새 SSH 연결이 정상적으로 작동하는지 확인할 때까지 현재 세션을 닫지 마세요.

2. 환경 변수 만들기

디렉터리를 준비합니다.

mkdir -p /opt/n8n
cd /opt/n8n

.env를 만듭니다. 아래 명령은 PostgreSQL, n8n 암호화, 태스크 러너에 사용할 서로 다른 무작위 비밀값을 즉시 생성합니다.

cat > .env <<EOF
N8N_VERSION=stable
N8N_HOST=n8n.example.com
GENERIC_TIMEZONE=Europe/Berlin

POSTGRES_DB=n8n
POSTGRES_USER=n8n
POSTGRES_PASSWORD=$(openssl rand -hex 32)

N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)
RUNNERS_AUTH_TOKEN=$(openssl rand -hex 32)
EOF

chmod 600 .env

첫 실행에는 stable 태그가 편리합니다. 설치를 확인한 뒤에는 다음 이미지 업데이트가 예기치 않게 적용되지 않도록 특정 n8n 버전을 고정하는 것이 좋습니다.

N8N_ENCRYPTION_KEY는 절대 잃어버리면 안 됩니다. n8n은 이 키로 저장된 비밀번호, 토큰, 기타 자격 증명을 암호화합니다. 키 없이 PostgreSQL만 복원하면 레코드는 데이터베이스에 남아 있지만 n8n은 내용을 읽을 수 없습니다.

3. Docker Compose 만들기

compose.yaml 파일을 만듭니다.

services:
  postgres:
    image: postgres:18-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      PGDATA: /var/lib/postgresql/data
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
    restart: unless-stopped
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_PORT: "5432"
      DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
      DB_POSTGRESDB_USER: ${POSTGRES_USER}
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}

      N8N_HOST: ${N8N_HOST}
      N8N_PORT: "5678"
      N8N_PROTOCOL: https
      N8N_EDITOR_BASE_URL: https://${N8N_HOST}
      N8N_WEBHOOK_URL: https://${N8N_HOST}/
      N8N_PROXY_HOPS: "1"
      GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}
      TZ: ${GENERIC_TIMEZONE}

      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: "true"
      N8N_BLOCK_ENV_ACCESS_IN_NODE: "true"

      N8N_RUNNERS_MODE: external
      N8N_RUNNERS_AUTH_TOKEN: ${RUNNERS_AUTH_TOKEN}
      N8N_RUNNERS_BROKER_LISTEN_ADDRESS: 0.0.0.0

      EXECUTIONS_DATA_PRUNE: "true"
      EXECUTIONS_DATA_MAX_AGE: "168"
      EXECUTIONS_DATA_PRUNE_MAX_COUNT: "10000"
    volumes:
      - n8n_data:/home/node/.n8n
    expose:
      - "5678"
    depends_on:
      postgres:
        condition: service_healthy

  n8n-runner:
    image: n8nio/runners:${N8N_VERSION}
    restart: unless-stopped
    environment:
      N8N_RUNNERS_AUTH_TOKEN: ${RUNNERS_AUTH_TOKEN}
      N8N_RUNNERS_TASK_BROKER_URI: http://n8n:5679
    depends_on:
      - n8n

  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    environment:
      N8N_HOST: ${N8N_HOST}
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - n8n

volumes:
  postgres_data:
    name: n8n_postgres_data
  n8n_data:
    name: n8n_data
  caddy_data:
    name: n8n_caddy_data
  caddy_config:
    name: n8n_caddy_config

외부 태스크 러너는 n8n의 기본 프로세스와 분리해 코드를 실행합니다. 내부 모드보다 안전하며 Code node의 오류가 편집기와 webhook 처리에 쉽게 영향을 주지 않도록 합니다.

4. HTTPS 연결하기

Caddyfile을 만듭니다.

{$N8N_HOST} {
    reverse_proxy n8n:5678
}

DNS가 이미 VPS를 가리키고 포트 80과 443에 접근할 수 있다면 Caddy가 TLS 인증서를 자동으로 발급받습니다. 내부 포트 5678은 인터넷에 공개되지 않습니다. 외부에서는 80과 443만 열리고 Caddy는 Docker 네트워크를 통해 n8n에 연결합니다.

N8N_WEBHOOK_URLN8N_PROXY_HOPS 변수는 편집기가 올바른 공개 webhook 주소를 생성하고 하나의 리버스 프록시에서 전달된 헤더를 신뢰하도록 하는 데 필요합니다.

5. n8n 실행하기

최종 구성을 확인하고 컨테이너를 시작합니다.

docker compose config
docker compose up -d
docker compose ps
docker compose logs --tail=100 n8n caddy

다음 주소를 엽니다.

https://n8n.example.com

소유자 계정을 생성합니다. 비밀번호를 동료와 공유하지 마세요. 팀에서 사용할 때는 별도 계정을 만들고 필요한 권한만 부여해야 합니다.

첫 번째로 만들어 볼 유용한 워크플로

웹사이트 신청을 처리하는 흐름은 좋은 테스트입니다.

  1. POST 메서드를 사용하는 Webhook 노드를 추가합니다.
  2. Edit Fields로 이름, 이메일, 유입 경로만 남깁니다.
  3. If 노드로 필수 데이터가 없는 신청을 거부합니다.
  4. CRM에 거래를 만들거나 HTTP Request로 요청을 보냅니다.
  5. Telegram 알림을 추가합니다.
  6. Respond to Webhook 노드로 흐름을 끝냅니다.
  7. 테스트 후 워크플로를 활성화하고 테스트 webhook을 운영 URL로 바꿉니다.

이 예제는 도메인, HTTPS, 수신 요청, 자격 증명, 외부 연동을 한 번에 확인합니다. 그다음 기본 흐름에 장애가 생겼을 때 알림을 보내는 별도의 Error Workflow를 추가하는 것이 좋습니다.

설치 후 n8n 보안

n8n을 설치했다고 해서 곧바로 안정적인 n8n이 되는 것은 아닙니다. 실행 후 다음 사항을 확인하세요.

  • 편집기는 HTTPS로만 접근할 수 있어야 합니다;
  • .env 권한은 600이며 Git에 포함되지 않아야 합니다;
  • 외부 API 키에는 최소한의 권한만 부여해야 합니다;
  • webhook은 출처의 서명 또는 비밀값을 확인해야 합니다;
  • 실행 기록은 자동으로 삭제되어야 합니다;
  • 중요한 워크플로의 오류는 관리자에게 전송되어야 합니다.

Community nodes는 패키지로 설치되며 워크플로 데이터와 서버에 접근할 수 있습니다. 검토하지 않은 알 수 없는 노드를 추가하지 마세요. 필요하지 않다면 N8N_COMMUNITY_PACKAGES_ENABLED=false로 비활성화하세요.

내장 감사를 실행합니다.

docker compose exec n8n n8n audit

보호되지 않은 webhook, 위험한 노드, 자격 증명 문제를 찾는 데 도움이 되지만 수동 검토를 대체하지는 않습니다.

실행 기록과 개인정보

n8n은 디버깅을 위해 입력과 출력 데이터를 저장합니다. 이와 함께 이메일, 전화번호, 문서, API 응답이 데이터베이스에 남을 수 있습니다.

위 구성에서는 실행 기록이 7일 후 삭제되고 최대 10,000개로 제한됩니다. 민감한 프로세스는 데이터 보존 정책에 따라 기간을 선택하고 불필요한 필드는 워크플로가 끝나기 전에 제거하세요.

백업과 업데이트

복원하려면 PostgreSQL 덤프, n8n_data 볼륨, 구성 파일, 그리고 N8N_ENCRYPTION_KEY가 포함된 .env가 필요합니다. 복사 전에 PostgreSQL은 실행한 상태로 두고 처리 컨테이너를 중지합니다. 이 과정에서 워크플로가 잠시 중단됩니다.

cd /opt/n8n
mkdir -p backup
docker compose stop n8n n8n-runner

docker compose exec -T postgres sh -c \
  'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' \
  | gzip > "backup/n8n-db-$(date +%F).sql.gz"

docker run --rm \
  -v n8n_data:/source:ro \
  -v "$PWD/backup":/backup \
  alpine sh -c \
  'tar -czf /backup/n8n-data-$(date +%F).tar.gz -C /source .'

tar -czf "backup/n8n-config-$(date +%F).tar.gz" \
  .env compose.yaml Caddyfile

docker compose start n8n n8n-runner

.env가 포함된 압축 파일에는 비밀값이 들어 있습니다. 암호화하고 VPS 외부에 보관하세요. 정기적으로 테스트 복원을 수행해 백업을 검증해야 합니다.

업데이트 전에는 백업을 만들고 릴리스 노트를 확인합니다.

cd /opt/n8n
docker compose pull
docker compose up -d
docker compose ps

태스크 러너와 기본 컨테이너는 같은 버전 태그를 사용해야 합니다.

확장이 필요한 시점

실제 부하가 생기기 전부터 Redis와 여러 worker를 도입하지 마세요. PostgreSQL을 사용하는 단일 인스턴스는 관리하기 쉽고 보통 소규모 내부 프로세스에 충분합니다.

긴 작업 때문에 webhook이 지연되거나, 많은 워크플로가 동시에 시작되거나, 파일 처리가 자주 모든 메모리를 사용할 때 queue mode가 필요합니다. 이때 기본 인스턴스가 이벤트를 받고 Redis가 작업을 분배하며 worker가 병렬로 실행합니다. 모든 구성 요소는 같은 PostgreSQL에 연결하고 동일한 N8N_ENCRYPTION_KEY를 사용해야 합니다.

n8n용 VPS 선택 방법

n8n, PostgreSQL, Caddy, 태스크 러너를 함께 운영한다면 2 vCPU, 4 GB RAM, NVMe 디스크로 시작하는 것이 합리적입니다. tropic.host에서는 Light 요금제가 이 구성에 해당합니다. 2 vCPU, 4 GB RAM, 25 GB NVMe입니다. 무거운 파일 처리가 없는 첫 운영 워크플로에는 충분합니다.

문서, 대용량 데이터, 많은 병렬 AI 워크플로를 다룬다면 8 GB RAM을 선택하는 편이 좋습니다. 안정적인 네트워크도 중요합니다. webhook, OAuth 콜백, 예약 작업은 항상 접근 가능해야 합니다.

결론

n8n은 반복 작업을 보기 쉬운 흐름으로 바꿉니다. 준비된 노드는 시작을 빠르게 하고, HTTP Request는 거의 모든 API를 연결하며, Code node는 직접 만든 로직을 추가할 수 있게 합니다.

Self-hosted 버전은 서버와 데이터베이스에 대한 제어권을 주지만 HTTPS, 제한된 키 권한, 기록 정리, 검증된 백업이 필요합니다. PostgreSQL과 함께 N8N_ENCRYPTION_KEY를 보관하세요. 이 키가 없으면 복원된 자격 증명을 복호화할 수 없습니다.

FAQ

n8n을 무료로 사용할 수 있나요?

네. Community Edition은 개인 및 사내 프로세스용으로 자체 서버에 무료로 설치할 수 있습니다. 호스팅된 n8n을 별도의 SaaS로 재판매하는 것은 fair-code 라이선스로 제한됩니다.

도메인 없이 n8n을 설치할 수 있나요?

로컬 테스트에는 가능합니다. 공개 webhook과 OAuth에는 도메인과 HTTPS를 사용하는 것이 좋습니다.

n8n에는 RAM이 얼마나 필요한가요?

간단한 개인용 워크플로는 2 GB RAM으로 충분한 경우가 많습니다. PostgreSQL, Caddy, 태스크 러너와 함께 n8n을 사용한다면 4 GB가 더 합리적이며, 파일과 병렬 실행에는 8 GB 이상이 필요할 수 있습니다.

모든 데이터가 VPS 안에 남나요?

워크플로가 외부로 보내지 않는 데이터만 남습니다. 데이터베이스와 실행 기록은 VPS에 있지만 Telegram, CRM 또는 외부 AI 모델 노드는 선택한 데이터를 해당 서비스로 전송합니다.

n8n 백업에는 무엇을 포함해야 하나요?

PostgreSQL 덤프, n8n_data 볼륨, compose.yaml, Caddyfile, 그리고 N8N_ENCRYPTION_KEY가 포함된 .env입니다. 암호화한 백업을 VPS 밖에 보관하고 복원 테스트로 확인하세요.