Chuyện gì đang xảy ra
Nginx từ chối khởi động, và log lỗi (hoặc systemctl status nginx) hiển thị thông báo như sau:
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()
Cổng 80 đã bị chiếm. Chỉ một tiến trình có thể giữ một cổng tại một thời điểm, vì vậy Nginx thoát ra ngay lập tức.
Những nguyên nhân phổ biến nhất:
- Một tiến trình Nginx trước đó bị crash hoặc không tắt sạch — nó vẫn đang giữ cổng.
- Apache, Caddy, hoặc một web server khác đã chiếm cổng 80 trước.
- Một ứng dụng Node.js, Python, hoặc ứng dụng khác được khởi động trực tiếp trên cổng 80.
- File
/run/nginx.pidcũ trỏ đến một tiến trình đã chết khiến systemd khởi động thêm một instance Nginx thứ hai.
Bước 1 — Tìm xem cái gì đang dùng cổng 80
Đừng đoán mò. Hãy chạy một trong các lệnh sau trước tiên.
Dùng ss (khuyến nghị)
sudo ss -tlnp | grep ':80'
Kết quả mẫu:
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=12345,fd=6))
Cột cuối cùng cho bạn biết tên tiến trình và PID — đó là tất cả những gì bạn cần.
Dùng lsof
sudo lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 12345 root 6u IPv4 98765 0t0 TCP *:http (LISTEN)
nginx 12346 www-data 6u IPv4 98765 0t0 TCP *:http (LISTEN)
Dùng fuser
sudo fuser 80/tcp
Lệnh này chỉ in ra PID. Thêm -v để xem tên tiến trình kèm theo:
sudo fuser -v 80/tcp
Bước 2 — Khắc phục dựa theo những gì bạn tìm thấy
Trường hợp A: Một instance Nginx khác đang chạy
Đây là nguyên nhân phổ biến nhất. Bạn có hai Nginx worker cùng tranh giành một cổng — thường xảy ra khi chạy lệnh sudo nginx trực tiếp trên server được quản lý bởi systemd.
Thử cách sạch sẽ trước:
sudo systemctl stop nginx
systemctl báo đã dừng rồi nhưng tiến trình vẫn còn sống? Hãy kill theo PID:
sudo kill 12345
Vẫn còn bị kẹt? Dùng lệnh mạnh hơn:
sudo kill -9 12345
Sau đó xóa bất kỳ file PID cũ nào:
sudo rm -f /run/nginx.pid
Bây giờ khởi động Nginx:
sudo systemctl start nginx
Trường hợp B: Apache đang chạy trên cổng 80
Apache và Nginx đều mặc định dùng cổng 80 — chúng không thể dùng chung. Hãy dừng Apache trước:
sudo systemctl stop apache2 # Debian/Ubuntu
sudo systemctl stop httpd # CentOS/RHEL
Không có kế hoạch dùng Apache trên server này? Hãy vô hiệu hóa nó để nó không tự khởi động lại sau khi reboot:
sudo systemctl disable apache2
Sau đó khởi động Nginx:
sudo systemctl start nginx
Trường hợp C: Một ứng dụng khác (Node.js, Python, v.v.) đang dùng cổng 80
Lấy PID từ Bước 1 và kiểm tra xem thực sự đang chạy cái gì:
sudo ps -p 12345 -o comm=
Có hai hướng giải quyết:
- Dừng ứng dụng đó và để Nginx đứng trước nó như một reverse proxy — đây là cấu hình chuẩn cho hầu hết các stack.
- Chuyển ứng dụng đó sang cổng khác (ví dụ: 3000 hoặc 8000) và proxy qua Nginx.
Kill tiến trình trực tiếp:
sudo kill 12345
Hoặc dừng qua service của chính nó nếu có:
sudo systemctl stop myapp
Bước 3 — Ngăn chặn lỗi tái diễn
Luôn dùng systemctl, không dùng lệnh nginx trực tiếp
Chạy lệnh sudo nginx trực tiếp sẽ bỏ qua cơ chế theo dõi tiến trình của systemd. Đó chính xác là cách các tiến trình mồ côi giữ cổng 80 rất lâu sau khi bạn nghĩ Nginx đã dừng.
Hãy gắn bó với bốn lệnh sau:
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl reload nginx # tải lại cấu hình graceful, không có downtime
sudo systemctl restart nginx
Giữ Nginx ở trạng thái enabled để systemd quản lý đúng cách
sudo systemctl enable nginx
Muốn kiểm tra toàn bộ cấu hình service?
sudo systemctl cat nginx
Kiểm tra xem phần [Service] có bao gồm ExecStartPre=/usr/sbin/nginx -t không. Với dòng này, lỗi cú pháp trong cấu hình sẽ thất bại nhanh — trước khi Nginx thậm chí cố gắng bind cổng.
Chạy cả Apache và Nginx trên cùng một server
Chuyển Apache sang cổng 8080 và đặt Nginx ở phía trước. Trong file /etc/apache2/ports.conf:
Listen 8080
Sau đó trong server block của Nginx:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Bước 4 — Xác nhận đã sửa thành công
Kiểm tra Nginx có thực sự đang chạy không:
sudo systemctl status nginx
Tìm dòng Active: active (running). Sau đó xác nhận cổng 80 hiện do Nginx sở hữu:
sudo ss -tlnp | grep ':80'
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=9876,fd=6))
Một bài kiểm tra HTTP nhanh để khẳng định:
curl -I http://localhost
HTTP/1.1 200 OK nghĩa là cổng đã trống và Nginx đang phục vụ. Vậy là xong.
Tóm tắt nhanh
# 1. Tìm xem ai đang chiếm cổng 80
sudo ss -tlnp | grep ':80'
# 2. Dừng tiến trình xung đột (ví dụ: apache)
sudo systemctl stop apache2
# 3. Xóa file PID cũ nếu cần
sudo rm -f /run/nginx.pid
# 4. Khởi động Nginx
sudo systemctl start nginx
# 5. Xác nhận
sudo systemctl status nginx
curl -I http://localhost

