Nginx를 웹 서버로 구성하는 방법을 정말로 이해하고 계십니까?
읽기 전에 먼저 Nginx 소개를 읽어보는 것이 좋습니다. 그 다음에는 Nginx 구성을 살펴보겠습니다.
추상적으로 말하면 Nginx를 웹 서버로 구성하는 것은 처리할 URL과 이러한 URL에 해당하는 요청을 처리하는 방법을 정의하는 것입니다. 구체적으로는 특정 IP와 도메인 이름으로 요청을 제어하기 위해 일부 가상 서버(Virtual Server)를 정의하는 것입니다.
보다 구체적으로 Nginx는 일련의 위치를 정의하여 URIS 선택을 제어합니다. 각 위치는 자신에게 매핑된 요청에 대한 처리 시나리오를 정의합니다. 즉, 파일 또는 프록시 요청을 반환하거나 다른 오류 코드를 기반으로 다른 오류 페이지를 반환합니다. 또한 URI에 따라 요청이 다른 서버나 위치로 리디렉션될 수도 있습니다.
가상 서버 설정
들어보세요:
Nginx 구성 파일에는 가상 서버를 정의하는 데 사용되는 서버 명령이 하나 이상 포함되어 있습니다. 요청이 오면 Nginx는 먼저 요청을 처리할 가상 서버를 선택합니다.
가상 서버는 http 컨텍스트의 서버에 정의됩니다:
http { 서버 { # 서버 구성
}
}
참고: http
에서 여러 서버를 정의할 수 있습니다.
서버 구성 블록은 Listen 명령을 사용하여 로컬 IP 및 포트 번호(Unix 도메인 소켓 및 경로 포함)를 모니터링합니다. IPv6 주소는 대괄호로 묶어야 합니다.
서버 { 수신 127.0.0.1:8080; # IPv4 주소, 포트 8080
# 수신 [2001:3CA1:10F:1A:121B:0:0:10]:80 # IPv6 주소, 포트 80
# 수신 [::]:80; # 이 머신의 모든 IPv4 및 IPv6 주소, 포트 80을 수신합니다
# 나머지 서버 구성}
위 구성에서 포트 번호를 쓰지 않으면 기본적으로 포트 80이 사용됩니다. IP를 쓰지 않으면 로컬 컴퓨터의 모든 IP가 모니터링됩니다.
서버 이름 :
여러 서버의 수신 IP와 포트 번호가 정확히 동일한 경우 Nginx는 요청 헤더에 Host
를 전달합니다.
Nginx를 웹 서버로 구성하는 방법을 정말로 이해하고 계십니까?
요청을 처리할 적절한 가상 서버를 선택하려면 server_name으로 정의된 호스트 이름과 비교하세요.
서버 {80 듣기;
서버 이름 lufficc.com www.lufficc.com;
...
}
server_name의 매개변수는 다음과 같습니다.
api.lufficc.com과 같은 전체 호스트 이름입니다.
*.lufficc.com 또는 api.*와 같은 와일드카드(* 포함)를 포함합니다.
~로 시작하는 정규식.
와일드카드 문자는 시작이나 끝에만 올 수 있으며 . www.*.example.org와 w*.example.org 모두 유효하지 않습니다. 그러나 ~^www..+.example.org$ 및 ~^w.*.example.org$와 같은 정규식을 사용하여 이러한 이름을 일치시킬 수 있습니다. 그리고 *는 여러 부분과 일치할 수 있습니다. *.example.org 이름은 www.example.org뿐만 아니라 www.sub.example.org와도 일치합니다.
정규식의 경우: Nginx에서 사용하는 정규식은 Perl 프로그래밍 언어(PCRE)에서 사용하는 정규식과 호환됩니다. 정규식을 사용하려면 ~로 시작해야 합니다.
명명된 정규 표현식은 변수를 캡처한 후 다음을 사용할 수 있습니다.
서버 { 서버 이름 ~^(www.)?(?
}
}
괄호() 사이에 일치하는 내용은 나중에 $1에서 참조할 수도 있으며, $2는 두 번째 이전()의 내용을 나타냅니다. 따라서 위 내용은 다음과 같이 쓸 수도 있습니다.
서버 { 서버 이름 ~^(www.)?(.+)$ 위치 / { 루트 /sites/$2;
}
}
서버 이름 예시:
서버 {80 듣기;
server_name api.lufficc.com *.lufficc.com;
...
}
마찬가지로 여러 이름이 Host 헤더와 일치하는 경우 Nginx는 다음 순서로 선택합니다.
api.lufficc.com과 같은 전체 호스트 이름입니다.
*.lufficc.com과 같이 *로 시작하는 가장 긴 와일드카드 이름입니다.
api.*와 같이 *로 끝나는 가장 긴 와일드카드 이름입니다.
첫 번째로 일치하는 정규식입니다. (구성 파일의 순서를 따름)
즉, 우선순위는 api.lufficc.com > *.lufficc.com > api.* >
Host 헤더가 server_name과 일치하지 않으면 Nginx는 요청을 기본 가상 서버로 라우팅합니다. 기본 가상 서버는 nginx.conf 파일의 첫 번째 서버 또는 default_server로 명시적으로 선언된 서버를 나타냅니다.
서버 { 수신 80 default_server;
...
}
위치 구성
URI와 위치 매개변수 매칭
서버를 선택한 후 Nginx는 URI를 기반으로 적절한 위치를 선택하여 요청을 프록시할지 아니면 파일을 반환할지 결정합니다.
위치 지시문은 두 가지 유형의 매개변수를 허용합니다:
접두사 문자열(경로 이름)
정규식
접두사 문자열 매개변수의 경우 URI는 반드시 접두사로 시작해야 합니다. 예를 들어 /some/path/ 매개변수의 경우 /some/path/document.html과 일치하지만 /my-site/some/path는 /some으로 시작하지 않기 때문에 /my-site/some/path와 일치하지 않습니다. /길/.
위치 /일부/경로/ {
...
}
정규식의 경우 ~로 시작하면 대소문자를 구분하고 ~*로 시작하면 대소문자를 구분하지 않습니다. 경로의 .는 . 예를 들어 .html 또는 .htm으로 끝나는 URI와 일치하는 위치:
위치 ~ .html?
...
}
정규식은 접두사 문자열보다 우선순위가 높습니다. 일치하는 접두사 문자열이 발견되면 정규식 검색은 계속되지만 접두사 문자열이 ^~ 로 시작하는 경우 정규식은 더 이상 확인되지 않습니다.
구체적인 검색 및 매칭 과정은 다음과 같습니다.
URI를 모든 접두사 문자열과 비교합니다.
= 수정자는 URI가 접두사 문자열과 동일해야 함(시작이 아니라 동일)을 나타내며, 발견되면 검색이 중지됩니다.
발견된 가장 긴 접두사 일치 문자열이 ^~로 시작하는 경우 정규식은 더 이상 일치 항목을 검색하지 않습니다.
일치하는 가장 긴 접두사 문자열을 저장합니다.
URI를 정규식과 비교하여 테스트합니다.
첫 번째로 일치하는 정규식을 찾은 후 중지됩니다.
정규식 일치가 없으면 4에 저장된 접두사 문자열에 해당하는 위치가 사용됩니다.
= 수정자의 우선순위가 가장 높습니다. 웹사이트의 홈페이지를 자주 방문하는 경우 위치를 구체적으로 정의하여 검색 일치 수를 줄이고(=로 수정된 일치 위치에 대한 검색은 검색을 중지하므로) 속도를 향상시킬 수 있습니다.
위치 = / {
...
}
정적 파일 및 프록시
또한 위치는 일치하는 요청을 처리하는 방법(정적 파일을 반환하거나 프록시 서버에 전달하는 방법)을 정의합니다. 아래 예에서 첫 번째 위치는 /data 디렉터리의 정적 파일을 반환하고, 두 번째 위치는 처리를 위해 요청을 https://lufficc.com 도메인 이름의 서버로 전달합니다.
서버 { 위치 /images/ { 루트 /data;
} 위치 / { Proxy_pass https://lufficc.com;
}
}
루트 지시문은 정적 파일의 루트 디렉터리를 정의하고 URI와 연결되어 최종 로컬 파일 경로를 형성합니다. 예를 들어 /images/example.png를 요청하면 스플라이싱 후 로컬 서버 파일 /data/images/example.png가 반환됩니다.
Proxy_pass 지시어는 URL이 가리키는 프록시 서버에 요청을 전달합니다. 그런 다음 프록시 서버의 응답이 클라이언트로 전달됩니다. 위의 예에서 /images/로 시작하지 않는 URI에 대한 모든 요청은 처리를 위해 프록시 서버로 전달됩니다.
예를 들어, Proxy_pass를 https://www.baidu.com/으로 설정하면 http://search.lufficc.com/에 접속하면 바이두 홈페이지와 동일한 응답(페이지)을 받게 됩니다. (관심있는 어린이 신발은 검색해보시면 됩니다.) 자체적으로) 기능은 Baidu와 다르지 않습니다.):
서버{
80을 들어보세요;
server_name search.lufficc.com;
위치 / {
Proxy_pass https://www.baidu.com;
}
}
변수 사용
변수를 사용하여 Nginx가 다양한 요청을 다르게 처리하도록 할 수 있습니다. 변수는 런타임에 계산되어 명령어에 대한 인수로 사용됩니다. 변수는 $로 시작하는 기호로 표시됩니다. 변수는 현재 처리된 요청의 속성과 같은 Nginx 상태를 기반으로 정보를 정의합니다.
핵심 HTTP 변수와 같은 사전 정의된 변수가 많이 있으며 set, map 및 geo 지시문을 사용하여 사용자 정의 변수를 정의할 수도 있습니다. 대부분의 변수는 런타임 시 계산되며 특정 요청과 관련된 정보를 포함합니다. 예를 들어 $remote_addr에는 클라이언트 IP 주소가 포함되고 $uri에는 현재 URI 값이 포함됩니다.
일반적으로 사용되는 변수는 다음과 같습니다.
변수명 기능
$uri 내부 리디렉션을 통해 또는 인덱스 지시문을 사용하여 수정할 수 있는 요청의 현재 URI(요청 매개변수 없음) $uri에는 /foo/bar.html과 같은 호스트 이름이 포함되어 있지 않습니다.
$arg_name은 요청의 매개변수 이름입니다. 즉, "?" 다음에 arg_name=arg_value 형식의 arg_name
입니다.
$hostname 호스트 이름
요청의 $args 매개변수 값
$query_string은 $args와 동일
$request는 클라이언트의 요청 주소를 나타냅니다
$request_uri 이 변수는 일부 클라이언트 요청 매개변수를 포함하는 원래 URI와 동일합니다. 이는 수정할 수 없으며 /cnphp/test.php?arg=freemouse와 같은 호스트 이름을 포함하지 않습니다.
... ...
간단한 애플리케이션은 경로 정보를 사용하여 http에서 https로 리디렉션하는 것입니다.
서버{
... 301 반환 https://lufficc.com$request_uri;
...
}
특정 상태 코드 반환
웹사이트의 일부 리소스가 영구적으로 제거된 경우 가장 빠르고 간결한 방법은 return 명령을 사용하여 직접 돌아가는 것입니다.
위치 /잘못/url { return 404;
}
return의 첫 번째 매개변수는 응답 코드입니다. 선택적 두 번째 매개변수는 리디렉션의 URL(코드 301, 302, 303, 307에 해당) 또는 응답 본문에 반환된 텍스트일 수 있습니다. 예:
위치 /permanently/moved/url { return 301 http://www.example.com/moved/here;
}
return 지시문은 위치 및 서버 컨텍스트에 포함될 수 있습니다.
서버{
위치 / { 404 반환;
}
}
또는:
서버{
...404를 반환합니다.
위치 / {
...
}
}
오류 처리
error_page 명령은 특정 오류 코드에 대한 오류 페이지를 구성하거나 다른 페이지로 리디렉션할 수 있습니다. 다음 예에서는 404 오류가 발생하면 /404.html 페이지를 반환합니다.
error_page 404 /404.html;
error_page 명령은 오류 처리 방법을 정의하므로 직접 반환되지 않지만 return은 즉시 반환됩니다. 처리 중에 프록시 서버 또는 Nginx가 해당 오류 코드를 생성하면 해당 오류 페이지가 반환됩니다.
아래 예에서 Nginx는 페이지를 찾을 수 없으면 코드 404를 코드 301로 바꾸고 클라이언트를 http://example.com/new/path.html로 리디렉션합니다. 예를 들어, 이 구성은 클라이언트가 이전 URI를 사용하여 페이지에 계속 액세스하려고 할 때 유용합니다. 301 코드는 페이지가 영구적으로 제거되었으며 반환된 새 주소로 자동 교체되어야 함을 브라우저에 알립니다.
위치 /old/path.html { error_page 404 =301 http:/example.com/new/path.html;
}
URI 다시 작성
rewrite 지시문은 요청된 URI를 여러 번 수정할 수 있습니다. rewrite의 첫 번째 매개변수는 URI가 일치해야 하는 정규식이고, 두 번째 매개변수는 대체할 URI입니다. 세 번째 매개변수는 선택사항이며 리디렉션 코드(301 또는 302)를 계속 재정의할지 아니면 반환할지 여부를 나타냅니다. 예:
위치 /users/ { 다시 쓰기 ^/users/(.*)$ /show?user=$1 break;
}
서버 및 위치 컨텍스트에 여러 다시 쓰기 지시문을 포함할 수 있습니다. Nginx는 발생한 순서대로 명령어를 하나씩 실행합니다. 서버를 선택하면 서버의 다시 쓰기 지시문이 한 번 실행됩니다.
Nginx는 일련의 재작성 지시문을 처리한 후 새 URI를 기반으로 위치를 선택합니다. 선택한 위치에 여전히 재작성 지시어가 포함되어 있으면 순서대로 실행됩니다. URI가 모두 일치하면 정의된 모든 다시 쓰기 지시문이 처리된 후 새 위치가 검색됩니다.
다음 예에서는 return 지시문과 함께 rewrite 지시문을 사용합니다.
서버 {
...
^(/download/.*)/media/(.*)..*$ $1/mp3/$2.mp3 마지막으로 다시 작성하세요.
^(/download/.*)/audio/(.*)..*$ $1/mp3/$2.ra를 마지막으로 다시 작성하고 403을 반환하세요.
...
}
/download/some/media/file과 같은 URI는 /download/some/mp3/file.mp3 로 변경됩니다. 마지막 플래그로 인해 후속 명령(두 번째 rewrite 지시문 및 return 지시문)은 건너뛰지만 Nginx는 변경된 URI로 요청을 계속 제공합니다. 마찬가지로 /download/some/audio/file과 같은 URI는 /download/some/mp3/file.ra로 대체됩니다. URI가 다시 쓰기 지시문과 일치하지 않으면 Nginx는 클라이언트에 403 오류 코드를 반환합니다.
last와 break의 차이점은 다음과 같습니다.
last : 현재 서버 또는 위치 컨텍스트에서 재작성 지시문의 실행을 중지하지만 Nginx는 재작성된 URI와 일치하는 위치를 계속 검색하고 새 위치에 재작성 지시문을 적용합니다(즉, URI가 다시 변경될 수 있음을 의미).
break : 현재 컨텍스트에서 rewrite 지시어 처리를 중지하고 새 URI와 일치하는 위치 검색을 취소합니다. 새 위치의 rewrite 지시어는 실행되지 않습니다.
부록
자주 사용되는 일반 규칙
.: 개행 문자를 제외한 모든 문자
와 일치합니다.
?: 0~1회 반복
+: 1회 이상 반복
*: 0회 이상 반복
d: 숫자 일치
^: 문자열의 시작과 일치
$: 문자열 매칭 소개
{n}: n번 반복
{n,}: n회 이상 반복
[c]: 단일 문자 c와 일치
[a-z]: 소문자 a-z 중 하나와 일치
전역변수
$args: #이 변수는 요청 라인의 매개변수와 동일하며 $query_string
과 동일합니다.
$content_length: 요청 헤더의 콘텐츠 길이 필드입니다.
$content_type: 요청 헤더의 Content-Type 필드입니다.
$document_root: 현재 요청에 대한 루트 지시문에 지정된 값입니다.
$host : 호스트 헤더 필드를 요청하고, 그렇지 않으면 서버 이름입니다.
$http_user_agent: 클라이언트 에이전트 정보
$http_cookie: 클라이언트 쿠키 정보
$limit_rate: 이 변수는 연결 속도를 제한할 수 있습니다.
$request_method: 클라이언트가 요청한 작업(보통 GET 또는 POST)입니다.
$remote_addr: 클라이언트의 IP 주소.
$remote_port: 클라이언트의 포트입니다.
$remote_user: Auth Basic Module에서 인증된 사용자 이름입니다.
$request_filename: 루트 또는 별칭 지시문과 URI 요청에 의해 생성된 현재 요청의 파일 경로입니다.
$scheme: HTTP 메서드(예: http, https).
$server_protocol: 요청에 사용되는 프로토콜(일반적으로 HTTP/1.0 또는 HTTP/1.1)입니다.
$server_addr: 서버 주소, 이 값은 시스템 호출을 완료한 후 결정될 수 있습니다.
$server_name: 서버 이름.
$server_port: 요청이 서버에 도달하는 포트 번호입니다.
$request_uri: 호스트 이름을 제외하고 요청 매개변수를 포함하는 원래 URI(예: /foo/bar.php?arg=baz).
$uri: 요청 매개변수가 없는 현재 URI인 $uri에는 /foo/bar.html과 같은 호스트 이름이 포함되어 있지 않습니다.
$document_uri: $uri와 동일합니다.
예를 들어 요청: http://localhost:88/test1/test2/test.php
$호스트:로컬호스트
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.php