Sửa lỗi Nginx ERR_TOO_MANY_REDIRECTS: Giải quyết lỗi 'Internal Redirection Cycle'

intermediate Nginx2026-03-30| Ubuntu 20.04/22.04, Debian 11/12, CentOS 7/8, Nginx 1.18.x hoặc cao hơn, PHP-FPM 7.4/8.x

Error Message

rewrite or internal redirection cycle while internally redirecting to "/index.php"
#nginx#devops#php-fpm#server-config#troubleshooting

Vấn đềBạn truy cập trang web của mình, nhưng thay vì trang chủ, trình duyệt lại hiển thị thông báo ERR_TOO_MANY_REDIRECTS đầy khó chịu. Khi kiểm tra log lỗi của Nginx (thường ở /var/log/nginx/error.log), bạn có thể sẽ thấy một dòng thông báo cụ thể như thế này:

2023/10/24 10:15:30 [error] 1234#0: *1 rewrite or internal redirection cycle while internally redirecting to "/index.php", client: 192.168.1.1, server: example.com, request: "GET / HTTP/1.1", host: "example.com"

Nginx có giới hạn an toàn là 10 lần chuyển hướng nội bộ. Nếu một yêu cầu bị kẹt trong vòng lặp và không bao giờ tìm thấy tệp cuối cùng để xử lý, Nginx sẽ dừng tiến trình để ngăn CPU của máy chủ bị quá tải.

Bước 1: Xác định vòng lặp bằng CurlMột bài kiểm tra nhanh bằng curl sẽ tiết lộ vòng lặp nằm ở logic của trình duyệt hay nằm sâu bên trong Nginx. Chạy lệnh này từ terminal của bạn:

curl -I http://example.com

Quan sát kỹ kết quả. Nếu bạn thấy hàng chục header HTTP/1.1 301 Moved Permanently nhảy qua lại giữa HTTP và HTTPS, bạn đang gặp vòng lặp chuyển hướng logic. Tuy nhiên, nếu bạn thấy lỗi 500 Internal Server Error, bạn đang đối mặt với chu kỳ rewrite nội bộ được đề cập trong log.

Bước 2: Kiểm tra chỉ thị try_filesHầu hết các ứng dụng PHP—như Laravel, WordPress hoặc Symfony—dựa vào chỉ thị try_files để xử lý URL. Một cấu hình chuẩn và hoạt động tốt thường trông như thế này:

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

Chu kỳ bắt đầu khi Nginx không thể tìm thấy index.php trong thư mục gốc (root). Vì tệp bị thiếu, Nginx sẽ chuyển sang tham số cuối cùng, kích hoạt block location ~ \.php$, thất bại lần nữa và bắt đầu lại quá trình tìm kiếm. Hãy kiểm tra kỹ đường dẫn root của bạn. Nếu ứng dụng của bạn nằm ở /var/www/my-app/public nhưng Nginx lại tìm kiếm trong /var/www/my-app, nó sẽ không bao giờ tìm thấy tệp thực thi.

server {
    listen 80;
    server_name example.com;
    root /var/www/html/public; # Đảm bảo đường dẫn này chứa index.php
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    }
}

Bước 3: Giải quyết vòng lặp kết thúc SSLBạn đang sử dụng Cloudflare hay AWS Load Balancer? Bạn có thể đang bị kẹt trong một trận đấu "ping-pong" SSL. Điều này xảy ra khi proxy của bạn giao tiếp với Nginx qua cổng 80 (HTTP), nhưng Nginx lại yêu cầu chuyển hướng mọi thứ sang HTTPS. Proxy gửi yêu cầu, Nginx báo "Hãy chuyển sang HTTPS", và proxy lại gửi ngược lại dưới dạng HTTP.

Để ngăn chặn điều này, hãy sử dụng header X-Forwarded-Proto để phát hiện giao thức gốc. Cập nhật cấu hình của bạn để chỉ chuyển hướng nếu yêu cầu chưa được bảo mật:

# Thêm dòng này vào bên trong block server của bạn
if ($http_x_forwarded_proto != "https") {
    return 301 https://$host$request_uri;
}

Bước 4: Sử dụng 'Cầu chì' cho PHPĐôi khi Nginx bị nhầm lẫn về việc nên thực thi script nào nếu thiếu SCRIPT_FILENAME. Thêm một "cầu chì" (circuit breaker) là cách tốt nhất để dừng vòng lặp ngay lập tức. Thêm try_files $fastcgi_script_name =404; vào bên trong block PHP của bạn. Điều này yêu cầu Nginx dừng lại và trả về lỗi 404 nếu không tìm thấy tệp, thay vì cố gắng thực hiện một lần chuyển hướng nội bộ khác.

location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    
    # Dòng này sẽ ngắt vòng lặp nếu không tìm thấy tệp
    try_files $fastcgi_script_name =404;
    
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/var/run/php/php-fpm.sock;
}

Bước 5: Kiểm tra và Tải lại cấu hìnhKiểm tra các thay đổi trước khi áp dụng để tránh làm trang web bị ngoại tuyến. Chạy lệnh kiểm tra cú pháp Nginx:

sudo nginx -t

Nếu bài kiểm tra vượt qua, hãy tải lại dịch vụ để các thay đổi có hiệu lực:

sudo systemctl reload nginx

Cuối cùng, chạy lại curl -I một lần nữa. Bây giờ bạn sẽ thấy mã trạng thái HTTP/1.1 200 OK sạch sẽ hoặc một lần chuyển hướng 301 duy nhất theo sau là mã 200.

Danh sách kiểm tra tóm tắt- Kiểm tra Root: Đảm bảo chỉ thị root trỏ chính xác đến thư mục chứa tệp index.php của bạn.- Dừng tìm kiếm: Sử dụng try_files ... =404; trong các block PHP để ngăn Nginx tìm kiếm vô tận các tệp bị thiếu.- Nhận biết Proxy: Nếu bạn sử dụng Cloudflare, hãy dựa vào header X-Forwarded-Proto thay vì biến $scheme.- Bật Gỡ lỗi: Nếu bạn vẫn gặp rắc rối, hãy thêm rewrite_log on; vào cấu hình và đặt mức độ log lỗi thành notice để xem các bước chuyển đổi URL chi tiết.

Related Error Notes