Sửa lỗi Nginx "bind() to 0.0.0.0:80 failed (98: Address already in use)"

beginner Nginx2026-03-21| Linux (Ubuntu, Debian, CentOS), Nginx 1.18+

Error Message

bind() to 0.0.0.0:80 failed (98: Address already in use)
#nginx#port#bind

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.pid cũ 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

Related Error Notes