SSD Nodes Learn Hosting plans →
가이드 Matt Connor작성자 Matt Connor

Dify Docker Compose로 VPS에 직접 설치하는 방법

Dify는 15개의 컨테이너로 구성되며 최소 4 GiB RAM이 필요합니다. 보안을 위해 첫 실행 전 .env 파일에서 기본 비밀번호를 반드시 변경하십시오. 설치 후에는 타인보다 먼저 /install 경로에 접속하여 관리자 계정을 선점해야 합니다.

Dify의 정의 및 운영을 위해 알아야 할 사항

Dify는 대규모 언어 모델 기반의 애플리케이션을 구축하기 위한 자체 호스팅 플랫폼입니다. 챗봇, 에이전트, 검색 파이프라인을 설계할 수 있는 웹 인터페이스와 이를 코드에서 호출할 수 있는 API를 제공하며, 프롬프트, 데이터셋, 모델 키를 한곳에서 관리할 수 있습니다. 소규모 팀이 API 키를 여러 스크립트에 분산시키지 않고, 하나의 공유된 비공개 기반 위에서 협업할 수 있도록 돕는 도구입니다. 에이전트, 도구 호출(tool call), 검색 파이프라인과 같은 개념이 생소하다면, 먼저 해당 개념을 기초부터 학습하십시오. 그래야 Dify의 빌더 화면이 복잡한 설정의 나열이 아닌 익숙한 제어 도구로 보일 것입니다.

직접 운영한다는 것은 많은 구성 요소를 관리해야 함을 의미합니다. 2026년 10월 기준으로 Dify의 기본 스택은 15개의 상시 실행 컨테이너와 파일 권한을 설정하고 종료되는 1개의 일회성 작업으로 구성됩니다. 이 중 7개는 API 서버, 웹소켓 서버, 백그라운드 워커, 스케줄러, 웹 프론트엔드, 플러그인 데몬, 에이전트 백엔드 등 Dify 자체 서비스입니다. 나머지 8개는 Postgres 데이터베이스, Redis 캐시, Weaviate 벡터 데이터베이스, nginx 프론트엔드, 2개의 코드 샌드박스, 2개의 SSRF 프록시와 같은 의존성 서비스입니다. Docker Compose가 이들을 연결하지만, 이는 상당한 규모의 스택이며 Dify가 권장하는 최소 사양은 4 GiB RAM과 2개의 CPU 코어입니다. 만약 해당 VPS에서 다른 서비스도 함께 운영할 계획이라면, 광고된 사양이 아닌 실제 측정값을 기준으로 크기를 산정하십시오. PhotoPrism이나 Immich의 실제 최소 RAM 요구량은 공개된 사양보다 훨씬 높으며, 사진 서버와 자원을 공유할 경우 Dify의 데이터베이스와 벡터 저장소가 가장 먼저 자원 부족을 겪게 됩니다. CPU 경합도 마찬가지입니다. Jellyfin 라이브러리는 단순히 아트워크를 탐색할 때는 자원을 거의 소모하지 않지만, 트랜스코딩이 시작되는 순간 Dify의 워커 작업이 뒤로 밀리게 됩니다. 다행인 점은 Dify의 컨테이너 개수는 애플리케이션을 얼마나 많이 구축하든 고정되어 있다는 것입니다. 이는 AI 동료마다 컨테이너와 브라우저를 개별적으로 생성하여 신규 인원이 추가될 때마다 메모리 하한선이 높아지는 OpenBot 방식보다 비용 측면에서 훨씬 안정적입니다.

Dify는 모델 API 키와 검색을 위해 업로드한 비공개 문서를 보관하므로, 설치 초기부터 서버를 민감한 자산으로 취급해야 합니다. 이 가이드는 Dify를 설치한 후, 비밀 정보를 다루는 모든 서비스와 동일한 수준으로 보안을 강화하는 방법을 다룹니다.

사전 요구 사항

Ubuntu 24.04를 실행 중인 VPS, 최소 4 GiB의 RAM, 2개의 CPU 코어가 필요합니다. 또한 Docker와 Docker Compose 플러그인이 설치되어 있어야 합니다(Dify는 Compose 2.24.0 이상 버전이 필요합니다). 사용자 계정은 sudo 권한을 가지고 있거나 docker 그룹에 속해 있어야 합니다. 아래의 복제 명령은 git, curl, jq도 사용합니다. Docker가 처음이라면 VPS에서 Docker Compose 기초 문서를 통해 설치 방법과 이 가이드에서 가정하는 핵심 명령어를 확인할 수 있습니다. 서버를 가리키는 도메인 이름을 준비하는 것이 좋습니다. IP 주소를 직접 노출하기보다 Dify 앞에 TLS를 적용하는 것이 바람직하기 때문입니다.

1단계: Dify 및 Compose 파일 가져오기

Dify는 Docker 설정을 메인 저장소에서 관리합니다. 개발 브랜치가 아닌 최신 릴리스를 복제하고 docker 디렉터리로 이동합니다.

git clone --branch "$(curl -s https://api.github.com/repos/langgenius/dify/releases/latest | jq -r .tag_name)" https://github.com/langgenius/dify.git
cd dify/docker
cp .env.example .env

복제 시 "Remote branch null" 오류가 발생하면 GitHub API 조회 결과가 없는 것이므로, 릴리스 페이지에서 버전을 선택하여 --branch에 직접 입력하십시오.

.env 파일은 핵심 설정 파일입니다. 작업을 시작하기 전에 내용을 확인하십시오. 가장 먼저 설정해야 할 값은 비밀번호와 보안 키 관련 항목인 SECRET_KEY, Postgres 비밀번호, Redis 비밀번호입니다. SECRET_KEY는 비어 있는 상태로 제공되며, 그대로 두면 Dify가 키를 생성하여 저장소 디렉터리에 보관합니다. 비밀번호는 다른 문제입니다. 예제 파일은 Postgres와 Redis에 동일한 difyai123456를 설정하며, 코드 샌드박스, 플러그인 데몬, Weaviate에 대해 고정된 공개 키를 사용합니다. 이를 기본값 그대로 두는 것은 자가 호스팅 Dify가 해킹당하는 가장 흔한 원인입니다. 직접 비밀 키를 설정하려면 다음 명령어로 생성하십시오.

openssl rand -base64 42

생성된 키를 SECRET_KEY에 붙여넣고, 파일 내의 모든 비밀번호와 키 필드에 강력하고 고유한 값을 설정하십시오. Redis 비밀번호는 CELERY_BROKER_URL 내부에도 포함되어 있으므로, 워커가 Redis에 접근할 수 있도록 해당 파일에서도 동일하게 변경해야 합니다.

2단계: 서비스 시작

스택을 실행합니다:

docker compose up -d

첫 실행 시 여러 이미지를 내려받고 데이터베이스를 초기화하므로 1분 정도 기다려야 합니다. 컨테이너가 정상 상태인지 확인합니다:

docker compose ps

상시 실행되는 모든 서비스는 running 상태여야 합니다. 일회성 권한 설정 작업은 완료 후 종료됩니다. Dify는 기본적으로 80번 포트에서 번들된 nginx 컨테이너를 통해 웹 인터페이스를 제공합니다. http://YOUR_SERVER/install에 처음 접속하면 관리자 계정을 생성하게 됩니다. 다른 사용자가 해당 포트에 접근하기 전에 즉시 계정을 생성하십시오. 계정이 생성되기 전까지는 페이지에 접속하는 누구나 인스턴스의 소유권을 가져갈 수 있기 때문입니다.

3단계: 원시 상태로 노출하지 마십시오. TLS와 방화벽을 앞단에 배치하십시오

대부분의 빠른 설치는 여기서 멈추고, 대부분의 사고는 여기서 시작됩니다. Dify의 자체 nginx는 모든 인터페이스의 80번 포트에서 평문으로 수신 대기하며 443번 포트도 공개합니다. 관리자 로그인 정보와 모델 키가 평문 HTTP로 전송되는 것을 원치 않을 것이며, 내부 서비스가 외부에서 접근 가능한 상태가 되는 것도 피해야 합니다.

SSH와 웹 트래픽만 허용하는 기본 거부(default-deny) 방화벽으로 서버를 보호하십시오:

sudo ufw default deny incoming
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

IPv4만 다루는 방화벽은 IPv6에서도 동일한 포트를 열어둘 수 있음을 기억하십시오. 이는 많은 자가 호스팅 사용자가 겪는 IPv6 방화벽 공백입니다. 두 스택 모두 필터링되는지 확인하십시오. 또한 Docker가 공개하는 포트는 ufw가 아닌 Docker 자체 방화벽 규칙에 의해 처리된다는 점을 알아야 합니다. 기본 스택은 플러그인 데몬의 디버깅 포트인 5003번을 모든 인터페이스에 공개합니다. 다른 머신에서 플러그인을 디버깅할 목적이 아니라면 .env 내의 EXPOSE_PLUGIN_DEBUGGING_PORT을 127.0.0.1:5003로 설정하십시오.

TLS의 경우, 가장 깔끔한 방법은 Dify의 웹 포트를 루프백(loopback)에 바인딩하고 앞단에 Let's Encrypt 인증서를 사용하는 리버스 프록시를 실행하는 것입니다. 이렇게 하면 공용 인터넷에는 HTTPS를 사용하는 프록시만 노출됩니다. Dify의 .env을 사용하면 노출되는 포트를 변경할 수 있습니다. 이를 127.0.0.1에 바인딩되도록 설정하고 프록시가 해당 포트를 가리키게 하십시오. Dify의 nginx가 기본적으로 호스트의 443번 포트를 점유하므로, 프록시가 이를 사용해야 하므로 EXPOSE_NGINX_SSL_PORT에 대해서도 동일하게 처리하십시오. VPS에서 AI 에이전트를 안전하게 실행하기에 나오는 에이전트 강화 아이디어도 여기에 적용됩니다. 가동 요소는 루프백에 유지하고, 공개가 필수적인 것만 노출하며, 하나의 강화된 현관문이 TLS를 처리하게 하십시오. 도구의 인터페이스가 오직 사용자 본인만을 위한 것이고 인증서가 전혀 필요 없다면, 프록시를 건너뛰고 SSH 터널을 통해 접근하십시오. open-kritt 보안 스캐너 자가 호스팅 사례처럼 대시보드를 루프백에 바인딩하고 공개하는 대신 노트북으로 포워딩하는 방식입니다. 팀 전체가 Dify를 사용해야 하지만 공용 인터넷에는 노출하고 싶지 않다면, 오버레이 네트워크를 통해 이 아이디어를 확장할 수 있습니다. 서버의 사설 서브넷을 tailnet에 광고하기를 사용하면 방화벽은 SSH 외의 모든 접근을 차단한 상태에서도 승인된 모든 장치가 사설 주소로 빌더에 접근할 수 있습니다. 수동이 아닌 코딩 에이전트를 통해 이 서버를 관리한다면, 에이전트에게 권한을 부여하기 전에 무인 상태에서 어느 정도까지 작업을 허용할지 결정하십시오. Claude Code의 권한 모드에 따라 .env을 수정하거나 스택을 재시작하기 전에 사용자에게 확인을 요청할지 여부가 결정되기 때문입니다. 한 세션에서는 컨테이너 로그를 확인하고 다른 세션에서는 프록시 설정을 편집하는 상황이라면, 두 세션 간에 동일한 서버 내에서 텍스트를 주고받을 수 있습니다. 이는 스택을 재시작할 때마다 터미널 간에 출력을 복사하는 것보다 효율적입니다.

단계 4: 패치 유지

Dify는 빠르게 발전하며, 업데이트에는 보안 수정 사항이 포함됩니다. 릴리스 태그를 클론했으므로, 업데이트는 브랜치를 풀(pull)하는 것이 아니라 다음 태그를 체크아웃하는 방식으로 진행합니다. 먼저 데이터베이스를 백업한 다음, docker 디렉터리에서 다음을 수행하십시오:

docker compose down
git fetch --tags
git checkout NEW_VERSION
docker compose pull
docker compose up -d

데이터베이스 마이그레이션은 시작 시 자동으로 실행되며, 일부는 되돌릴 수 없으므로 반드시 먼저 백업해야 합니다. 메이저 업데이트뿐만 아니라 모든 업그레이드 전에 릴리스 노트를 읽으십시오. Dify는 릴리스마다 업그레이드 단계가 다르다고 명시하고 있습니다. 예를 들어 2026년 9월의 1.17.1 릴리스 노트는 기존 데이터를 포함한 번들 Weaviate를 실행 중인 사용자에게 해당 버전으로 바로 건너뛰지 말고 각 마이너 릴리스를 순차적으로 거칠 것을 권고합니다. 또한 Dify는 릴리스 간에 .env 스키마를 변경하므로, 새 태그를 체크아웃한 후 .env.example와 .env를 비교하여 변경 사항을 반영하십시오. 설정하지 않은 새로운 변수로 인해 컨테이너가 시작되지 않을 수 있기 때문입니다.

5단계: 재생성할 수 없는 데이터 백업하기

Dify 서버에서 대체 불가능한 데이터는 두 가지입니다. 앱, 사용자, 설정을 담고 있는 Postgres 데이터베이스와 업로드된 문서 및 벡터 인덱스를 저장하는 볼륨입니다. 두 데이터 모두 docker 디렉터리 내의 Docker 볼륨에 위치합니다. 이 볼륨들을 주기적으로 스냅샷으로 생성하고 서버 외부로 복사하십시오. 스냅샷에는 모든 모델 키와 업로드된 문서가 하나의 파일에 포함되므로, 서버 외부로 반출하기 전에 반드시 암호화해야 합니다. 이는 Vaultwarden 백업이 견고한 비밀번호 서버의 취약점이 되는 이유와 같은 맥락입니다. 모델 API 키는 재발급받을 수 있지만, 일주일 동안 공들여 만든 앱은 복구할 수 없습니다. 실행 중인 머신보다 더 오래 유지되어야 하는 상태를 가진 모든 에이전트도 같은 원칙이 적용됩니다. KiroCrew를 상시 가동 컨테이너로 유지하는 것은 재부팅 시 사라질 메모리와 스케줄을 스냅샷으로 보존하는 작업에 달려 있습니다.

이곳에서 구축한 에이전트가 개인 데이터셋을 넘어 실시간 웹을 검색하게 하려면, 직접 호스팅하는 SearXNG 인스턴스를 연결하여 쿼리 스트림을 직접 제어하는 하드웨어 내에 머물게 할 수 있습니다. 다만, 이를 활성화하기 전에 발생할 수 있는 프롬프트 인젝션 공격 표면에 대해 미리 숙지하는 것이 좋습니다. 더 자율적이고 코드를 실행하는 에이전트를 원한다면 Agent Zero 직접 호스팅을 참조하십시오. 또한 VPS에서 직접 AI 에이전트 구축하기는 이 모든 서비스의 기반이 되는 기초 지식을 다룹니다.

FAQ

Dify를 자체 호스팅하기 위한 시스템 요구 사항은 무엇입니까?

Dify는 최소 4 GiB의 RAM과 2개의 CPU 코어, 그리고 Docker Compose 2.24.0 이상의 버전을 요구합니다. 이 기준은 2026년 10월 기준으로 15개의 상시 실행 컨테이너와 1회의 초기화 작업으로 구성된 기본 스택의 규모를 반영한 것입니다. 업로드할 문서와 벡터 인덱스를 위한 충분한 디스크 공간을 확보하고, 다른 서비스와 서버를 공유한다면 메모리를 추가로 할당하십시오.

Dify를 80번 포트로 직접 노출해도 안전합니까?

아니요. Dify에 포함된 웹 서버는 일반 HTTP로 수신 대기하며, 관리자 로그인 페이지와 모델 API 키를 노출하게 됩니다. Let's Encrypt 인증서를 사용하는 리버스 프록시를 앞단에 배치하고, Dify의 포트는 루프백(loopback) 주소에 바인딩하여 HTTPS 프록시만 인터넷에 노출되도록 구성하십시오. 또한 IPv4와 IPv6를 모두 차단하는 기본 거부(default-deny) 방화벽을 함께 설정하십시오.

자체 호스팅 중인 Dify는 어떻게 업데이트합니까?

데이터베이스를 백업한 뒤, docker 디렉터리에서 docker compose down, git fetch --tags를 실행하고, 새로운 릴리스 태그로 git checkout를 수행한 다음, docker compose pull 및 docker compose up -d을 실행하십시오. 릴리스마다 업그레이드 절차가 다르고 마이그레이션이 비가역적일 수 있으며, Dify에 새로운 .env 변수가 추가되는 경우가 있으므로 반드시 릴리스 노트를 먼저 읽어보십시오. 설정 변수가 누락되면 컨테이너가 실행되지 않을 수 있습니다.

Dify 설치 후 가장 먼저 해야 할 일은 무엇입니까?

/install에 접속하여 즉시 관리자 계정을 생성하십시오. 해당 계정이 생성되기 전까지는 페이지에 접근할 수 있는 누구라도 계정을 선점할 수 있습니다. 컨테이너가 정상적으로 실행되는 즉시, 그리고 방화벽을 외부로 개방하기 전에 관리자 계정을 설정하십시오.