티스토리 뷰

Server

[Nginx] Nginx 예시/샘플 설정 공유 및 설정 시의 주의사항

망나니개발자 2023. 4. 18. 10:00
반응형

아래의 내용은 Nginx 설정을 정리한 부분입니다. 관련 코드는 깃허브에 올려두었고, 가능한 모든 부분에 주석을 남겨두었으니, 상황에 맞게 수정해서 사용하시면 됩니다.

 

 

 

 

1. Nginx 예시/샘플 설정 공유


[ Nginx 설정 파일들 ]

실무에서 사용되는 Nginx 설정은 꽤나 복잡한데, 이를 아래와 같이 분리하였습니다.

  • mime.types: Nginx 서버에서 처리할 MIME 타입 모음
  • upstream.conf: upstream(서버 그룹)을 모아둔 설정 파일
  • header.conf: 요청을 다른 서버로 프록시할 때, 전달해주는 헤더 설정 파일
  • ssl.conf: SSL과 관련된 설정 파일, SSL 인증서 파일을 경로로 참조함
  • ssl-server.conf: SSL 요청(443 포트)로 들어오는 요청과 관련된 서버 블럭 설정 파일
  • http-server.conf: Http 요청(80 포트)로 들어오는 요청과 관련된 서버 블럭 설정 파일
  • nginx.conf: Nginx 서버에서 참고하는 설정 파일로 다른 설정 파일들을 include 함

 

 

 

 

mime.types

Nginx 서버에서 처리할 MIME 타입 모음, 전체 목록은 깃허브에서 참고

types {
    text/html                                        html htm shtml;
    text/css                                         css;
    text/xml                                         xml;
    image/gif                                        gif;
    image/jpeg                                       jpeg jpg;
    application/javascript                           js;
    application/atom+xml                             atom;
    application/rss+xml                              rss;

    ...
}

 

 

 

upstream.conf

upstream(서버 그룹)을 모아둔 설정 파일

# upstream은 nginx가 받은 요청을 넘겨 줄 서버 지시자
# keepalive는 upstream 접속에 사용될 connection 수

upstream tomcat-mangkyu {
    server 127.0.0.1:8523;
    keepalive 10;
}

upstream jp1-mangkyu {
    server jp1-github.mangkyu.com;
    keepalive 10;
}

 

 

 

header.conf

요청을 다른 서버로 프록시할 때, 전달해주는 헤더 설정 파일

proxy_pass_header Server;               # 프록시할 때 Server 헤더를 전달할 지 결정함(기본적으로 전달하지 않음)
proxy_set_header Host $http_host;       # 프록시할 때 Host 헤더를 설정함

 

 

 

ssl.conf

SSL과 관련된 설정 파일, SSL 인증서 파일을 경로로 참조함

listen 443 ssl http2;

ssl_certificate       ./ssl/cert.pem;
ssl_certificate_key   ./ssl/key.pem;

ssl_protocols  TLSv1.2 TLSv1.3;
ssl_ciphers    AES128:RC4:AES256:!ADH:!aNULL:!DH:!EDH:!eNULL:!LOW:!SSLv2:!EXP:!NULL;
ssl_prefer_server_ciphers   on;

 

 

 

 

ssl-server.conf

SSL 요청(443 포트)로 들어오는 요청과 관련된 서버 블럭 설정 파일

# https 443으로 들어온 요청에 대한 proxy pass 연결 부분
server {
	include ssl.conf;                                                        # ssl 관련 설정 추가
	server_name github.mangkyu.com kr1-github.mangkyu.com;                   # 이 server 블럭에서 처리할 도메인명들
	access_log  ./logs/nginx/access_ssl_mangkyu.log  main;                   # 파일로 로그 기록
	error_log   ./logs/nginx/error.log   error;                              # 파일로 에러 로그 기록

    # ~*은 정규 표현식을 사용하여 요청된 URI와 지정된 패턴을 비교하는 정규식 매칭 연산자

    # /actuator로의 요청은 외부에서 접근시 보안 이슈가 있으므로, 내부에서만 접근 가능하도록 제한함(SpringBoot Actuator를 사용하지 않는다면 제거)
    location ^~ /actuator {
        return 404;
    }

    # hello와 그 하위의 path에 대해 톰캣 서버로 proxy
	location ~* ^/(hello/) {

        # 쿠키에 있는 MANGKYU_LOC 값이 jp1이면 jp1-mangkyu upstream으로 proxy
        if ($cookie_WORKS_RE_LOC = 'jp1') {
	    	proxy_pass https://jp1-mangkyu;
	    	break;
        }

        proxy_pass http://tomcat-mangkyu$uri$is_args$args;
        break;
    }

    # 그 외의 path로 접근한 경우에는 404 반환
    location / {
        return 404;
        break;
    }

    error_page 400 /html/404.html;
    error_page 401 /html/404.html;
    error_page 403 /html/404.html;
    error_page 404 /html/404.html;
    error_page 405 /html/404.html;
    error_page 500 /html/404.html;
    error_page 501 /html/404.html;
    error_page 502 /html/404.html;
    error_page 503 /html/404.html;
}

 

 

 

http-server.conf

Http 요청(80 포트)로 들어오는 요청과 관련된 서버 블럭 설정 파일

# http 80으로 들어온 요청에 대한 proxy pass 연결 부분
server {
    listen       80;  	                                   # 80번 요청에 대한 listen
    server_name github.mangkyu.com kr1-github.mangkyu.com; # 이 server 블럭에서 처리할 도메인명들
    access_log  ./logs/nginx/access_mangkyu.log  main;     # 파일로 로그 기록

    # ~*은 정규 표현식을 사용하여 요청된 URI와 지정된 패턴을 비교하는 정규식 매칭 연산자

    # /actuator로의 요청은 외부에서 접근시 보안 이슈가 있으므로, 내부에서만 접근 가능하도록 제한함(SpringBoot Actuator를 사용하지 않는다면 제거)
    location ^~ /actuator {
        return 404;
    }

    # /api 그 하위의 path에 대해 https로 rewrite
    location ~* ^/(api/) {
        rewrite ^(.*) https://$http_host$1 permanent;
    }

    # 그 외의 path로 접근한 경우에는 404 반환
    location / {
        return 404;
        break;
    }

    error_page 400 /html/404.html;
    error_page 401 /html/404.html;
    error_page 403 /html/404.html;
    error_page 404 /html/404.html;
    error_page 405 /html/404.html;
    error_page 500 /html/404.html;
    error_page 501 /html/404.html;
    error_page 502 /html/404.html;
    error_page 503 /html/404.html;

}

 

 

 

nginx.conf

Nginx 서버에서 참고하는 설정 파일로 다른 설정 파일들을 include 함

## CPU Core에 맞는 적절한 Work Process를 할당함
worker_processes  auto;

## Worker Process가 수용할 수 있는 Connection 개수
events {
    worker_connections  4000;
}

http {
    include       mime.types;               # 해당 http 블럭에서 처리할 mime type 모음, 기본으로 octet_stream을 사용함
    default_type  application/octet-stream; # octet_stream은 file이나 data의 content-type을 식별하기 어려운 경우에 사용할 수 있는 기본 타입임

    sendfile       on;                      # 디스크에서 네트워크로 파일을 전송할 때 sendfile()이라는 system call을 사용할지 여부를 결정함
    tcp_nopush     on;                      # TCP 패킷을 가능한 빨리 전송할 지(on) 또는 조금 기다렸다가 모아서 전송할 지(off)를 결정함

    keepalive_timeout  65;                  # keep-alive connection는 유휴 상태의 keep-alive 커넥션이 얼마나 오래 유지될지를 결정함(default 75)
    keepalive_requests 100;                 # keep-alive requests는 단일 keep-alive 커넥션이 최대 몇 개의 요청을 전송할 수 있는지를 결정함(default 100)

    gzip          on;                       # gzip 압축을 활성화함

    send_timeout       15s;                 # send_timeout는 nginx가 WAS로 요청을 보내고, 응답을 기다리는 시간임(default 60s)
    resolver_timeout   5s;                  # resolver_timeout는 DNS를 찾는 것을 완료하기까지 기다리는 시간임(default 30s)


    large_client_header_buffers 20 32k;     # 요청 헤더를 읽을 때 사용되는 버퍼의 최대 개수와 크기(default 4, 8k), 초과 시 414 에러 반환
    client_header_buffer_size   8k;         # 요청 헤더를 저장하기 위한 버퍼 크기(default 1k), 초과 시 414 에러 반환 ex)쿠키 크기가 커질 경우
    client_max_body_size        100M;       # 요청 바디의 최대 크기(default 1M), 초과 시 413 에러 반환
    client_body_buffer_size     1M;         # 요청 바디를 저장하기 위한 버퍼 크기(default 8k), 초과 시 버퍼 데이터를 메모리에서 디스크로 저장함
    output_buffers 20 32k;                  # 응답 바디를 저장하기 위한 버퍼 크기(default 1, 32k), 32K짜리 버퍼 1개를 응답에 사용하겠다는 의미임

    ignore_invalid_headers off;             # 요청 헤더에 유효하지 않은 헤더가 있을 경우 무시할지 결정함
    server_tokens off;                      # 응답 헤더에 nginx 버전 정보를 넣을지 결정함
    autoindex off;                          # 요청 경로 대상이 디렉토리인 경우, 파일 리스팅을 할지 여부(off 시 403 에러 반환)

    # 요청을 다른 서버로 프록시할 때, 헤더를 세팅해줌
    include header.conf

    # nginx 로그 포맷
    log_format  main  '$remote_addr $remote_user "$request" '
                   '$status $body_bytes_sent "$http_referer" "$request_time" '
                   '"$http_user_agent" ';

    include upstream.conf;      # upstream(서버 그룹)을 모아둔 설정 파일
    include http-server.conf;   # Http 요청(80번 포트)로 들어오는 경우 처리하는 서버 블럭
    include ssl-server.conf;    # SSL 요청(443 포트)로 들어오는 경우 처리하는 서버 블럭

}

 

 

 

 

 

2. Nginx 설정 시의 주의사항


[ server_name 주의사항 ]

nginx는 요청이 들어오면 먼저 어느 서버 블록이 요청을 처리할 지 판단하게 되는데, server_name에 설정된 값이 이를 결정한다. 예를 들어, 80번 포트에 대한 3개의 서버 블록이 존재하는 상황이라고 하자.

server {
    listen      80;
    server_name mangkyu.org www.mangkyu.org;
    ...
}

server {
    listen      80;
    server_name mangkyu.net www.mangkyu.net;
    ...
}

server {
    listen      80;
    server_name mangkyu.com www.mangkyu.com default_server;
    ...
}

 

 

nginx는 요청 헤더의 “Host” 값을 바탕으로 어느 서버에 요청을 라우팅할지 결정한다. 그리고 만약 매칭되는 server_name이 없거나 Host 헤더 값이 없다면, 해당 포트의 default 서버로 요청을 보내게 되고, 만약 default로 지정된 server_name이 없다면 위에서부터 가장 먼저 매칭되는 서버 블록이 처리하게 된다. Host 헤더 필드가 없는 경우에 요청을 drop 시키려면 다음과 같이 설정할 수도 있다.

server {
    listen      80;
    server_name "";
    return      444;
}

 

 

하나의 서버에 여러 개의 DNS가 매핑되는 상황에서 nginx를 설정하려다 보면 원하지 않는 server 블록이 요청을 처리하게 되는 문제가 발생할 수 있다. 이러한 경우에는 server_name이 올바르게 매핑되는지 확인해보면 된다.

 

 

 

 

 

[ proxy_set_header 주의사항 ]

proxy_pass 시에 추가적인 헤더를 전달하기 위해서는 proxy_set_header를 사용해야 하며, http, server, location 블록에서 사용할 수 있다. 만약 별도의 설정이 없다면 아래의 2가지 헤더를 기본적으로 갖게 된다.

proxy_set_header Host       $proxy_host;
proxy_set_header Connection close;

 

 

proxy_set_header는 기본적으로 상위 수준의 설정을 상속받는다. 즉, 상위 블록에 해당 설정이 있다면 하위 블록에서도 사용하게 되는 것이다. 예를 들어 proxy_set_header가 http 또는 server 블록에 존재한다면, location 블록에서도 이를 사용할 수 있다.

하지만 하위 수준의 블록에서 proxy_set_header를 해준다면, 상위 수준의 블록에 존재하는 proxy_set_header는 날라가고 해당 블록의 proxy_set_header만 남게 된다.

예를 들어 다음과 같은 server 블록이 있다고 하자. 서로 다른 2개의 key(Hello, MangKyu)를 갖는 proxy_set_heade가 각각 server 블록과 locatino 블록에 존재한다. 이 경우에 전달되는 헤더는 어떤 것이 있을까?

 server {
    listen       80;
    server_name  localhost;
    
    # 상위 블록에 존재하는 설정은 key가 다름에도 불구하고 무시됨
    proxy_set_header Hello "Hello";
    
    location / {
        proxy_set_header MangKyu "MangKyu";
        proxy_pass http://developers;
    }        
    
    ...
}

 

 

여기서 proxy_pass로 전달되는 헤더는 MangKyu 뿐이다. 왜냐하면 더 좁은 블록인 location에 proxy_set_header가 존재하므로, 상위 블록들의 proxy_set_header 설정들은 무시되기 때문이다. 상위 블록에 존재하는 proxy_set_header 설정은 key와 하위 블록에 존재하는 key가 다름에도 불구하고 무시된다. 그러므로 이러한 부분을 주의해서 사용해야 한다.

 

 

 

 

아래의 내용은 Nginx 설정을 정리한 부분입니다. 관련 코드는 깃허브에 올려두었고, 가능한 모든 부분에 주석을 남겨두었으니, 상황에 맞게 수정해서 사용하시면 됩니다.

 

 

 

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함