목차

Nginx 서버 관련 조사

내 서버의 nginx.conf 파일을 조사

주석을 포함한 나의 현재 nginx.conf 파일의 상태이다.

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid    logs/nginx.pid;

events {
  worker_connections  1024;
}

http {
  include     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  logs/access.log  main;

  sendfile    on;
  #tcp_nopush   on;

  #keepalive_timeout  0;
  keepalive_timeout  65;

  #gzip  on;

  server {
    listen     80;
    server_name  localhost;

    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    #location / {
    #  root   html;
    #  index  index.html index.htm;
    #}

    location / {
       root   html;
       index  index.php index.html index.htm;
       try_files $uri $uri/ @dokuwiki;
    }

    location @dokuwiki {
      rewrite ^/_media/(.*) /lib/exe/fetch.php?media=$1 last;
      rewrite ^/_detail/(.*) /lib/exe/detail.php?media=$1 last;
      rewrite ^/_export/([^/]+)/(.*) /doku.php?do=export_$1&id=$2 last;
      rewrite ^/(.*) /doku.php?id=$1 last;
    }

    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   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  $document_root$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;
    }

    # docuwiki
    location ~ ^/doku/(data|conf|bin|inc)/ {
      deny all;
    }
  }

  # another virtual host using mix of IP-, name-, and port-based configuration
  #
  #server {
  #  listen     8000;
  #  listen     somename:8080;
  #  server_name  somename  alias  another.alias;

  #  location / {
  #    root   html;
  #    index  index.html index.htm;
  #  }
  #}


  # HTTPS server
  #
  #server {
  #  listen     443;
  #  server_name  localhost;

  #  ssl          on;
  #  ssl_certificate    cert.pem;
  #  ssl_certificate_key  cert.key;

  #  ssl_session_timeout  5m;

  #  ssl_protocols  SSLv2 SSLv3 TLSv1;
  #  ssl_ciphers  HIGH:!aNULL:!MD5;
  #  ssl_prefer_server_ciphers   on;

  #  location / {
  #    root   html;
  #    index  index.html index.htm;
  #  }
  #}

}

이것들이 과연 무엇을 의미하는가? Nginx의 documentation을 뒤져가면서 직접 공부해 보았다. 분량이 많아지긴 했지만 코드를 하나하나 잘라가면서 사용법을 파악해본다.

각 지시자(directive)에 대한 조사

access_log

ngx_http_log_module의 지시자 중 하나이다. 접속 기록에 대한 로그를 남긴다. 기본값은

access_log logs/access.log combined

여기서 combinded는

$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"

로그의 예:

127.0.0.1 - - [02/Feb/2013:10:38:54 -0300] "GET /doku/lib/tpl/vector/static/3rd/dokuwiki/logo.png HTTP/1.1" 304 0 "http://changwoo/doku/doku.php" "Mozilla/5.0 (Windows NT 6.2; rv:18.0) Gecko/20100101 Firefox/18.0"
* [[http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log | 원문 링크]]

charset

ngx_http_charset_module의 지시자 중 하나이다. 이 모듈은 'Content-Type' 응답 헤더 필드에 지정한 문자집합을 추가하는 역할을 맡는다. charset의 기본값은 off로, 서버가 부가적으로 헤더 필드에 값을 추가하지 않는다.

default_type

ngx_core_module의 지시자 중 하나이다. 기본값은 'default_type text/plain'이다. 응답의 기본 MIME-type을 지정한다. 기본적으로 확장자를 가진 파일의 MIME-type은 types 지시자에 의해 결정된다. type 지시자에 의해 지정되지 않은 나머지 파일에 대한 MIME-type은 default_type 지시자에 의해 결정된다. * 원문 링크

deny

ngx_http_access_module의 지시자 중 하나이다. 기본값이 따로 정해져 있지는 않다. 반대의 개념으로 http://nginx.org/en/docs/http/ngx_http_access_module.html#allow가 있다. 주소 이름, CIDR, 그리고 'all'이란 키워드를 사용할 수 있다.

사용 예:
location / {
  deny  192.168.1.1;
  allow 192.168.1.0/24;
  allow 10.1.1.0/16;
  allow 2001:0db8::/32;
  deny  all;
}
192.168.1.1의 접속은 차단하되, 나머지 2~255는 허용한다. 10.1.1.0/16은 1.1.0.1부터 1.1.255.255의 접속을 허용한다.

error_log

ngx_core_module의 지시자 중 하나이다. 에러에 대한 로그를 남긴다. 기본값은 'error_log logs/error.log error'이다. 로그 레벨이 있는데 심각도는 'debug', 'info', 'notice', 'warn', 'error', 'crit', 'alert', 'emerg' 순으로 증가한다. 심각도 이상의 로그를 기록한다.

error_page

ngx_core_module의 지시자 중 하나이다. 기본값으로 정해져 있지는 않다. 지정한 에러 코드에 대해 특정한 웹 페이지 메시지를 출력해준다. 특정 에러 코드를 다른 에러 코드로 변환하는 것도 가능하다.

error_page 404 /404.html; # 404 에러 코드에 대해 /404.html을 리턴
error_page 500 502 503 504 /50x.html; # 50X 에러 코드에 대해  /50x.html을 리턴
error_page 404 =200 /empty.gif; # 404 에러를 200(정상)으로 바꾸고 empty.gif를 리턴
error_page 404 = /404.php; # php 스크립트로 error page를 대체하고 응답 코드 또한 스크립트가 전달하는 response 코드를 사용한다.

events

연결 과정에 영향을 미치는 지시자들의 설정을 기록할 때 사용된다. events 블록 안에서만 설정 가능한 몇몇 지시자들이 있다.

fastcgi_index

URI가 슬래시로 끝나는 경우 기본적으로 뒤에 붙여지는 파일 이름.

fastcgi_param

FastCGI 서버에 전달되는 파라미터를 설정한다.

fastcgi_pass

FastCGI 서버의 주소를 지정한다.

gzip

ngx_http_gzip_module 모듈은 HTTP 압축과 관련 있다. HTTP 문서를 응답할 때 HTML gzip 압축을 해제하거나 설정한다.

http

http 서버 설정에 대한 지시자를 모아 놓는다.

include

이 지시자가 있는 자리에 파일의 내용으로 대체한다. 대체되는 파일의 내용은 nginx의 설정 문법에 맞아야 한다. 아래의 예처럼 파일 이름에 마스크를 줄 수 있다.

include mime.types; 
include vhosts/*.conf; 

ngx_core_module

index

인덱스로 사용될 파일 이름. ngx_http_index_module

keepalive_timeout

keep-alive 시간을 결정한다. 기본값은 75초.

listen

서버가 수신할 주소를 결정한다. 옵션이 꽤 다양한데, 포트 번호 뿐만 아니라 서버 주소도 설정할 수 있다. listen 지시자를 통해 다양한 주소와 포트에서 들어오는 요청을 처리할 수 있다.

location

요청 URI에 관련된 설정이 이루어진다. 매칭은 정규화된 URI 문자열로 이루어진다. 그러므로 URI내부에 %XX 와 같은 인코딩 문자열 및 상대 경로, 이중 슬래시 등은 제거된 상태에서 매칭이 시작된다. 규칙은 접두사나 정규식으로 지정할 수 있는데, 정규식을 사용하기 위해서는 '~*'나 '~' 문자를 앞에 지정해주어야 한다. '~*'는 대소문자를 구분하지 않는다.

location이 요청 경로를 찾는 과정은 다음과 같다. 우선 접두어를 기준으로 가장 상세하게 경로를 기술한 부분을 찾는다. 그리고 설정 파일에 기록된 순서대로 정규식에 대해 경로를 검사한다. 정규식이 매칭되지 않는다면 접두어 기준으로 가장 상세하게 기술된 부분이 사용된다. 접두사 기준으로 규칙을 설정하는 부분에 '^~' 을 사용할 수 있는데, 이렇게 되면 정규식 검사가 이루어지지 않는다. '=' 기호는 URI가 정확하게 매칭되어야 함을 지시한다. @'가 접두사로 붙을 수 있는데, 이를 문서에서는 'named location'이라고 부르며 설정 파일에서만 사용되는 가상의 경로이다.

ngx_core_module

log_format

로그 파일에 기록되는 양식을 조절한다. 기본값은 log_format combined “…”;

pid

main process의 id가 이 경로의 파일에 기록된다.

proxy_pass

프록시 서버의 경로를 기록한다.

rewrite

syntax: rewrite regex replacement [flag] URI가 지정된 정규표현식 regex에 부합하게 되면, 그 URI를 지정된 다른 문장 replacement로 치환한다. rewrite는 설정 파일에 있는 순서대로 실행된다. flag는 지시자의 나머지 처리를 제어하는데 사용된다. replacement string이 'http:'나 'https:'로 시작하면 처리는 멈추고 redirect가 클라이언트로 전달된다. flag는 다음 중 하나가 될 수 있다.

last와 break의 차이는 다음 예를 들어 명확히 설명하고자 한다. rewrite 모듈의 규칙으로 .php 파일의 경로를 치환한다고 하자. 클라이언트로부터 '/wiki/content' 경로를 요청받으면 서버는 이 주소를 '/mywiki/wiki.php?id=content'라는 주소로 변경해야 한다고 하면 다음과 같이 rewrite 규칙을 작성할 수 있다.

rewrite /wiki/(.*) /mywiki/wiki.php?id=$1

이 때 flag로 last를 적는다면, 치환된 /mywiki/wiki.php?id=content 가 서버 경로상에 존재하는지 다시 한 번 살펴본다. 이 과정에서 FastCGI를 사용한다면 FastCGI에 URI를 질의하게 되고 PHP 등이 처리를 마친 온전한 HTML이 전달된다. 그러나 여기서 break을 적는다면 /mywiki/wiki.php?id=$1라는 URI는 서버에 존재하는지 체크하는 과정을 다시 거치지 않고 rewrite 프로세싱을 마치므로 '/mywiki/wiki.php' 경로가 프로세싱의 최종 결과가 된다. 그러면 서버는 실제 PHP 파일을 읽어서 원본 그대로 클라이언트로 넘겨버린다.

root

요청의 루트 디렉토리를 지정한다. 서버의 디스크 중 어떤 경로를 웹에 공개할지 결정하기 위한 지시자이다.

sendfile

http://www.kernel.org/doc/man-pages/online/pages/man2/sendfile.2.html sendfile() 함수의 사용 여부를 결정한다. sendfile() 함수는 두 파일 디스크립터 사이에 데이터를 복사하는 데 사용된다. 복사가 커널 내부에서 진행되므로 일반적으로 유저 공간에서 사용되는 read, write 함수보다 더욱 효율적이다. 그러나 Windows 계열의 OS에서는 당연히 찾아 볼 수 없는 함수이며, manpage에서도 본 함수는 POSIX 표준이 아니므로 이식성이 중요한 프로그램에서는 사용하지 말 것을 권고한다. 사용하는 OS가 이 함수를 지원하면 사용하되, 아니라면 사용해서는 안 된다. sendfile에 대해서는 Use sendfile() to optimize data transfer 칼럼을 참고한다.

server

가상 서버를 설정하기 위한 지시자. 문서에 따르면 IP기반과 이름 기반의 가상 서버에 대한 명확한 구분은 없으며, server_name 지시자와 listen 지시자에서 설정한 주소와 포트에 따라 가상 서버가 만들어진다.

server_name

가상 서버의 이름을 지정한다. 서버 이름을 지정하는 방법은 여러 가지가 있다. 1. 와일드카드에 의한 방법

server_name example.com *.example.com www.example.*;
처음 두 개의 이름은 다음과 같이 하나로 묶을 수 있다.
server_name .example.com

2. 정규표현식에 의한 방법

틸데(~)를 앞에 붙인 문자열은 정규식으로 간주한다.
server_name www.example.com ~^www\d+\.example\.com$;

* [[http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name|원문 링크]]

ssl

서버에 ssl 기능을 활성화시킨다. 문서에 의하면 이 지시자보다는 listen의 지시자에 ssl 파라미터를 사용하기를 권장한다. 예시는 다음과 같다.

listen 443 ssl;

HTTPS 서버를 설정하는 방법은 Configuring HTTPS servers를 참고한다.

ssl_certificate

ssl 인증서 파일을 지정한다.

ssl_certificate_key

ssl 비밀 키를 지정한다.

ssl_ciphers

암호 체계를 설정한다. 이 문자열의 포맷은 OpenSSL library에서 사용된다.

ssl_prefer_server_ciphers

서버의 암호화가 클라이언트의 암호화에 대해 우선하도록 한다. on/off로 조절한다.

ssl_protocols

지정된 규약을 활성화한다. 기본값은 'ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2'이다.

ssl_session_timeout

캐시에 저장된 세션 파라미터를 재사용할 시간을 설정한다. 기본은 5분이다. 'ssl_session_timeout 5m'

tcp_nopush

FreeBSD의 TCP_NOPUSH 소켓 옵션, 리눅스의 TCP_CORK 소켓 옵션을 활성화시킨다. 이 옵션은 sendfile이 사용될 때만 활성화된다. 이 옵션을 활성화 하면 리눅스 및 FreeBSD 4.* 에서 파일의 처음과 응답 헤더를 한 패킷에 보낸다. 그리고 파일을 전체 패킷에 담아 보낸다.

TCP_CORK 소켓 옵션에 대해서는 Manpage나 TCP/IP options for high-performance data transmission 칼럼을 참고한다.

try_files

문법: try_files file … uri;

    try_files file ... =code;

server, location 컨텍스트 하에서 사용하며 file이 존재하는지 순서대로 검사하고 가장 처음으로 발견된 것을 요청 작업에 사용한다. 어떤 file도 검색되지 않으면 uri나 code가 사용된다. uri는 named location이 사용될 수 있다. named location이란 location 후에 실제 경로가 나오는 것이 아니라 접두어 '@' 가 붙어 설정 파일 내부에만 사용되는 것이다.

user

worker process를 이용하는 user와 group을 설정한다. group을 생략하면 group은 user와 같은 이름으로 설정된다. 기본값은 'user nobody nobody'가 된다.

worker_connections

한 worker process가 최대 몇 개까지의 연결을 처리할 수 있는지를 설정한다. 기본은 512다. 이 숫자는 클라이언트와의 연결 뿐만이 아닌 프록시 서버 등등을 포함한 모든 연결을 포함한다.

worker_processes

worker process의 개수를 설정한다. 숫자를 입력할 수도 있고 'auto'를 입력하여 자동으로 체크하도록 할 수도 있다. 최적값은 여러 조건에 따라 달라질 수 있다.