Mình vừa onboard một bạn junior vào team, và câu hỏi đầu tiên bạn ấy hỏi là: “Tạo user mới trên server thì dùng useradd hay adduser?” — Tưởng đơn giản nhưng câu hỏi đó lại mở ra cả một chủ đề mà nhiều người dùng Linux lâu năm vẫn hay nhầm.
Sau 3 năm quản lý hơn 10 VPS, mình đã tự tay bị lock out khỏi server vì cấu hình sudo sai, và chứng kiến một site downtime gần 2 tiếng chỉ vì permission sai trên thư mục upload. Với user và permission, sai một chút là hậu quả ngay — không như code thông thường còn có thể git revert.
1. Tạo User: useradd vs adduser — Cái Nào Nên Dùng?
Hai lệnh này trông giống nhau nhưng hoạt động khác nhau đáng kể.
useradd — Low-level, bare minimum
useradd là lệnh low-level, tạo user với các thông số tối thiểu. Nếu không thêm flag, nó sẽ không tạo home directory, không đặt shell mặc định hợp lý, không tạo password.
# useradd đơn giản — thiếu nhiều thứ
sudo useradd newuser
# Kết quả: user tồn tại nhưng không có home dir, shell mặc định là /bin/sh
# Cần thêm đủ flag để dùng được
sudo useradd -m -s /bin/bash -c "Nguyen Van A" newuser
# -m: tạo home directory
# -s: chỉ định shell
# -c: comment (thường là full name)
adduser — High-level, interactive, thân thiện hơn
adduser trên Debian/Ubuntu là wrapper script, tự động tạo home directory, hỏi password, comment. Trên CentOS/RHEL thì adduser chỉ là symlink tới useradd — tức là hoạt động y hệt nhau.
# adduser trên Ubuntu/Debian — interactive, dễ dùng hơn
sudo adduser newuser
# Script sẽ hỏi: password, full name, phone...
# Tự động tạo /home/newuser và copy skeleton từ /etc/skel
Nên dùng cái nào?
- useradd: Có trên mọi distro, phù hợp cho script automation, nhưng cần tự quản lý từng flag — dễ bỏ sót
- adduser: Thân thiện khi dùng tay, chỉ có trên Debian-based, không dùng được trong script cross-platform
Tóm gọn: Dùng tay trên Ubuntu/Debian → adduser. Viết script tự động hoặc chạy trên CentOS/RHEL → useradd -m -s /bin/bash với đủ flag.
2. Permission: Chmod Số vs Chmod Chữ
Nhiều người học theo kiểu “nhớ mấy số thần thánh” mà không hiểu tại sao — rồi khi bí thì chmod 777 cho xong, sau đó không biết tại sao site bị khai thác.
Chmod bằng số (Octal) — Nhanh khi đã thuộc
# Công thức: read=4, write=2, execute=1
# 755 = rwxr-xr-x
# Owner: 4+2+1=7 | Group: 4+1=5 | Others: 4+1=5
chmod 755 /var/www/html
# 644 = rw-r--r-- (file thông thường)
chmod 644 index.html
# 600 = rw------- (file nhạy cảm: SSH key, password file)
chmod 600 ~/.ssh/id_rsa
# 700 = rwx------ (directory chỉ owner dùng)
chmod 700 ~/private
Chmod bằng chữ (Symbolic) — Dễ hiểu khi mới học
# u=user/owner, g=group, o=others, a=all
# +thêm, -bỏ, =đặt chính xác
# Thêm execute cho owner
chmod u+x deploy.sh
# Bỏ write của group và others
chmod go-w config.yaml
# Đặt chính xác: owner rwx, group r-x, others không có gì
chmod u=rwx,g=rx,o= script.sh
Khi nào dùng kiểu nào?
- Octal: Gõ nhanh hơn, nhưng cần tính trong đầu — dễ nhầm khi mệt
- Symbolic: Rõ ràng hơn, chỉ thay đổi bit cần thiết mà không đụng đến phần còn lại — an toàn hơn khi sửa permission đang tồn tại
Tip thực chiến: Dùng stat -c "%a %n" filename để xem permission dạng octal — tiện hơn ls -l khi cần copy sang chỗ khác.
# Xem permission dạng octal
stat -c "%a %n" /etc/passwd
# Output: 644 /etc/passwd
# Kiểm tra nhiều file cùng lúc
stat -c "%a %n" /var/www/html/*
3. Ownership: chown và chgrp
Permission đúng nhưng owner sai thì vẫn bị denied. Đây là lỗi phổ biến khi deploy web app — file do root tạo ra, nginx/apache chạy dưới user www-data nên không đọc được.
# Đổi owner
sudo chown www-data /var/www/html/uploads
# Đổi cả owner và group cùng lúc
sudo chown www-data:www-data /var/www/html/uploads
# Đổi đệ quy cả thư mục — cẩn thận với -R!
sudo chown -R www-data:www-data /var/www/html/
# Chỉ đổi group
sudo chgrp developers /var/log/app.log
Cảnh báo: Khi dùng chown -R, hãy chắc chắn path đúng. Mình từng thấy người nhầm path và chown toàn bộ /var — sau đó nhiều service không start được vì ownership sai hết.
4. Sudo: Phân Quyền Đúng Cách
Hay gặp nhất là hai thái cực: cho tất cả vào group sudo cho tiện, hoặc khóa hoàn toàn rồi mọi việc cần root phải SSH bằng tài khoản riêng. Cả hai đều dở theo cách riêng.
Cách 1: Thêm vào group sudo — Đơn giản nhưng rủi ro
# Ubuntu/Debian
sudo usermod -aG sudo username
# CentOS/RHEL/Fedora
sudo usermod -aG wheel username
# Kiểm tra user thuộc group nào
id username
groups username
Cách 2: Cấp quyền cụ thể qua sudoers — An toàn hơn
# LUÔN dùng visudo để edit — tự check syntax trước khi save
sudo visudo
# Hoặc tạo file riêng trong /etc/sudoers.d/ (khuyến nghị)
sudo visudo -f /etc/sudoers.d/deployer
# Cho phép user 'deployer' reload nginx không cần password
deployer ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload nginx
# Cho phép group 'developers' xem log
%developers ALL=(ALL) NOPASSWD: /usr/bin/tail -f /var/log/nginx/access.log
Vì sao toàn quyền sudo lại nguy hiểm?
- Group sudo toàn quyền: Tiện cho môi trường dev, nhưng user có thể làm bất cứ điều gì trên production — kể cả vô tình xóa nhầm
- Sudoers cụ thể: Theo least privilege — chỉ cho làm đúng việc cần, không hơn không kém
Trên production, mình luôn dùng sudoers cụ thể cho service account. Deploy user chỉ được reload nginx và restart app service — không làm được gì khác dù muốn.
5. Audit Permission — Đừng Bỏ Qua Bước Này
Biết cách đặt permission là một chuyện, kiểm tra xem hệ thống hiện tại có đúng không lại là chuyện khác. Mấy lệnh này mình dùng thường xuyên khi review server mới — đặc biệt server nhận bàn giao từ người khác:
# Tìm file có SUID bit (tiềm ẩn rủi ro bảo mật)
find / -perm /4000 -type f 2>/dev/null
# Tìm file world-writable — ai cũng ghi được, cực kỳ nguy hiểm
find /var/www -perm -002 -type f 2>/dev/null
# Tìm file không có owner (orphan files)
find /home -nouser -o -nogroup 2>/dev/null
# Kiểm tra user có thể sudo lệnh gì
sudo -l -U username
Tổng Kết: Làm Đúng Ngay Từ Đầu
- Server production: Tạo dedicated service user (không dùng root), cấp quyền tối thiểu, sudoers cụ thể cho từng lệnh cần thiết
- Dev/staging: Thoải mái hơn, nhưng vẫn không nên cho developer dùng trực tiếp root — tạo thói quen xấu lên production
- Web server files: Owner là web user (www-data/nginx), permission 644 cho file, 755 cho directory, 600 cho file nhạy cảm
- Script automation: Dùng
useraddvới đủ flag, đừng phụ thuộc vào behavior mặc định của từng distro
Một rule mình áp dụng từ đầu: chmod 777 là dấu hiệu của sự lười biếng, không phải giải pháp. Khi gặp permission denied, hãy dừng lại và hiểu nguyên nhân trước khi mở toang toàn bộ quyền.
Thực hành trên VM hoặc container trước, nắm rõ từng lệnh, rồi mới đưa lên production — đó là cách mình học và cũng là lời khuyên mình hay nói với người mới vào nghề.

