Tự host Dify trên VPS bằng Docker Compose
Dify mặc định chạy 15 container và cần tối thiểu 4 GiB RAM. Đổi password trong .env trước lần boot đầu, rồi claim admin tại /install trước người khác.
Dify là gì và bạn đang đăng ký vận hành những gì
Dify là một platform có thể tự host để xây dựng ứng dụng trên các large language model. Bạn có một web interface để thiết kế chat app, agent và retrieval pipeline; một API để gọi chúng từ code của bạn; cùng một nơi để quản lý prompt, dataset và model key. Đây là loại công cụ mà một team nhỏ triển khai để mọi người cùng xây dựng trên một nền tảng private dùng chung, thay vì rải API key trong các script. Nếu các khái niệm như agent, tool call và retrieval pipeline vẫn chưa rõ, trước tiên hãy tìm hiểu các khái niệm đó từ đầu để các màn hình builder của Dify trở thành những control quen thuộc thay vì một bức tường switch không có nhãn.
Tự vận hành Dify nghĩa là phải chạy nhiều thành phần. Tính đến tháng 10 năm 2026, stack mặc định được Dify ghi trong tài liệu sẽ khởi động 15 container chạy lâu dài, cùng một task chạy một lần để thiết lập quyền file rồi thoát. Bảy container là service riêng của Dify: API server, websocket server, background worker, scheduler, web frontend, plugin daemon và agent backend. Tám container còn lại là dependency: database Postgres, Redis cache, vector database Weaviate, nginx front door, hai code sandbox và hai SSRF proxy. Docker Compose kết nối tất cả các thành phần này, nhưng đây vẫn là một stack thực sự; mức tối thiểu được Dify ghi trong tài liệu là 4 GiB RAM và 2 CPU core. Nếu VPS đó còn chạy dịch vụ khác, hãy sizing dựa trên số liệu đo thực tế thay vì con số được công bố, vì mức RAM thực tế của PhotoPrism và Immich cao hơn đáng kể so với mức tối thiểu được công bố, và photo server dùng chung máy sẽ làm database và vector store của Dify thiếu tài nguyên trước. CPU contention cũng gây ảnh hưởng tương tự: một thư viện Jellyfin được làm giao diện như cửa hàng video thập niên 90 gần như không tốn tài nguyên khi chỉ duyệt artwork, nhưng ngay khi có người bắt đầu transcode, các worker queue của Dify sẽ phải chờ. Điểm thuận lợi là số lượng container của Dify không đổi dù bạn xây dựng bao nhiêu app, nên chi phí tài nguyên dễ kiểm soát hơn OpenBot, nơi mỗi AI coworker có container riêng và browser riêng; mỗi coworker mới lại đẩy mức RAM tối thiểu lên thêm.
Vì Dify lưu model API key của bạn và thường lưu cả các tài liệu private đã nạp để retrieval, hãy coi máy chạy Dify là hệ thống nhạy cảm ngay từ phút đầu tiên. Guide này cài đặt Dify, sau đó harden hệ thống như cách bạn harden bất kỳ service nào lưu secret.
Điều kiện cần
Bạn cần một VPS chạy Ubuntu 24.04 với ít nhất 4 GiB RAM và 2 lõi CPU, Docker đã cài Docker Compose plugin (Dify yêu cầu Compose 2.24.0 trở lên), cùng một user có sudo hoặc thuộc group docker. Lệnh clone bên dưới cũng sử dụng git, curl và jq. Nếu bạn chưa quen với Docker, phần hướng dẫn cơ bản về Docker Compose trên VPS trình bày cách cài đặt và các lệnh cốt lõi được dùng trong bài này. Bạn nên có một domain trỏ đến server, vì bạn sẽ muốn đặt TLS phía trước Dify thay vì dùng địa chỉ IP trực tiếp.
Bước 1: Tải Dify và các file Compose
Dify lưu cấu hình Docker trong repository chính. Hãy clone bản release mới nhất, không dùng branch development, rồi chuyển vào thư mục 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 .envNếu lệnh clone lỗi với thông báo "Remote branch null", truy vấn GitHub API không trả về kết quả. Hãy chọn một version trên trang releases và truyền version đó cho --branch theo cách thủ công.
File .env là cấu hình cốt lõi. Hãy đọc file này trước khi bắt đầu. Trước hết, cần chú ý các giá trị dùng để đặt password và secret: SECRET_KEY, password của Postgres và password của Redis. SECRET_KEY được phát hành ở trạng thái rỗng. Nếu để nguyên, Dify sẽ tự tạo một key và lưu key đó trong thư mục storage. Password lại là vấn đề khác: file mẫu dùng cùng một difyai123456 cho cả Postgres và Redis, đồng thời dùng các key cố định và đã được công khai cho code sandbox, plugin daemon và Weaviate. Để nguyên các giá trị mặc định này là nguyên nhân phổ biến nhất khiến một hệ thống Dify tự host bị breach. Nếu muốn tự đặt secret key, hãy tạo một key:
openssl rand -base64 42Dán key đó vào SECRET_KEY, rồi đặt một giá trị mạnh và duy nhất cho mọi trường password và key trong file. Password của Redis cũng xuất hiện trong CELERY_BROKER_URL, vì vậy hãy đổi tại đó. Nếu không, worker sẽ không thể kết nối đến Redis.
Bước 2: Khởi động
Khởi động stack:
docker compose up -dLần chạy đầu tiên sẽ pull một số image và khởi tạo database, nên hãy chờ khoảng 1 phút. Kiểm tra các container đã healthy:
docker compose psMọi service chạy lâu dài phải đọc running; task cấp quyền chạy một lần sẽ thoát sau khi hoàn tất công việc. Theo mặc định, Dify cung cấp giao diện web thông qua container nginx đi kèm trên port 80. Trong lần đầu truy cập http://YOUR_SERVER/install, hãy tạo tài khoản admin. Thực hiện ngay việc này trước khi bất kỳ thành phần nào khác có thể truy cập port, vì trước khi tài khoản đó tồn tại, bất kỳ ai tải trang cũng có thể đăng ký tài khoản và chiếm quyền instance của bạn.
Bước 3: Không để dịch vụ lộ trực tiếp. Đặt TLS và firewall ở phía trước
Đây là nơi hầu hết các lần cài đặt nhanh dừng lại, và cũng là nơi hầu hết sự cố bắt đầu. nginx của Dify tự listen trên port 80, không mã hóa, trên mọi interface, đồng thời cũng publish port 443. Bạn không muốn thông tin đăng nhập admin và các model key truyền qua HTTP không mã hóa. Bạn cũng không muốn các service nội bộ có thể truy cập từ bên ngoài.
Khóa chặt máy chủ bằng firewall có chính sách mặc định từ chối, chỉ cho phép SSH và web traffic:
sudo ufw default deny incoming
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enableHãy nhớ rằng firewall chỉ áp dụng cho IPv4 có thể để các port tương tự mở trên IPv6. Đây là khoảng trống firewall trên IPv6 thường khiến nhiều self-hoster gặp sự cố. Xác nhận cả hai stack đều được lọc. Ngoài ra, các port mà Docker publish được xử lý bằng firewall rule riêng của Docker, không phải của ufw. Stack mặc định publish port debug của plugin daemon, 5003, trên mọi interface. Đặt EXPOSE_PLUGIN_DEBUGGING_PORT trong .env thành 127.0.0.1:5003, trừ khi bạn thực sự cần debug plugin từ một máy khác.
Để dùng TLS, cách gọn nhất là bind web port của Dify vào loopback và chạy reverse proxy với certificate Let's Encrypt ở phía trước. Khi đó, thành phần duy nhất trên public internet là proxy nói HTTPS. .env của Dify cho phép bạn thay đổi port được expose. Đặt nó để bind trên 127.0.0.1 rồi trỏ proxy đến đó. Làm tương tự với EXPOSE_NGINX_SSL_PORT, vì nginx của Dify mặc định chiếm host port 443 và proxy của bạn cần port này. Các nguyên tắc hardening agent trong chạy AI agent an toàn trên VPS cũng áp dụng ở đây: giữ các thành phần trên loopback, chỉ expose những gì bắt buộc phải public, và để một front door đã harden xử lý TLS. Nếu interface của một tool chỉ dành riêng cho bạn và không cần certificate, hãy bỏ qua proxy và truy cập nó qua SSH tunnel. Cách này tương tự tự host trình quét bảo mật open-kritt, trong đó dashboard được bind vào loopback và forward đến laptop của bạn thay vì publish ra ngoài. Nếu cả team cần dùng Dify nhưng không muốn public internet truy cập, overlay network có thể mở rộng cách này vượt ra ngoài một laptop: quảng bá subnet riêng của server vào tailnet cho phép mọi thiết bị được phê duyệt truy cập builder qua private address, trong khi firewall vẫn chặn mọi thứ ngoài SSH. Nếu bạn quản trị máy này bằng coding agent thay vì thao tác thủ công, hãy xác định trước agent được phép tự làm đến mức nào trước khi giao key cho nó, vì permission mode bạn để Claude Code sử dụng quyết định việc agent có dừng lại để hỏi trước khi ghi đè .env hoặc restart stack hay không. Nếu một session đang tail container log trong khi session khác chỉnh proxy config, hai session đó có thể truyền text cho nhau trên cùng máy chủ, thuận tiện hơn việc phải sao chép output giữa các terminal mỗi lần restart stack.
Bước 4: Luôn cập nhật bản vá
Dify phát hành nhanh, và các bản cập nhật có thể bao gồm bản vá bảo mật. Vì bạn đã clone một release tag, để cập nhật, hãy checkout tag tiếp theo thay vì pull một branch. Trước tiên hãy sao lưu database, sau đó chạy các lệnh sau trong thư mục docker:
docker compose down
git fetch --tags
git checkout NEW_VERSION
docker compose pull
docker compose up -dDatabase migration chạy tự động khi khởi động. Một số migration không thể hoàn tác, nên phải sao lưu trước. Hãy đọc release notes trước mọi lần nâng cấp, không chỉ các bản nâng cấp lớn. Dify cho biết các bước nâng cấp thay đổi tùy theo từng release. Ví dụ, release notes của 1.17.1 (September 2026) yêu cầu những người đang chạy Weaviate đi kèm với dữ liệu hiện có không được nâng cấp thẳng lên phiên bản đó. Thay vào đó, hãy lần lượt đi qua từng minor release. Dify cũng thay đổi schema của .env giữa các release. Vì vậy, sau khi checkout tag mới, hãy so sánh .env.example với .env và chuyển các thay đổi của bạn sang. Một variable mới chưa được set có thể khiến container không khởi động.
Bước 5: Sao lưu những dữ liệu không thể tạo lại
Có 2 thứ trên một máy Dify không thể thay thế: database Postgres chứa các app, user và thiết lập của bạn, cùng volume lưu tài liệu đã upload và vector index. Cả 2 đều nằm trong Docker volume ở thư mục docker. Hãy snapshot chúng theo lịch và sao chép các snapshot ra ngoài server. Các snapshot này chứa mọi model key và tài liệu đã upload trong một file duy nhất, vì vậy hãy mã hóa chúng trước khi đưa ra khỏi server, cũng vì lý do một bản sao lưu Vaultwarden có thể trở thành điểm yếu của một password server vốn được bảo mật tốt. Model API key có thể cấp lại; app mà bạn mất cả tuần để xây dựng thì không thể. Cách suy luận này cũng áp dụng cho mọi agent có state cần tồn tại lâu hơn máy đang chạy nó: duy trì KiroCrew chạy dưới dạng container luôn bật thực chất là snapshot memory và lịch chạy, nếu không chúng sẽ biến mất ở lần reboot tiếp theo.
Khi muốn các agent xây dựng tại đây truy cập vượt ra ngoài dataset của bạn và tìm kiếm web trực tiếp, trỏ chúng đến một instance SearXNG tự host sẽ giữ luồng truy vấn trên phần cứng do bạn kiểm soát. Tuy nhiên, bạn nên tìm hiểu về bề mặt tấn công prompt injection phát sinh trước khi bật tính năng này. Với một agent tự chủ hơn, có thể chạy code, hãy xem tự host Agent Zero. Tự xây dựng AI agent trên một VPS trình bày các nền tảng dùng chung cho tất cả các agent này.
FAQ
Yêu cầu hệ thống để self-host Dify là gì?
Dify nêu yêu cầu tối thiểu là 4 GiB RAM và 2 CPU core, cùng Docker Compose 2.24.0 trở lên. Mức tối thiểu này phản ánh quy mô của stack mặc định: 15 container chạy lâu dài và 1 tác vụ khởi tạo chạy một lần, tính đến tháng 10 năm 2026. Hãy dành đủ dung lượng disk cho tài liệu đã upload và vector index. Nếu máy còn chạy dịch vụ khác, hãy cấp thêm memory.
Expose trực tiếp Dify trên port 80 có an toàn không?
Không. Web server đi kèm Dify chỉ listen trên HTTP không mã hóa. Nó cũng đứng trước trang admin login và các model API key của bạn. Hãy đặt một reverse proxy có certificate Let’s Encrypt ở phía trước, bind port riêng của Dify vào loopback, và chỉ cho HTTPS proxy giao tiếp với Internet. Kết hợp với firewall default-deny áp dụng cho cả IPv4 và IPv6.
Làm cách nào để update Dify self-hosted?
Hãy backup database. Sau đó, từ thư mục docker, chạy docker compose down, git fetch --tags, git checkout tag của release mới, docker compose pull và docker compose up -d. Đọc release note trước vì các bước upgrade thay đổi giữa các release. Migration có thể không thể hoàn tác. Dify đôi khi cũng thêm các biến .env mới, và thiếu một biến có thể khiến container không khởi động.
Việc đầu tiên cần làm sau khi cài đặt Dify là gì?
Truy cập /install và tạo admin account ngay. Cho đến khi account đó tồn tại, bất kỳ ai truy cập được trang này đều có thể chiếm quyền tạo account. Hãy thiết lập account ngay khi các container đã healthy, trước khi mở firewall cho Internet.