가장 중요한 한 가지: encryption key 찾기
n8n이 저장하는 모든 credentials(API 키, OAuth 토큰, 데이터베이스 비밀번호)는 하나의 encryption key로 암호화됩니다. 다른 컴퓨터로 옮겨서 키가 달라지면 credentials를 하나도 복호화할 수 없고, 전부 다시 설정해야 합니다.
키는 다음 두 곳 중 하나에 있습니다.
- 환경 변수
N8N_ENCRYPTION_KEY: Zeabur 서비스의 Variables 탭에서 확인하세요 - n8n 폴더 안의
config파일: 환경 변수가 없으면 n8n이 처음 시작할 때 키를 자동으로 만들어 이 파일에 기록합니다. 공식 이미지에서의 경로는/home/node/.n8n/config이고 내용은 다음과 같습니다.
{
"encryptionKey": "무작위 문자열"
}
키를 적어서 비밀번호 관리자에 보관하세요.
테스트에서 발견한 함정: 잘못된 키로 가져와도 n8n은 오류를 내지 않는다.
KEY_A로 내보낸 credentials를 KEY_B로 설정한 n8n에 가져왔더니
Successfully imported 1 credential.이라고 나오며 아무 문제 없어 보였습니다. 실제로 쓰려고 할 때가 되어서야 다음 오류가 나왔습니다.
Credentials could not be decrypted. The likely reason is that a different "encryptionKey" was used to encrypt the data.그러니 이전 후에는 꼭 아래 ‘4단계’ 검증을 하세요. 가져오기 성공 메시지를 믿으면 안 됩니다.
1단계: Zeabur에서 내보내기
Zeabur 문서에 따르면 서비스의 Overview 탭에 있는 Command 영역에서 컨테이너 안에서 명령어를 실행할 수 있습니다. workflow와 credentials를 n8n 폴더로 내보냅니다.
n8n export:workflow --all --output=/home/node/.n8n/workflows.json
n8n export:credentials --all --output=/home/node/.n8n/credentials.json
같은 탭의 Files 영역에서 컨테이너 안의 파일을 둘러보고 내려받을 수 있습니다. 이 두 파일과 config를 내려받으세요.
내보낸 credentials.json은 암호화되어 있어서 열어 봐도 비밀번호를 읽을 수 없습니다. 테스트에서 설정해 둔 SECRET123이라는 값은 파일 어디에서도 찾을 수 없었습니다. 그래서 원래 키와 함께 있어야만 쓸모가 있습니다.
다른 방법: 볼륨을 통째로 백업하기. n8n이 내장 SQLite를 쓴다면(폴더에 database.sqlite가 있음), Zeabur Backup 탭의 오프라인 백업으로 폴더 전체를 내려받을 수 있습니다. Zeabur 문서상 먼저 서비스를 일시 중지해야 하는데(Settings → Suspend Service), 이게 맞는 방법입니다. 실행 중인 SQLite에는 -wal 파일이 있어서 멈추지 않고 복사하면 데이터가 불완전할 수 있습니다.
2단계: VPS에 새 n8n 구축
Ubuntu VPS를 만들어 Docker를 설치하고, 도메인(예: n8n.example.com)의 A 레코드를 VPS IP로 지정한 다음, 다음 두 파일을 만듭니다.
# docker-compose.yml
services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
environment:
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY} # Zeabur에서 쓰던 키를 그대로 사용
- N8N_HOST=n8n.example.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.example.com/
volumes:
- n8n_data:/home/node/.n8n
caddy:
image: caddy:2
restart: unless-stopped
ports: ["80:80", "443:443"]
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
volumes:
n8n_data:
caddy_data:
# Caddyfile
n8n.example.com {
reverse_proxy n8n:5678
}
echo "N8N_ENCRYPTION_KEY=Zeabur에서 적어 온 키" > .env
docker compose up -d
DNS가 이 VPS를 가리키고 80, 443 포트가 열려 있으면 Caddy가 HTTPS 인증서를 자동으로 발급받습니다. n8n을 리버스 프록시 뒤에서 돌릴 때는 n8n 문서에 따라 WEBHOOK_URL을 설정해야 n8n이 만드는 Webhook URL이 올바른 공개 주소가 됩니다.
3단계: 가져오기
docker compose cp workflows.json n8n:/tmp/
docker compose cp credentials.json n8n:/tmp/
docker compose exec n8n n8n import:workflow --input=/tmp/workflows.json
docker compose exec n8n n8n import:credentials --input=/tmp/credentials.json
4단계: credentials가 정말 복호화되는지 검증
docker compose exec n8n n8n export:credentials --all --decrypted --output=/tmp/check.json
docker compose exec n8n cat /tmp/check.json
- 평문 내용이 보인다: 키가 맞음
Credentials could not be decrypted가 나온다: 키가 틀림, 첫 번째 섹션으로 돌아가 확인
확인한 뒤에는 바로 파일을 지우세요. 평문 비밀번호가 들어 있습니다.
docker compose exec n8n rm /tmp/check.json /tmp/credentials.json
5단계: 마무리
- workflow를 하나씩 열어 트리거를 확인하고, Webhook으로 실행되는 것은 상대 서비스(LINE, Stripe, 폼 도구)에서 URL을 새 주소로 바꾸기
- Zeabur에서 보안 사고가 있었으니 credentials에 저장된 외부 API 키는 모두 교체하기를 권합니다(보안 편 참고)
- 매일 백업 설정하기: 최소한 매일
n8n_data볼륨을 압축해 다른 곳에 보관
Dify, LobeChat처럼 여러 서비스로 이루어진 도구는 공식 저장소의 docker-compose.yml을 쓰고 같은 방식으로 Caddy를 추가하면 됩니다. 데이터베이스 이전은 데이터베이스 편을 참고하세요.