워크플로우 자동화에 관심이 있다면 한 번쯤 들어봤을 법한 n8n(엔 에잇 엔이라고 발음하며, 유튜브 튜토리얼에서는 엔 에이텐으로 들리기도 함)을 설치하는 방법을 소개하려고 합니다. 유명한 솔루션으로는 Zapier, Make.com, Microsoft Power Automate, UiPath 등이 있습니다. 그러나 무료로 Self-hosting 방식으로 내 시스템에 직접 설치하여 사용할 수 있는 솔루션으로는 n8n이 유일한 것 같습니다.
Self-hosting 방식으로 설치하면 몇 가지 기능 제한이 있긴 하지만, 개인 업무 자동화에는 부족함이 없습니다. 물론 조직이나 그룹에서도 사용할 수 있지만, admin 계정은 하나만 생성 가능하다는 점을 유의해야 합니다. 이 글에서는 n8n의 설치 방법에 집중하려고 합니다. 솔루션에 대한 자세한 내용은 다른 글에서 정리해 보겠습니다.
1. n8n 설치 진행 전에
설치관련 공식 문서 URL: https://docs.n8n.io/hosting/installation/server-setups/docker-compose/
공식 문서에서 “자체 호스팅(Self-Hosting) 방식”은 전문가에게 권장하고, 서버 관리 경험이 없다면 n8n Cloud를 추천한다고 합니다. 이 글을 읽고 계신 분은 삽질할 각오가 되어 있으실 거라 믿습니다.
1.1 자체 호스팅(Self-Hosting) 전제 조건
자체 호스팅(Self-Hosting) 방식에서는 다음을 포함한 기술 지식이 필요합니다.
- 서버와 컨테이너 설정 및 구성
- 애플리케이션 리소스 관리 및 확장
- 서버 및 애플리케이션 보안
- n8n 구성
1.2 최신 버전
n8n은 대략 몇 주 간격으로 마이너 버전을 출시 한다고 합니다. latest는 프로덕션용이고, next는 최신 릴리즈입니다. next는 베타 버전으로 이해하시면 됩니다.
따라서 불안정할 수 있습니다.
- 현재 latest: 1.45.1
- 현재 next: 1.46.0
2. Docker 설치
서버로 사용할 Linux 배포판에 따라 설치 방법이 다릅니다. 여기서는 Ubuntu 22.04 언저리 버전에서 설치하는 방법을 설명합니다.
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
3. (옵션) Non-root 유저
docker 실행이 허용되어야 하는 사용자에게 권한을 부여합니다.
sudo usermod -aG docker ${USER}
su - ${USER}
4. Docker Compose 설치
sudo apt-get install docker-compose-plugin
5. DNS 셋팅
하위 도메인을 활용해서 접속하실 수 있도록 DNS의 A 레코드를 추가합니다. 그리고 Let’s Encrypt 설정시 이 도메인을 활용하기 때문에 함께 설정 해주는 것이 좋습니다.
혹시 도메인이 없다면 Docker Compose 방식으로 설치 하지 마시고 Docker 만 설치하고, 8번 Volume 생성한 다음 아래 명령으로 실행 하시면 간단합니다.
docker run -it --rm --name n8n -e N8N_SECURE_COOKIE=false -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n
Type: A
Name: n8n (or the desired subdomain)
IP address: <IP_OF_YOUR_SERVER>
6. Docker Compose 파일 작성
mkdir n8n
cd n8n
vi docker-compose.yml
version: "3.7"
services:
traefik:
image: "traefik"
restart: always
command:
- "--api=true"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
- "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- traefik_data:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
ports:
- "127.0.0.1:5678:5678"
labels:
- traefik.enable=true
- traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
- traefik.http.routers.n8n.tls=true
- traefik.http.routers.n8n.entrypoints=web,websecure
- traefik.http.routers.n8n.tls.certresolver=mytlschallenge
- traefik.http.middlewares.n8n.headers.SSLRedirect=true
- traefik.http.middlewares.n8n.headers.STSSeconds=315360000
- traefik.http.middlewares.n8n.headers.browserXSSFilter=true
- traefik.http.middlewares.n8n.headers.contentTypeNosniff=true
- traefik.http.middlewares.n8n.headers.forceSTSHeader=true
- traefik.http.middlewares.n8n.headers.SSLHost=${DOMAIN_NAME}
- traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true
- traefik.http.middlewares.n8n.headers.STSPreload=true
- traefik.http.routers.n8n.middlewares=n8n@docker
environment:
- N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
volumes:
- n8n_data:/home/node/.n8n
volumes:
traefik_data:
external: true
n8n_data:
external: true
n8n을 사용할 때 로컬 파일을 읽고 쓸 계획이라면 이를 위한 데이터 디렉토리를 구성해야 합니다. 아래 내용을 n8n의 volumes 파트에 추가하세요.
- /home/<YOUR USERNAME>/n8n-local-files:/files
7. .env 파일 작성
docker-compose.yml 파일이 있는 위치에 .env 파일을 생성합니다.
# The top level domain to serve from
DOMAIN_NAME=example.com
# The subdomain to serve from
SUBDOMAIN=n8n
# DOMAIN_NAME and SUBDOMAIN combined decide where n8n will be reachable from
# above example would result in: https://n8n.example.com
# Optional timezone to set which gets used by Cron-Node by default
# If not set New York time will be used
GENERIC_TIMEZONE=Asia/Seoul
# The email address to use for the SSL certificate creation
SSL_EMAIL=user@example.com
8. Docker volume 생성
이제 Docker volume을 생성합니다. n8n_data는 SQLite 데이터베이스 파일과 이 볼륨의 암호화 키를 저장할 목적으로 사용됩니다.
sudo docker volume create n8n_data
traefik 데이터를 위한 volume을 생성합니다.
sudo docker volume create traefik_data
9. Docker Compose 시작
Docker Compose 시작은 11번 작업을 완료 한 후에 하세요.
n8n 시작하기
sudo docker compose up -d
container 종료하기
sudo docker compose stop
10. 완료
브라우저에서 https://n8n.example.com 으로 접속하셔서 계정을 생성하신 후 로그인 할 수 있습니다.
11. 정신건강을 위한 추가 작업(IPv6 비활성화)
n8n 설치하고 Telegram 노드를 테스트 할때 API 통신이 “ETIMEDOUT” 에러가 발생했습니다.
계속 삽질하다 관련 글을 찾아보니 IPv6를 비활성화 해야 해결할 수 있는 문제라는 것을 알게 되었습니다.
아래와 같이 작업하고 나서 문제를 해결할 수 있었습니다. grub 파일에 “ipv6.disable=1” 을 추가하시고 반영 한 후, 리붓까지 해 주시면 깔끔하게 설치가 완료된 것입니다.
이제 9, 10번 단계로 돌아가셔서 작업 마무리 하시면 됩니다.
sudo vi /etc/default/grub
GRUB_CMDLINE_LINUX="ipv6.disable=1"
sudo update-grub
sudo reboot