Khi triển khai website (WordPress, CodeIgniter, Laravel, …) thường sẽ có một thư mục dùng để lưu cache (ví dụ /var/www/cache). Nếu phân quyền không đúng, webserver (chạy với user www-data) sẽ gặp lỗi khi ghi cache:

Permission denied: cannot write to cache

Trong bài viết này, mình sẽ hướng dẫn chi tiết cách cấu hình chown, chmod và ACL để đảm bảo thư mục cache luôn có thể ghi thoải mái, kể cả khi file được tạo bởi root hoặc user khác.


1. Thư mục cache mặc định

Ví dụ thư mục cache của bạn là:

/var/www/cache

2. Đổi chủ sở hữu thư mục về www-data

Thông thường webserver (Nginx, Apache, PHP-FPM) chạy với user www-data. Vì vậy bạn cần cấp quyền sở hữu cho user này:

sudo chown -R www-data:www-data /var/www/cache
  • -R: áp dụng đệ quy cho toàn bộ thư mục con và file bên trong.
  • Sau khi chạy, toàn bộ file sẽ thuộc về www-data:www-data.

3. Cấp quyền đọc/ghi/thực thi cơ bản bằng chmod

Để www-data có thể đọc/ghi thư mục cache, bạn nên dùng:

sudo chmod -R 2775 /var/www/cache

Giải thích:

  • 775 = Owner + Group có toàn quyền (đọc/ghi/thực thi).
  • 5 = Other chỉ được đọc + truy cập.
  • 2 (setgid) = đảm bảo mọi file/folder mới tạo bên trong sẽ luôn giữ group = www-data.

4. Bật ACL để luôn đảm bảo www-data có quyền

Để tránh tình huống root hoặc user khác tạo file mà www-data không sửa/xóa được, bạn nên dùng ACL:

Cài đặt ACL (nếu chưa có)

Ubuntu/Debian:

sudo apt install acl -y

CentOS/RHEL:

sudo yum install acl -y

Thiết lập ACL cho thư mục cache

sudo setfacl -R -m g:www-data:rwx /var/www/cache
sudo setfacl -dR -m g:www-data:rwx /var/www/cache

Giải thích:

  • -m = gán quyền ngay cho các file/thư mục hiện có.
  • -d = default ACL → áp dụng cho mọi file/thư mục mới tạo sau này.
  • g:www-data:rwx = group www-data luôn có quyền đọc/ghi/thực thi.

5. Kiểm tra kết quả

Tạo thử một file trong cache bằng root:

sudo touch /var/www/cache/test.php
ls -l /var/www/cache/test.php

Kết quả sẽ giống:

-rw-rw-r--+ 1 root www-data 0 Aug 16 13:06 test.php
  • Owner = root
  • Group = www-data
  • Quyền = rw-rw-r--www-data có thể đọc + ghi
  • Có dấu + → ACL đang hoạt động

Xem ACL chi tiết:

getfacl /var/www/cache/test.php

6. Kết luận

Với cấu hình trên:

  • Bất kỳ ai (kể cả root) tạo file trong /var/www/cache thì www-data vẫn có thể đọc, ghi, xóa.
  • WordPress / CI3 / Laravel / custom PHP code ghi cache thoải mái, không lo bị lỗi Permission denied.
  • Thư mục cache luôn an toàn và nhất quán.

✅ Lệnh đầy đủ một lần duy nhất:

sudo chown -R www-data:www-data /var/www/cache
sudo chmod -R 2775 /var/www/cache
sudo setfacl -R -m g:www-data:rwx /var/www/cache
sudo setfacl -dR -m g:www-data:rwx /var/www/cache

7. Cách chạy quyền cho cronjob tạo file cache

Khi bạn dùng cronjob để tạo cache, có 2 tình huống:

a) Cronjob chạy bằng root

Nếu bạn viết trong sudo crontab -e, cronjob sẽ chạy dưới quyền root. Lúc này file cache sẽ do root tạo ra, có thể gây lỗi khi webserver không sửa được.
👉 Cách khắc phục:

  • Dùng setfacl như trên để www-data luôn có quyền ghi.
  • Hoặc ép cronjob chạy dưới www-data: sudo -u www-data crontab -e Cronjob tạo ra file sẽ giống như webserver tạo → không còn lỗi phân quyền.

b) Cronjob chạy bằng user www-data

Bạn chỉ cần thêm job bằng:

sudo -u www-data crontab -e

Ví dụ:

* * * * * php /var/www/html/artisan schedule:run >> /dev/null 2>&1

Lúc này file cache sinh ra sẽ luôn có user www-data, group www-data → an toàn tuyệt đối.


Kết luận

  • Nếu muốn đơn giản: sudo chown -R www-data:www-data /var/www/cache là đủ.
  • Nếu có nhiều tiến trình khác nhau tạo cache: dùng chmod 2775 hoặc setfacl.
  • Khi dùng cronjob, nên chạy bằng www-data thay vì root để tránh xung đột quyền.