Nextcloud thực sự kém ở đâu trên VPS?
Tìm giới hạn Nextcloud trên VPS: 400.000 file nhỏ làm chậm database, sync client gặp cây thư mục lớn, cron và memory cho Office cần cấu hình đúng.
Nextcloud kém ở đâu, theo thứ tự bạn sẽ gặp phải
Phần lớn giới hạn của Nextcloud trên VPS đến từ số lượng file và số lượng request, không phải từ dung lượng disk. Một thư viện video 200 GB hoạt động bình thường trên một server nhỏ. Cũng 200 GB đó nhưng trải trên 400,000 file nhỏ sẽ khiến việc liệt kê thư mục chậm đi và biến database thành tiến trình bận nhất trên máy. Thứ tự dưới đây là thứ tự mà người tự host thường gặp các giới hạn này: mô hình request của PHP, sau đó là sync client, các thiết lập mặc định của database, background job, rồi đến memory.
Một số trường hợp được gọi là “Nextcloud chậm” thực ra là do một thiết lập mặc định chưa được thay đổi. Phần còn lại là giới hạn của thiết kế, và việc tuning sẽ không loại bỏ được. Mỗi phần sẽ nói rõ trường hợp đó thuộc loại nào.
Vì sao PHP quyết định giới hạn concurrency của bạn
Nextcloud được viết bằng PHP, và ứng dụng PHP không phải là server chạy lâu dài. Mỗi request được xử lý bởi một worker process trong pool PHP-FPM (FastCGI process manager), và worker đó giữ request từ đầu đến cuối. Vì vậy, số request mà server có thể xử lý cùng lúc là pm.max_children, và mỗi worker có vùng nhớ riêng.
Từ đó có hai hệ quả. Một request chậm giữ worker trong toàn bộ thời gian xử lý, nên một người dùng đang tạo upload 4 GB sẽ chiếm một slot mà người khác không thể dùng. Khi mọi worker đều bận, request mới phải chờ trong socket backlog. Pool sẽ ghi rõ điều này trong log:
WARNING: [pool www] server reached pm.max_children setting (5), consider raising itNgười đọc thường gặp triệu chứng trước tiên dưới dạng lỗi 504 từ web server phía trước:
upstream timed out (110: Connection timed out) while reading response header from upstreamPool mặc định của bản phân phối thường được phát hành với pm.max_children = 5. Đây là mức ước tính hợp lý cho một máy dùng chung, nhưng quá thấp đối với một instance Nextcloud có hàng chục client sync kết nối. Hãy tính dựa trên lượng memory thực tế bạn có: đo resident size của một worker đang bận, chừa đủ chỗ cho database và cache, rồi chia ra.
pm = dynamic
pm.max_children = 12
pm.max_requests = 500
php_value[memory_limit] = 512Mmemory_limit là giới hạn cho mỗi request, không phải lượng memory được cấp phát sẵn. Hầu hết request chỉ dùng một phần nhỏ của giới hạn này. Tạo preview và xử lý upload lớn là những tác vụ có thể dùng gần hết phần còn lại. Vì vậy phải chọn giới hạn này cùng với số child.
Các request cũng không dùng chung application memory. Mỗi request khởi động lại framework: config, app đã enable, route và event listener. OPcache giữ bytecode đã biên dịch, nên hệ thống thực thi bytecode thay vì parse lại. APCu (alternative PHP cache) giữ một key-value store cục bộ nhỏ trong shared memory. Vì vậy, dòng "No memory cache has been configured" trong phần tổng quan của admin rất quan trọng. Nếu không có memory cache, những lookup có thể trả lời từ memory sẽ phải truy vấn database trong từng request. Đây là vấn đề cấu hình. Mô hình một process cho mỗi request bên dưới nó là vấn đề kiến trúc.
Tại sao nhiều file nhỏ gây chậm từ lâu trước khi đầy disk
Nextcloud lưu metadata của mọi file và folder trong một bảng database, oc_filecache: path, path hash, size, modification time, etag và storage id. Danh sách folder là một query trên bảng đó, không phải là readdir trên disk. Mỗi lần ghi sẽ cập nhật row của file, sau đó truyền size và etag mới lên từng folder cha cho đến root. Một lần upload gồm một HTTP request, vài câu lệnh SQL và thêm một lần update cho mỗi cấp độ sâu.
Việc truyền dữ liệu cũng tính theo từng file. Sync protocol là WebDAV (web distributed authoring and versioning), và WebDAV chuyển từng file trong một request. 400,000 file tương đương 400,000 request. Mỗi request đều phải xử lý authentication, khởi tạo framework, kiểm tra quyền và ghi database. Nếu server mất 25 ms cho mỗi request, riêng phần overhead đã gần 3 giờ, chưa tính một byte payload nào. Hãy xem đây là phép tính, không phải benchmark. Điểm quan trọng là: chi phí tăng theo số lượng file, không phải theo kích thước của chúng.
Storage nhanh hơn sẽ giúp giảm một phần chi phí này. Random read và write với block nhỏ là điểm tạo khác biệt lớn nhất giữa storage NVMe và SATA SSD trên VPS, nên NVMe đáng dùng cho instance lớn. Tuy nhiên, nó không làm giảm chi phí trên mỗi request, vì chi phí đó nằm ở PHP và SQL chứ không phải disk.
Có một hệ quả mà hầu như ai cũng sẽ gặp ít nhất một lần. Các file được copy vào server bên ngoài Nextcloud không tồn tại theo góc nhìn của Nextcloud, vì chưa có thao tác nào ghi row tương ứng. Chúng chỉ xuất hiện sau khi occ files:scan duyệt qua tree và ghi các row còn thiếu. Với tree lớn, quá trình scan này sẽ mất nhiều thời gian. Nếu bạn chưa rõ các file đó nằm ở đâu trong một container install, bố cục data directory của Nextcloud trong Docker được trình bày trong một hướng dẫn riêng. Nội dung này mang tính kiến trúc: database chính là danh sách file.
Vì sao desktop client chậm khi làm việc với cây thư mục lớn
Sync client thông minh hơn danh tiếng của nó. Khi một thao tác ghi cập nhật etag lên thư mục gốc, client chỉ cần gửi một truy vấn nhẹ để biết có thay đổi nào hay không, rồi chỉ đi sâu vào những thư mục có etag khác. Vì vậy, việc polling khi rảnh không tự nó gây tốn tài nguyên.
Những chi phí còn lại là có thật. Lần sync đầu tiên sẽ duyệt mọi thư mục, gửi một request PROPFIND cho mỗi thư mục và tải xuống mọi file. Một thao tác đổi tên ở gần gốc cây sẽ làm thay đổi etag của mọi thứ bên dưới, nên client phải kiểm tra lại toàn bộ subtree đó. Client cũng duy trì database riêng và thực hiện stat trên các file cục bộ. Vì vậy, ổ đĩa laptop chậm hoặc antivirus scanner quét quá tích cực có thể làm tăng độ trễ mà hoàn toàn không liên quan đến server của bạn.
Nếu không có app Client Push, notify_push, mọi client đã kết nối đều polling theo timer. Ba mươi client tạo ra một tốc độ request nền ổn định lên cùng worker pool đang phục vụ web interface. notify_push là một service riêng nhỏ, duy trì một websocket cho mỗi client và báo cho chúng khi có thay đổi. Nhờ đó, phần lớn traffic khi rảnh được loại bỏ. Trên một instance bận, đây là một trong những bổ sung mang lại giá trị cao nhất mà bạn có thể thêm.
Không có cơ chế merge. Hai người cùng chỉnh sửa một file khi đang offline sẽ tạo ra một bản sao xung đột, được đặt tên như budget (conflicted copy 2026-08-22 141530).ods, và phải có người xử lý thủ công. Chỉnh sửa thông qua office service sẽ tránh được việc này, vì khi đó chỉ có một bản sao trên server là bản có thẩm quyền. Virtual files, trong đó file hiển thị dưới dạng placeholder cho đến khi được mở, hoạt động ổn định trên Windows và macOS nhưng mất nhiều thời gian hơn để ổn định trên Linux. Vì vậy, hãy kiểm tra phiên bản client trước khi xây dựng workflow dựa trên tính năng này. Polling là vấn đề cấu hình. Một request cho mỗi file là vấn đề kiến trúc.
Những gì bản cài đặt mặc định chưa cấu hình
Nextcloud mới cài có thể hoạt động. Tuy nhiên, trên một bản cài đặt thủ công điển hình vẫn còn thiếu 4 thứ. Cả 4 đều hiển thị trong Settings, Administration, Overview.
- Không có memory cache. Overview hiển thị "No memory cache has been configured". APCu gần như không tốn chi phí và loại bỏ rất nhiều lần truy vấn lặp lại vào database.
- File locking trong database. Nextcloud khóa file trong khi ghi file đó. Nếu không có Redis, lock được lưu trong một bảng database. Điều này làm tăng tải ghi và để lại các lock cũ sau khi một request bị dừng đột ngột. Người dùng sẽ thấy lỗi cho biết file đang bị khóa. Chỉ cleanup thủ công mới xóa được các lock này.
- Thiếu database indexes. Overview hiển thị "The database is missing some indexes" và nêu tên
occ db:add-missing-indices. Với filecache có hàng triệu dòng, các index này quyết định việc listing nhanh hay chậm. - SQLite. Bản cài đặt thủ công có thể dùng SQLite. Tài liệu chỉ khuyến nghị SQLite cho mục đích testing và các instance tối giản. Các thao tác ghi bị serialize, nên chỉ cần có người dùng thứ 2 hoạt động là đã quá nhiều.
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'redis' => [
'host' => 'localhost',
'port' => 6379,
],Không có điểm nào trong số này là bất thường. Tất cả đều là cấu hình. Nếu muốn bắt đầu với một bản cài đặt đã có sẵn các quyết định này, bản cài đặt Docker có TLS và backup sẽ khởi động cache và cron container trong cùng stack.
Vì sao background job bị đình trệ khi chưa cấu hình cron
Nextcloud đưa các tác vụ thực tế vào background job: tạo preview, xóa các phiên bản file đã hết hạn, định kỳ dọn trash, gửi email thông báo và dọn các share. Có 3 cách được hỗ trợ để chạy chúng, nhưng cách mặc định là yếu nhất.
Chế độ AJAX chạy 1 job khi trình duyệt tải một trang. Với một instance cá nhân không có ai truy cập trong 1 tuần, sẽ không có gì chạy trong 1 tuần. Các phiên bản và trash không bao giờ hết hạn, nên disk tiếp tục đầy dữ liệu mà người dùng nghĩ rằng họ đã xóa. Preview không được tạo sẵn, nên người đầu tiên mở một thư mục ảnh phải chờ trong lúc chính request của họ tạo preview. Cuối cùng, trang tổng quan báo rằng background job gần nhất đã chạy từ nhiều giờ trước và “Có vẻ đã xảy ra lỗi”, đây là cảnh báo duy nhất bạn nhận được.
Webcron và system cron đều khắc phục được vấn đề này. System cron chạy cron.php mỗi 5 phút dưới user của web server, còn bản cài đặt bằng container chạy cùng lệnh đó từ một cron container riêng. 5 phút là khoảng thời gian được tài liệu quy định, và các khoảng chạy job được điều chỉnh dựa trên khoảng thời gian này.
Chi phí còn lại là các job chạy tuần tự. Một job dài, một đợt tạo preview hoặc một lần quét file sẽ làm chậm mọi job xếp sau nó; trên VPS chỉ có 1 core, lần chạy đó còn cạnh tranh tài nguyên với các request đang hoạt động. Trên host bận, CPU steal time từ các tenant lân cận gây nhiễu kéo dài thời gian chạy hơn mức bạn dự đoán từ số liệu của chính mình. Cấu hình là cách khắc phục có giá trị cao nhất trên phần lớn instance bị bỏ quên.
Mức RAM tối thiểu sau khi thêm Office, Talk hoặc preview
Nextcloud cơ bản khá nhẹ: một PHP pool, database, Redis và web server. Một instance nhỏ chạy ổn với 2 GB. Mỗi tính năng người dùng thực sự cần lại là một service riêng với mức RAM tối thiểu riêng.
Preview. Theo mặc định, preview được tạo khi có yêu cầu đầu tiên, nên người dùng phải chờ ngay trong request cần preview đó. App Preview Generator chuyển công việc này sang cron, đổi thời gian chờ của người dùng lấy CPU trong các lần chạy cron. Dù theo cách nào, mỗi ảnh nguồn cũng tạo ra nhiều file preview ở các kích thước khác nhau. Vì vậy, thư viện ảnh làm số lượng file tăng lên nhiều lần và trực tiếp làm trầm trọng thêm vấn đề file nhỏ đã nêu ở trên. Ảnh nguồn lớn cũng là lúc chạm giới hạn bộ nhớ, như Allowed memory size of 536870912 bytes exhausted trong PHP error log. preview_max_x và preview_max_y không ngăn được việc này: chúng chỉ đặt kích thước của preview lớn nhất được lưu, còn ảnh nguồn vẫn được giải mã ở kích thước đầy đủ trước khi thu nhỏ xuống kích thước đó. Thiết lập giới hạn ảnh nguồn là preview_max_memory, mặc định 256 MB. Nextcloud đọc kích thước ảnh từ file header, giả định mỗi pixel cần 4 byte, rồi bỏ qua mọi ảnh cần nhiều bộ nhớ hơn giới hạn này và hiển thị icon file mặc định thay cho preview. Theo quy tắc đó, ảnh 20,000 x 20,000 pixel cần khoảng 1.6 GB, dù bạn đặt kích thước preview nhỏ đến đâu. preview_max_filesize_image, mặc định 50 MB, là giới hạn tương ứng trên kích thước file. Hãy giữ preview_max_memory thấp hơn đáng kể so với giới hạn PHP, thay vì cứ tăng cả hai mãi.
Office. Collabora Online và OnlyOffice Docs đều chạy dưới dạng service riêng, thường là một container riêng, với runtime riêng và lượng bộ nhớ riêng. Các session tài liệu dùng CPU và RAM của service đó, không phải của PHP. Hãy dự trù 1 hoặc 2 gigabyte trước khi hệ thống có tốc độ phản hồi tốt. Đọc yêu cầu hiện tại của nhà cung cấp tính đến tháng 8 năm 2026 trước khi chọn cấu hình máy. Hai sản phẩm này khác nhau ở nhiều điểm hơn mức sử dụng tài nguyên. Bài So sánh OnlyOffice với Collabora khi tự host trình bày rõ những khác biệt đó.
Talk. Theo mặc định, cuộc gọi đi peer-to-peer qua WebRTC và server chỉ chuyển tiếp các message signalling. Phần cài đặt quản trị của Talk cảnh báo rằng trong các cuộc gọi có hơn 2 người tham gia mà không có High Performance Backend, tức một signalling server riêng, người tham gia nhiều khả năng sẽ gặp vấn đề kết nối và thiết bị của họ sẽ chịu tải cao. Nhiều network cũng cần một server TURN (traversal using relays around NAT) như coturn. Khi đó, luồng media đi qua VPS của bạn, nên bandwidth trở thành một khoản chi phí thực tế.
Full-text search. Một instance Elasticsearch cần ít nhất một gigabyte heap cho riêng nó trước khi index bất kỳ dữ liệu nào.
Nextcloud cần VPS cấu hình thế nào?
Chỉ sizing theo số người dùng sẽ cho kết quả sai lệch, vì hành vi sử dụng mới là yếu tố quyết định. Năm developer đồng bộ một source tree có 300,000 file sẽ tạo tải lớn hơn 30 người chỉ mở tài liệu trên trình duyệt. Hãy dùng các mức dưới đây làm điểm bắt đầu để kiểm thử với số lượng file thực tế của bạn, không coi đó là số đo tuyệt đối.
- 1 vCPU và 1 đến 2 GB: một hoặc hai người dùng, chỉ dùng file và calendar, giới hạn chặt việc tạo preview, không dùng office service. Upgrade và quét toàn bộ file sẽ là những tác vụ chậm nhất từng chạy trên máy.
- 2 vCPU và 4 GB: khoảng 5 đến 15 người dùng thường xuyên, có APCu, Redis locking, system cron và tạo preview bằng cron.
- 4 vCPU và 8 GB: cùng phạm vi người dùng trên nhưng có thêm office service, hoặc 15 đến 40 người dùng nhẹ nếu không có office service. Các office session là yếu tố làm tăng memory trong trường hợp này.
- 4 vCPU trở lên và 16 GB: dùng Talk với High Performance Backend, full-text search hoặc tạo hàng loạt preview cho một thư viện ảnh.
Disk cần được tính riêng. Preview, file version và trash được cộng thêm vào dữ liệu thực tế của bạn. Chúng chỉ giảm khi background job thực sự chạy. Việc toàn bộ hệ thống có rẻ hơn subscription hay không phụ thuộc vào các con số đó, và so sánh storage tự host với giá Dropbox sẽ tính phần chênh lệch này.
Những giới hạn nào của Nextcloud có thể xử lý bằng cấu hình, và giới hạn nào mang tính kiến trúc
Có thể xử lý trong một buổi chiều: memory cache và Redis locking, các database index còn thiếu, chế độ background job, kích thước FPM pool và PHP memory limit, cấu hình kích thước OPcache, notify_push và các giới hạn preview. Một instance đã cấu hình đầy đủ những mục này là một phần mềm khác so với bản cài đặt mặc định, dù chạy trên cùng phần cứng.
Các giới hạn cố định, dù bạn có tinh chỉnh thế nào:
- Mỗi request dùng một process. Mức concurrency bị giới hạn bởi RAM, và một request chậm sẽ giữ một worker trong toàn bộ thời gian xử lý.
- Mỗi file tương ứng với một database row, trong đó size và etag được cập nhật lên mọi thư mục cha. Chi phí tăng theo số lượng file.
- Mỗi file tạo ra một request trên network. Việc sync nhiều file nhỏ bị giới hạn bởi overhead của request thay vì bandwidth.
- Đây là một nền tảng groupware có tích hợp file application. Bản cơ sở phải tải các thành phần mà một công cụ sync thuần túy không bao giờ cần.
- Upgrade được thực hiện tuần tự. Các major version được áp dụng từng bản một trong maintenance mode, và phải xử lý xong khả năng tương thích của app ở mỗi bước.
Không điều nào trong số này là bug. Đây là chi phí để hỗ trợ share link, cộng tác viên bên ngoài, mobile client và một account system dùng chung cho tất cả chức năng đó. Mua enterprise edition giúp bạn có support và một số app bổ sung, nhưng không thay đổi request model được mô tả ở trên. Đây là một trong những nội dung mà Nextcloud edition miễn phí thực sự bao gồm trình bày.
Ai không nên chạy Nextcloud trên VPS
- Bạn chỉ muốn đồng bộ nhanh một cây thư mục lớn giữa vài máy và không cần gì khác. Công cụ peer-to-peer không lưu một dòng dữ liệu cho từng file trong database của ứng dụng web, nên chi phí xử lý file nhỏ khác hẳn: Syncthing so với Nextcloud để chỉ đồng bộ file.
- Bạn muốn chia sẻ và có giao diện web, nhưng dữ liệu gồm hàng triệu file nhỏ. Seafile lưu nội dung trong block store thay vì lưu mỗi file thành một file riêng, nên cách tính chi phí thay đổi. Đổi lại, dữ liệu không còn là các file thông thường trên disk: Seafile so với Nextcloud.
- Bạn chỉ muốn xem trong trình duyệt các file đã có sẵn trên server, không cần sync client và không muốn có các dòng dữ liệu cho từng file đứng trước chúng trong database. Đây là mục đích của các file manager self-hosted nhẹ hơn.
- Yêu cầu thực tế của bạn chỉ là một shared drive cho 4 người. Hãy bắt đầu với giải pháp nhẹ hơn và bổ sung sau: các lựa chọn self-hosted thay cho Nextcloud.
- Bạn có 1 vCPU và 1 GB nhưng muốn chỉnh sửa office bằng trình duyệt. Tổ hợp này không phù hợp, và không có mức tuning nào có thể khắc phục.
Hãy chạy Nextcloud khi bạn cần các tính năng groupware: chia sẻ với người ngoài tổ chức, lịch và danh bạ trên mọi điện thoại, chỉnh sửa trong trình duyệt và một lần đăng nhập cho tất cả tính năng đó. Sự cố thường tiến triển chậm thay vì xảy ra đột ngột. Số lượng file tăng dần, hệ thống vẫn không có cache và cron, rồi một ngày một thư mục mất 8 giây để mở. Mọi phần của vấn đề này đều có thể đo được, và phần lớn có thể khắc phục trước khi xảy ra.
FAQ
Một Nextcloud VPS có thể phục vụ bao nhiêu người dùng?
Hành vi sử dụng quyết định điều này nhiều hơn số người dùng. Một server có 2 vCPU và 4 GB RAM được tối ưu có thể phục vụ thoải mái khoảng 5 đến 15 người dùng thường xuyên làm việc với file, lịch và danh bạ. Nếu thêm office service, thường cần 8 GB RAM. Giới hạn bạn gặp trước tiên thường là số PHP worker so với RAM khả dụng, hoặc database khi oc_filecache lớn. Vì vậy, hãy kiểm thử với số lượng file thực tế trước khi chốt cấu hình.
Vì sao Nextcloud chậm khi có nhiều file nhỏ?
Vì mỗi file là một row trong database và một request WebDAV riêng. Khi liệt kê một thư mục, hệ thống chạy một SQL query. Khi ghi file, hệ thống cập nhật row của file, sau đó cập nhật kích thước và etag của mọi thư mục cha. Khi truyền file, mỗi file cần một HTTP request riêng, kèm xác thực và khởi tạo framework. Vì vậy, chi phí phụ thuộc vào số lượng file hơn là tổng dung lượng. Storage nhanh hơn sẽ giảm phần chi phí do disk, nhưng không loại bỏ chi phí cố định của từng request.
Tôi có cần Redis cho Nextcloud không?
Với một người dùng thì không. Với mọi hệ thống có nhiều người dùng thì có. Nếu không có Redis, transactional file locking sẽ chạy qua một table trong database. Điều này làm tăng write load và để lại các lock cũ khi một request bị lỗi giữa chừng. Người dùng sẽ thấy lỗi cho biết file đang bị khóa. Cấu hình thường dùng là APCu cho local cache và Redis cho locking, cả hai được thiết lập trong config.php.
Điều gì xảy ra nếu tôi không bao giờ cấu hình background jobs của Nextcloud?
Chế độ AJAX mặc định chạy một job sau mỗi lần tải page, nên không có job nào chạy khi không có người đăng nhập. Preview không được tạo trước. File version và trash không bao giờ hết hạn, nên disk tiếp tục đầy lên. Notification mail cũng ngừng gửi. Cuối cùng, phần tổng quan quản trị sẽ báo rằng background job gần nhất đã chạy từ nhiều giờ trước và có vấn đề xảy ra. Cách khắc phục là chuyển sang system cron chạy mỗi 5 phút. Với cài đặt bằng container, việc này được thực hiện từ một cron container riêng.