Развертывание django на VDS используя Apache, mod_wsgi, Django, MySQL, Virtualenv в Ubuntu\Debian

Развертывание django на VDS используя Apache, mod_wsgi, Django, MySQL, Virtualenv в Ubuntu\Debian

Инструкция запуска django-сайта на VDS\VPS используя Apache, mod_wsgi, Django, MySQL, Virtualenv в Ubuntu или Debian.
Использовал на таких версиях ПО: Ubuntu 14.04.4 LTS \ Debian 8.1, Apache 2.4.7, Python 2.7.6

Установка нужных пакетов:

apt-get update
apt-get upgrade
apt-get install gcc mysql-server python-mysqldb python-profiler w3m python-setuptools libmysqlclient-dev git-core python-dev
aptitude install apache2 libapache2-mod-wsgi
easy_install virtualenv

Добавляем пользователя, от лица которого будем развертывать сервер:

adduser u2django

Вводим пароль, остальные данные пользователя можно не заполнять.
Переходим в папку пользователя, создаем виртуальное окружение, активируем его, устанавливаем все необходимые пакеты:

cd /home/u2django
virtualenv mysite_env
source mysite_env/bin/activate
pip install Django==1.8 whitenoise  ...

Создаем папку с проектом и создаем джанго проект или копируем проект с гита:

git clone https://github.com/ __ .mysite.__.git

Получилась такая структура папок:
/home/u2django/mysite/static
/home/u2django/mysite/media
/home/u2django/mysite/manage.py
/home/u2django/mysite/project/settings.py
/home/u2django/mysite/logs

Пока отложим работу с файлами сайта, займемся настройкой апача. Можно выйти из окружения командой deactivate.
В каталоге /etc/apache2/sites-available создаем файл НАЗВАНИЕ_САЙТА.conf :

cd /etc/apache2/sites-available/
echo >mysite.conf

Добавим в этот файл следующий код:

# путь к сайту:путь к виртуальному окружению. Не работает если используется режим демона.
# WSGIPythonPath /home/u2django/mysite:/home/u2django/mysite_env/lib/python2.7/site-packages
<VirtualHost *:80>
# Описание сервера
ServerAdmin mail@mail.ru
# домен сайта
ServerName mysite.ru
ServerAlias www.mysite.ru

# Логи
ErrorLog    /home/u2django/mysite/logs/error_log
CustomLog   /home/u2django/mysite/logs/access_log common

# wsgi-обработчик (см. ниже)
WSGIScriptAlias / /home/u2django/mysite/django.wsgi

# режим демона - нужно если планируется запускать несколько разных джанго-сайтов
# Через двоеточие указывается путь к виртуальному окружению
WSGIDaemonProcess mysite.ru processes=2 python-path=/home/u2django/mysite:/home/u2django/mysite_env/lib/python2.7/site-packages
WSGIProcessGroup mysite.ru

<Directory "/home/u2django/mysite">
Require all granted
</Directory>

# путь к статичному файлу
Alias /robots.txt /home/u2django/mysite/static/robots.txt

# Статические файлы django-админки
Alias "/static/admin/" "/home/u2django/mysite/static/admin/"
<Location "/home/u2django/mysite/static/admin">
SetHandler None
</Location>

# Статические файлы проекта
Alias "/media/" "/home/u2django/mysite/media/"
<Location "/media/">
SetHandler None
</Location>

# Статические файлы проекта
Alias "/static/" "/home/u2django/mysite/static/"
<Location "/home/u2django/mysite/static/">
SetHandler None
</Location>

</VirtualHost>

В самом начале оставил закоменченным WSGIPythonPath. Он нужен если мы хотим использовать виртуальное окружение и не хотим использовать режим демона. А режим демона нужен для работы нескольких джанго сайтов. Если это не нужно, то можно удалить параметры WSGIDaemonProcess и WSGIProcessGroup.

Перейдем в каталог /home/u2django/mysite/ и создадим там файл django.wsgi , и добавим в этот файл следующий код:

import os, sys
sys.path.append('/home/u2django/mysite')

os.environ['DJANGO_SETTINGS_MODULE'] = 'project.settings'

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

Так как мы все делали от рута, настроим владельцем проекта добавленного в начале пользователя. Право на чтение для www-data необходимо для корректной отдачи статики.

chown u2django:www-data -R /home/u2django/mysite_env
chown u2django:www-data -R /home/u2django/mysite
chmod u=rwx,g=rx,o= -R /home/u2django/mysite

 

Включаем виртуальный хост, и перезагрузка Apache

a2ensite mysite.conf
service apache2 reload

Далее заходим на сайт и проверяем что у нас вышло. Т.к. мы еще не сделали миграции, не подключили бд то скорее все будет ошибка 500. Более подробно об ошибке можно найти тут /home/u2django/mysite/logs в файле error_log.
Если при заходе на сайт висит ошибка доступа 403, то скорее всего что-то не так написали в файле mysite.conf или плохо настроили права chown для пользователя. Надо перепроверить и перезагрузить апач.

 

Далее создаем базу, подключаем ее к проекту, делаем миграции.

Для создания базы зайдем в MySql:

mysql --user=root -p

И создадим новую базу данных и нового пользователя, и добавим пользователю права пользоваться базой:

mysql> CREATE DATABASE mysite_db CHARACTER SET utf8;
Query OK, 1 row affected (0.01 sec)

mysql> CREATE USER mysite_user@localhost IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT ALL ON mysite_db.* TO mysite_user@localhost;
Query OK, 0 rows affected (0.00 sec)

После миграций необходимо выполнить collectstatic — собрать все статичные файлы в папку mysite/staic/

python manage.py collectstatic
yes

Проверяем сайт. Должно все работать. Если выпадает ошибка 500 ну или какая другая, то смотрим файл в логах
/home/u2django/mysite/logs/error_log. Скорее всего там сказано в чем проблема.

 

Ошибки\Проблемы

при выполнении service apache2 reload  вываливается ошибка:
Job for apache2.service failed. See ‘systemctl status apache2.service’ and ‘journalctl -xn’ for details.

Как тут и сказано следует выполнить команду:

systemctl status apache2.service

Среди прочих строчек может присутствовать такая:
Invalid command ‘WSGIScriptAlias’, perhaps misspelled or defined by a module not included in the serv…iguration

Нужно включить wsgi mod в Apache:

sudo a2enmod wsgi

Если при этом появляется ошибка ERROR: Module mod-wsgi does not exist!
Выполнить следующие команды:

apt-get install libapache2-mod-wsgi
a2enmod wsgi
service apache2 restart

Если включение a2enmod wsgi не проканывает, то зайти в папку /etc/apache2/mods-available и посмотреть есть ли там файл wsgi.load, если нет то создать. В файле написать:

LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi.so

предварительно удостоверившись что файл /usr/lib/apache2/modules/mod_wsgi.so существует. У меня вместо него был файл mod_wsgi.so-2.7, поэтому в файле wsgi.load должна быть такая строка:

LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi.so-2.7

 

Еще при выполнении systemctl status apache2.service Среди прочих строчек может присутствовать такая:
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80
— значит чем-то занят 80-й порт.
нужно выполнить команду:

netstat -ltnp | grep :80

если она покажет что-то вроде:

tcp     0   0 0.0.0.0:80     0.0.0.0:*   LISTEN   5784/nginx -g daemo
tcp6    0   0 :::80          :::*        LISTEN   5784/nginx -g daemo

т.е. строки содержащие порт :80.
То нужно убить процессы занимающие этот порт:

kill -9 5784

Конечно удостоверившись что эти процессы точно не нужны. В данном случае мы не используем nginx.

 

Ошибка при добавлении файла-картинки к материалу:

OSError at /admin/core/news/add/
[Errno 13] Permission denied: ‘/home/u2django/mysite/media/news/images/image.jpg’

Значит нет прав на добавление файла в нужную папку. Дадим 770 всем папкам в media:

find /home/u2django/mysite/media/ -type d -exec chmod 770 {} \;

За основу взята статья и видеоурок и еще немного отсюда.