개요
- nginx(엔진엑스)는 러시아에서 만든 HTTP 서버, 리버스 프록시 서버다. 2002년 Igor Sysoev가 rambler.ru 에서 사용하기 위해 만들었으며, 쓰레드 기반이 아닌 이벤트 기반이며, 비동기식 서버다. 현재 알려져 있는 것 중에서는 윈디하나의 솔라나라: lighttpd와 함께 경량이면서도 빠른 것으로 알고 있다.
- 필자의 경우 nginx를 주로 리버스 프록시(웹캐시)로 사용하지만, 이 문서에서는 PHP-FPM(FastCGI Process Manager)를 이용해 PHP와 nginx 연동한다. PHP와 연동하려면 윈디하나의 솔라나라: AMP – PHP: Hypertext Preprocessor의 PHP-FPM을 설치하자.
- 참조
설치
-
Freetype
- 무료 오픈소스 폰트 라이브러리
configure
전에include/config/ftoption.h
의FT_CONFIG_OPTION_SUBPIXEL_RENDERING
을 언코멘트 하면 서브픽셀렌더링을 사용할 수 있지만, 기본적으로 비활성화되어있다. 마이크로소프트의 특허때문이다. FreeType & Patents를 읽어보자.- harfbuzz 라이브러리와 같이 설치하면, 더 좋은 힌팅 기능을 사용할 수 있다.
- freetype 과 같이 컴파일시
“/usr/local/include/ft2build.h”, line 56: cannot find include file: <freetype/config/ftheader.h>
와 유사한 오류가 나면/usr/local/include/ft2build.h
파일을 지운다. 이 파일은 더이상 사용되지 않으며/usr/local/include/freetype2/ft2build.h
으로 대체되었다. - 공식홈페이지: The FreeType Project
# wget http://download.savannah.gnu.org/releases/freetype/freetype-2.5.5.tar.bz2 # tar xvfj freetype-2.5.5.tar.bz2 # cd freetype-2.5.5 # GNUMAKE="/usr/sfw/bin/gmake" ./configure --with-harfbuzz=no # /usr/sfw/bin/gmake # /usr/sfw/bin/gmake install
-
LibGD
- 동적 이미지 생성 라이브러리
- 공식홈페이지: LibGD
- freetype 라이브러리가 필요
# wget --no-check-certificate https://bitbucket.org/libgd/gd-libgd/downloads/libgd-2.1.1.tar.bz2 # tar xvfj libgd-2.1.1.tar.bz2 # cd libgd-2.1.1 # ./configure --with-xpm=/usr --with-tiff=/usr ... Support for Zlib: yes Support for PNG library: yes Support for JPEG library: yes Support for VPX library: no Support for TIFF library: yes Support for Freetype 2.x library: yes Support for Fontconfig library: yes Support for Xpm library: yes Support for pthreads: yes .... # /usr/sfw/bin/gmake # /usr/sfw/bin/gmake install
-
Perl Compatible Regular Expressions
- 펄 호환 정규 표현식 라이브러리
- 공식홈페이지: PCRE – Perl Compatible Regular Expressions
- 솔라리스 11에는 번들되어있다.
- libedit 필요
# wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.36.tar.bz2 # tar xvfj pcre-8.36.tar.bz2 # cd pcre-8.36 # ./configure CFLAGS="-I/usr/local/include"\ --enable-utf \ --enable-unicode-properties \ --enable-pcregrep-libz \ --enable-pcregrep-libbz2 \ --enable-newline-is-anycrlf \ --enable-pcre16 \ --enable-pcre32 \ --enable-jit \ --enable-pcretest-libedit 1) # make # make install
1) pcretest에 라인 편집 기능이 필요하지 않다면 이 줄을 제외하고 컴파일 해도 된다.
-
GeoIP C 라이브러리
- MaxMind 의 GeoIP 용 C 라이브러리
- 공식홈페이지: GeoIP C API
# wget http://www.maxmind.com/download/geoip/api/c/GeoIP-latest.tar.gz # tar xvfz GeoIP-latest.tar.gz # cd GeoIP-1.6.0 # CC=/usr/sfw/bin/gcc CFLAGS="-std=gnu99" ./configure # make # make install # vi /usr/local/include/GeoIPCity.h 1) // union { // int metro_code; /* metro_code is a alias for dma_code */ int dma_code; // };
1) Solaris Studio 는 anonymous union 을 허용하지 않기 때문에 주석처리 한다.
-
nginx
이 섹션을 실행하기 전에 윈디하나의 솔라나라: OpenSSL을 참조해 OpenSSL 소스를 받은 후, 압축을 풀어놓는다.
root@wl ~/src # wget http://nginx.org/download/nginx-1.6.1.tar.gz root@wl ~/src # tar xvfz nginx-1.6.1.tar.gz root@wl ~/src # cd nginx-1.6.1 root@wl ~/src/nginx-1.6.1 # vi auto/lib/openssl/make 1) ... && ./Configure --prefix=$ngx_prefix no-shared solaris-x86-cc $OPENSSL_OPT \\ ... root@wl ~/src/nginx-1.6.1 # ./configure \ --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_realip_module \ --with-http_addition_module \ --with-http_xslt_module \ --with-http_image_filter_module \ --with-http_geoip_module \ --with-http_sub_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_mp4_module \ --with-http_gzip_static_module \ --with-http_random_index_module \ --with-http_secure_link_module \ --with-http_degradation_module \ --with-http_stub_status_module \ --with-http_auth_request_module \ --with-http_spdy_module \ --with-pcre-jit \ --with-pcre=../pcre-8.35 \ --with-cc-opt="-O4" \ --with-openssl=../openssl-1.0.1i 2) root@wl ~/src/nginx-1.6.1 # make root@wl ~/src/nginx-1.6.1 # make install root@wl ~/src/nginx-1.6.1 # /usr/local/nginx/sbin/nginx -v nginx version: nginx/1.6.1
1) 59번째 라인의 [&& ./config –prefix=$ngx_prefix no-shared $OPENSSL_OPT \\]을 변경한다.
2) 64비트로 컴파일 하려면 –with-cpu-opt=amd64 을 붙인다.
설정
-
nginx.conf 설정
문서 루트를 정의하고 php 와의 연동을 위한 설정을 한다.
root@wl ~ # vi /usr/local/nginx/conf/nginx.conf ... events { use eventport; 1) ... } http { ... server { ... # 문서의 루트를 정의. /usr/local/nginx/html location / { ... root html; ... } # NGINX 상태 보기(http_stub_status_module 사용) 2) location /nginx_status { stub_status on; access_log off; allow w.x.y.z; deny all; } ... # Fast-CGI로 PHP와 연동한다. location ~ \.php$ { try_files $uri =404; 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; } ... root@wl ~ #
1) 솔라리스 10에 추가된 Event Port를 사용하도록 해준다. 하지만 솔라리스 10의 커널 패치(102485이상)를 하지 않으면 커널 패닉이 일어날 수 있으니 반드시 패치한다. (솔라리스 10 u10을 사용하고 있다면 이미 패치 되어있다. Sun Alert 102485 Security Vulnerabilities in The Solaris Event Port API May Result in a Denial of Service (DoS) Condition을 읽어보자) 이 옵션을 지정하지 않으면 /dev/poll 을 사용한다. 이외에도 리눅스에서는 epoll, BSD계열은 kqueue 를 사용할 수 있다. 자세한 사항은 Optimizations – Nginx Community을 참고하자.
2) http://w.x.y.z/nginx_status 에 접속해보면 아래와 유사한 화면을 볼 수 있다.Active connections: 291 server accepts handled requests 16630948 16630948 31070465 Reading: 6 Writing: 179 Waiting: 106
text/plain 형식으로 제공되기 때문에 커맨드라인 툴로 잘라내서 원하는 곳에서 사용할 수 있다. 의미는 다음과 같다.
- Active connections: 활성 커넥션 수
- accepts: 접속 승인 개수
- handled: 접속 처리 개수. 오류가 발생한 것이 아니라면, 일반적으로 accepts 와 동일하다.
- requests: 총 요청 건수. keep-alive 가 off 인경우 handled 와 requests 가 동일하다.
- 커넥션 수 상세
- Reading: 읽기(클라이언트에서 요청을 받음)중인 활성 커넥션 수
- Writing: 쓰기(클라이언트로 응답을 전송)중인 활성 커넥션 수
- Waiting: 대기중인 활성 커넥션 수
따라서 Active connections = Reading + Writing + Waiting 이 성립한다.
- Active connections: 활성 커넥션 수
-
특정 국가의 IP 블록
GeoIP, GeoLiteCity 를 사용해 특정 국가를 블록할 수 있다. 속도는 생각만큼 느리지 않은 것으로 생각한다.
root@wl ~ # mkdir /usr/local/geoip root@wl ~ # cd /usr/local/geoip root@wl /usr/local/geoip # wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz root@wl /usr/local/geoip # gunzip GeoIP.dat.gz root@wl /usr/local/geoip # wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz root@wl /usr/local/geoip # gunzip GeoLiteCity.dat.gz
nginx.conf 는 아래와 같은 설정을 추가한다. 이 설정은 중국IP를 블록한다.
root@wl ~ # vi /usr/local/nginx/conf/nginx.conf ... http { ... geoip_country /usr/local/geoip/GeoIP.dat; geoip_city /usr/local/geoip/GeoLiteCity.dat; ... map $geoip_country_code $ip_allow { default yes; cn no; } server { ... if ($ip_allow = no) { return 403; } } } root@wl ~ #
-
리버스 프록시(Reverse Proxy)
- 서문에도 나와있듯, 필자는 nginx 를 주로 리버스 프록시로 사용한다.
- nginx 를 웹 서버로 사용하기 보단 리버스 프록시 서버로 사용하고, 프록시 서버에서 gzip 압축을 통해 외부로 나가는 트래픽을 줄이도록 설정하자. 웹 서버는 ‘같은 호스트의 81번 포트’에서 서비스하고 있다고 가정한다. 설정 파일을 수정해야 할 곳이 많기 때문에 nginx의 전체 conf 파일을 싣는다. 그리고 이 설정은 필자가 사용하고 있는 설정과 비슷하다.
- proxy 로 설정한후, proxy_pass 지시자를 사용하는게 핵심이다. 단 프록시를 사용하는 곳이 더 비효율적인 경우에는 nginx 가 직접 호스트하도록 한다.
root@wl ~ # cat /usr/local/nginx/conf/nginx.conf user nobody; worker_processes 2; error_log logs/error.log; pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; access_log logs/access.log; sendfile on; tcp_nopush on; keepalive_timeout 5; server_tokens off; limit_conn_zone $binary_remote_addr zone=zoneone:10m; gzip on; gzip_comp_level 5; gzip_http_version 1.0; gzip_min_length 0; gzip_types text/plain text/css image/x-icon application/x-javascript; gzip_vary on; geoip_country /usr/local/geoip/GeoIP.dat; geoip_city /usr/local/geoip/GeoLiteCity.dat; map $geoip_country_code $ip_allow { default yes; cn no; } proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-PORT $remote_port; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; client_header_buffer_size 64k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 16k; proxy_buffers 32 16k; proxy_busy_buffers_size 64k; server { listen 80; server_name www.xxx.com; access_log logs/www.xxx.com.access.log; error_log logs/www.xxx.com.error.log debug; location / { proxy_pass http://localhost:81/; limit_conn zoneone 10; } location = /_.gif { empty_gif; } location /admin { proxy_pass http://localhost:81/admin; allow 127.0.0.1; deny all; } location /images { proxy_pass http://localhost:81/images; expires max; } location /thumbimages { proxy_pass http://localhost:81/images; image_filter resize 150 100; image_filter_buffer 1M; image_filter_jpeg_quality 75; error_page 415 = /_.gif; } location /share { root /share/; expires max; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } if ($ip_allow = no) { return 403; } } } root@wl ~ #
아파치 로그파일에는 접속IP가 모두 nginx 가 설치된 서버의 IP로 저장된다. 따라서 http.conf 의 로그 포맷을 바꿔야 한다.
root@wl ~ # vi /usr/local/apache2/conf/httpd.conf ... LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio LogFormat "%{X-Real-IP}i:%{X-Real-PORT}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio-forward ... SetEnvIf X-Real-IP "^.*\..*\..*\..*" forward CustomLog "/var/log/httpd-access.log" combinedio-forward env=forward CustomLog "/var/log/httpd-access.log" combinedio env=!forward ...
운영
-
시작 및 종료
※ nginx는 별도의 실행 스크립트를 제공하지 않는다. 아래와 같이 시작한다.
root@wl ~ # /usr/local/nginx/sbin/nginx
※ 실행한 후 http://localhost/ 을 보면 아래와 같은 화면이 나온다.
※ 종료는 아래와 같이 할 수 있다.root@wl ~ # /usr/local/nginx/sbin/nginx -s stop
-
PHP 연동 확인
아래와 같이 실행해 http://localhost/phpinfo.php 에서 잘 실행되는지 확인하자. 만약 php에 접근할때 [No input file specified.] 가 나오면 SCRIPT_FILENAME 부분을 다시 한번 살펴보자.
root@wl ~ # vi /usr/local/nginx/html/phpinfo.php <?php phpinfo(); ?> root@wl ~ # /etc/init.d/php-fpm start 1)
1) 이 스크립트는 윈디하나의 솔라나라: AMP에서 PHP, PHP-FPM 설치및 설정 섹션에 설명했다.
-
시작/종료 스크립트
nginx 홈페이지에서는 아래와 같은 실행 파일을 제공해준다. 적당히 수정했다.
출처: http://wiki.nginx.org/Standalone_daemonnginx.sh
다운로드 (774 바이트) 123456789101112131415161718192021222324252627282930313233343536373839404142434445#!/bin/sh
NGINX_BASE_DIR=
"/usr/local/nginx"
NGINX_DAEMON=
"${NGINX_BASE_DIR}/sbin/nginx"
NGINX_CONF=
"${NGINX_BASE_DIR}/conf/nginx.conf"
__launch_signal( ) {
${NGINX_DAEMON} -s ${1} &>
/dev/null
}
__checkconfig( ) {
${NGINX_DAEMON} -c ${NGINX_CONF} -t &>
/dev/null
}
__start( ) {
[ -r ${NGINX_CONF} ] ||
exit
1
__checkconfig && ${NGINX_DAEMON} -c ${NGINX_CONF} &>
/dev/null
||
return
${?}
}
__stop( ) {
__launch_signal stop
}
__reload( ) {
__checkconfig && __launch_signal reload ||
return
${?}
}
__restart( ) {
__stop && __start
}
__show_usage( ) {
echo
"Usage: ${0} {start|stop|restart|reload}"
exit
3
}
case
"${1}"
in
start|stop|restart|reload)
[ -x ${NGINX_DAEMON} ] ||
exit
2
__${1}
;;
*)
__show_usage
;;
esac