본문 바로가기

인프라/MW

Nginx

간략하게, Nginx에 대한 장점에 대해서 소개하겠다.

Nginx는 비교적 가벼운 모듈로써 적은 리소스로 최고의 성능을 자랑하는 WEB모듈로써 현재 많은 곳에서 인지도를 높이고 있다.

아파치와 다르게 비동기식으로 이벤트 요청을 처리하기에 적은 리소스로 빠른 서비스를 제공해준다.

Nginx는 성능면과 빠른 업데이트 버그패치등에 대한 장점이 존재하며, 

아파치는 아파치나름대로 안전성/확장성등의 장점이 있기에 사용목적에 따라 사용할 WEB모듈을 선택하면 될 것이다.

여러 상세내용에 대해서는 공식사이트가 더욱 상세하기에 기재를 생략하겠으며 본론으로 들어가겠다.


NGINX Compile 설치방법(WEB/Install)

더보기

0. 들어가기전 주의사항

- Nginx에는 2가지 버전이 지속적으로 배포가 되고있다. (Mainline버전/Stable버전)

- Nginx 공식사이트로 부터, Mainline버전을 기반을 설치하여 지속적인 업데이트를 권장하고 있으나,

  본인이 사용할 환경의 제약사항에 맞게 고려하여 선택하는 것이 가장 중요할 것이다.

- 환경적인 측면에서의 고려

 > Mainline버전 : 새로운 특징/기능/버그 패치 등 지속적인 패치가 이루어지는 환경에서 사용 

 > Stable버전 : 3rd Party모듈과의 호환성문제 또는 새로운 기능이 도입됨에 따라, 생길 수 있는 문제를 차단하고,

                    지속적인 업데이트를 하지 못하는 환경에서 사용

 

1. Nginx 설치를 위한 계정 생성 & 권한부여(사전준비)

#- nginx 계정 생성
sudo useradd nginx -b /home -s /bin/bash

#- 현재 접속 계정이 root일 시
sudo echo "nginx1234\!" | passwd --stdin nginx

#- 현재 접속 계정이 root가 아닐 시
sudo passwd nginx nginx1234!

#- 계정권한조율은 References(Sudoers)를 참고 
설정이유 : * nginx 계정으로 package 설치를 편하게 하기위해
          * 설정 하고 싶지 않을 시, root권한으로 작업 진행
$ sudo vi /etc/sudoers

nginx ALL=(ALL) NOPASSWD:ALL

 

# 경로 간소화를 위한 변수 사용설정

export ID=`whoami`
export BASE_DIR=`cat /etc/passwd|grep ${ID}|cut -f6 -d ':'`

 

$ vi ${BASE_DIR}/.bash_profile

## Edit Server Env Setting
export ID=`whoami`
export BASE_DIR=`cat /etc/passwd|grep ${ID}|sed '2d'|cut -f6 -d ':'`
export PS1='[`id -nu`@`hostname`:$PWD]# '
export LANG=ko_KR.utf-8
export VISUAL=vim

#stty erase "^H" kill "^U" intr "^C" eof "^D" susp "^Z" cs8 -ixany -parenb -istrip

#- user control dir_path
export NGINX_HOME=/nginx/nginx
export SCT_DIR=${BASE_DIR}/scripts

#- define environment set
export PATH=${NGINX_HOME}/sbin:$PATH

#- user log alias
alias webstart='sh ${SCT_DIR}/nginx_ctrl.sh start'
alias webstop='sh ${SCT_DIR}/nginx_ctrl.sh stop'
alias webreload='sh ${SCT_DIR}/nginx_ctrl.sh reload'
alias pscheck='sh ${SCT_DIR}/nginx_ctrl.sh pscheck'

 

계정 .bash_profile 환경변수 설정정보(주의:BASE_DIR변수 내, sed '2d') <- 계정정보2개존재하기에 선택삭제지정

 

※ 만약, 사용자 서버가 (구)Nginx가 설치되어있는 Legacy 서버일 경우, 하단의 Tab 계정분리작업 참조

 

 # 환경변수 적용

source ${BASE_DIR}/.bash_profile

 

 #- OS 내장 라이브러리 패치 및 필수 라이브러리 다운로드

$ yum check-update 
$ yum update -y 

 

저자가 사용된 서버는 레거시 서버로써 오랫동안 패치가 이루어지지고 있지 않았기에 전체 업데이트 강행(사전에 영향도파악후 진행必)

 

$ yum install -y perl perl-devel perl-ExtUtils-Embed libxslt libxslt-devel libxml2 libxml2-devel gd gd-devel GeoIP GeoIP-devel

 

Nginx를 Compile 설치를 위한 필수 라이브러리 및 모듈을 다운로드 진행

 

 

2. Nginx 설치 진행(본작업)

#- Nginx 가이드라인 구성을 위한 Package 내, 메뉴얼 구성

$ cp /nginx/src/nginx-1.16.1/man/nginx.8 /usr/share/man/man8 
$ gzip /usr/share/man/man8/nginx.8 
$ man nginx 


# PCRE – Supports regular expressions. Required by the NGINX Core and Rewrite modules.

$ wget https://ftp.pcre.org/pub/pcre/pcre-8.44.tar.gz 
$ tar -zxf pcre-8.44.tar.gz 
$ cd pcre-8.44; ./configure;  
$ make & make install


# zlib – Supports header compression. Required by the NGINX Gzip module. 

$ wget http://zlib.net/zlib-1.2.11.tar.gz 
$ tar -zxf zlib-1.2.11.tar.gz 
$ cd zlib-1.2.11; ./configure; make & make install


# OpenSSL – Supports the HTTPS protocol. Required by the NGINX SSL module and others. 

$ wget http://www.openssl.org/source/openssl-1.1.1d.tar.gz 
$ tar -zxf openssl-1.1.1d.tar.gz 
$ cd openssl-1.1.1d; ./Configure linux-x86_64 --prefix=/usr; make & make install


# Nginx - Downloading the Sources(Mainline/Stable Version Choice)

> 최신 Mainline 버전의 소스를 다운로드하고 압축해제(20/04/24기준)

$ wget https://nginx.org/download/nginx-1.17.9.tar.gz 
$ tar zxf nginx-1.17.9.tar.gz 
$ cd nginx-1.17.9


> 최신 Stable 버전의 소스 파일을 다운로드하고 압축해제(20/04/24기준)

$ wget https://nginx.org/download/nginx-1.16.1.tar.gz 
$ tar zxf nginx-1.16.1.tar.gz 
$ cd nginx-1.16.1

 

# Nginx Source Compile

$ ./configure \ 
--prefix=/nginx/nginx \ 
--with-pcre=/nginx/src/pcre-8.44 \ 
--with-zlib=/nginx/src/zlib-1.2.11 \ 
--with-http_ssl_module \ 
--with-stream \ 
--with-mail

$ make && make install 

$ chown root:nginx /nginx/nginx/sbin/nginx 
$ chmod +s /nginx/nginx/sbin/nginx

 

# 주의사항

일부 레거시 서버같은경우 권한문제로 설치가 매끄럽게 이루어지지 않는 경우가 많다.
이로 인하여 강제적으로 설치 진행 시, root권한으로 설치를 진행하여 하위 디렉터리 영역
전체를 nginx계정 권한으로 강제 부여하여 사용할수도 있다.

간혹, 설치하다 Shared Object가 없다거나 권한으로 인하여 오류가 발생할 경우 컴파일을 다시 진행하여야하는 경우도 있을 것이다. 하기 명령어를 참고하여 오류를 해결하면 될것이다.

#- 컴파일 과정에서 생성된 부산물(Object) 초기화
$ make clean

#- 설치된 모듈 언인스톨
$ make uninstall

 

 


Nginx Configuration Files

더보기

# nginx.conf / default.conf / server.conf 설정

$ vi ${NGINX_HOME}/conf/nginx.conf

user  nginx;
worker_processes  4;

error_log  logs/error.log crit;
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  65;
    #gzip  on;
    autoindex       off;
    server_tokens   off;

    include conf.d/*.conf;
    include extra/*.conf;
}

 

# conf파일 분리를 위한 디렉터리 생성
$ mkdir -p ${NGINX_HOME}/conf/conf.d
$ mkdir -p ${NGINX_HOME}/conf/extra

 

$ vi ${NGINX_HOME}/conf/conf.d/default.conf

# generated 2020-05-06, Mozilla Guideline v5.4, nginx 1.16.1, OpenSSL 1.1.1d, intermediate configuration
# https://ssl-config.mozilla.org/#server=nginx&version=1.16.1&config=intermediate&openssl=1.1.1d&guideline=5.4

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    return 301 https://$host$request_uri;
}

server {
    #listen 443 ssl http2;
    #listen [::]:443 ssl http2;
    listen 443 ssl;
    listen [::]:443 ssl;

    ssl_certificate             /nginx/nginx/ssl_private/certs/temp/temp_crt.pem;
    ssl_certificate_key         /nginx/nginx/ssl_private/certs/temp/temp_key.pem;
    ssl_session_timeout         5m;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
    ssl_dhparam /nginx/nginx/ssl_private/dh_parameter;

    # intermediate configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Security "max-age=63072000" always;

    # OCSP stapling
    #ssl_stapling on;
    #ssl_stapling_verify on;

    # verify chain of trust of OCSP response using Root CA and Intermediate certs
    #ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

    access_log     /nginx/nginx/logs/default/nx_access.log combined;
    error_log      /nginx/nginx/logs/default/nx_error.log;

    # replace with the IP address of your resolver
    resolver 127.0.0.1;
    
    # Add author settings 
    location / {
        root     /nginx/nginx/html;
        index     index.html;

        proxy_intercept_errors on;
        error_page 404 500 502 503 504 /50x.html;
        location = /50x.html {
            root /nginx/nginx/html;
            internal;
        }

        if ($request_method !~ ^(GET|POST|HEAD)$) {
            return 444;
        }
    }
}

 

$ vi ${NGINX_HOME}/conf/extra/server.conf

#### nexus : nexus-oss.org : 9980

upstream user_nexus {
    ip_hash;
    server 127.0.0.1:9980;
}

server {
    listen         80;
    server_name    nexus-oss.org;

    client_max_body_size        100M;

    access_log    /nginx/nginx/logs/nexus/nx_access.log;
    error_log     /nginx/nginx/logs/nexus/nx_error.log;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;

        proxy_pass http://user_nexus;
        proxy_redirect off;
        charset utf-8;
   }
}

#### jenkins : jenkins-ci.org : 10080

upstream user_jenkins {
    ip_hash;
    server 127.0.0.1:10080;
}

server {
    listen         80;
    server_name    jenkins-ci.org;

    access_log    /nginx/nginx/logs/jenkins/nx_access.log;
    error_log     /nginx/nginx/logs/jenkins/nx_error.log;

    # Return a temporary redirect to the /jenkins/ directory 
    # when user requests '/'
    location = / {
        return 302 /jenkins/;
    }

    # Load balance requests for /jenkins/ across Tomcat application servers
    location /jenkins/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;

        proxy_pass http://user_jenkins;
        proxy_redirect off;
        charset utf-8;
   }
}

#### user_front : user-front.org : 10180
upstream user_front {
    ip_hash;
    server 127.0.0.1:10180;
}

server {
    listen         80;
    server_name    user-front.org;
    return         301 https://$host$request_uri;
}

server {
    listen         443 ssl;
    server_name    user-front.org;

    client_max_body_size        100M;

    ssl_certificate             /nginx/nginx/ssl_private/certs/temp/temp_crt.pem;
    ssl_certificate_key         /nginx/nginx/ssl_private/certs/temp/temp_key.pem;
    ssl_session_timeout         5m;
    ssl_protocols               TLSv1.2 TLSv1.3;
    ssl_ciphers                 ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:!RC4:HIGH:!MD5:!aNULL:!EDH;
    ssl_prefer_server_ciphers   on;

    access_log    /nginx/nginx/logs/user_front/nx_access.log;
    error_log     /nginx/nginx/logs/user_front/nx_error.log;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;

        proxy_pass        http://user_front;
        proxy_redirect    off;
        charset           utf-8;
        index             index.html;
   }
}

 

 


Nginx 기동명령어 간소화를 위한 스크립트

더보기

#- 참고용 스크립트

#- 스크립트 디렉터리생성
$ mkdir -p ${SCT_DIR};

 

$ vi ${SCT_DIR}/nginx_ctrl.sh

#!/bin/bash

#--------------------------------------------------------------------------
#-- Set Error if Variable is Not Set
#-- Set Exit if Error is Occured
#--------------------------------------------------------------------------

#set -o nounset
#set -o errexit

#--------------------------------------------------------------------------
# // Check Parameter & Define Variable
#--------------------------------------------------------------------------

source /home/nginx/.bash_profile

if [[ $# -lt 1 ]]; then
    if [[ $# != $1 ]]; then
        echo
        echo "[ ERROR ] NOT FOUND CMD : ($1)"
        echo "[ INFO ] ex ) ./nginx_ctrl.sh {start|stop|restart|reload}"
        echo
        exit 1
    fi
fi

ARGS1=$1

#- PATHS
APP_NAME=nginx_ctrl
ID=`id -u -n`
BASE_DIR=`cat /etc/passwd|grep ${ID}|sed '2d'|cut -f6 -d ':'`/scripts
APP_DIR=/nginx/nginx
LOG_DIR=${BASE_DIR}/logs

#- ETC
TIMESTAMP=`date +%Y%m%d-%H%M%S`
CHECK_DATE=`date +%Y-%m-%d`
DATE=`date +%Y%m%d`

#- CMD_LIST
CMD_LIST=("start" "stop" "restart" "reload" "pscheck")

#- PID COUNT
PIC=`ps -ef | egrep -i "master process|worker process" | grep -v "grep" | wc -l`

#---------------------------------------------------------------
# // Validate Parameter & Run Script
#---------------------------------------------------------------

func_main() {
    echo
    echo "[ INFO ] func_main"
    func_chk_dir ${LOG_DIR}
    export CMD=$(func_chk_parm ${ARGS1} CMD_LIST)
    if [[ -z ${CMD} ]]; then
        echo
        echo "[ ERROR ] PLEASE CHECK YOUR CMD ARGUMENT_1 : ${ARGS1}"
        echo "[ INFO ] ex ) ./${APP_NAME}.sh {start|stop|restart|reload}"
        echo
        exit 1
    fi
    func_remove ${LOG_DIR}
    func_cmd ${APP_DIR}/sbin ${APP_NAME} ${CMD} CMD_LIST ${PIC} 2>&1 | tee "${LOG_DIR}/${APP_NAME}_${CMD}_${TIMESTAMP}".log
}

func_remove() {
    local VAL1=$1
    echo
    echo "[ INFO ] func_remove"
    echo "[ INFO ] cd ${VAL1}; find ./* -name '*.log' -mtime +7 | xargs -n1 rm -f"
    cd ${VAL1}; find ./* -name "*.log" -mtime +7 | xargs -n1 rm -f
}

func_cmd() {
    local VAL1=$1
    local VAL2=${2%%_*}
    local VAL3=$3
    local VAL4=$4[@]
    local VAL4=("${!VAL4}")
    local VAL5=$5

    echo
    echo "[ INFO ] func_cmd"
    if [[ ${VAL3} == ${VAL4[0]} ]]; then
        func_valid_proc ${VAL5} ${VAL3} $4
        echo "[ INFO ] cd ${VAL1}; ${VAL2}"
        cd ${VAL1}; ${VAL2}
        func_chk_proc ${VAL2} $2
    elif [[ ${VAL3} == ${VAL4[1]} ]]; then
        func_valid_proc ${VAL5} ${VAL3} $4
        echo "[ INFO ] cd ${VAL1}; ${VAL2} -s ${VAL3}"
        cd ${VAL1}; ${VAL2} -s ${VAL3}
        func_chk_proc ${VAL2} $2
    elif [[ ${VAL3} == ${VAL4[4]} ]]; then
        func_chk_proc ${VAL2} $2
    else
        echo "[ INFO ] cd ${VAL1}; ${VAL2} -s ${VAL3}"
        cd ${VAL1}; ${VAL2} -s ${VAL3}
        func_chk_proc ${VAL2} $2
    fi
}

func_valid_proc() {
    local VAL1=$1
    local VAL2=$2
    local VAL3=$3[@]
    local VAL3=("${!VAL3}")
    if [[ ${VAL2} == ${VAL3[0]} ]]; then
        if [[ ${VAL1} -gt 1 ]]; then
            echo "[ INFO ] NGINX is Already ${VAL2}ed."
            echo "[ INFO ] exit."
            exit 0
        fi
    elif [[ ${VAL2} == ${VAL3[1]} ]]; then
        if [[ ${VAL1} -lt 1 ]]; then
            echo "[ INFO ] NGINX is Already ${VAL2}ed."
            echo "[ INFO ] exit."
            exit 0
        fi
    fi
}

func_chk_proc() {
    local VAL1=$1
    local VAL2=$2
    echo
    echo "[ INFO ] func_chk_proc"
    echo "ps -ef | grep ${VAL1} | grep -v grep | grep -v ${VAL2}"
    ps -ef | grep ${VAL1} | grep -v "grep" | grep -v "${VAL2}"
}

func_chk_parm() {
    local VAL1=$1
    local VAL2=$2[@]
    local VAL2=("${!VAL2}")
    for VALID in ${VAL2[@]} ;do
        if [[ ${VAL1} == ${VALID%/*} ]]; then
            echo "${VAL1}"
        else
            continue
        fi
    done
}

func_chk_dir() {
    local VAL1=$1
    echo
    echo "[ INFO ] func_chk_dir"
    if [[ ! -d ${VAL1} ]]; then
        echo "[ INFO ] mkdir -p ${VAL1}"
        mkdir -p ${VAL1}
    fi
}

func_main

 

 


NGINX 계정분리작업(구서버 일시 참조)

더보기

#- mkhomedir_helper  모듈을 이용한 방식(계정정보수정/홈디렉터리생성)

$ cat /etc/passwd | grep nginx
>> nginx:x:994:990:nginx user:/var/cache/nginx:/sbin/nologin 

 

$ usermod -s /bin/bash nginx

$ cat /etc/passwd | grep nginx
>> nginx:x:994:990:nginx user:/var/cache/nginx:/bin/bash

$ usermod -d /home/nginx nginx

$ cat /etc/passwd | grep nginx
>> nginx:x:994:990:nginx user:/home/nginx:/bin/bash

 

$ /sbin/mkhomedir_helper nginx 0022 /etc/skel

 

#- mkhomedir_helper 모듈이 정상동작 안될 시(계정정보수정/홈디렉터리생성)

$ cat /etc/passwd | grep nginx
>> nginx:x:994:990:nginx user:/var/cache/nginx:/sbin/nologin 

 

$ usermod -s /bin/bash nginx

$ cat /etc/passwd | grep nginx
>> nginx:x:994:990:nginx user:/var/cache/nginx:/bin/bash

$ usermod -d /home/nginx nginx

$ cat /etc/passwd | grep nginx
>> nginx:x:994:990:nginx user:/home/nginx:/bin/bash

 

$ export id_dir=/home/nginx 
$ mkdir ${id_dir}; cd ${id_dir}; cp -r /etc/skel/. .; chown -R nginx:nginx .

 

 

# 설치완료 후, 정상여부 확인

기동정상여부 확인완료

 

#- References

nginx_download_page

[docs]nginx_install

[mozilla]SSL_Configuration_Generator

[Unix_Manual]mkhomedir_helper

[stackexchange]does-usr-sbin-nologin-as-a-login-shell-serve-a-security-purpose

'인프라 > MW' 카테고리의 다른 글

[GitLab/Linux or Unix] password reset (Root/Admin)  (0) 2019.12.20
(Keystore)Self-Signed-Cert-Trust-Manager(InstallCert.java)  (0) 2019.10.16
SVN(Subversion)  (0) 2019.09.26
Apache  (0) 2019.09.26
Jenkins  (0) 2019.09.25