❤️ AZDIGI chính thức cập nhật hệ thống blog mới hoàn chỉnh. Tuy nhiên có thể một số bài viết bị sai lệch hình ảnh, hãy ấn nút Báo cáo bài viết ở cuối bài để AZDIGI cập nhật trong thời gian nhanh nhất. Chân thành cám ơn.
Trên một VPS, không phải chỉ có mỗi bạn đang dùng. Hệ thống Linux chạy rất nhiều service cùng lúc, mỗi service lại chạy dưới một user riêng. Web server chạy dưới user www-data (hoặc nginx), database chạy dưới mysql, mail server chạy dưới postfix. Nếu tất cả đều có quyền đọc/ghi mọi thứ trên hệ thống thì sẽ ra sao? Một lỗ hổng ở web server có thể cho phép kẻ tấn công đọc luôn database, sửa config SSH, thậm chí cài backdoor.

Phân quyền file và thư mục là cách Linux giải quyết vấn đề này. Mỗi file, mỗi thư mục đều có thông tin rõ ràng: ai sở hữu, ai được đọc, ai được ghi, ai được thực thi. Hiểu được cách phân quyền hoạt động thì bạn sẽ biết tại sao web bị lỗi 403, tại sao script không chạy được, tại sao SSH Key bị từ chối.
Tại sao cần phân quyền?
Chạy ps aux trên VPS là bạn sẽ thấy ngay:
ps aux | head -20
Output sẽ cho thấy mỗi process chạy dưới một user khác nhau. Ví dụ:
root 1234 ... /usr/sbin/sshd
www-data 2345 ... nginx: worker process
mysql 3456 ... /usr/sbin/mysqld
nobody 4567 ... /usr/sbin/vsftpd
Mỗi user chỉ nên truy cập được đúng những gì nó cần. www-data cần đọc file web, nhưng không cần đọc /etc/shadow. mysql cần ghi vào thư mục data, nhưng không cần sửa file config của Nginx.
Nếu không phân quyền đúng, hậu quả thường gặp:
- Website trả về lỗi 403 Forbidden vì web server không có quyền đọc file
- SSH từ chối key vì file
authorized_keyscó quyền quá mở - Script deploy không chạy được vì thiếu quyền execute
- Bị hack leo thang quyền (privilege escalation) vì file nhạy cảm ai cũng đọc được
Đọc permission từ ls -la
Lệnh ls -la là cách nhanh nhất để xem quyền của file và thư mục:
ls -la /var/www/
Output trông như thế này:
drwxr-xr-x 3 www-data www-data 4096 Mar 15 10:00 .
drwxr-xr-x 14 root root 4096 Mar 10 08:30 ..
-rw-r--r-- 1 www-data www-data 612 Mar 15 10:00 index.html
-rwxr-xr-- 1 www-data www-data 2048 Mar 14 09:15 deploy.sh
lrwxrwxrwx 1 root root 24 Mar 10 08:30 html -> /var/www/html
Chuỗi 10 ký tự đầu tiên chứa toàn bộ thông tin phân quyền. Mình tách ra cho dễ hiểu:
-rwxr-xr--
│└┬┘└┬┘└┬┘
│ │ │ │
│ │ │ └── Others (người khác): r-- = chỉ đọc
│ │ └────── Group (nhóm): r-x = đọc + thực thi
│ └────────── Owner (chủ sở hữu): rwx = đọc + ghi + thực thi
└──────────── Type: - = file thường
Ký tự đầu tiên cho biết loại:
-= file thườngd= directory (thư mục)l= symbolic link
9 ký tự còn lại chia thành 3 nhóm, mỗi nhóm 3 ký tự:
r(read) = quyền đọc, giá trị số là 4w(write) = quyền ghi, giá trị số là 2x(execute) = quyền thực thi, giá trị số là 1-= không có quyền đó
Cách tính giá trị số: cộng các quyền lại. rwx = 4+2+1 = 7. r-x = 4+0+1 = 5. r-- = 4+0+0 = 4.
Vậy -rwxr-xr-- viết dạng số là 754.
Với thư mục, quyền x có nghĩa hơi khác: nó cho phép cd vào thư mục đó. Thư mục có r nhưng không có x thì bạn list được nội dung (ls) nhưng không vào được bên trong.
Sau chuỗi permission là 2 trường quan trọng: owner (chủ sở hữu) và group (nhóm). Trong ví dụ trên, www-data www-data nghĩa là file thuộc sở hữu của user www-data, nhóm www-data.
chmod: thay đổi quyền
chmod (change mode) dùng để thay đổi quyền đọc/ghi/thực thi của file hoặc thư mục. Có 2 cách viết: dạng số và dạng chữ.
Dạng số (octal)
Đây là cách phổ biến nhất. Bạn dùng 3 chữ số, mỗi chữ số đại diện cho owner, group, others:
# Thư mục: owner full quyền, group và others đọc + vào được
chmod 755 /var/www/html
# File thường: owner đọc/ghi, group và others chỉ đọc
chmod 644 index.html
# File nhạy cảm: chỉ owner đọc/ghi, không ai khác
chmod 600 ~/.ssh/id_rsa
# Script: owner full quyền, không ai khác
chmod 700 backup.sh
Bảng quyền phổ biến mà bạn sẽ gặp thường xuyên:
| Giá trị | Quyền | Dùng cho |
|---|---|---|
755 | rwxr-xr-x | Thư mục web, thư mục chứa script |
644 | rw-r–r– | File HTML, CSS, JS, ảnh, config thường |
600 | rw——- | SSH private key, file chứa password |
700 | rwx—— | Script riêng, thư mục .ssh |
444 | r–r–r– | File chỉ đọc (read-only) |
Dạng chữ (symbolic)
Dạng chữ tiện khi bạn chỉ muốn thêm hoặc bớt một quyền cụ thể, không muốn set lại toàn bộ:
# Thêm quyền execute cho owner
chmod u+x deploy.sh
# Bỏ quyền write của group và others
chmod go-w config.php
# Thêm quyền đọc cho tất cả
chmod a+r readme.txt
# Set chính xác quyền cho owner, bỏ hết của others
chmod u=rwx,g=rx,o= secret-script.sh
Ký hiệu: u = owner (user), g = group, o = others, a = all (tất cả). Dấu + thêm quyền, - bớt quyền, = set chính xác.
Recursive với -R
Khi cần đổi quyền cho cả thư mục và tất cả nội dung bên trong, dùng -R:
chmod -R 755 /var/www/html
Cẩn thận với chmod -R: nó sẽ set cùng một quyền cho cả file lẫn thư mục. Thường thì thư mục cần 755 nhưng file chỉ cần 644. Nếu cần phân biệt, dùng find:
# Set 755 cho thư mục, 644 cho file
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
Combo find + chmod này rất hay dùng khi setup web server. Bạn nên lưu lại để xài.
chown: thay đổi owner
chown (change owner) thay đổi chủ sở hữu và/hoặc group của file. Cú pháp:
# Đổi cả owner và group
chown www-data:www-data index.html
# Chỉ đổi owner
chown nginx index.html
# Chỉ đổi group (để ý dấu : phía trước)
chown :developers project/
# Đổi recursive cho cả thư mục
chown -R www-data:www-data /var/www/html
chown yêu cầu quyền root. Nếu bạn đang login bằng user thường, thêm sudo phía trước:
sudo chown -R www-data:www-data /var/www/html
Lệnh này bạn sẽ dùng rất nhiều khi cài web. Upload file qua SFTP thì owner thường là user SSH của bạn, nhưng web server lại cần file thuộc về www-data (hoặc nginx) thì mới đọc được.
chgrp: thay đổi group
chgrp (change group) chỉ đổi group, không đổi owner. Thực tế ít dùng hơn chown vì chown :group file cũng làm được việc tương tự.
# Đổi group thành developers
chgrp developers project/
# Recursive
chgrp -R www-data /var/www/html
chgrp hữu ích khi bạn muốn nhiều user cùng truy cập một thư mục thông qua group chung, mà không cần đổi owner. Ví dụ: team dev cùng thuộc group developers, thư mục project thuộc group developers với quyền 775, thì ai trong team cũng ghi được.
Quyền đặc biệt: SUID, SGID, sticky bit
Ngoài 3 nhóm quyền cơ bản, Linux còn có 3 quyền đặc biệt. Đây là phần hay bị bỏ qua nhưng quan trọng để hiểu cách hệ thống hoạt động.
SUID (Set User ID) – giá trị 4000
Khi file có SUID, nó sẽ chạy với quyền của owner file đó, không phải quyền của người thực thi. Ví dụ kinh điển là lệnh passwd:
ls -la /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Mar 14 10:00 /usr/bin/passwd
Thấy chữ s ở vị trí execute của owner không? Lệnh passwd thuộc về root, nhưng user thường vẫn chạy được và nó chạy với quyền root để sửa file /etc/shadow. Nếu không có SUID, user thường không thể đổi password được.
# Set SUID
chmod u+s file
chmod 4755 file
SGID (Set Group ID) – giá trị 2000
Tương tự SUID nhưng cho group. Khi set SGID lên thư mục, mọi file tạo mới bên trong sẽ tự động thuộc group của thư mục đó, thay vì group mặc định của người tạo.
# Tạo thư mục shared cho team
mkdir /opt/project
chgrp developers /opt/project
chmod 2775 /opt/project
# Giờ mọi file tạo trong /opt/project sẽ tự thuộc group developers
touch /opt/project/newfile.txt
ls -la /opt/project/newfile.txt
# -rw-rw-r-- 1 thach developers 0 Mar 15 10:00 newfile.txt
SGID rất tiện cho thư mục dùng chung trong team. Không cần ai nhớ chạy chgrp mỗi lần tạo file mới.
Sticky bit – giá trị 1000
Khi thư mục có sticky bit, chỉ owner của file mới có quyền xóa file đó, dù thư mục cho phép ghi. Ví dụ điển hình nhất là /tmp:
ls -ld /tmp
drwxrwxrwt 15 root root 4096 Mar 15 10:00 /tmp
Chữ t ở cuối là sticky bit. Thư mục /tmp cho phép mọi user tạo file (quyền 777), nhưng nhờ sticky bit, user A không xóa được file của user B.
# Set sticky bit
chmod +t /shared
chmod 1777 /shared
umask: quyền mặc định khi tạo file
Khi bạn tạo file mới, nó không phải luôn có quyền 644. Quyền mặc định được quyết định bởi umask.
umask hoạt động kiểu “trừ đi”: quyền mặc định = quyền tối đa – umask.
- File mới: quyền tối đa là 666 (không có execute)
- Thư mục mới: quyền tối đa là 777
# Xem umask hiện tại
umask
# Output: 0022
# Với umask 0022:
# File mới: 666 - 022 = 644 (rw-r--r--)
# Thư mục mới: 777 - 022 = 755 (rwxr-xr-x)
Cách tính: umask 022 nghĩa là bỏ quyền write (2) của group và others. Kết quả là file mới cho owner đọc/ghi, còn group và others chỉ đọc.
# Đổi umask cho session hiện tại
umask 027
# File mới: 666 - 027 = 640 (rw-r-----)
# Thư mục mới: 777 - 027 = 750 (rwxr-x---)
Muốn umask áp dụng vĩnh viễn, thêm vào ~/.bashrc hoặc /etc/profile.
umask 027 là lựa chọn tốt cho server production: group vẫn đọc được nhưng others không có quyền gì. An toàn hơn mặc định 022.
Sai lầm phổ biến
Mình liệt kê vài lỗi mà người mới hay gặp. Biết trước để tránh, đỡ mất thời gian fix.
chmod 777: “fix nhanh” mà đắt giá
Website lỗi 403? Google “fix 403 linux” và đống kết quả đầu tiên sẽ bảo bạn chạy chmod 777. Đừng nghe.
chmod 777 nghĩa là mọi user trên hệ thống đều có quyền đọc, ghi, thực thi file đó. Nếu web server bị lỗ hổng, kẻ tấn công có thể sửa bất kỳ file nào có quyền 777. Upload shell, sửa config, chèn mã độc, thoải mái.
# ❌ ĐỪNG LÀM THẾ NÀY
chmod -R 777 /var/www/html
# ✅ Làm đúng
chown -R www-data:www-data /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
Nguyên tắc: nếu bạn đang gõ 777 thì dừng lại, suy nghĩ xem vấn đề thực sự là gì. 99% trường hợp là sai owner, không phải thiếu quyền.
chown -R root:root / : phá hệ thống trong 1 giây
Lệnh này đổi owner của toàn bộ hệ thống thành root. Nghe vô hại nhưng nó sẽ phá mọi thứ: SSH không login được (vì home directory đổi owner), database không khởi động được (vì data directory cần thuộc về user mysql), web server chết, cron job fail.
# ❌ KHÔNG BAO GIỜ CHẠY
chown -R root:root /
chmod -R 755 /
# Cũng tệ không kém:
chown -R www-data:www-data /
Nếu lỡ chạy thì gần như phải cài lại OS. Không có cách fix đơn giản vì mỗi file, mỗi thư mục cần owner khác nhau. Luôn kiểm tra lại đường dẫn trước khi chạy chown -R hoặc chmod -R.
Quên sudo
Nếu bạn chạy chown mà không có quyền root, lệnh sẽ báo “Operation not permitted”. Nhớ thêm sudo nếu đang dùng user thường. Còn nếu đang là root rồi thì không cần.
Ví dụ thực tế trên VPS
Đây là những tình huống bạn sẽ gặp thường xuyên nhất khi quản trị VPS:
Setup web directory
# Đổi owner cho thư mục web
sudo chown -R www-data:www-data /var/www/html
# Set quyền đúng: thư mục 755, file 644
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
# Nếu có file cần web server ghi (upload, cache):
sudo chmod 775 /var/www/html/wp-content/uploads
Trên AlmaLinux, web server mặc định chạy dưới user nginx hoặc apache, không phải www-data như Ubuntu. Kiểm tra bằng ps aux | grep nginx hoặc xem config để dùng đúng user.
SSH key
# Thư mục .ssh: chỉ owner
chmod 700 ~/.ssh
# Private key: chỉ owner đọc/ghi
chmod 600 ~/.ssh/id_rsa
# Public key: owner đọc/ghi, others đọc
chmod 644 ~/.ssh/id_rsa.pub
# authorized_keys: chỉ owner đọc/ghi
chmod 600 ~/.ssh/authorized_keys
SSH rất nghiêm về quyền. Nếu private key có quyền quá mở (ví dụ 644), SSH sẽ từ chối dùng nó và báo lỗi “Permissions are too open”. Tương tự, nếu file authorized_keys mà group hoặc others ghi được thì SSH cũng bỏ qua.
Script deploy
# Tạo file script
nano deploy.sh
# Thêm quyền execute
chmod +x deploy.sh
# Hoặc cụ thể hơn: chỉ owner chạy được
chmod 700 deploy.sh
# Chạy
./deploy.sh
File mới tạo mặc định không có quyền execute (nhớ umask ở trên không?). Bạn luôn phải chmod +x trước khi chạy script.
Database data directory
# MySQL/MariaDB data phải thuộc về user mysql
sudo chown -R mysql:mysql /var/lib/mysql
sudo chmod 750 /var/lib/mysql
SELinux vs AppArmor
Hệ thống permission ở trên (rwx, owner, group) gọi là DAC (Discretionary Access Control). Linux còn có một lớp bảo mật bổ sung gọi là MAC (Mandatory Access Control), hoạt động ở mức cao hơn.
Hai distro trong serie này dùng 2 hệ thống MAC khác nhau:
- AlmaLinux dùng SELinux (Security-Enhanced Linux), mặc định bật ở chế độ Enforcing
- Ubuntu dùng AppArmor, mặc định bật
Cách kiểm tra trên AlmaLinux:
# Xem SELinux đang bật hay tắt
getenforce
# Output: Enforcing / Permissive / Disabled
# Xem SELinux context của file
ls -Z /var/www/html/
# -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
Cách kiểm tra trên Ubuntu:
# Xem trạng thái AppArmor
sudo aa-status
# Xem profile đang enforce
sudo aa-status | grep enforce
Đôi khi bạn set permission đúng hết rồi mà service vẫn không truy cập được file, rất có thể là do SELinux hoặc AppArmor chặn. Trên AlmaLinux, kiểm tra log SELinux:
# Xem SELinux có đang chặn gì không
sudo ausearch -m AVC --recent
Đừng tắt SELinux hay AppArmor để “fix lỗi”. Giống như chmod 777, nó chỉ là cách giấu vấn đề, không phải fix. Mình sẽ nói chi tiết về SELinux và AppArmor trong serie Bảo mật sau.
Checkpoint
Bạn thử tự làm mấy bài tập này trên VPS để kiểm tra lại kiến thức:
Bài 1: Set quyền cho thư mục web hoàn chỉnh.
# Tạo thư mục test
sudo mkdir -p /var/www/testsite
sudo chown -R www-data:www-data /var/www/testsite
sudo find /var/www/testsite -type d -exec chmod 755 {} \;
sudo find /var/www/testsite -type f -exec chmod 644 {} \;
# Kiểm tra
ls -la /var/www/testsite
Bài 2: Tạo script và làm cho nó chạy được.
# Tạo script
echo '#!/bin/bash' > ~/test-script.sh
echo 'echo "Hello from script"' >> ~/test-script.sh
# Thử chạy (sẽ lỗi Permission denied)
./test-script.sh
# Thêm quyền execute
chmod +x ~/test-script.sh
# Chạy lại
~/test-script.sh
Bài 3: Đọc permission và giải mã.
# Xem quyền các file hệ thống
ls -la /etc/passwd
ls -la /etc/shadow
ls -la /usr/bin/passwd
# Trả lời:
# 1. Ai đọc được /etc/passwd? Ai đọc được /etc/shadow?
# 2. Tại sao /usr/bin/passwd có chữ 's' trong permission?
# 3. /etc/shadow có quyền số là bao nhiêu?
Nếu trả lời được hết thì bạn đã nắm vững phần permission rồi. Bài tiếp theo mình sẽ nói về quản lý package trên Linux, cách cài đặt phần mềm trên cả Ubuntu và AlmaLinux.
Có thể bạn cần xem thêm
- Quản lý file và thư mục trên Linux - Lệnh cơ bản cho VPS
- User và Permission nâng cao trên Linux VPS - Least Privilege
- Cấu trúc thư mục Linux - Mọi thứ nằm ở đâu trên VPS
- Backup VPS Linux - rsync, tar và chiến lược sao lưu toàn diện
- Tăng cường bảo mật Kernel và Network trên Linux VPS - sysctl, AppArmor và SELinux
- User, Group và Sudo trên Linux - Quản lý tài khoản VPS
Về tác giả
Trần Thắng
Chuyên gia tại AZDIGI với nhiều năm kinh nghiệm trong lĩnh vực web hosting và quản trị hệ thống.