Nginx 일반 오류 문제 해결: 실용 가이드

Nginx 오류가 발생하셨나요? 이 실용 가이드는 일반적인 문제를 진단하고 해결하는 데 도움을 줍니다. 설정 문제, 권한 거부 오류, 연결 거부, 502/504 게이트웨이 오류 등을 해결하는 방법을 배우세요. 명확한 설명, 실행 가능한 해결책, 필수 Nginx 명령어를 제공하여 사이트를 항상 접근 가능하고 원활하게 운영할 수 있도록 도와드립니다.

Nginx 일반 오류 문제 해결: 실용 가이드

Nginx 일반 오류 문제 해결은 상태 코드를 전체 문제로 취급하지 않을 때 훨씬 쉬워집니다. 502는 충돌한 앱, 잘못된 소켓 경로, 또는 잘못된 헤더를 반환한 백엔드 때문일 수 있습니다. 403은 파일 권한, 누락된 인덱스 파일, 또는 예상보다 더 많이 일치한 거부 규칙 때문일 수 있습니다.

증거부터 시작하세요: 오류 로그, 액세스 로그, nginx -t, 그리고 Nginx가 앱에 프록시하는 경우 백엔드 로그입니다. 브라우저 페이지에서 추측하는 것은 시간 낭비입니다.

빠른 확인부터 시작하세요

설정을 변경하기 전에 다음을 실행하세요:

sudo nginx -t
sudo systemctl status nginx --no-pager
sudo tail -n 80 /var/log/nginx/error.log
sudo tail -n 80 /var/log/nginx/access.log

nginx -t는 설정을 구문 분석할 수 있는지 알려줍니다. 서비스 상태는 Nginx가 실행 중인지 알려줍니다. 로그는 Nginx가 요청을 처리하는 동안 본 내용을 알려줍니다.

문제가 하나의 URL에 국한된 경우 curl로 재현하여 헤더와 상태를 명확히 확인하세요:

curl -I https://example.com/problem/path
curl -v https://example.com/problem/path

문제가 특정 호스트 이름에서만 발생하는 경우 포함하세요:

curl -I -H 'Host: app.example.com' http://127.0.0.1/

이렇게 하면 Nginx 라우팅을 DNS, CDN 및 로드 밸런서 동작과 분리할 수 있습니다.

Nginx가 시작되지 않거나 다시 로드되지 않음

시작 실패는 일반적으로 구문 오류, 잘못된 컨텍스트의 중복 지시문, 누락된 include 파일 또는 인증서 경로 문제로 인해 발생합니다.

다음을 사용하세요:

sudo nginx -t
sudo journalctl -u nginx -n 100 --no-pager

일반적인 메시지는 직접적입니다:

  • unknown directive는 오타, 지원되지 않는 모듈 또는 잘못된 Nginx 빌드에 배치된 지시문을 의미합니다.
  • directive is not allowed here는 지시문이 잘못된 컨텍스트에 있음을 의미합니다. 예를 들어 http 전용 지시문을 server 내부에 넣는 경우입니다.
  • cannot load certificate는 경로가 잘못되었거나, 파일이 없거나, 권한이 Nginx가 읽지 못하게 차단함을 의미합니다.
  • bind() to 0.0.0.0:80 failed는 종종 다른 프로세스가 이미 포트를 사용하고 있음을 의미합니다.

다음으로 포트를 확인하세요:

sudo ss -tulnp | grep ':80\|:443'

nginx -t가 통과할 때까지 다시 로드하지 마세요. 실패한 다시 로드는 일반적으로 이전 작업자 프로세스를 계속 실행하지만, 실패한 재시작은 사이트를 중단시킬 수 있습니다.

(13: Permission denied)403 Forbidden

Permission denied는 Nginx 작업자 사용자가 파일을 읽거나 디렉토리를 탐색할 수 없을 때 오류 로그에 나타납니다. 브라우저는 403 Forbidden을 볼 수 있습니다.

먼저 작업자 사용자를 찾으세요:

grep -R '^user ' /etc/nginx/nginx.conf

Debian 및 Ubuntu에서는 종종 www-data입니다. RHEL 호환 시스템에서는 종종 nginx입니다.

/var/www/html과 같은 정적 루트의 경우 Nginx는 모든 상위 디렉토리에 대한 실행 권한과 파일에 대한 읽기 권한이 필요합니다:

sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;

애플리케이션 디렉토리에 대해 반사적으로 chown -R www-data:www-data를 실행하지 마세요. 오류가 사라질 수 있지만 웹 서버에 필요하지 않은 쓰기 액세스 권한을 부여할 수 있습니다. 더 안전한 패턴은 배포 소유권을 분리하고 Nginx에 읽기 액세스 권한을 부여하는 것입니다.

권한이 정상으로 보이면 요청이 인덱스 파일이 없는 디렉토리에 대한 것인지 확인하세요:

location / {
    root /var/www/html;
    index index.html index.htm;
}

/docs/index.html이 없고 autoindex가 꺼져 있으면 Nginx는 403을 반환합니다. 이것은 올바른 동작입니다.

SELinux는 RHEL 계열 시스템에서 권한 스타일 오류를 유발할 수도 있습니다. 파일 권한이 올바르지만 Nginx가 여전히 읽거나 프록시할 수 없는 경우 SELinux를 비활성화하기 전에 감사 로그를 확인하세요:

sudo ausearch -m avc -ts recent

(111: Connection refused)502 Bad Gateway

Connection refused는 Nginx가 업스트림에 연결을 시도했지만 대상이 적극적으로 거부했음을 의미합니다. 앱이 다운되었거나, 다른 주소에서 수신 중이거나, 존재하지 않는 소켓 경로를 사용 중일 수 있습니다.

이 프록시의 경우:

location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

확인하세요:

sudo ss -tulnp | grep 3000
curl -I http://127.0.0.1:3000
sudo systemctl status your-app --no-pager

Nginx가 Unix 소켓을 사용하는 경우 소켓 파일을 확인하세요:

ls -l /run/gunicorn/app.sock

작업자 사용자는 소켓을 읽고 쓸 수 있어야 합니다.

502 Bad Gateway는 더 광범위합니다. Nginx가 업스트림에 도달했지만 응답이 유효하지 않거나, 불완전하거나, 너무 일찍 종료되었거나, Nginx가 예상한 것과 다릅니다. Nginx 오류와 동일한 타임스탬프에서 앱 로그를 확인하세요. 타임스탬프 일치가 중요합니다. 그렇지 않으면 어제의 예외를 추적하게 됩니다.

PHP-FPM의 경우 fastcgi_pass가 구성된 풀 소켓 또는 포트와 일치하는지 확인하세요. 예:

fastcgi_pass unix:/run/php/php8.3-fpm.sock;

그런 다음 확인하세요:

sudo systemctl status php8.3-fpm --no-pager
ls -l /run/php/php8.3-fpm.sock

504 Gateway Timeout

504는 Nginx가 업스트림을 기다렸지만 적시에 응답을 받지 못했음을 의미합니다. 보고서, 가져오기 또는 느린 관리 작업의 경우 시간 초과를 늘리는 것이 유효할 수 있지만 모든 요청에서 느린 공개 엔드포인트에 대한 유일한 수정 사항이 되어서는 안 됩니다.

location /api/reports/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_connect_timeout 10s;
    proxy_send_timeout 60s;
    proxy_read_timeout 180s;
}

그런 다음 백엔드 타이밍을 확인하세요. 아직 없는 경우 액세스 로그에 업스트림 타이밍을 추가하세요:

log_format proxy_timing '$remote_addr "$request" $status '
                        'request_time=$request_time '
                        'upstream_time=$upstream_response_time';

$upstream_response_time이 높으면 앱 또는 데이터베이스에 집중해야 할 가능성이 높습니다. Nginx가 시간 초과를 표시하지만 앱 로그가 빠르게 응답했다고 표시하면 네트워크 홉, 컨테이너 네트워킹, 호스트 내부의 DNS 확인 또는 Nginx와 앱 사이의 로드 밸런서를 확인하세요.

413 Request Entity Too Large

413은 일반적으로 간단합니다. 요청 본문이 Nginx가 허용하는 것보다 큽니다. 업로드, 대용량 JSON 페이로드 및 양식 게시물이 이를 트리거할 수 있습니다.

가장 좁은 유용한 위치에 client_max_body_size를 설정하세요:

server {
    server_name example.com;

    location /upload/ {
        client_max_body_size 100M;
        proxy_pass http://127.0.0.1:3000;
    }
}

거대한 글로벌 제한을 설정하는 것은 거의 좋은 생각이 아닙니다. 대부분의 경로에는 필요하지 않으며, 더 큰 허용 본문은 잘못된 클라이언트가 스택에 강제로 가할 수 있는 작업량을 증가시킵니다.

SSL 및 인증서 오류

TLS 오류는 발견 위치에 따라 다르게 보이는 경우가 많습니다. Nginx가 다시 로드되지 않거나, 브라우저가 인증서에 대해 경고하거나, 클라이언트가 핸드셰이크에 실패할 수 있습니다.

인증서 날짜 확인:

openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -dates -subject -issuer

공개 서비스가 제공하는 내용 확인:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer

두 명령이 다른 인증서를 표시하면 로드 밸런서, CDN 또는 다른 호스트가 트래픽을 제공하고 있을 수 있습니다.

400 Bad Request 및 헤더 문제

400은 일반적으로 Nginx가 요청 구문을 수락하지 않았음을 의미합니다. 실제 브라우저에서는 덜 일반적이지만 봇, 오래된 클라이언트, 비정상적인 프록시 또는 대용량 헤더가 원인이 될 수 있습니다.

client sent too large request header와 같은 메시지를 찾으세요. 합법적인 SSO 또는 애플리케이션 쿠키가 너무 큰 경우 헤더 버퍼 설정을 조정해야 할 수 있습니다. 이를 첫 번째 응답이 아닌 대상 수정으로 취급하세요. 대용량 쿠키는 종종 애플리케이션에서 수정하는 것이 좋습니다.

실용적인 작업 순서

Nginx 문제가 발생했을 때 반복 가능한 순서를 사용하세요:

  1. 정확한 URL, 호스트, 상태 코드 및 시간을 확인합니다.
  2. nginx -t 및 서비스 상태를 확인합니다.
  3. 액세스 로그에서 요청을 찾습니다.
  4. 오류 로그에서 동일한 타임스탬프를 찾습니다.
  5. 프록시하는 경우 업스트림 서비스 상태 및 로그를 확인합니다.
  6. Nginx 호스트에서 업스트림을 직접 테스트합니다.
  7. 증거에 맞는 가장 작은 설정 변경을 수행합니다.
  8. nginx -t를 실행하고, 다시 로드하고, 재테스트하는 동안 로그를 확인합니다.

대부분의 Nginx 문제는 실패가 발생한 위치(Nginx 이전, Nginx 내부, Nginx와 업스트림 사이, 업스트림 서비스 내부)를 알면 평범해집니다.