create-react-app으로 만들어진 React에서 시스템의 환경변수를 가져오는 방법을 알아보자.


환경 및 선수조건

  • npm
  • nodejs
  • React
  • create-react-app
  • npm을통한 create-react-app의 설치 및 프로젝트 생성 (참고)


환경변수 가져오기

create-react-app을 통해서 생성한 React 프로젝트는 process.env를 통해서 쉽게 환경변수를 가져올 수 있습니다.

다음 아래가 해당 코드입니다. 주의해야 할점은 반드시!

  • 꼭 앞에 접미사로 REACT_APP_를 붙여줘야 합니다.
  • 시스템에 저장된 시스템 변수의 이름이 LINKU_SERVER_ENVIRONMENT라면 REACT_APP_를 붙여서 REACT_APP_LINKU_SERVER_ENVIRONMENT라고 해야합니다!
if (process.env.REACT_APP_LINKU_SERVER_ENVIRONMENT=== 'local')
    console.log("local");
else
    console.log("not local")


추가

  • .bash_profile에 추가하시고 source 명령어로 환경변수를 적용해줘야 돌아가는데 가끔 가져오지 못한다면 컴퓨터를 재부팅하시면 됩니다. (이거에 대한 자세한 이슈는 조사가 필요할듯 싶네요)


업데이트(2020.07.19): Ubuntu 지원 버전에 따른 설치 방법 업데이트

업데이트(2018.03.03): 기존에 webroot plugin 방식에서 python-certbot-nginx을 사용하는 방식을 추가하였습니다. python-certbot-nginx를 통해서 설치하는게 훨씬 간단합니다.

무료 인증서 서비스를 제공하는 Let’s Encrypt를 통해서 서비스에 ssl 설정을 추가하자


환경

  • Ubuntu 20.04 (LTS)
  • Ubuntu 18.04 (LTS)
  • Ubuntu 16.04 (LTS)
  • Ubuntu 14.04 (LTS)
  • Nginx (version: 1.4.6)(apt-get을 통한 설치)
  • 도메인


사전 준비사항

  • Nginx에 대한 간단한 사용법
  • HTTPS와 인증서에 대한 개념
  • 도메인도 하나 필요합니다. 여기에서는 example.com이라는 도메인이 있다고 가정하고 진행하겠습니다.


소개

이 글은 How To Secure Nginx with Let’s Encrypt on Ubuntu 20.04를 간단하게 요약 정리한 글이며 SSL과 인증서에 대한 소개는 다음 포스팅에서 하도록 하겠습니다.

Let’s Encrypt는 Certificate Authority (CA). 즉, 인증기관으로 보다 쉬운 방법과 무료로 TLS/SSL 인증서를 발급해서 HTTPS 통신을 가능하게 해주는 서비스 기관입니다.

Let’s Encrypt는 certbot 이라는 소프트웨어를 통해서 이를 쉽게 자동화하도록 만들어져 있습니다.


1. certbot 설치

Ubuntu 16.04 (LTS), Ubuntu 18.04 (LTS) 저장소 세팅

저장소 설정 및 업데이트 진행

$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository universe
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update

Ubuntu 20.04 (LTS) 저장소 세팅

저장소를 설정 및 업데이트 진행

$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository universe
$ sudo apt-get update

공통

certbot 설치

$ sudo apt-get install certbot python3-certbot-nginx


2. Nginx 세팅

Certbot이 자동으로 SSL을 세팅해주기 때문에 server blockserver_name을 설정해주면 됩니다.

$ sudo vim /etc/nginx/sites-available/[your server block]

아래는 제 예시입니다. undang_backend_nginx.conf에 블록들이 있기 때문에 아래처럼 되었습니다.

$ sudo vim /etc/nginx/sites-available/undang_backend_nginx.conf

이제 서버 블록 파일 안에 server_name을 설정하고자 하는 도메인 이름으로 변경해주시면 됩니다. 저는 아래와 같습니다.

...
# configuration of the server
server {

    listen      80;
    listen [::]:80;
    # Put your domain next to server_name
    server_name undang.twpower.me;
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

...

}

설정이 완료 되었다면 저장하고 아래 명령어를 통해서 재시작합니다.

$ sudo nginx -t
$ sudo service nginx reload


3. SSL 인증 획득하기

다음 아래 명령어를 사용하면 nginx plugin을 통해서 가능합니다. 도메인을 추가적으로 더 하고 싶다면(위에 server_name에도 물론 설정이 되어있어야겠죠?) -d 옵션을 주고 더 주가하면 됩니다.

$ sudo certbot --nginx -d example.com -d www.example.com

제 예시는 아래와 같습니다.

$ sudo certbot --nginx -d undang.twpower.me

그러면 아래와 같이 1과 2를 선택하는 화면이 나오는데 저와 같은 경우는 모든 경우를 https로 하고 싶어서 redirect를 허용하는 2번을 하였습니다.

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

번호를 선택해주면 아래처럼 진행되며 key들도 자동으로 생성해줍니다. success


4. 인증서 자동갱신 설정 확인

설정한 certbot은 90일 동안만 유효하기 때문에 갱신을 해줘야합니다. 매번 해주기 귀찮으나 설치한 certbot은 자동으로 갱신을 이틀 단위로 해줍니다.

해당하는 갱신이 제대로 되는지는 아래 명령어를 통해서 확인 가능하며 에러가 나타나지 않으면 renewal이 정상적으로 작동 할겁니다.

$ sudo certbot renew --dry-run

Ubuntu의 경우 /etc/cron.d/에 보면 certbot이 생성되어있습니다.


5. SSL 적용 확인 및 평가

본인의 서버에 SSL이 적용이 잘 되었는지 평가할 수 있는 여러 사이트가 있는데 들어가서 본인의 서버 도메인을 입력하면 됩니다.

https://www.ssllabs.com/ssltest/

ssl-test


참고자료






아래는 webroot plugin 방식을 통해 설정하는 방법입니다.

1. certbot 설치

apt-get에 certbot저장소를 추가해줍니다.

$ sudo add-apt-repository ppa:certbot/certbot

패키치 목록을 업데이트해주고 certbot을 설치합니다.

$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx

간혹 업데이트와 업그레이드가 되지 않는 경우가 있는데 그러면 직접 아래처럼 업그레이드를 해줍니다. 업데이트가 자주 바뀌며 지원되는게 달라지기 때문에 certbot 최신 버전을 설치하시길 추천드립니다.

$ sudo add-apt-repository ppa:certbot/certbot


2. 인증서 발급받기

Let’s Encrypt는 다양한 plugin들을 통해서 SSL 인증서를 제공합니다. 아파치를 제외한 대부분의 설치 플러그인들은 발급만 해주고 나머지 설정을 들을 직접 해주어야합니다.

본문에서는 webroot plugin을 통해서 인증서를 발급해 보겠습니다.


Webroot Plugin 사용하기

Webroot Plugin은 /.well-known이라는 폴더에 파일을 추가해서 Let’s Encrypt 서버가 접속할 수 있도록 합니다.

우선, /etc/nginx/sites-available/에 있는 conf 파일들 중에서 추가하고자 하는 파일을 열어줍니다. 여기서는 default conf 파일을 통해 설정해보도록 하겠습니다.

$ sudo vim /etc/nginx/sites-available/default


이제 해당 파일의 server 블럭 안에 다음을 추가합니다.

server {
        . . .

        location ~ /.well-known {
                allow all;
        }

        . . .
}


nginx의 설정 파일이 문법이 제대로 되었는지 확인하고 재시작합니다.

$ sudo nginx -t
$ sudo service nginx restart


이제 server block에서 root설정이 어디인지 알아보고 인증서를 발급해보겠습니다. 인증서를 발급하기 위해서는 webroot-path라는 부분에 server blockroot 경로를 지정해줘야 발급이 가능하다고 합니다.

다음 명령어를 통해서 설정파일에 들어갑니다. 이번에도 역시 /etc/nginx/sites-available/에 있는 default를 이용하겠습니다.

$ vim /etc/nginx/sites-available/default


문서의 server block을 보시면 아래처럼 나와있는 root에 설정된 경로를 기억해주시면됩니다. 다른 설정을 하지 않았다면 기본으로 /usr/share/nginx/html으로 나와있습니다.

server {
        . . .
        root /usr/share/nginx/html; # 이 경로를 기억해야합니다.
        . . .
}


이제 인증서를 발급해봅시다. --webroot-path에 위에 있던 root로 설정된 폴더 경로를(여기서는 /usr/share/nginx/html), -d 옵션을 통해서 지정하고자 하는 도메인명을 넣어줍니다. 여러 도메인을 적용하고 싶다면 최상위 도메인부터 앞에서부터 적어주어야 합니다. 만약 본문처럼 example.comdev.example.com 둘다 하고 싶다면 아래처럼 적용하면 됩니다.

$ sudo certbot certonly --webroot --webroot-path=/usr/share/nginx/html -d example.com -d dev.example.com


처음 적용하는거라면 Email과 Terms of Service에 동의해야 합니다. 입력하고 동의를 하고 나면 다음처럼 성공적으로 완료되었다는 창이 나오며 인증서들과 키가 어떤 경로에 위치한다는 정보와 만기일이 나옵니다. 다음 아래 내용은 How To Secure Nginx with Let’s Encrypt on Ubuntu 14.04에 있는 결과를 가져왔습니다.

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert
   will expire on 2017-07-26. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - If you lose your account credentials, you can recover through
   e-mails sent to sammy@example.com.
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le


Certificate 파일

webroot plugin을 통해 잘 발급을 받았다면 아래와 같은 4개의 파일들이 생성됩니다.

  • cert.pem: 도메인의 인증서
  • chain.pem: Let’s Encrypt chain 인증서
  • fullchain.pem: cert.pem + chain.pem
  • privkey.pem: 인증서의 개인키


위의 파일들은 /etc/letsencrypt/archive에 위치하며 /etc/letsencrypt/live/[your_domain_name]에서 가장 최근의 인증서들에 대해 symbolic link를 가지고 있습니다. 이 위치에서 가장 최신의 인증서를 가지고 있기 때문에 인증서와 키들을 참조할 때 /etc/letsencrypt/live/[your_domain_name] 폴더를 이용해야 합니다.

다음 아래의 명령어를 통해 해당 4개의 파일들이 존재하는지 확인할 수 있습니다.

$ sudo ls -l /etc/letsencrypt/live/your_domain_name


디프-헬만 그룹 추가하기

보안을 위해서 디프-헬만 그룹을 추가해야한다고 합니다. 아래의 명령어를 통해 실행해줍니다. 화면에 여러 점들이 찍히면서 진행이되며 시간이 다소 몇분 소요됩니다

$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

다 생성이 되면 /etc/ssl/certs/에서 dhparam.pem 파일을 확인 할 수 있습니다.


3. TLS/SSL 설정하기

이제 Nginx의 server block들을 처리해서 TLS/SSL 설정을 하도록 하겠습니다. nginx에서 default 파일을 수정합시다.

$ sudo vim /etc/nginx/sites-available/default


server block에서 80포트에 대한 기본정보가 아래처럼 나와 있을텐데 지워줍니다.

server{
    ...
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;
    ...
}    


이제 SSL 관련 설정 세팅을 시작해봅시다. server block안에 다음 내용들을 추가합니다. 여기서 [domain]은 등록하신 도메인을 입력해야합니다!

server{
    ...
    listen 443 ssl;

    server_name [domain] [another_domain];

    ssl_certificate /etc/letsencrypt/live/[domain]/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/[domain]/privkey.pem;
    ...
}


위의 작업이 끝났다면 아래의 내용도 그대로 server block에 추가합니다.

server{
    ...
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Strict-Transport-Security max-age=15768000;
    ...
}


마지막으로 아래에 다음과 같은 새로운 server block을 추가합니다.

해당 block은 해당 도메인에 대한 http의 요청을 https로 redirect 해주는 block입니다.

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}


자, 이제 설정이 다 끝났습니다. 다음처럼 문법을 확인하고 재시작해줍시다. 아래와 같은 스크린샷이 나오면 정상적으로 작동하는겁니다.

$ sudo nginx -t
$ sudo service nginx restart
or
$ sudo /etc/init.d/nginx restart
# sudo service nginx restart가 실행되지 않으면 위의 명령어로도 실행 가능합니다.

Nginx Restart


추가로! 다음 아래 사이트에서 마지막 d=에 설정하신 도메인을 넣어주시면 ssl 설정이 완료되었는지 등급이 어느정도인지 알 수 있습니다. 제대로 따라오셨다면 A+가 나와야합니다.

https://www.ssllabs.com/ssltest/analyze.html?d=[domain]


4. 갱신 자동화하기

Let’s Encrypt는 3개월간 유효하며 이를 자동적으로 갱신을 해야하는데 crontab을 통해서 그 일을 자동화시켜 보겠습니다.

다음 명령어를 통해서 crontab을 엽니다.

$ sudo crontab -e


텍스트 에디터로 열리면 아래의 명령어를 파일의 끝에 추가해줍니다.

. . .
15 3 * * * /usr/bin/certbot renew --quiet --renew-hook "/usr/sbin/service nginx reload"

간단히 설명을 하면

  • 15 3 * * *: 매일 3:15 AM에 실행하겠다는 의미입니다.
  • /usr/bin/certbot: 실행하는 파일이며
  • renew: 자동으로 certbot이 인증서들을 보고 갱신이 필요하면 갱신을 진행해줍니다.
  • –quiet: 사용자에게 output을 전달하지 않고 실행합니다.(백그라운드)
  • –renew-hook “/usr/sbin/service nginx reload”: 파일이 새로 갱신되었다면 Nginx를 reload해줍니다.


참고자료

ini 파일을 통해서 쉽게 uWSGI를 실행하자


환경


사전 준비사항


uWSGI ini 파일 작성

사용하고자하는 프로젝트 root 폴더에 ini파일을 하나 생성합니다.

Django와 같은 경우 manage.py가 있는 폴더에 생성해주시면 됩니다.

$ touch ini_file_name.ini

지금 진행하는 프로젝트의 경우 파일 이름을 linku_uwsgi.ini로 하였습니다.

$ touch linku_uwsgi.ini


uWSGI ini 파일 작성

LinkU 프로젝트 ini파일 예시

linku_uwsgi.ini

#linku_uwsgi.ini file
[uwsgi]

# Django-related settings
# the base directory (full path)
chdir           = /home/linku/LinkU/linku_backend
# Django's wsgi file
module          = linku.wsgi
# the virtualenv (full path)
home            = /home/linku/.pyenv/versions/LinkU/
virtualenv = /home/linku/.pyenv/versions/LinkU/

# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 4
# the socket (use the full path to be safe
socket=/home/linku/LinkU/linku_backend/linku.sock

# ... with appropriate permissions - may be needed
chmod-socket    = 666
# clear environment on exit
vacuum          = true
# daemonize the process
daemonize=/home/linku/LinkU/linku_backend/linku.log
# process pid
pidfile=/tmp/linku_backend.pid

# newrelic settings
enable-threads = true
single-interpreter = true
lazy-apps = true

  • chdir: 프로젝트 기본 경로입니다. django의 경우 manage.py가 위치는 곳을 경로로 잡아주면 됩니다.
  • module: django 프로젝트를 생성하면 해당 프로젝트 이름으로 생성되는 wsgi.py가 생성되는데 해당 파일을 모듈로 불러옵니다. 프로젝트이름.wsgi로 해주시면됩니다.
  • home, virtualenv: 파이썬 가상환경이 위치한 폴더의 경로를 잡아주면 됩니다.
  • master: uWSGI 프로세스를 master로 돌아가게 해줍니다.
  • processes: 프로세스 수 입니다.
  • socket: UNIX socket 파일의 위치입니다. socket file의 위치를 잡아줘도 되며 localhost와 port를 명시해줘도 됩니다.
  • chmod-socket: UNIX socket에 대한 권한 설정입니다. 666을 해야 실행이 가능합니다.
  • vacuum: uWSGI를 통해서 생성된 파일들은 삭제하는 옵션입니다.
  • daemonize: 백그라운드로 돌리기 위한 설정이며 log파일을 남길 경로를 지정해주면 됩니다.
  • pidfile: 생성할 pid 파일의 위치입니다.
  • enable-threads: thread 사용을 앱(uWSGI) 내에서 가능하게 해줍니다.
  • single-interpreter: 단일한 python interpreter를 사용하게 하는 옵션입니다.
  • lazy-apps: master말고 각각의 worker에(master에서 spawn한 자식들) 앱을 로드하는 설정입니다.


uWSGI 실행하기

uWSGI가 pip를 통해 설치되어 있는 환경이라 한다면 다음과 같은 명령어로 실행이 가능합니다.

$ uwsgi --ini [ini filename or path]

예시

$ uwsgi --ini linku_uwsgi.ini


참고자료

UNIX Socket을 통해서 uWSGI를 실행하자


환경 및 선수조건


UNIX socket을 쓰는 이유?

  • UNIX socket을 쓰면 overhead가 적어서 더 좋은 성능을 낼 수 있습니다.


기존 Port를 이용한 uWSGI실행

기존에 port를 이용해서 실행하는 방법은 장고 프로젝트 내에서 다음과 같은 명령어를 통해서 실행이 가능합니다.

$ uwsgi --http :[port] --module [module_name.wsgi]


UNIX socket 파일 생성

python 기반 프로젝트 root 폴더에 다음과 같이 socket file을 생성합니다.

socket file의 이름을 linku라고 하고 생성해보겠습니다.

$ touch linku.sock

파일만 생성하시면 되며 다른 작업은 하지 않으셔도 됩니다:)


UNIX socket을 통한 UWSGI 실행

생성한 UNIX socket을 통한 uWSGI 실행은 다음과 같습니다.

$ uwsgi --socket linku.sock --module [module_name.wsgi]


참고자료

업데이트(2021.05.10): 일부 용어 변경 및 잘못된 url 삭제

업데이트(2018.05.31): nginx<->uwsgi에서 http를 socket으로 오류 정정

업데이트(2018.04.16): 포맷 변경 및 내용 조금 보충

업데이트(2018.02.20): .conf 파일의 생성위치와 symlink 부분을 수정하였습니다.

Ubuntu에서 Nginx, uWSGI 그리고 Django를 연결하자.


환경


사전 준비사항

  • Django에서 manage.py runserver를 통한 서버 환경 실행 경험 필요
  • pip 사용법 숙지
  • Django 프로젝트 생성(이 문서에서는 LinkU라는 프로젝트 명으로 진행합니다.)
  • Server와 Port의 개념
  • [선택] pyenv 및 virtualenv 사용법 숙지(단, 여기서는 가상환경에서 진행합니다.)


[선택] pyenv와 virtualenv를 통해서 가상환경 설정하기

우선 uWSGI를 pip를 통해서 전체에서 설정을 해도 되지만 가상환경을 직접 설정해서 설치하고 돌려보겠습니다 우선 만드시려는 python 환경 프로젝트를 virtualenv를 통해서 생성해줍니다.

관련 생성은 위에 있는 링크를 타고 가시면 참고 하실 수 있으며 pyenv와 virtualenv가 설칭되어있다고 가정할 때 간단한 예시는 아래와 같습니다.

$ pyenv virtualenv [python version] [project virtualenv name]

프로젝트 가상환경의 이름이 LinkU이고 python version이 3.5.2일 때는 아래와 같습니다.

$ pyenv virtualenv 3.5.2 LinkU


[선택] 가상환경 실행

가상환경을 실행하고 uWSGI를 설치해 보겠습니다.

$ pyenv activate LinkU // LinkU에는 설정하실 가상환경 이름이 들어가면 됩니다.


프로젝트 환경에 uWSGI 설치하기

uWSGI는 pip를 통해서 설치가 가능합니다.

(LinkU)$ pip install uwsgi


uWSGI를 통해서 Django 서버 돌리기

사용했던 python manage.py runserver 대신에 uWSGI명령어를 통해서 실행 해보도록 하겠습니다. 생성한 Django 프로젝트로 이동해서 manage.py 있는곳으로 가줍니다.

다음 아래와 같은 방식을

(LinkU)$ python manage.py runserver

다음처럼 할 수 있습니다. linku.wsgi는 wsgi.py를 포함하고 있는 폴더명으로 해주시면 됩니다.

# linku.wsgi는 wsgi.py를 포함하고 있는 폴더명으로 해주시면 됩니다.
(LinkU)$ uwsgi --http :8000 --module linku.wsgi


명령어에 대해 설명하면

  • http는 http 통신을 하겠다는 의미이며 8000포트를 사용한다는 것입니다.
  • http가 아닌 Nginx와 함께 UNIX Socket 방식을 사용하고 싶다면 --socket :[port number]의 형태로 이용하면 되며 아래에 더 자세한 예제가 나옵니다.
  • module은 wsgi 모듈을 통해서 실행하겠다는 의미이며
  • 단순하게 파일을 사용하려면 --wsgi-file [app.py(python 실행 파일 이름)]의 형태로도 사용가능합니다.

조금 더 추가적인 설명을 드리자면

  • 외부에서 8000 포트로 들어온 http요청을 uWSGI가 받아서
  • 그 요청을 처리하는 애플리케이션에(이 경우에는 Django 혹은 Django Rest Framework) 넘겨주고 처리를 해준 후에 응답을 해줍니다.
  • 현재 구조: web Client <-> uWSGI(port 8000) <-> Django


Nginx에 upstream 설정해주기

이제 외부에서 특정포트로 Nginx를 통해 http 요청을 받았을 때 그 요청을 uWSGI를 통해서 Django로 넘겨 봅시다.


프로젝트 폴더에 uwsgi_params 추가

Nginx 설정 파일들 폴더(/etc/nginx)에 있는 uwsgi_params파일을 복사해서 manage.py가 있는 프로젝트 폴더에 복사해 추가합니다.

package를 통해서 설치한 경우에는 다음과 같습니다.

$ cp /etc/nginx/uwsgi_params [Django project folder]

만약에 없다면 uwsgi_params 파일을 생성해서 다음 아래 코드를 복사해서 붙여넣습니다. 이 코드는 nginx github에서 가져온 코드입니다.

uwsgi_params

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;


nginx에서 사용 할 conf 파일 만들기

이제 nginx에서 사용할 설정 파일을 만들어서 /etc/nginx/sites-available 폴더에 추가해봅시다.

  • /etc/nginx/sites-available로 이동해서 아래와 같이 파일을 생성해줍니다.
(LinkU) $ touch linku_backend_nginx.conf // 설정 파일의 이름은 자유입니다.


해당 파일을 vim 혹은 에디터를 통해서 아래처럼 설정해줍니다.

  • 프로젝트 이름과 가상환경 사용할 port에 따라서 설정 파일이 다를수도 있습니다! (당연한 이야기)

linku_backend_nginx.conf

# linku_backend_nginx.conf

# upstream(proxy) 설정
upstream django{
    #1 uWSGI를 이용한 django 서버가 listening 할 ip주소와 port 번호를 적어주시면 됩니다. upstream에 다른 외부 서버를 연결할수도 있지만 여기서는 로컬에 있는 django에 보내니 주소가 127.0.0.1이고 포트는 8001로 설정하였습니다.
    server 127.0.0.1:8001;
}

# configuration of the server
server {
    #2 django가 아니라 외부에서 어떤 port를 listening 할지 정해줍니다.
    listen      [Port Number];
    #3 실행하는 서버의 IP주소 혹은 Domain을 적어주시면 됩니다.
    #4 이 server_name을 여러개 만들어서 subdomain도 각각 다르게 처리 가능합니다.
    server_name [IP Address];
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    #5 Django media 디렉토리 경로
    location /media  {
        alias /home/linku/LinkU/linku_backend/media;
    }

    #6 Django static 디렉토리 경로
    location /static {
        alias /home/linku/LinkU/linku_backend/static;
    }

    #7 media와 static을 제외한 모든 요청을 upstream으로 보냅니다.
    location / {
        #8 uwsgi_pass [upstream name] (위에 upstream으로 설정한 block의 이름)
        uwsgi_pass  django;
        #9 uwsgi_params의 경로
        include /home/linku/LinkU/linku_backend/uwsgi_params;
    }
}
  • []로 만들어 놓은 부분은 작성하시는 분에 따라서 직접 넣어주셔야 합니다.
  • #1 uWSGI를 이용한 django 서버가 listening 할 ip주소와 port 번호를 적어주시면 됩니다. upstream에 다른 외부 서버를 연결할수도 있지만 여기서는 로컬에 있는 django에 보내니 주소가 127.0.0.1이고 포트는 8001로 설정하였습니다.
  • #2 django가 아니라 외부에서 어떤 port를 listening 할지 정해줍니다.
  • #3 실행하는 서버의 IP주소 혹은 Domain을 적어주시면 됩니다.
  • #4 이 server_name을 여러개 만들어서 subdomain도 각각 다르게 처리 가능합니다.
  • #5 Django media 디렉토리 경로
  • #6 Django static 디렉토리 경로
  • #7 media와 static을 제외한 모든 요청을 upstream으로 보냅니다.
  • #8 uwsgi_pass [upstream name] (위에 upstream으로 설정한 block의 이름)
  • #9 uwsgi_params의 경로



nginx 설정파일들이 있는 폴더로 이동

Ubuntu에서 apt-get을 통해 nginx 설치하기 및 간단한 정리에 기록을 해두었지만 sites-enablednginx.conf를 통해서 nginx의 설정이 가능합니다.

해당 폴더와 파일의 경로는 위 문서에 기록한 것처럼 /etc/nginx,/usr/local/nginx/conf, /usr/local/etc/nginx중에 하나에 위치합니다.

nginx_folder


symlink는 쉽게 생각해 바로가기와 같다고 보면 편합니다.

$ sudo ln -s /etc/nginx/sites-available/mysite_nginx.conf /etc/nginx/sites-enabled/

지금까지 진행한 linku_backend_nginx.conf에 대해서 symlink를 만드는 경우의 예시는 아래와 같습니다.

$ sudo ln -s /etc/nginx/sites-available/linku_backend_nginx.conf /etc/nginx/sites-enabled/

추가된 모습

symlink


Static file들 모으기

Django 프로젝트 폴더에 있는 settings.py에 아래와 같은 코드를 추가합니다. media에 관한 설정도 안되어 있다면 같이 해주도록 합시다.

settings.py

...
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
...

프로젝트 폴더에서 collectstatic 명령어을 통해서 static file들을 모아줍니다.

$ python manage.py collectstatic


설정파일 적용 및 테스트

nginx 재시작

# 다음 3가지 명령어 중에 하나만 하시면 됩니다.
$ sudo service nginx restart
$ sudo systemctl restart nginx
$ sudo /etc/init.d/nginx restart

아래와 같이 OK가 뜬다면 제대로 실행이 된것입니다.

restarting


uWSGI 실행

  • 여기서 Port 번호는 위에 conf파일에 있는 upstream 블록의 Port 번호와 같아야합니다.
(LinkU)$ uwsgi --socket :8001 --module linku.wsgi


이제 도메인을 통해서 domain.com:port를 통해서 접속하면 여기서의 Port는 위에 conf파일에 있는 server 블록에 있는 Port번호 입니다. 장고에서 해당하는 응답을 보여줌을 확인 할 수 있습니다.


uWSGI가 실행이 되지 않는다면

nginx error log(/var/log/nginx/error.log)를 확인해서 아래와 같은 오류가 나온다면

connect() to unix:///path/to/your/mysite/mysite.sock failed (13: Permission denied)


다음 아래 두 명령어중에 하나를 시도해보시면 됩니다. 권한 떄문에 생기는 문제인데 nginx의 사용자 그룹에 현재 접속한 유저를 추가해주셔야 됩니다.

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=666 # (very permissive)

또는

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=664 # (more sensible)


완료된 상황 및 구조

현재까지 완료된 상황을 보면 아래와 같습니다.

  • Web Client <-> Nginx(Web Server) <-> uWSGI(port:8001) <-> Django(Application Server)


추후 계획


참고자료