웹 서비스를 운영하기 위해선 필수적으로 apache 혹은 nginx가 필요하다.

이번 포스트에서는 nginx의 기본적인 설정에 대해 알아본다.


#sites-available & sites-enabled

nginx의 폴더 안을 들여다 보면 sites-availablesites-enabled라는 폴더가 존재한다. 이 폴더들은 한 웹서버에서 여러가지 웹 서비스를 다른 도메인으로 운영 할 때를 대비해서 있는 폴더라고 이해하면 된다.

sites-available에는 각 도메인의 고유 설정 파일을 저장 해 두고, sites-enabled에 심볼릭 링크를 작성 혹은 삭제 함으로서 손쉽게 웹 서비스를 실행 혹은 중단 시키는 것이 가능하다.

예를 들면 /etc/nginx/sites-available/example.com의 서버 설정 파일을 생성 후, 아래 커맨드로 심볼릭 링크를 생성 할 수 있다.

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com

그러면 이제 example.com으로 웹서비스에 접속 할 수 있게 되는 것이다. 만약 서비스를 중단하고 싶다면 심볼릭 링크를 삭제해 주면 된다.

cd /etc/nginx/sites-enabled
sudo rm example.com

이렇게 하면 각 서비스마다의 서버 설정 파일을 유지 한 채로, 서비스에 접속하는 것만을 간단하게 중단 시키는 것이 가능해 진다.


#내부 서비스를 위한 ssl

안전한 통신을 위해서 ssl 설정은 이제 선택이 아닌 필수이다. 기본적인 설정법에 대해 알아본다.

self-signed key와 certificate 생성

개인적으로 외부에서 접속 가능한 서비스를 구축한다면 Let's Encrypt의 ssl 증명서를 이용하는 것이 일반적이지만 내부 서비스를 위한 증명서는 스스로 발급해서 설정한다. 이 포스트의 목적은 어디까지나 내부 서비스를 운영할 때도 https 통신으로 내용을 암호화 하는 것이 목적이기 때문에 스스로 발급한 증명서를 사용한다. 외부에 공개하는 실제 서비스는 절대로 스스로 발급한 증명서를 사용하지 말자.

아래 커맨드로 키와 증명서를 스스로 사인하여 발급할 수 있다.

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

이 커맨드를 실행하면 몇가지 질문에 대한 입력을 요구한다.

Country Name (2 letter code) [AU]:KR
State or Province Name (full name) [Some-State]:Seoul
Locality Name (eg, city) []:Seoul
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Server
Organizational Unit Name (eg, section) []:My Server
Common Name (e.g. server FQDN or YOUR name) []:192.168.0.2
Email Address []:test@test.com

뭘 입력하든 사실 크게 문제는 없으니 대충 입력하자.

다 입력했으면 /etc/ssl/private 디렉토리에 키가, /etc/ssl/certs/ 디렉토리에 1년동안 유효한 증명서가 생성 되었을 것이다. 증명서의 유효기간을 바꾸고 싶다면 --days의 설정 값 (365로 되어있는 부분)을 바꾸면 된다.

dhparam 생성

다음 커맨드로 dhparam 파일을 생성해 준다.

sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096

생성이 완료 될 때까지 조금 시간이 걸린다.

환경설정 스니펫 만들기

서버 블록에 직접 써도 되지만 환경설정 스니펫을 따로 만들어서 사용하면 관리가 편해진다. 우선 키와 증명서에 대한 설정 내용을 저장하는 환경설정 스니펫을 생성한다.

sudo nano /etc/nginx/snippets/self-signed.conf

내용은 증명서와 키의 위치에 관한 설정을 적어준다.

ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

다음으로 ssl 관련 설정 내용을 저장 할 스니펫을 생성한다. 이 스니펫은 일반적이고 보편적으로 쓰이는 ssl 설정이기 때문에 다른 도메인의 서버 블록에서도 그대로 활용하는 것이 가능하다.

sudo nano /etc/nginx/snippets/ssl-params.conf

내용은 아래와 같이 적어준다.

ssl_dhparam /etc/nginx/dhparam.pem;
ssl_session_timeout  10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_ecdh_curve secp384r1;

ssl_stapling on;
ssl_stapling_verify on;

add_header Strict-Transport-Security max-age=31536000;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";

이것으로 서버블록을 위한 설정 스니펫이 준비가 되었다.


ssl을 서버 블록에 설정

내부 서비스를 위한 서버 블록 설정이기 때문에 nginx 설치시 자동으로 설정되는 default의 서버 블록을 수정하여 사용하기로 한다.

우선 수정하기 전에 백업 파일을 만들어준다.

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak

그 다음 default 파일을 열어서 서버 블록을 수정.

sudo nano /etc/nginx/sites-available/default

우선 80 (http) 접속에 관한 서버블록은 원래 있는 내용에서 root와 index, location에 관한 설정을 지워주고 https로 리다이렉션 하도록 바꾼다.

server {
    listen 80;
    listen [::]:80;
    server_name _;
    
    return 301 https://$server_name$request_uri;
}

다음으로 443 (https) 접속에 관한 서버블록을 추가해 준다.

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;

    server_name _;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

스니펫 파일을 include로 넣어 준 덕분에 서버블록의 내용을 깔끔하게 정리 할 수 있다.

이제 마지막으로 모든 설정이 문제 없는지 확인 해 준다.

sudo nginx -t

그럼 "ssl_stapling"이 무시되었다는 경고가 나오는데 이건 증명서를 인증된 기관에서 발급 받은게 아니고 스스로 발급 했기 때문에, 애초에 캐쉬 할 수 있는 인증기관의 OCSP답변 내용이 없기 때문이다. 내부용으로 사용하는 증명서이기 때문에 딱히 문제 될 건 없으니 신경쓰지 않아도 된다.

설정에 별 다른 문제가 없게 나왔다면 nginx를 다시 시작 해 준다.

sudo service nginx restart

마지막으로 자신의 웹 서버에 접속되는지 확인 해 보자. 스스로 발급한 증명서이기 때문에 접속이 되기 전에 브라우저에서 경고 메세지를 보여준다. 그냥 무시하고 접속하기를 선택하면 된다. 크롬은 따로 설정을 하지 않으면 스스로 발급한 증명서를 보여주는 서버에는 접속을 못하게 막아버리기 때문에 파이어폭스 같은 다른 브라우저를 사용하면 확인이 가능하다.


nginx의 기본적인 설정 방법에 대해 알아보았다. 내부 서비스를 기준으로 작성했지만 증명서 부분만 certbot을 이용하여 Let's Encrypt에서 발급 받아서 사용하면 외부 서비스를 위해서도 충분히 활용 할 수 있는 내용이라고 생각한다.