Linux chmod và chown: 3 Năm Quản Lý 10+ VPS Dạy Tôi Điều Gì Về Phân Quyền

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

Hai Cách Tư Duy Về Phân Quyền Linux — Và Tại Sao Một Cách Gây Ra Rắc Rối

Sau 3 năm quản lý hơn 10 VPS Linux, tôi đã thấy hai nhóm sysadmin xử lý phân quyền file theo hai cách hoàn toàn khác nhau. Nhóm đầu tiên dùng chmod và chown như một giải pháp tạm thời — họ chạy chmod 777 cho một thư mục rồi xem như xong. Nhóm thứ hai hiểu toàn bộ mô hình phân quyền và không bao giờ phải cuống cuồng lúc 2 giờ sáng vì web server phục vụ những file không đáng lẽ phải phục vụ.

Đây không phải là bài giải thích “phân quyền là gì” thông thường. Đây là những gì 3 năm đó thực sự dạy tôi về cách hai cách tiếp cận này diễn ra trong môi trường production thực tế.

So Sánh Hai Cách Tiếp Cận: Lối Tắt Dễ Dãi vs. Nguyên Tắc Đặc Quyền Tối Thiểu

Lối Tắt Dễ Dãi (Điều Hầu Hết Người Mới Làm)

Hầu hết người mới gặp lỗi permission denied đều làm cùng một việc: mở rộng quyền cho đến khi ứng dụng không còn phàn nàn. Bạn thấy lỗi, và bạn chạy:

chmod 777 /var/www/html/uploads
chown -R root:root /var/www/html

Ứng dụng chạy được. Vấn đề đã giải quyết, đúng không? Không hẳn. Mọi file giờ đây đều có thể đọc và ghi bởi tất cả mọi người. Bất kỳ tiến trình nào trên server đó — kể cả một script PHP bị xâm phạm — đều có quyền ghi vào thư mục upload. Sở hữu mọi thứ bằng root, và một lỗ hổng web duy nhất sẽ chạy với quyền root trên toàn bộ hệ thống.

Tôi đã thấy chính xác thiết lập này trên các server production nơi mọi người không thể hiểu tại sao WordPress của họ cứ bị tấn công thay đổi nội dung. Nguyên nhân hầu như luôn là thư mục uploads 777 với quyền sở hữu root.

Đặc Quyền Tối Thiểu (Cách Bạn Nên Làm)

Đặc quyền tối thiểu có nghĩa là mỗi tiến trình và người dùng chỉ nhận được đúng những quyền họ thực sự cần. Không hơn không kém. Để làm được điều đó cần hiểu cách chmod và chown hoạt động cùng nhau — không chỉ riêng lẻ từng cái.

Hãy nghĩ theo cách này: chown quyết định ai sở hữu file, còn chmod quyết định chủ sở hữu đó thực sự có thể làm gì với nó. Bạn cần cả hai hoạt động cùng nhau mới xây dựng được thứ gì đó hợp lý.

# Tạo người dùng chuyên dụng cho ứng dụng web
useradd -r -s /bin/false www-data

# Đặt quyền sở hữu đúng (người dùng:nhóm)
chown -R www-data:www-data /var/www/html

# Đặt quyền hợp lý: chủ sở hữu rwx, nhóm rx, người khác không có gì
chmod -R 750 /var/www/html

# Chỉ riêng thư mục uploads: chủ sở hữu rwx, nhóm rwx
chmod 770 /var/www/html/uploads

Bây giờ tiến trình web server (chạy với tư cách www-data) có thể đọc và thực thi các file ứng dụng, ghi vào uploads — nhưng người dùng bên ngoài hay tiến trình lạ không thể dò xét trong cây thư mục của bạn.

Ưu và Nhược Điểm: Chỗ Nào Mỗi Cách Tiếp Cận Thất Bại

Cách Tiếp Cận Dễ Dãi

  • Ưu: Thiết lập nhanh, loại bỏ lỗi phân quyền ngay lập tức
  • Ưu: Không cần hiểu mô hình bên dưới
  • Nhược: Một script bị xâm phạm có thể ghi ở bất cứ đâu
  • Nhược: File có thể đọc bởi mọi người làm lộ file cấu hình, log, thông tin đăng nhập
  • Nhược: File web thuộc sở hữu root nghĩa là lỗ hổng web chạy với quyền root
  • Nhược: Gần như không thể kiểm tra — bạn mất dấu cái gì nên và không nên có quyền ghi

Cách Tiếp Cận Đặc Quyền Tối Thiểu

  • Ưu: Giới hạn phạm vi ảnh hưởng nếu có thứ gì đó bị xâm phạm
  • Ưu: Dễ kiểm tra hơn — phân quyền phản ánh đúng mục đích
  • Ưu: Buộc bạn phải hiểu cách ứng dụng của mình truy cập file
  • Nhược: Tốn công cấu hình ban đầu hơn
  • Nhược: Cần kiến thức về chế độ số và chế độ ký hiệu
  • Nhược: Debug vấn đề phân quyền mất nhiều thời gian hơn lúc đầu

Những nhược điểm cuối thực ra chỉ là đường cong học tập. Sau khi cấu hình đúng cho 3–4 server, debug vấn đề phân quyền trở thành bản năng thứ hai — thường chỉ mất 30 giây kiểm tra bằng ls -la.

Thiết Lập Khuyến Nghị Cho Linux Server

Hiểu Bộ Ba Phân Quyền Trước Tiên

Mỗi file và thư mục trong Linux có ba bộ phân quyền: chủ sở hữu, nhóm, và người khác. Mỗi bộ có ba bit: đọc (r=4), ghi (w=2), thực thi (x=1). Chế độ số chỉ là tổng của các bit đó cho mỗi bộ.

# Các giá trị phân quyền phổ biến trong production:
# 755 = rwxr-xr-x  (thư mục, script)
# 644 = rw-r--r--  (file thường, cấu hình)
# 600 = rw-------  (khóa riêng tư, bí mật)
# 750 = rwxr-x---  (thư mục ứng dụng, nhóm có thể đọc)
# 770 = rwxrwx---  (thư mục dùng chung có quyền ghi)

# Kiểm tra nhanh: một file thực sự có những quyền gì?
ls -la /etc/ssh/sshd_config
# -rw-r--r-- 1 root root 3287 Jan 10 09:12 /etc/ssh/sshd_config

Thiết Lập VPS Chuẩn Của Tôi

Sau hơn mười server, đây là mô hình phân quyền tôi áp dụng không cần nghĩ mỗi khi một VPS mới đi vào hoạt động:

# Khóa SSH riêng tư: chỉ chủ sở hữu đọc được, không ai khác
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 700 ~/.ssh

# File ứng dụng web
chown -R appuser:www-data /var/www/myapp
find /var/www/myapp -type f -exec chmod 640 {} \;
find /var/www/myapp -type d -exec chmod 750 {} \;

# Thư mục có quyền ghi (uploads, cache)
chmod 770 /var/www/myapp/storage
chmod 770 /var/www/myapp/public/uploads

# File cấu hình chứa thông tin bí mật
chmod 600 /var/www/myapp/.env

Cách dùng find đó rất quan trọng. Đừng bao giờ chạy chmod -R 755 trên thư mục chứa file thường — nó đánh dấu mọi file là có thể thực thi, và hầu như đó không bao giờ là điều bạn muốn. Luôn xử lý file và thư mục riêng biệt.

Hướng Dẫn Thực Hành: chmod và chown Trong Thực Tế

chown: Đặt Quyền Sở Hữu

# Chỉ thay đổi chủ sở hữu
chown appuser /var/log/myapp.log

# Thay đổi chủ sở hữu và nhóm
chown appuser:appgroup /var/log/myapp.log

# Thay đổi quyền sở hữu đệ quy (dùng cẩn thận)
chown -R appuser:appgroup /var/www/myapp

# Kiểm tra quyền sở hữu hiện tại
stat /var/www/myapp/index.php
# File: /var/www/myapp/index.php
# Uid: ( 1001/ appuser)   Gid: (   33/ www-data)

chmod: Đặt Phân Quyền

# Chế độ số (phổ biến nhất trong production)
chmod 644 config.ini
chmod 755 deploy.sh
chmod 600 .env

# Chế độ ký hiệu (dễ đọc hơn trong script)
chmod u+x deploy.sh          # thêm quyền thực thi cho chủ sở hữu
chmod g-w /etc/myapp/config  # bỏ quyền ghi của nhóm
chmod o= /var/secrets        # bỏ toàn bộ quyền của người khác

# Áp dụng cho tất cả file đệ quy (chỉ file)
find /var/www -type f -exec chmod 644 {} +

# Áp dụng cho tất cả thư mục đệ quy
find /var/www -type d -exec chmod 755 {} +

Các Bit Đặc Biệt: setuid, setgid, sticky

Những bit này ít gặp hơn, nhưng bạn sẽ đụng phải chúng trên bất kỳ server thực nào.

# Sticky bit trên thư mục dùng chung (chỉ chủ sở hữu mới xóa được file của mình)
chmod +t /tmp
chmod 1777 /tmp
# Kết quả: drwxrwxrwt — chữ 't' ở cuối là sticky bit

# setgid trên thư mục dự án dùng chung
# (file mới kế thừa nhóm của thư mục, không phải nhóm chính của người tạo)
chmod g+s /var/www/shared
chmod 2775 /var/www/shared
# Kết quả: drwxrwsr-x

# Kiểm tra bằng ls -la:
ls -la /tmp
# drwxrwxrwt 12 root root 4096 Mar 6 08:00 /tmp

Kiểm Tra Trước Khi Áp Dụng Lên Production

Từng bị đốt một lần vì thay đổi phân quyền sai trên server đang chạy, giờ tôi tuân theo quy trình nghiêm ngặt trước khi thay đổi. Đừng bỏ qua bước này trên production:

# 1. Ghi lại trạng thái hiện tại trước khi thay đổi bất cứ thứ gì
ls -laR /var/www/myapp > /tmp/permissions_before.txt

# 2. Thử nghiệm với một file trước
chmod 640 /var/www/myapp/index.php

# 3. Xác nhận ứng dụng vẫn hoạt động
curl -I https://myapp.example.com/

# 4. Áp dụng cho tất cả file chỉ khi thử nghiệm thành công
find /var/www/myapp -type f -exec chmod 640 {} +

# 5. Kiểm tra những gì đã thay đổi
ls -laR /var/www/myapp > /tmp/permissions_after.txt
diff /tmp/permissions_before.txt /tmp/permissions_after.txt

Bước diff đó đã cứu tôi ít nhất hai lần khỏi việc tự khóa mình ra khỏi ứng dụng của mình.

Debug Lỗi Phân Quyền

Khi ứng dụng báo lỗi permission denied, đây là con đường nhanh nhất để chẩn đoán:

# 1. Tìm xem tiến trình của bạn đang chạy với tư cách người dùng nào
ps aux | grep nginx
ps aux | grep php-fpm

# 2. Kiểm tra quyền thực tế của file
ls -la /path/to/problematic/file

# 3. Kiểm tra xem người dùng đó có truy cập được file không
sudo -u www-data ls /var/www/myapp/storage
sudo -u www-data cat /var/www/myapp/.env

# 4. Kiểm tra quyền thư mục cha (thường là thủ phạm thực sự)
namei -l /var/www/myapp/storage/logs/app.log
# Lệnh này hiển thị quyền của từng thành phần trong đường dẫn

Lệnh namei -l là thứ tôi ước mình biết từ ngày đầu. Nó in ra quyền của mỗi thư mục trong đường dẫn, giúp bạn lập tức phát hiện tầng nào đang chặn quyền truy cập — thay vì phải đoán mò từng bước xuống cây thư mục.

Thiết Lập Nào Thực Sự Hiệu Quả

Lối tắt dễ dãi có vẻ nhanh hơn — cho đến khi bạn phải dọn dẹp một trang WordPress bị tấn công lúc nửa đêm. Bạn mất khả năng kiểm soát, mất bảo mật, và rồi mất giấc ngủ khi sự cố xảy ra. Mô hình đặc quyền tối thiểu chỉ tốn thêm khoảng 20 phút trên một server mới. Không đáng kể so với hàng giờ xử lý sự cố mà nó giúp bạn tránh được sau này.

Nguyên tắc cá nhân của tôi: nếu tôi không thể giải thích tại sao một file có những quyền như vậy, đó là dấu hiệu cảnh báo đáng điều tra. Phân quyền phải phản ánh cách ứng dụng của bạn thực sự truy cập file — không chỉ là bất cứ thứ gì làm thông báo lỗi biến mất.

Share: