/etc/nginx/nginx.conf 의미 알아보기

ny0011·2023년 3월 3일

nginx 1.23.3 기준 docker container 내부에 있는 기본 설정 파일
/etc/nginx/nginx.conf

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

/etc/nginx/nginx.conf 설정 파일 구조

  • directives(지시문)은 simple directives와 block directives로 나뉨
    • simple directives 예시
     user  nginx;
    • block directives 예시
     events {                     
      worker_connections  1024;
     }
    • block directives 괄호 안에 다른 directives가 올 수 있으면 context 라고 부름

core 모듈

  • user : nginx의 worker 프로세스에서 사용되는 user 정보
  • worker_processes : worker 프로세스의 수를 정의
    • CPU core수, HDD수, load 패턴 등에 따라 최적값이 달라짐
    • 뭐로 해야 될지 모르면 CPU core수로 하는 걸 추천
    • auto로 써도 되는데 auto는 1.3.8, 1.2.5 버전부터 지원
  • error_log 파일 위치 레벨 : 로깅 설정
    • 레벨은 debug, info, notice, warn, error, crit, alert, or emerg 중 하나로 설정됨
    • 기본값은 error임
      • error로 설정하면 error, crit, alert, emerg 로그가 기록됨
    • debug 레벨로 로깅하고 싶으면 nginx를 --with-debug로 빌드해야 함. https://nginx.org/en/docs/debugging_log.html 참고하기
  • pid : 메인 프로세스의 PID가 저장되는 파일 위치, nginx 종료 시 사용됨
  • events : 연결 처리에 영향을 주는 지시문을 event 안에 정의하게 됨.
  • worker_connections : worker process가 열 수 있는 동시 접속 최대수
    • 클라이언트와 접속 뿐만 아니라 프록시 서버 접속 등 모든 접속에 해당됨
    • 실제 동시접속 수가 열려있는 파일의 최대수의 제한을 초과할 수 없음. worker_rlimit_nofile에서 main 프로세스를 재시작하지 않고 열린 파일 최대수 제한을 변경할 수 있음

http core 모듈

  • http : HTTP 트래픽 처리를 위한 지시문을 http 안에 정의
  • include : 외부 파일을 설정에 포함시킴
    • mime.types : 미디어 타입, 원래는 이메일 안에 첨부파일을 텍스트 문자로 변환하는 용도였지만 지금은 웹으로 바이너리 파일을 전송할 때 텍스트 파일로 변환해주는 역할인듯.
    • /etc/nginx/conf.d/*.conf :
  • default_type : response의 기본 MIME 유형 정의
    • application/octet-stream : 이미 정의된 타입(text/plain, image/gif 등) 외에는 모두 이 타입으로 정의됨.
    • 기본값으로 보통 설정해두나봄..
    • conf/mime.types에 파일 확장자별 타입 목록이 있는데 여기에 없는 확장자에 대한 타입을 설정한다.
  • sendfile : sendfile() 사용할지 말지 설정
    • 기본 설정은 off로 nginx는 파일을 보내기 전에 버퍼에 파일을 복사하게 됨
    • on : nginx에서 정적파일을 보내도록 설정
      • 데이터를 버퍼로 복사하는 단계가 제거되고 file descriptor에서 다른 file descriptor로 직접 데이터가 복사됨
        • 커널에서 실행되는 프로세스(syscall)
        • 로컬에 저장된 정적 파일을 제공하는 경우 웹 서버 속도를 높이려면 on으로 설정해주자
        • Nginx를 리버스 프록시로 사용하여 애플리케이션 서버에서 페이지를 제공하는 경우는 off 해주자
      • 어떤 파일에서 다른 파일로 바로 복사되는 방식인듯
      • worker process전체를 점유하지 않게 추가로 sendfile_max_chunk 설정으로 sendfile() call 하나 당 데이터 전송량을 제한해둘 수 있음
  • tcp_nopush : TCP_NOPUSH socket option을 활성화 할지 말지 설정
    • sendfile이 on 상태일 때 사용 가능
    • 기본 옵션은 off인데 on 으로 바꾸면
      • Linux 및 FreeBSD 4.*에서 응답 헤더와 파일 시작 부분을 하나의 패킷으로 전송합니다.
      • 전체 패킷으로 파일을 보냅니다. => 버퍼가 다 찼을 때 패킷 전송
        => 서버 트래픽 감소됨
  • tcp_nodelay : TCP_NODELAY를 활성화 할지 말지 설정
    • 기본 옵션은 on
      • 패킷 크기에 관계없이 소켓이 버퍼의 데이터를 강제로 보냅니다.
    • keep-alive 상태로 전환되거나 버퍼링없는 프록시, 웹소켓 프록싱을 위한 SSL 연결에서 활성화됨
      • keepalive를 사용하면 새 연결을 시작하지 않고 모든 HTTP 요청에 대해 TCP 3방향 핸드셰이크를 재생하지 않고도 더 많은 데이터를 보낼 수 있습니다.
      • 이렇게 하면 모든 데이터 전송 후 FIN_WAIT로 전환되지 않으므로 시간과 소켓이 모두 절약됩니다.
        => 대기시간 감소
    • tcp_nopush와 반대로 작용
  • keepalive_requests : 하나의 keep-alive 연결을 통해 처리할 수 있는 최대 요청 수를 설정
    • 기본값 : 1000
    • 최대 요청 수에 도달하면 연결이 닫힘
    • keep-alive?
      • http에서 persistent connection하기 위해서 쓰는 것
        • 같은 클라이언트가 연속해서 서버에 여러 요청을 보낼 때 연결을 유지하고 싶을 것임
        • HTTP/1.1부터 HTTP Application이 요청마다 TCP connection을 close하지 않고 재사용하는 방법 제공
      • HTTP/1.0에서는 keep alive로 persistent connection을 구현하는듯..?
      • 설계상 문제점(ex: proxy)이 있어서 HTTP/1.1부터는 사용되지 않음
  • keepalive_timeout : keep-alive 클라이언트 연결이 서버에 열려있는 시간을 제한
    • 기본값 : 75(초)
    • 0이면 keep-alive 클라이언트 연결 비활성화

http log 모듈

  • log_format 이름 형식 : ~형식을 가진 log_format을 이름이라고 한다고 정의하는 곳인듯
  • access_log 파일 위치 format 이름 : access_log를 기록할 파일 위치와 로그 형식을 정의. log_format에서 선언한 이름을 여기에 적는듯

http gzip 모듈

  • gzip : gzip 방식을 사용해 응답을 압축
    • on : gzip 압축 방식 사용

/etc/nginx/conf.d/default.conf

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

/etc/nginx/conf.d/default.conf 설정 파일 구조
http core 모듈

  • server : 가상 서버(virtual server)를 설정

  • listen : 서버가 request를 받을 IP address와 port를 설정하거나 UNIX-domain 소켓의 경로를 설정

    • 주소만 있으면 80번 포트가 기본으로 사용됨
    • listen 지시문이 없으면, nginx가 su권한으로 실행되면 80번 포트, 일반 권한이면 8000을 사용함
    listen 127.0.0.1:8000;
    listen 127.0.0.1;
    listen 8000;
    listen *:8000;
    listen localhost:8000;
    
    # IPv6 주소
    listen [::]:8000;
    listen [::1];
    
    # UNIX-domain 소켓은 unix: 접두어를 붙여야함
    listen unix:/var/run/nginx.sock;
  • server_name : 가상 서버의 이름을 설정

    • 맨 처음에 오는 게 기본 서버 이름이 됨
    # example.com이 기본 서버 이름
    server {
      server_name example.com www.example.com;
    }
    
    # 이름의 처음과 마지막 부분에 *가 붙을 수 있음 -> wildcard 이름
    server {
      server_name example.com *.example.com www.example.*;
    }
    
    # 첫번째 예제와 두번째 예제를 합치면 아래처럼 요약 가능
    server {
      server_name .example.com;
    }
  • location : request URI에 따라 설정

    • 접두사나 정규식으로 정의 가능

    • 주어진 request와 일치하는 location을 찾기 위해서 nginx는 접두사 문자열을 사용해 정의된 위치를 확인

      • 그 중에 일치하는 접두사가 가장 긴 위치가 선택되어 기억됨
      • config 파일에 나타나는 순서대로 정규식을 검사
      • 정규식 검색은 첫 번째 일치되면 종료되고 그 구성을 사용함
      • 정규식에서 일치하는 항목이 없으면 맨 처음에 기억해둔 접두사 location이 사용됨
    • ~* : 대소문자를 구분하지 않는 일치

    • ~ : 대소문자를 구분하는 일치

    • = : URI의 정확한 위치가 매칭되게 하고 싶을 때 지정

      • 정확히 일치하는 항목이 발견되면 검색이 종료되어서 처리 속도가 빨라짐
      location = / {
         [ configuration A ]
       }
       location / {
         [ configuration B ]
       }
       location /documents/ {
         [ configuration C ]
       }
       location ^~ /images/ {
         [ configuration D ]
       }
       location ~* \.(gif|jpg|jpeg)$ {
         [ configuration E ]
       }
    • 위 예시에 해당하는 요청

      • / 요청은 A 설정
      • /index.html 요청은 B설정
      • /documents/document.html 요청은 C
      • /images/1.gif 요청은 D. E에도 해당되지만 D가 E보다 앞에 있어서 D가 됨
      • /documents/1.jpg 요청은 E
    • 만약 location 이 /로 끝나고 요청이 proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass 중에 하나라면 특별한 방식이 실행됨

      • URI가 location 문자열과 같지만 뒤에 /가 없는 요청에 대한 응답으로 301이 포함된 permanent redirection이 /가 추가되어서 요청된 URI로 반환됨
      • 이걸 원하지 않으면 =를 사용해서 정확한 위치가 일치하도록 설정하면 됨
      location /user/ {
        proxy_pass http://user.example.com;
      }
      
      location = /user {
        proxy_pass http://login.example.com;
      }

http proxy 모듈

  • proxy_pass URL : 프록시 서버의 프로토콜 및 주소와 위치를 매핑해야 하는 URI를 설정
    • protocol : http or https
    • 주소 : 도메인 이름 or IP주소 or IP주소 + 포트 or unix 도메인 소켓 경로
      • 도메인 이름이 여러 IP주소를 갖고 있으면 모든 주소가 round-robin 방식으로 사용됨
      • 주소 지정 시 upstream directive를 사용해 server group으로 지정할 수 있음
        upstream backend {
           server backend1.example.com       weight=5;
           server backend2.example.com:8080;
           server unix:/tmp/backend3;
           server backup1.example.com:8080   backup;
         }
         
         server {
            location / {
                proxy_pass http://backend;
            }
        }
      • parameter 값으로 변수가 될 수 있음. 만약 주소가 특정 도메인 이름으로 지정되면 server group 안에서 찾고 못 찾으면 resolver로 결정됨
    • request URI가 다음과 같이 서버에 전달됨
      • proxy_pass가 URI로 지정되어 있으면 request가 이 서버로 전달됨
        • location이 일치하는 정규화된 request URI의 일부가 proxy_pass에 적혀있는 URI로 대체됨
        # http://localhost/name -> http://127.0.0.1/remote/
        location /name/ {
           proxy_pass http://127.0.0.1/remote/;
        }
      • proxy_pass가 URI로 지정되어 있지 않으면 request URI가 클라이언트에서 보냈던 형식 그대로 서버로 전달됨
        # http://localhost/some/path -> http://127.0.0.1/some/path
        location /some/path/ {
             proxy_pass http://127.0.0.1;
        }
    • ❓ 아래의 경우 대체될 request URI의 일부를 결정할 수 없음
      • 정규식을 사용해 location을 표현하고 named location이 안에 있을 때 : proxy_pass 에 URI를 제외해야 함
      • rewrite를 사용해 프록시된 location 안에서 URI가 변경 되고 request(break)를 처리할 때 같은 구성일 때
        : (proxy_pass) directive에 적힌 URI는 무시되고 전체 변경된 request URI가 서버로 전달됨
         location /name/ {
              rewrite    /name/([^/]+) /users?name=$1 break;
              proxy_pass http://127.0.0.1;
         }
      • proxy_pass에 변수가 사용될 때
        : (proxy_pass) directive에 적힌 URI가 있으면 원래 request URI를 대체하고 그대로 서버에 전달
        location /name/ {
             proxy_pass http://127.0.0.1$request_uri;
        }
  • proxy_redirect : 프록시 서버 응답의 locationrefresh 헤더 필드에서 변경되어야 하는 텍스트를 설정
    • 예를 들어 프록시 서버가 헤더 필드를 Location: http://localhost:8000/two/some/uri/로 리턴했다고 가정하면
    proxy_redirect http://localhost:8000/two/ http://frontend/one/;
    : 이 directive는 Location: http://frontend/one/some/uri/ 으로 변경해줌
    • 기본값 : default

      • locationproxy_pass의 parameter를 사용함
      • 아래 두 예제는 같은 말
      location /one/ {
      proxy_pass     http://upstream:port/two/;
      proxy_redirect default;
      
      location /one/ {
      proxy_pass     http://upstream:port/two/;
      proxy_redirect http://upstream:port/two/ /one/;
      
      • proxy_pass가 변수를 사용하면 default 값을 사용할 수 없음
    • off 값으로 설정하면 이전 설정 레벨에서 상속받은 proxy_redirect 영향을 취소함

  • proxy_set_header : 프록시 서버로 전달되는 request header를 재정의하거나 추가할 수 있음
    • 기본값 : 아래 두 필드가 정의됨
    proxy_set_header Host       $proxy_host;
    proxy_set_header Connection close;
    • $host 변수는 request header 필드의 "Host"에 있는 서버 이름과 같거나 이 필드가 없으면 primary server 이름이 됨
    proxy_set_header Host       $host;
    • 서버 이름이 프록시 서버의 port도 같이 전달될 수 있음
    proxy_set_header Host       $host:$proxy_port;

참고

0개의 댓글