본문 바로가기
Python

[파이썬으로 웹개발] flask를 wsgi 서버에서 구동하기 (https 프로토콜)

by 돈민찌 2021. 10. 2.
반응형

출처 digitalocean.com

네 앞 과정을 잘 따라오셨을 것이라 믿고 다음 단계를 진행합니다. nohup 등으로 직접적으로 flask 서버를 돌리는 것이 아닌 안전하고 안정적인 환경에서 작동시키고, 또 접속 프로토콜을 443포트로 받을 수 있도록 해 더 많은 기능과 보안을 제공할 수 있습니다.

우분투에서 필요한 파이썬 환경을 위해 몇가지 프로그램을 설치하겠습니다. 중간에 Enter를 기입하라거나 Y를 입력하라는 문구가 나올 수 있습니다.

sudo apt update
sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools

다음으로는 파이썬 가상환경 패키지를 설치합니다.

sudo apt install python3-venv

다음 과정은 flask 프로젝트의 가장 기본적인 구조를 만들어보고, https 프로토콜로 접속이 되게끔 하는 것입니다. 한번 튜토리얼대로 끝까지 진행을 해보시고, 오류가 없으시다면 이 단계에서 git을 이용해 작업하신 flask 웹앱 프로젝트를 clone 하여 나머지 과정을 진행하시면 됩니다. (이 경우 rm -rf 로 해당 디렉토리를 삭제하고 진행해야 합니다)

가상환경을 만들어봅니다 이름은 자유지만 코드블럭을 활용하실 거라면 이름을 모두 그대로 해주시는 것이 좋습니다.

mkdir ~/myproject
cd ~/myproject
python3.6 -m venv myprojectenv
source myprojectenv/bin/activate

각각 myproject라는 폴더에 만들고 디렉토리에 들어간 후, 파이썬 가상환경을 만들고 실제로 activate하는 과정입니다.

가상환경을 실행 중이라는 (myprojectvenv)가 보이면 다음 코드를 작동합니다.

pip install wheel uwsgi flask

pip3 사용을 할 필요는 없습니다. 오히려 pip에서 지원가능한 낮은 버전을 사용하는 것이 나중에 발생할 수 있는 많은 문제를 줄여줍니다. 그리고 가상환경 내에서는 pip3가 아닌 pip를 사용하는 것이 맞습니다. 일반적으로 app.py라고 생성하는 플라스크 메인 파일을 프로젝트 이름과 똑같게 만듭니다(사실 app만 아니면 괜찮을 것 같습니다.)

nano ~/myproject/myproject.py

플라스크 앱의 기본 형태입니다.

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

플라스크 앱을 만들어보셨다면 바로 이해가 되실 거라 생각합니다. return 다음에 html 코드를 삽입하거나 templates 폴더를 만들고 그 안에 index.html을 만들어 플라스크의 render_template('index.html') 이런 식으로 사용해도 됩니다.

저장하고 닫기 (Ctrl + x > Shift + Y > Enter)

애플리케이션을 테스트해보기 위해 5000포트를 직접 열어주겠습니다.

sudo ufw allow 5000

앱을 실행시켜봅니다.

python myproject.py

다음과 같은 문구가 나오면 성공입니다. 앞에 설명드린 Use a production WSGI server instead. 문구가 나옵니다.

* Serving Flask app "myproject" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

http://입력했던 도메인:5000 을 입력해서 Hello There!이 잘 출력되는지 확인하고 Ctrl + C 를 눌러 종료합니다.

Use a production WSGI server instead. 문구에 따라 wsgi 서버에서 구동할 준비를 해보겠습니다.

nano ~/myproject/wsgi.py

nano 말고도 다른 기본 에디터(gedit, vim)들이 있지만 nano가 편한 것 같습니다.

from myproject import app

if __name__ == "__main__":
    app.run()

위 내용대로 파일을 완성하고 닫아줍니다. myproject는 프로젝트 폴더 이름이 아니라 플라스크 메인 앱의 이름입니다. 그 안에서 run 되는 app 객체를 가져오는 것입니다.

다음으로 wsgi파일의 app객체(wsgi:app)를 동작 코드를 작성합니다. 제대로 진행 중이라면 현재까지 가상환경 내에 있어야 합니다.

uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app

이번엔 http://도메인이름:5000 번에 접속해봅니다. 문제없이 따라오셨다면 다시 Hello There!이 출력되는 창을 보시게 될 것인데, 단 Use a production WSGI server instead.  부분이 콘솔에 찍혀있지 않을 것입니다.

이제 가상환경을 종료합니다.

deactivate

uWSGI의 구성파일이 될 myproject.ini 파일을 myproject 폴더 내에 만듭니다.

nano ~/myproject/myproject.ini

내용은 다음과 같이 작성합니다. 

[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = myproject.sock
chmod-socket = 660
vacuum = true

die-on-term = true

wsgi 파이썬 파일의 app을 master 권한으로 run 할 것이고, 5개의 프로세스를 사용할 것이며, 더 빠르고 안전한 웹앱을 위해 myproject.sock을 대상으로 unix socket  기능을 사용할 것입니다. socket의 권한 설정으로 660코드가 입력되고, 프로세스가 중지될때 소켓도 함께 정리될 수 있도록 vacuum 옵션을 사용합니다. .ini 시스템파일과 uWSGI 프로세스가 정렬되어 예상 범위대로 구현될 수 있도록 die-on-term 옵션을 사용합니다. 저장하고 닫습니다.

시스템 단위 파일을 생선해 서버가 부팅될 때마다 flask 앱을 제공할 수 있도록 다음 파일을 만듭니다.

sudo nano /etc/systemd/system/myproject.service
[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/myproject
Environment="PATH=/home/ubuntu/myproject/myprojectenv/bin"
ExecStart=/home/ubuntu/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

[Install]
WantedBy=multi-user.target

저장하고 닫습니다. 이제 다음 명령을 실행하면 해당 파일로 인해 서버가 부팅될 때마다 uWSGI 서비스가 실행될 것입니다.

sudo systemctl start myproject
sudo systemctl enable myproject
sudo systemctl status myproject
● myproject.service - uWSGI instance to serve myproject
   Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2018-07-13 14:28:39 UTC; 46s ago
 Main PID: 30360 (uwsgi)
    Tasks: 6 (limit: 1153)
   CGroup: /system.slice/myproject.service
           ├─30360 /home/ubuntu/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
           ├─30378 /home/ubuntu/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
           ├─30379 /home/ubuntu/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
           ├─30380 /home/ubuntu/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
           ├─30381 /home/ubuntu/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
           └─30382 /home/ubuntu/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

이런 코드만 출력되면 잘 따라온 것입니다. 이외에 다른 불필요한 에러코드가 함께 출력된다면 앞의 과정을 제대로 실행하셨는지 한번 확인!!!이 필요합니다.

이제 nginx 서버의 라우팅에 추가될 수 있도록 서버 블록을 추가합니다.

sudo nano /etc/nginx/sites-available/myproject
server {
    listen 80;
    server_name catminzzi.shop www.catminzzi.shop;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/ubuntu/myproject/myproject.sock;
    }
}

이제 이 서버 블록을 sites-enabled 디렉토리에 연결(바로가기 만들기)합니다.

sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

구문 테스트를 실행합니다. 역시 아무 오류 없이 두줄의 코드가 나타나면 정상입니다.

sudo nginx -t

nginx 프로세스를 재실행합니다.

sudo systemctl restart nginx

방화벽을 이제 다시 조정해줍니다. 더 이상 5000 포트로 직접 접속할 필요가 없어졌으니 해당 룰을 제거합니다. 그리고 Nginx Full 액세스(80포트+443포트)를 허용합니다.

sudo ufw delete allow 5000
sudo ufw allow 'Nginx Full'
sudo ufw status

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                  
Nginx Full                 ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)             
Nginx Full (v6)            ALLOW       Anywhere (v6)

이런 결과가 나타나면 성공입니다. 이제 5000포트에서 직접 80포트로 포트 포워딩하는 것보다 훨씬 안전한 방식으로 사이트에 접속할 수 있습니다. 아직은 http 서버이지만 도메인 접속이 가능해졌습니다.

혹시 과정 중에 오류가 발생한 것 같다면, 아래 명령문으로 자세한 에러코드를 읽어보세요

  • sudo less /var/log/nginx/error.log: checks the Nginx error logs.
  • sudo less /var/log/nginx/access.log: checks the Nginx access logs.
  • sudo journalctl -u nginx: checks the Nginx process logs.
  • sudo journalctl -u myproject: checks your Flask app’s uWSGI logs.

자 이제 대망의 https 서버 만들기입니다. SSL 인증서를 발급받기 위해 let's encrypt라는 비영리 SSL 발급 사이트에서 SSL을 발급받을 것입니다. certbot을 설치해줍니다.

sudo add-apt-repository ppa:certbot/certbot

Enter를 입력하면 설치가 완료됩니다.

sudo apt install python-certbot-nginx

nginx를 위한 cerbot 패키지까지 설치했습니다. 이제 certbot에 완성한 도메인에 대한 인증서를 요구해야 합니다.

sudo certbot --nginx -d catminzzi.shop -d www.catminzzi.shop

연결될 이메일을 입력하고, 서비스약관에 동의하는 커맨드를 입력하면 HTTPS 설정을 구성할 방법을 묻는 메세지가 표시됩니다.

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):

1번은 https로 접속했을 시에 그것을 https로 리다이렉트하지 않겠다는 뜻이고, 웹구성변경 X
2번은 http로 접속했을 때 모든 요청을 https로 리다이렉트 해주겠다는 의미입니다.

적절한 숫자를 선택한 다음 엔터를 입력합니다.

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at: (인증서 및 체인이 다음 위치에 저장되었습니다.)
   /etc/letsencrypt/live/catminzzi.shop/fullchain.pem
   Your key file has been saved at: (키 파일은 다음 위치에 저장되었습니다.)
   /etc/letsencrypt/live/catminzzi.shop/privkey.pem 
   Your cert will expire on 2018-07-23. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - 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

congratilations 로 시작하는 아웃풋이 나오면 성공입니다.

이제 방화벽 설정을 마치면 https:catminzzi.shop으로 사이트를 이용할 수 있게 됩니다.

sudo ufw delete allow 'Nginx HTTP'
sudo ufw status

 

이 글을 디지털오션 페이지의 게시물을 번역 및 수정한 게시물입니다. 본 저작물의 권한은 digitalocean.com에 있습니다.

반응형

댓글