-
[Nginx] Nginx 예시 및 설정시 주의사항카테고리 없음 2023. 8. 6. 00:00
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가 다름에도 불구하고 무시된다. 그러므로 이러한 부분을 주의해서 사용해야 한다.