n8n의 진짜 매력은 '내 서버에서 돌린다'입니다. 데이터는 밖으로 나가지 않고, 실행 수에 따른 과금도 없습니다. 그리고 첫 화면까지 30분이면 충분합니다. 이 글은 Docker 한 줄에서 시작해 실서비스에 근접한 구성까지 한 번에 훑습니다.
왜 셀프호스팅인가
- 데이터 주권 — 고객 정보가 우리 인프라를 벗어나지 않는다
- 정액 요금 — 실행 수와 무관하게 서버비 하나로 끝
- 커스터마이즈 — Community 노드, Code 노드, 내부 API까지 자유롭게
- 속도 — 사내망에서 ERP를 부를 때 지연이 사실상 0
필요한 것
- Docker가 설치된 리눅스 서버 (2코어 / 4GB RAM 권장)
- 외부에서 붙일 도메인 하나 (선택, HTTPS를 붙이려면 필수)
- 터미널과 5분의 인내심
1. 한 줄로 띄우기
가장 빠른 방법은 Docker로 컨테이너 하나를 올리는 것입니다. 볼륨 하나만 잘 잡아 두면 컨테이너를 재기동해도 워크플로우와 크리덴셜이 살아남습니다.
docker run -d \
--name n8n \
--restart unless-stopped \
-p 5678:5678 \
-v n8n_data:/home/node/.n8n \
-e GENERIC_TIMEZONE=Asia/Seoul \
-e TZ=Asia/Seoul \
docker.n8n.io/n8nio/n8n브라우저에서 http://localhost:5678(또는 서버 IP)로 접속하면 첫 오너 계정 생성 화면이 뜹니다. 이메일과 비밀번호를 입력하면 곧바로 캔버스로 넘어갑니다. 여기까지 5분.
2. 데이터 유지 확인
위 명령의 핵심은 -v n8n_data:/home/node/.n8n 한 줄입니다. 워크플로우 JSON, 크리덴셜, 실행 로그가 이 볼륨에 저장됩니다. 컨테이너를 지워도 볼륨이 살아 있으면 데이터가 살아 있습니다.
docker volume inspect n8n_data
docker exec n8n ls /home/node/.n8n3. 아키텍처
4. 실서비스라면 docker-compose
장난감이 아니라 실무에 쓸 거라면 컨테이너 단독 실행 대신 docker-compose로 PostgreSQL과 함께 구성하세요. 데이터베이스를 분리하면 백업, 업그레이드, 성능 튜닝이 완전히 다른 세계가 됩니다.
services:
postgres:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: n8n
volumes:
- pg_data:/var/lib/postgresql/data
n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
ports:
- '5678:5678'
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: ${DB_PASSWORD}
N8N_HOST: n8n.example.com
N8N_PROTOCOL: https
WEBHOOK_URL: https://n8n.example.com/
volumes:
- n8n_data:/home/node/.n8n
depends_on:
- postgres
volumes:
pg_data:
n8n_data:- 위 파일을
docker-compose.yml로 저장 - 같은 폴더에
.env파일 만들고DB_PASSWORD=...채우기 docker compose up -d실행docker compose logs -f n8n으로 기동 확인- 브라우저에서 도메인 접속, 첫 계정 생성
5. HTTPS는 리버스 프록시로
n8n 컨테이너 자체는 5678 포트에 평문 HTTP로 응답합니다. 실서비스에서는 앞에 Nginx나 Caddy를 두고 Let's Encrypt로 인증서를 자동 갱신하세요. Caddy는 설정 세 줄이면 끝납니다.
n8n.example.com {
reverse_proxy localhost:5678
}WEBHOOK_URL 환경변수를 도메인 기준으로 정확히 넣어야 외부에서 발급되는 웹훅 URL이 HTTPS로 나옵니다. 이걸 빼먹으면 웹훅 URL이 http://localhost:5678/...로 나와 외부 서비스가 못 붙습니다.6. 백업 — 잊기 전에 지금
- PostgreSQL 덤프를 매일 새벽 S3나 외부 스토리지로
n8n_data볼륨 스냅샷을 주 1회- 복구 리허설을 최소 분기당 한 번
셀프호스팅은 '서버 관리'가 아니라 '데이터 주권'이다. 한 번 띄워두면 나머지는 워크플로우가 알아서 한다.— SynAct.ai 인프라팀
자주 마주치는 함정
- 볼륨을 안 잡고 컨테이너를 지워 워크플로우 전체 증발
WEBHOOK_URL미설정으로 외부 웹훅이 안 붙음- 타임존이 UTC라서 스케줄이 9시간씩 어긋남
- 메모리 2GB로 부족해서 대용량 실행 시 OOM
자주 묻는 질문
- Q. n8n Cloud vs self-hosted, 어느 쪽을 선택해야 하나요? A. 데이터가 국내에 머물러야 하거나 실행 수가 많거나 커스텀 노드 · 커스텀 credential이 필요하면 self-hosted가 유리합니다. 팀이 5명 이하이고 인프라 관리자를 붙일 여유가 없으면 Cloud가 총소요비용이 더 낮습니다.
- Q. Docker Compose와 Kubernetes 중 어느 걸 쓰는 게 낫나요? A. 단일 서버라면 Docker Compose로 충분합니다. 워커 노드를 수평으로 스케일해야 하는 규모(월 실행 100만 건 이상)에서만 K8s를 고려하세요. 그 사이라면 Compose에 별도 워커 컨테이너를 추가하는 방식이 실무에서 가장 흔한 선택.
- Q. 백업은 어떻게 해야 하나요? DB만 백업하면 되나요? A. PostgreSQL을 쓰는 경우 워크플로우 · credential · 실행 이력이 모두 DB에 있으므로
pg_dump가 기본입니다. 다만 credential 암호화 키(N8N_ENCRYPTION_KEY)와~/.n8n디렉토리(설정 파일)도 함께 보관해야 완전 복원이 가능합니다. - Q. HTTPS는 어떻게 붙이나요? A. 가장 간단한 조합은 Caddy 또는 Nginx + Let's Encrypt. Docker Compose에 caddy 컨테이너 하나 추가하고 도메인만 설정하면 자동으로 인증서를 발급 · 갱신합니다. 회사 내부망이라면 사내 CA로 발급받은 인증서를 마운트하는 방식.
- Q. PostgreSQL vs SQLite, 어떤 걸 선택해야 하나요? A. 실무는 PostgreSQL이 정답입니다. SQLite는 개발 · 데모용으로만 쓰세요. 동시 실행이 늘어나면 SQLite가 락으로 워크플로우를 실패시키고, 백업 · 마이그레이션도 훨씬 까다롭습니다. 처음부터 PostgreSQL로 시작하면 나중에 옮길 이유가 없어집니다.
- Q. 업그레이드 시 뭘 조심해야 하나요? A. 세 가지 — (1) DB 마이그레이션이 있는지 릴리스 노트 확인, (2) 커스텀 노드나 커스텀 credential이 있다면 새 버전에서 호환되는지 사전 테스트, (3) 업그레이드 직전
pg_dump+N8N_ENCRYPTION_KEY백업. 이 셋만 지키면 다운타임 없이 롤링 업그레이드 가능.
다음 글에서 다룰 것
여기까지 왔다면 이미 사내 어디에도 안 밀리는 자동화 서버 하나를 가진 셈입니다. 이제 필요한 건 워크플로우뿐입니다. 다음 편에서는 큐 모드로 실행을 분산하는 법, 그리고 모니터링과 알림 설정을 다룹니다.