동기
최근 도메인을 산 김에 토이 프로젝트로 요즘 유행하는 익명 질답 서비스를 간단하게 만들어보려고 했다. Bitnami에서 클릭 몇 번으로 스택을 구성할 수 있는 것처럼 보여서 AWS 프리 티어랑 합쳐서 두 세 시간 정도 삽질을 했다. 무료 티어에서는 micro급 EC2 인스턴스를 무료로 제공해 주는데, Auto Scaling이 필요한 수준은 돼야 AWS의 장점을 느낄 수 있을 것 같고 이 정도로는 다른 VPS랑 비교해서 딱히 장점이 느껴지지 않았다. 그래서 차라리 오래 쓸 목적으로 싸고 적당한 VPS 하나를 맞추고자 가상서버 호스팅 비교글을 보고 가격 대비 트래픽과 하드 용량이 좋은 ConoHa에서 제일 싼 서버를 하나 맞췄다.
예전에 학교 서버에서 급식 평가 사이트 돌릴 때 서버 세팅에서 삽질을 많이 했었기 때문에 이번에는 세팅하면서 삽질 과정을 포스팅에 메모해 놓기로 했다. 서버 첫 설치부터 시작해서 삽질의 과정을 내가 나중에 다시 보면 기억날 수준으로만 간단하게 정리해 보았다. nginx + Django + uWSGI로 디플로이 할 일이 제일 많을 것 같아서 이 세팅으로 저장해 두었고, 사용하는 프레임워크 따라 적절히 변경해서 사용하면 된다. 작성하면서 이 글을 참고했다.
1. 설치
처음 설치하고 나서 root 계정으로 필요한 것들을 깔아준다. Ubuntu 14.04 기준이고 대부분의 작업에 python3를 사용한다.
$ apt-get update $ apt-get upgrade $ apt-get install build-essential zsh git python3-dev python3-pip nginx lrzsz $ pip3 install virtualenv
2. SSH 키 생성하기
useradd qwaz
로 유저를 추가한다.groupadd admin
으로 어드민 그룹 생성.usermod -a -G admin qwaz
로 유저를 어드민 그룹에 추가.login qwaz
로 로그인 후 sudo 되는지 테스트.- XShell 등에서 사용자 키를 생성하고 공개키를
.ssh/authorized_keys
위치에 업로드한다. 디렉터리가 없는 경우 생성하고 권한은 700으로 준다. - 로그아웃 후 Key 사용해서 로그인 되는지 테스트.
3. zsh 세팅하기
curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh | sh
로 oh-my-zsh 설치chsh -s /bin/zsh
로 기본 셸을 zsh로 변경 후 터미널 재접속..zshrc
를 수정해 테마나 플러그인을 취향대로 변경. bullet-train이 괜찮더라.
4. virtualenv 세팅
개발용 계정은 하나를 쓰고 projects 디렉터리 내부에 개발하는 프로젝트를 관리할 것이다. 프로젝트마다 계정을 생성해도 되는데 개인적으로는 이 방식이 편하게 느껴진다.
프로젝트 디렉터리가 없는 경우 mkdir projects
로 생성하고 ~/projects
디렉터리로 이동한다.
toytest라는 프로젝트를 예시로 진행해보겠다.
$ virtualenv toytest $ cd toytest $ source bin/activate $ pip install django $ cd django
virtualenv toytest
로 가상 환경을 만든다. 이렇게 만든 가상환경은 source toytest/bin/activate
로 활성화하고 deactivate
로 비활성화 할 수 있다.
virtualenv를 켜기 전에는 파이썬 버전에 따라 pip
, pip3
로 명령어가 다르지만 virtualenv를 python3로 설치했기 때문에 활성화 후에는 그냥 pip
명령어만 입력해도 python3 버전으로 작업할 수 있다. pip가 사용중인 파이썬 버전은 pip -V
로 확인할 수 있다.
5. Django 프로젝트 생성
서버에서 바로 django-admin startproject toytest
로 시작해도 되고, 로컬에서 생성한 뒤 git clone
등을 이용해 가져오게 설정해도 된다. 과정은 거의 동일하기 때문에 서버에서 바로 생성하는 방법으로 설명하겠다.
~/projects/toytest
디렉터리에서 django-admin startproject toytest
명령으로 toytest 프로젝트를 시작하자.
6. nginx 세팅
생성한 Django 프로젝트를 수정하기 전에, ~/projects/toytest
에 로그나 소켓 등을 먼저 설정한다.
$ mkdir misc log $ cd log $ touch access.log error.log toytest.log $ cd .. $ cd misc
misc 디렉터리에 toytest_nginx.conf
를 만들고 다음과 같은 내용을 추가하자.
server { # the port your site will be served on listen 80; # the domain name it will serve for server_name toytest.qwaz.io; charset utf-8; access_log /home/qwaz/projects/toytest/log/access.log; error_log /home/qwaz/projects/toytest/log/error.log; location / { include /etc/nginx/uwsgi_params; uwsgi_pass unix:///home/qwaz/projects/toytest/misc/toytest.sock; } }
이 파일을 symlink로 nginx 디렉터리에 추가한다.
sudo ln -s ~/projects/toytest/misc/toytest_nginx.conf /etc/nginx/sites-enabled/
7. uWSGI 세팅
여기를 참고했다.
우선 virtualenv를 잠시 꺼두고, pip3로 uWSGI를 system-wide로 설치한다.
$ deactivate $ sudo pip3 install uwsgi
virtualenv를 다시 켜고 python manage.py runserver 0.0.0.0:8000
로 Django를 돌려보자. 웹브라우저에서 toytest.qwaz.io:8000로 접속해 접속이 되는지 테스트 해본다.
잘 동작했다면 이번에는 uwsgi --http :8000 --module toytest.wsgi -H ~/projects/toytest
로 uWSGI를 사용해 다시 한 번 테스트 해본다.
여기까지 성공했다면 이제 아래 toytest_uwsgi.ini
파일을 misc 폴더에 만들자. 설정 파일 만들 때는 여기를 참고했다.
[uwsgi] # Django-related chdir = /home/qwaz/projects/toytest/toytest module = toytest.wsgi # virtualenv home = /home/qwaz/projects/toytest # process-related master = true processes = 8 # permission uid = qwaz gid = www-data # misc files socket = /home/qwaz/projects/toytest/misc/toytest.sock chmod-socket = 664 pidfile = /home/qwaz/projects/toytest/misc/toytest.pid daemonize = /home/qwaz/projects/toytest/log/toytest.log harakiri = 60 max-requests = 4096 reload-on-as = 512 reload-on-rss = 192 limit-as = 1024 no-orphans = true vacuum = true
uwsgi --ini toytest_uwsgi.ini
로 uwsgi를 실행시키고 sudo service nginx restart
로 추가한 sites-enabled를 읽도록 nginx를 재시작하고 브라우저로 접속해보자. 접속에 성공했다면 sudo kill -9 $(cat /home/qwaz/projects/toytest/misc/toytest.pid)
로 프로세스를 죽인다.
8. Emperor Mode
웹서버 관련 설정은 거의 다 끝났다. 이제 uWSGI를 Emperor Mode로 실행시키고 서버가 시작했을 때 자동으로 실행되도록 만들어주자. Emperor Mode에서는 ini 파일이 변경될 때마다 새로운 인스턴스를 띄워준다.
sudo mkdir /etc/uwsgi sudo mkdir /etc/uwsgi/vassals sudo ln -s /home/qwaz/projects/toytest/misc/toytest_uwsgi.ini /etc/uwsgi/vassals/ sudo uwsgi --emperor /etc/uwsgi/vassals --uid qwaz --gid www-data
실행 되는 것을 확인했다면 프로세스를 종료하고, 마지막으로 서버가 켜질 때 uWSGI가 뜨도록 해 보자.
/etc/rc.local
파일을 열어 /usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid qwaz --gid www-data
를 추가하고 서버를 재부팅해서 사이트가 뜨는지 확인한다.
여기까지 마치면 디렉터리 구조는 다음과 같이 된다.
~/ └ projects/ └ toytest/ ├ (virtualenv 관련 파일들) ├ log/ │├ access.log │├ error.log │└ toytest.log ├ misc/ │├ toytest_nginx.conf │└ toytest_uwsgi.ini └ toytest/ ├ manage.py └ toytest/ ├ settings.py ├ urls.py └ wsgi.py
몇 부까지 있을지는 모르겠지만 다음에는 DB 세팅과 Django 세팅 파일 설정 등을 건드릴 예정이다.