Настраиваем Django + virtualenv + nginx + gunicorn + PostgreSQL + memcached + letsencrypt на Ubuntu 16.04
В данной статье я опишу процесс настройки связки Django + virtualenv + nginx + gunicorn + PostgreSQL + memcached + letsencrypt на Ubuntu 16.04 на VPS DigitalOcean для своего форума https://pythonworld.club.
DigitalOcean
Из всех VPS-провайдеров я выбрал DigitalOcean, так как:
- Начальный бонус 10$ после регистрации по ссылке (это месяц использования VPS в подарок)
- Бонус в 50$ для студентов
- Высокое качество и надёжность (за 3 года использования проблемы были только 2 раза, о них старались предупреждать заранее, и устранялись в кратчайшие сроки), а также низкая цена.
Впрочем, большая часть статьи подходит для VPS от любого провайдера.
Для активации аккаунта и получения стартового бонуса необходимо либо привязать банковскую карту, либо заплатить хотя бы 5$ через PayPal.
После этого можно выбрать тариф: для начала достаточно и самого дешёвого за 5$, но как только нагрузка на ваше приложение увеличится, ресурсов может не хватить. Тарифа за 10$ мне хватает вполне, поэтому, если у вас нет ничего экстраординарного, выше брать не стоит.
Ubuntu
Необходимо произвести начальную настройку. Если кратко:
- Создать нового пользователя (не будем же мы всё из-под root-а делать?)
- Дать ему права на выполнение команд через sudo
- (опционально) авторизация не по паролю, а по ключу
Подробнейшие инструкции на русском есть на сайте DigitalOcean, не считаю нужным повторяться.
Предположим, нового пользователя назовём steve (это понадобится в дальнейшем, когда будем прописывать пути, будьте внимательны и меняйте на имя созданного Вами пользователя!)
PostgreSQL
Устанавливаем пакеты
sudo apt-get update sudo apt-get install libpq-dev postgresql postgresql-contrib
Запускаем консоль PostgreSQL
sudo -u postgres psql
CREATE DATABASE myproject; CREATE USER myprojectuser WITH PASSWORD 'difficultpassword'; ALTER ROLE myprojectuser SET client_encoding TO 'utf8'; ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed'; ALTER ROLE myprojectuser SET timezone TO 'UTC'; GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
Некоторые приложения (и Misago в том числе) могут устанавливать расширения (extension) для PostgreSQL. Если у вас именно такой случай, необходимо ещё на время дать права суперпользователя базы новому пользователю:
ALTER ROLE myprojectuser superuser;
Теперь можно выйти из консоли PostgreSQL
\q
virtualenv
Устанавливаем pip и virtualenv:
sudo apt-get update sudo apt-get install python3-pip sudo pip3 install virtualenv
Создаём новое виртуальное окружение:
mkdir ~/newproject cd ~/newproject virtualenv newenv
Если вам нужно будет удалить виртуальное окружение, достаточно сделать rm -rf ~/newproject/newenv/.
Теперь активировать окружение можно с помощью команды
source newenv/bin/activate
запущенной из директории newproject.
Вы увидите, что после этой команды изменится приглашение интерпретатора bash: в начале появится (newenv).
Django
Установить Django в виртуальное окружение можно с помощью
pip install django psycopg2
в вашем окружении (заметьте, не pip3, несмотря на третий Python!)
Для выхода из окружения используйте команду deactivate (заметьте, она работает только в виртуальном окружении!)
По данным 2 пунктам есть туториал на DigitalOcean (на английском) (https://www.digitalocean.com/community/tutorials/how-to-install-the-django-web-framework-on-ubuntu-14-04).
Создаём Django-проект
django-admin.py startproject myproject ~/newproject
В моём случае (приложение Misago) была отдельная команда
pip install misago cd ~/newproject misago-admin testforum
Меняем настройки для доступа к базе данных. В settings.py прописываем:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'myproject', 'USER': 'myprojectuser', 'PASSWORD': 'difficultpassword', 'HOST': 'localhost', 'PORT': 5432, } }
Далее, стандартные действия:
python manage.py makemigrations python manage.py migrate python manage.py collectstatic python manage.py createsuperuser sudo -u postgres psql
После чего следует отобрать права суперпользователя для пользователя базы данных (если вы их выдавали).
ALTER ROLE myprojectuser nosuperuser; \q
nginx
Устанавливаем свежий nginx
nginx=stable sudo add-apt-repository ppa:nginx/$nginx sudo apt-get update sudo apt-get install nginx
Конфигурируем наш сервер
nano /etc/nginx/sites-available/testforum
server { server_name pythonworld.club; # Подставьте свой домен listen 80; location /.well-known { root /var/www/html; # Понадобится для letsencrypt } # Статические файлы location = /favicon.ico { alias /home/steve/newproject/testforum/static/favicon.ico; } location = /robots.txt { alias /home/steve/newproject/testforum/static/robots.txt; } location /static/ { root /home/steve/newproject/testforum/; } location /media/ { root /home/steve/newproject/testforum/; } # Взаимодействуем с Django-приложением через unix-сокет location / { include proxy_params; proxy_pass http://unix:/home/steve/newproject/forum.sock; } }
sudo ln -s /etc/nginx/sites-available/testforum /etc/nginx/sites-enabled
gunicorn
Вернёмся в виртуальное окружение (если вы из него выходили), и установим gunicorn
pip install gunicorn
Создадим файл конфигурации для gunicorn
sudo nano /etc/systemd/system/gunicorn.service
[Unit] Description=gunicorn daemon After=network.target [Service] User=steve Group=www-data WorkingDirectory=/home/steve/newproject/testforum/ ExecStart=/home/steve/newproject/newenv/bin/gunicorn --access-logfile - --error-logfile error.log --workers 2 --bind unix:/home/steve/newproject/forum.sock testforum.wsgi:application [Install] WantedBy=multi-user.target
Теперь мы можем запустить gunicorn, а далее он будет автоматически запускаться при загрузке.
sudo systemctl start gunicorn sudo systemctl enable gunicorn
Подробно на английском (с решением некоторых возможных проблем) описано в статье на DigitalOcean.
memcached
sudo apt-get install memcached libmemcached-dev sudo nano /etc/memcached.conf
# Start with a cap of 64 megs of memory. It's reasonable, and the daemon default # Note that the daemon will grow to this size, but does not start out holding this much # memory -m 256 # Ставим побольше, например 256Мб # Default connection port is 11211 #-p 11211 Комментируем, так как хотим связать с помощью UNIX-сокета # Run the daemon as root. The start-memcached will default to running as root if no # -u command is present in this config file -u memcache # Specify which IP address to listen on. The default is to listen on all IP addresses # This parameter is one of the only security measures that memcached has, so make sure # it's listening on a firewalled interface. #-l 127.0.0.1 Также комментируем # А UNIX-сокеты добавляем -s /tmp/memcached.sock -a 0766
Устанавливаем Python библиотеку (в виртуальное окружение) для связывания Django и memcached
pip install pylibmc
В settings.py Django-проекта добавляем
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', 'LOCATION': '/tmp/memcached.sock', } }
И, наконец, перезапускаем memcached:
sudo systemctl restart memcached
letsencrypt
Устанавливаем letsencrypt
sudo add-apt-repository ppa:certbot/certbot sudo apt-get update sudo apt-get install --upgrade letsencrypt
Создаём файл конфигурации
sudo nano /etc/letsencrypt/cli.ini
authenticator = webroot webroot-path = /var/www/html post-hook = service nginx reload text = True
Регистрация в letsencrypt
sudo certbot register --email my@email.com
Попробуем получить необходимый сертификат в режиме для тестов
sudo certbot certonly --dry-run -d pythonworld.club -d www.pythonworld.club
В конце вы должны получить сообщение
The dry run was successful.
Если всё прошло успешно, то можно получить сами сертификаты
sudo certbot certonly -d pythonworld.club -d www.pythonworld.club
После этого, редактируем настройки nginx
sudo nano /etc/nginx/sites-available/testforum
server { server_name pythonworld.club www.pythonworld.club default_server; listen 80; return 301 https://pythonworld.club; } server { server_name www.pythonworld.club; listen 443 ssl http2; ssl_certificate /etc/letsencrypt/live/pythonworld.club/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/pythonworld.club/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/pythonworld.club/chain.pem; ssl_stapling on; ssl_stapling_verify on; add_header Strict-Transport-Security "max-age=31536000"; return 301 https://pythonworld.club$request_uri; } server { server_name pythonworld.club; listen 443 ssl http2; ssl_certificate /etc/letsencrypt/live/pythonworld.club/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/pythonworld.club/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/pythonworld.club/chain.pem; ssl_stapling on; ssl_stapling_verify on; add_header Strict-Transport-Security "max-age=31536000"; add_header X-Frame-Options "SAMEORIGIN"; location /.well-known { root /var/www/html; # Понадобится для letsencrypt } # Статические файлы location = /favicon.ico { alias /home/steve/newproject/testforum/static/favicon.ico; } location = /robots.txt { alias /home/steve/newproject/testforum/static/robots.txt; } location /static/ { root /home/steve/newproject/testforum/; } location /media/ { root /home/steve/newproject/testforum/; } # Взаимодействуем с Django-приложением через unix-сокет location / { include proxy_params; proxy_pass http://unix:/home/steve/newproject/forum.sock; } }
Перезапускаем nginx
sudo systemctl restart nginx
Автопродление сертификатов
sudo crontab -e
45 */12 * * * certbot renew --quiet --allow-subset-of-names
Ещё про настройку letsencrypt: англ, рус.
Проверка правильности настройки SSL.
Вот и всё. Теперь Ваше Django-приложение доступно в Интернет! Пример применения данной статьи можно найти по адресу https://pythonworld.club.