Публикация сайта, созданного на python фреймворке Django, на сервере под Debian.
Был установлен linux Debian 10 (в моем случае на одноплатник Orange Pi PC), проброшены порты 80 и 443 на сервер, получен постоянный ip-адрес у провайдера и привязан к зарегистрированному доменному имени сайта.
Для публикации использовался web-сервер Nginx, WSGI-сервер Gunicorn, certbot для получения, добавления и обновления ssl-сертификата.
Заливка сайта
Все действия далее выполняются под полными правами:
sudo suВ установленном дистрибутиве python уже присутствовал, поэтому использовал его:
python3 --versionPython 3.7.3Если у вас по каким либо причинам отсутствует, установите:
apt-get install python3
apt-get install python3-venvНужно установить web-сервер:
apt-get install nginxДля примера использую заготовку сайта, размещенного на
githab.
Скачивание:
cd /var/www
git clone https://github.com/Virtblch/SiteOnPythonDjango.gitПо завершении в каталоге /var/www появился каталог SiteOnPythonDjango с загруженным сайтом. Далее создаем и запускаем виртуальное python-окружение:
cd SiteOnPythonDjango
python3 -mvenv venv
source ./venv/bin/activateЗаходим в каталог основного приложения (в данном случае "blog"), и в ранее созданном вируальном окружении ставим фреймворк Django:
cd blog
pip install djangoДалее в конфиге приложения необходимо изменить ip-адрес сервера и имя (для возможности доступа через браузер), в моем случае локальный ip-адрес 192.168.11.40, и имя сайта для доступа из внешней сети linux-bash.ru :
nano blog/settings.pyALLOWED_HOSTS = ['192.168.11.40', 'linux-bash.ru']Для проверки запускаем встроенный web-сервер python:
python3 ./manage.py runserver 0.0.0.0:8000И заходим через браузер из локальной сети на сайт:
http://192.168.11.40:8000 Если ок, можно тормозить встроенный сервер ( CTRL+C ) и двигаться дальше.
Теперь ставим
WSGI-сервер Gunicorn:
pip install gunicornУпрощенно говоря, WSGI представляет собой интерфейс между веб-сервером и самим приложением. Он устанавливает стандартное соединение между различными серверами и приложениями (фреймворками), что обеспечивает их взаимозаменяемость в случае необходимости. Теперь для проверки работоспособности можно запустить встроенный в gunicorn web-сервер:
gunicorn --bind 0.0.0.0:8000 blog.wsgiгде blog — это имя (и каталог) основного приложения, в котором лежит конфигурационный файл settings.py.
И также проверяем доступность сайта по адресу http://192.168.11.40:8000 , затем стопим сервер CTRL+C .
* Из-за различия версий python и , соответственно, django (имеющиеся на "боевом" старее) пришлось в коде приложения изменить свежую django-библиотеку "re_path" на прежнюю "url". Если также увидели соответствующую ошибку, то:
nano blog/urls.pyв коде "re_path" изменить на "url",
закоментить "import re_path", раcкоментить "import url" .
Если все ок, то нужно выключить отладочный режим сайта в конфигурационном файле:
nano blog/settings.pyDEBUG = FalseКоманда ниже собирает все статические файлы приложения (включая статические файлы админки) и из любых других папок, которые указаны в settings.py и копирует их в STATIC_ROOT :
python3 ./manage.py collectstaticИ снова проверяем доступность сайта после запуска сервера:
gunicorn --bind 0.0.0.0:8000 blog.wsgiПри отсутствии проблем стопим сервер и виртуальное окружение:
CTRL+CdeactivateДалее прописывам Gunicorn в автозапуск демоном, меняя пользователя, из под которого он будет стартовать (у меня в примере это orangepc, создайте пользователя, добавив его в группу www-data если пользователь еще не создан) и путь к публикуемому приложению (если уже пробуете публиковать свое):
nano /etc/systemd/system/gunicorn.socket[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.targetnano /etc/systemd/system/gunicorn.service[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=orangepc
Group=www-data
WorkingDirectory=/var/www/SiteOnPythonDjango/blog
ExecStart=/var/www/SiteOnPythonDjango/venv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
blog.wsgi:application
[Install]
WantedBy=multi-user.target*workers вычисляется как количество ядер процессора * 2 + 1 .
И даем права на каталог /var/www пользователю и группе:
sudo chown -R www-data:www-data /var/www
sudo usermod -aG www-data orangepc
sudo chmod go-rwx /var/www
sudo chmod go+x /var/www
sudo chgrp -R www-data /var/www
sudo chmod -R go-rwx /var/www
sudo chmod -R g+rwx /var/www*Убираем все разрешения для всех, а потом их назначаем конкретному пользователю и группе.
Затем старт демона и добавление в автостарт:
systemctl start gunicorn.socket
systemctl enable gunicorn.socket*Для применения измениний при последующем редактировании (если например где-то выше ошиблись и исправили):
systemctl daemon-reload
systemctl restart gunicornПроверка:
file /run/gunicorn.sock # Проверка создания сокета
systemctl status gunicorn # Статус демона
curl --unix-socket /run/gunicorn.sock 192.168.11.40 # В выводе должен быть html-код главной страницы сайта
Теперь
настраиваем Nginx
, указывая в конфиге пути к каталогам статичных файлов приложения, возможные имена сайта и использование WSGI-сервера Gunicorn:
nano /etc/nginx/sites-available/defaultserver {
listen 80;
server_name 192.168.11.40 linux-bash.ru;
location = /favicon.ico { access_log off; log_not_found off; }
location static/static/ {
alias /var/www/SiteOnPythonDjango/blog/static/static/;
}
location /static/files/ {
alias /var/www/SiteOnPythonDjango/blog/static/files/;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}Тестируем конфиг:
nginx -tИ, если ок, перезапускаем сервер:
systemctl restart nginxИ снова проверяем доступность сайта.
*Админка сайта в примере доступна по адресу http://<имя сайта>/admin (логин: admin пароль: admin).
На данном этапе сайт должен быть полностью работоспособен по протоколу HTTP.
Теперь настраиваем доступ по HTTPS, добавляя сертификат.
Установим certbot.
Certbot — это программный инструмент с открытым исходным кодом для автоматического использования сертификатов Let’s Encrypt на веб-сайтах для включения HTTPS.
apt-get install certbot python-certbot-nginxЗапуск интерактивной настройки:
certbot run --nginxНеобходимо ответить на вопросы, например указать ваш почтовый адрес, выбрать имя сайта и проч.
Т.к. сертификат выдается на 90 дней, создаем таймер и сервис автообновления сертификата. В данном примере таймер запускает раз в неделю сервис с прописанной командой обновления ключа:
nano /etc/systemd/system/certbot-renewal.service[Unit]
Description=Certbot Renewal
[Service]
ExecStart=/usr/bin/certbot renew --force-renewal --post-hook "systemctl reload nginx.service"nano /etc/systemd/system/certbot-renewal.timer[Unit]
Description=Timer for Certbot Renewal
[Timer]
OnBootSec=300
OnUnitActiveSec=1w
[Install]
WantedBy=multi-user.targetЗапускаем таймер, добавляем в автозагрузку, смотрим статус:
systemctl start certbot-renewal.timer
systemctl enable certbot-renewal.timer
systemctl status certbot-renewal.timerДолжен выпуститься сертификат, сайт должен стать доступен по https://<доменное имя сайта> .
May 29, 2022