(우분투 기준) nginx설치 후 /etc/nginx로 가보면 nginx.conf라는 파일이 있고, 여기엔 nginx의 설정 파일인 nginx.conf가 있다
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
여기서 http블록 안에 직접 server 블록을 작성해줌으로써 웹 서버에서 특정 도메인, 호스트 이름, 포트 또는 IP 주소와 관련하여 요청을 어떻게 처리할지를 정의할 수 있다. 또는 위에 적혀있듯이 /etc/nginx/sites-enabled나 /etc/nginx/conf.d에 작성한 conf파일에 적힌 내용을 include하는 식으로도 server 블록을 정의할 수 있다(즉 직접 nginx.conf안에 작성하든가, 아니면 외부에서 작성한 후 include로 끌고 올 수 있다)
이 server 블록은 각 블록별로 하나의 웹사이트 또는 가상 호스트(Virtual Host)를 의미한다. 즉 여러 개의 server 블록을 작성해 다수의 도메인을 하나의 서버에서 가동할 수 있는 것이고, 이는 다수의 도메인에 대해 하나의 서버에서 각기 다른 페이지를 서비스할 수 있다는 말이다. server 블록은 다음과 같이 작성 가능하다.
server {
listen 80;
server_name example.com;
location / {
# example.com에 대한 설정 ...
}
}
- listen : nginx server가 클라이언트로부터 요청을 수신하는 방법을 정의. 걍 어느 ip 어느 포트로 올 건지를 말 그대로 listen한다는 것을 설정하는 부분
- server_name : 해당 server 블록이 처리할 도메인이나 호스트네임 또는 ip주소를 지정. 클라이언트로부터 request가 오면 header에 있는 Host값과 이 server_name값이 일치하면 해당 server블록을 활성화하는 것임. server_name을 없애고 listen에 example.com:80으로도 작성 가능함
- location 블록 : 특정 URL 경로 또는 패턴에 대한 요청을 처리하는 방법을 정의. 해당 경로에 대한 프록시 패스를 처리한다든지..그런 것들을 설정해줄 수 있다. 위 예제에선 example.com의 모든 요청(/이니까~)에 대한 모든 요청에 대해 location블록에 설정한 내용이 동작할 것임. 필요에 따라 한 server 블록에 여러 location블록을 둘 수 있음
- 기타 다른 설정도 가능..
여기서 내가 처음에 헷갈렸던 건, "server_name으로 해당 server블록이 처리할 도메인을 적으라는 것". 아니 그러면 naver 도메인같은 걸 여기 적어줘도 되는거야? 란 생각이 들었다. 그러면 말이 안 되지 않나? 저 문장대로면 브라우저에 naver치고 들어가는 걸 naver서버가 아니라 내가 띄운 nginx가 처리해야 한다는 거 아닌가?
그리고 애당초 난 처음엔 server_name을 프록시 대상의 도메인이나 ip주소를 적어줘야 하는 줄 알고 있었다.. (nginx를 리버스 프록시로 쓸 생각으로 설치했었고 자료를 찾아봤어서...) 그래서 nginx 처음 쓰는데 server_name에 프록시 대상으로 was의 주소(nginx를 웹서버, spring boot를 was로 사용해서 was의 주소를 적어줬었음)를 줬는데 잘만 동작하길래 내가 이해한 게 맞다 싶었다. 근데 알고 보니 server_name으로는 server블록이 처리할 도메인과 같이 웹서버에 관한 뭔가를 쓰는 거여서 뭐지? 싶던 거.
"난 server_name으로 웹서버가 아닌 was에 대한 걸 적어줬는데 왜 프록시 패스가 잘 되는거지?"
그래서 실험을 좀 했다.
우선 server 블록은 다음과 같이 1개만 작성된 상태
server_name에 was(spring boot)의 사설 ip를 박아뒀었다. nginx는 public subnet에 띄웠었고, was랑 같은 vpc안에 있으니 사설 ip를 통해서도 접근이 가능하기 때문에, was의 사설 ip를 server_name에 박아줘도 된다고 생각했음. 그래서 proxy_pass에 server_name에 준 주소를 그대로 써먹은 모습을 확인 가능하다.
암튼 이렇게 두면, 잘 된다. nginx쪽에 request를 보내면 잘만 was쪽으로 request를 던져준다. 근데 왜 잘 되는 건지는 몰랐다. 일단 server_name에 10.0.1.88을 박아뒀으니 reqeust의 Host와 매칭되진 않을텐데? 근데 왜 프록시 패스가 잘 되지?
바보같은 생각이지만(?) Host와 server_name이 매칭이 안 되면 10.0.1.88로 뭔지 모르겠지만 보내나,,? 싶었다. 그래서 server 블록을 하나 더 추가해줬다.
이렇게 하니, 안된다. nginx쪽으로 보낸 request가 was쪽으로 던져지지 않는다(즉 was에 request가 오지 않음). 매칭이 안 된다고 10.0.1.88로 무조건 보내는 건 아닌 듯 하다. 근데 이상하게 두 server 블록의 순서를 바꿔주면 됐었음. (이때까진 이유를 몰랐다)
사실 이때까지도 server_name을 프록시 대상의 ip를 줘야 하지 않을까란 의심(?)을 버리지 못한 상태라,, server_name이랑 request의 Host가 정확히 어떻게 매칭이 되는거지라는 생각이 들었다.. server_name을 아예 nginx가 띄워져있는 ec2의 public ip를 주면 어떨까?란 생각이 들어서 바꿔봤고..실험해봤다
ㅇㅇ. 이렇게 하니 nginx로 보낸 request가 was로 잘 전달된다.
음 그러면 확실하게 server_name은 프록시 대상과는 아무런 연관이 없다. server_name과 request의 Host가 매칭돼야 하는거라면, nginx가 띄워진 ec2의 public ip를 server_name으로 줬을 때 해당 ip로 보내는 request의 Host와 매칭되는건 당연하다. 그러면 아까 들었던 의문으로 돌아가서.. server_name으로 아무 도메인(네이버 등)이나 막 줘도 request의 Host랑 매칭만 되면 동작하겠다는 생각이 들었다. 그러나 주소창에 naver를 치고 들어가면 당연히 내 nginx가 이를 캐치할 리는 없고..엇? nginx로 보내는 request에 담긴 Host값만 잘 조작하면 프록시 패스가 되겠네?란 생각이 들었다. 당장 실험에 옮기기로 했다
server_name에 www.naver.com 입력하고
nginx로 보내는 request의 Host를 www.naver.com적어서 보내본다.
결과는..!
response가 왔다는거 = nginx에서 was로 request를 던져줬다. 라는 것.. 즉 예측에 성공했다.
아하! server 블록을 여러 개 둔 뒤 블록별로 server_name을 이것저것 주면, 클라이언트에서 request의 Host를 직접 조작해서 보내는 것을 통해 이런저런 조작을 할 수 있구나~! 이렇게 활용하나보다~!
싶었으나! 이내 깨달았다.
"하나의 ip주소에 여러 도메인을 연결한다면"..!
즉..nginx는 물리적으로 하나의 콤퓨타 위에서 돌아가고 있으니, 해당 컴퓨터에 대한 하나의 ip로 요청을 보낼 건데.. 그 ip가 여러 도메인에 연결돼있다면, 우리 킹갓 nginx가 그 도메인들 별로 각기 다른 서비스를 제공해줄 수 있다는 거다. 뭐 클라이언트에서 직접 request의 Host를 직접 조작해서 보내는..그런 이상한 짓(?)은 안 하는거(물론 원한다면 할 순 있겠지만..)
근데 그러면 아까 server블록을 하나만 작성했는데 server_name이 request의 Host와 매칭이 안 됐는데도 동작했던 이유는 뭘까? 그리고 server블록을 여러 개 뒀었는데 순서에 따라 어떨 땐 동작하고 어떨 땐 동작하지 않던 이유는 뭘까?
간단하다. Host와 매칭되는 server블록이 하나도 없으면, 기본으로 설정된 server 블록 또는 제일 처음 작성된 server 블록이 활성화된다고 한다. 그래서 그랬던 거..따라서 server 블록의 server_name은 필요에 따라 굳이 작성할 필요가 없다. (server블록이 하나만 있다거나 등등..)
이런 삽질과 구글링을 통해 배운 걸 정리하면..
- nginx설정은 nginx.conf를 편집해서 가능
- server블록에 대한 걸 설정하려면 -> nginx.conf에 직접 작성 또는 /etc/nginx/sites-enabled에 심볼릭 링크로 걸어둔 파일을 통해(nginx.conf에서 여깄는 것들을 include로 땡겨오니까)
- server_name은 nginx가 띄워진 ip 또는 그 ip에 묶인 도메인들을 작성. ip에 묶인 도메인이 여러 개면 각 도메인별로 다른 페이지 등을 제공 가능
- server 블록이 여러 개일때 request의 Host와 server_name이 매칭되는게 하나도 없으면 기본 또는 젤 처음 작성된 server블록을 활성화