/Frishub

Тренировочный Python-Django проект использующий: WebSocket, Celery, Redis, PostgreSQL на бэке и много JavaScript на фронте.

Primary LanguagePython

-> frishub <-

Запуск проекта локально без докера

1) Необходим установленный и запущенный REDIS сервер на пк.

2) Загрузите репозиторий с помощью команды:

git clone https://github.com/Friskes/Frishub.git

3) Создайте виртуальное окружение (необходим Python==3.8 на пк):

py -3.8 -m venv venv

4) Обновите установщик pip:

python.exe -m pip install --upgrade pip

5) Установите зависимости необходимые для работы проекта:

pip install -r requirements.txt

6) Сгенерируйте статические файлы:

python manage.py collectstatic

7) Создайте миграции:

python manage.py makemigrations

8) Выполните миграцию:

python manage.py migrate

9) Создайте супер пользователя:

python manage.py createsuperuser

10) Для запуска проекта, в первой консоли, выполните команду:

python manage.py runserver

11) Для запуска CELERY необходимого для полноценной работы проекта, во второй консоли, выполните команду:

python manage.py runcelery

12) Откройте в браузере проект по адресу:

http://127.0.0.1:8000/

Для остановки программы нажмите сочетание клавиш CTRL+C в обеих консолях.

Запуск проекта локально с докером

1) Загрузите репозиторий с помощью команды:

git clone https://github.com/Friskes/Frishub.git

2) Необходимо создать файл .env в корне проекта с содержимым:

# IF DEPLOY OR DEV WITH DOCKER MUST BE TRUE ELSE FALSE
RUN_DEV_SERVER_WITH_DOCKER=1

PROJECT_NAME=FriskesSite

POSTGRES_DB=db
POSTGRES_USER=db
POSTGRES_PASSWORD=db
POSTGRES_HOST=postgres
POSTGRES_PORT=5432

REDIS_HOST=redis
REDIS_PORT=6379

CELERY_APP=FriskesSite
CELERY_FLOWER_URL_PREFIX=flower
CELERY_FLOWER_ADDRESS=celery-flower
CELERY_FLOWER_PORT=5555

SERVER_HOST=0
SERVER_IP=0

3) Запустите Docker Desktop на пк.

4) Создайте образ и запустите контейнер:

docker compose up --build

5) Создайте супер пользователя (для этого остановите контейнер):

docker compose run wsgiserver python manage.py createsuperuser

6) Снова запустите контейнер:

docker compose up

7) Откройте в браузере проект по адресу:

http://127.0.0.1:8000/

Для остановки программы нажмите сочетание клавиш CTRL+C


Развёртывание проекта на удаленном сервере:

  1. О чём говорится в этом документе
  2. Создание SSH ключа
  3. Установка серверных зависимостей
  4. Публикация проекта на Github
  5. Развёртывание github репозитория на сервере
  6. Создание systemd socket и service файлов для Gunicorn
  7. Дебаг (DEBUGGING)
  8. Установка и настройка Redis
  9. ASGI для размещения Django Channels в качестве отдельного приложения
  10. Развертывание Django Channels с помощью Daphne & Systemd
  11. Запуск daphne.service при загрузке сервера
  12. Настройка домена
  13. Установка Celery
  14. Установка Celery Beat
  15. Установка Celery Flower
  16. Создание суперпользователя
  17. FAQ
  18. References

О чём говорится в этом документе

Обо всём, что связано с публикацией веб-сайта django, оснащенного WebSockets, с использованием Django Channels, а так же о celery, celery beat, celery flower.

Создание SSH ключа

SSH key

Обязательно выберите SSH-ключ для аутентификации вместо пароля. В противном случае хакеры могут взломать пароли для входа на ваш сервер. Использование SSH-ключа намного безопаснее.

Чтобы сгенерировать SSH-ключ откройте командную строку в windows и выполните команду ssh-keygen, вам будет предложено ввести путь по которому будет сохранён сгенерированный ключ, после нажмите enter один раз. Обязательно сохраните резервную копию приватного и публичного ключа.

IP адрес вашего сервера

Запишите где-нибудь IP-адрес вашего сервера. Берётся он на хостинге где вы арендуете сервер. Он понадобится вам в дальнейшем для входа на ваш сервер.

Войдите на сервер с помощью SSH и FTP

Лично мне нравится использовать программу MobaXterm для входа на серверы (она бесплатная). Это здорово, потому что вы можете использовать SSH и FTP из одного окна. Это очень удобно.

SSH Настройки

  1. Установите IP-адрес сервера
  2. Установите root в качестве имени пользователя
  3. Под "Advanced SSH settings":
    1. кликните "use private key" и выберите место, где вы сохранили свой приватный SSH ключ.

Установка серверных зависимостей

Запустите эти команды в SSH-терминале.

passwd Установка пароля для root пользователя.

sudo apt update

sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

sudo -u postgres psql Войти в командную строку БД

CREATE DATABASE frishub_db;

CREATE USER friskes WITH PASSWORD 'пароль';

ALTER ROLE friskes SET client_encoding TO 'utf8';

ALTER ROLE friskes SET default_transaction_isolation TO 'read committed';

ALTER ROLE friskes SET timezone TO 'UTC';

GRANT ALL PRIVILEGES ON DATABASE frishub_db TO friskes;

\q Выйти из командной строки БД

sudo -H pip3 install --upgrade pip

sudo -H pip3 install virtualenv

sudo apt install git-all

sudo apt install libgl1-mesa-glx Устранить проблему с "cv2"

adduser django

Установка другой версии Python ( sudo apt-get install -y make build-essential libssl-dev zlib1g-dev

sudo apt-get install -y libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm

sudo apt-get install -y libncurses5-dev libncursesw5-dev xz-utils tk-dev

su root

cd /opt

wget https://www.python.org/ftp/python/3.8.9/Python-3.8.9.tgz

tar xzvf Python-3.8.9.tgz

cd Python-3.8.9

./configure --enable-optimizations

make

sudo make install )

(проверить какой текущий пользователь можно с помощью команды): id

переходим с root пользователя на friskes su friskes

cd /home/friskes/

mkdir project

cd project

Проверить версию Python в OS python3 -V

( Установить Python самой последней версии которая установлена на сервере в виртуальное окружение virtualenv venv

Либо

Установить Python конкретной версии которая установлена на сервере в виртуальное окружение python3.8 -m venv venv )

source venv/bin/activate В случае необходимости деактивация виртуального окружения происходит с помощью команды: deactivate

Публикация проекта на Github

  1. Войдите в Github.com
  2. Создайте новый репозиторий https://github.com/new
  3. Откройте терминал в вашем локальном каталоге проекта

Выполните эти команды: git init

git add .

git commit -m "init repo"

git remote add origin https://github.com/Friskes/Frishub.git

git push -u origin master

Создайте файл .env в корневом каталоге проекта

WINDOWS_REDIS_INSTALLED=0
# IF DEPLOY OR DEV WITH DOCKER MUST BE TRUE ELSE FALSE
RUN_DEV_SERVER_WITH_DOCKER=1

SECRET_KEY=<секретный_ключ>

# IF LOCAL IP EXISTS THEN START LOCAL SERVER ONLY WITH IT
MY_LOCAL_IPV4_ADDRESS=<ваш_локальный_ip_(не_обязательная_настройка)>

PROJECT_NAME=FriskesSite

POSTGRES_DB=<название бд>
POSTGRES_USER=<никнейм в бд>
POSTGRES_PASSWORD=<пароль в бд>
POSTGRES_HOST=postgres
POSTGRES_PORT=5432

REDIS_HOST=redis
REDIS_PORT=6379

CELERY_APP=FriskesSite
CELERY_FLOWER_URL_PREFIX=flower
CELERY_FLOWER_ADDRESS=celery-flower
CELERY_FLOWER_PORT=5555

SERVER_HOST=<хост сервера>
SERVER_IP=<айпи сервера>

Обновите код в Github после добавления нового файла

git add . git commit -m "add .env" git push origin master

Развёртывание github репозитория на сервере

Откройте MobaXterm и войдите на свой сервер через SSH.

Инициализируйте git в директории в которой будет находится проект git init

Загрузите проект в текущую директорию git pull https://github.com/Friskes/Frishub.git prod

попросит ввести github никнейм владельца репозитория (Friskes) и токен в качестве пароля (при создании токена необходимо указать права для Repository permissions -> Contents -> Read-only) иначе будет выдавать ошибку Токен создаётся здесь: https://github.com/settings/tokens?type=beta Токен надо сохранить куда нибудь локально т.к. он будет требоватся часто

Потребуется залогинится в гите с помощью данных команд git config --global user.name "your_github_username"

git config --global user.email "your_github_email"

Можно сохранить логин + пароль(токен) в store чтобы не вводить их каждый раз заного. источник Необходимо единоразово ввести команду перед исполнением git pull git config --global credential.helper store В будущем этот store можно удалить командами git config --local --unset credential.helper git config --global --unset credential.helper git config --system --unset credential.helper Принтануть store: git config credential.helper

Проверить версию пакетного менеджера pip pip -V

Обновляем пакетный менеджер pip pip install --upgrade pip

Необходимо обязательно удалить файл local_settings.py На сервере должен оставатся только prod_settings.py На локальной машине могут оставатся оба файла.

Не забываем добавить в requirements.txt пару библиотек перед установкой если их нету psycopg2-binary gunicorn

Переходим в директорию с проектом cd FriskesSite

посмотреть список библиотек из файла requirements.txt cat requirements.txt

перед установкой необходимо проверить, если присутствует библиотека twisted-iocpsupport её необходимо убрать перед установкой на линуксе. https://stackoverflow.com/questions/66428469/twisted-iocpsupport-error-when-using-pip-on-ubuntu-debian-io-h-missing

Устанавливаем библиотеки pip install -r requirements.txt

Для работы вебсокета дополнительно необходимо установить библиотеки pip install -U 'Twisted[tls,http2]'

Создаём пустую папку для медиа файлов если она ещё не создана mkdir media

Проверьте, можете ли вы запустить свой проект (Тестовый запуск)

su root

sudo ufw allow 8000

su friskes

source venv/bin/activate

cd FriskesSite

python manage.py makemigrations

python manage.py migrate

python manage.py runserver 0.0.0.0:8000

посетите http://<ваш_серверный_ip>:8000/

Остановить сервер CTRL+C

Может быть такая проблема что не будет нормально грузить static либо media для этого надо выполнить эти команды для диреторий static и media соответственно sudo chown -R www-data:www-data /home/friskes/project/FriskesSite/static

sudo chown -R www-data:www-data /home/friskes/project/FriskesSite/media

sudo chmod -R 777 /home/friskes/project/FriskesSite/static

sudo chmod -R 777 /home/friskes/project/FriskesSite/media

sudo usermod -a -G www-data $(whoami)

Создание systemd socket и service файлов для Gunicorn

Мы провели тест, чтобы узнать, запустится ли приложение, если мы запустим его вручную, но мы хотим, чтобы приложение автоматически запускалось / перезапускалось, когда это необходимо. Например, когда мы перезапускаем сервер или он по какой-то причине выходит из строя.

Один из способов сделать это - с помощью gunicorn. Запустив эту команду, вы увидите, что gunicorn может запускать приложение: gunicorn --bind 0.0.0.0:8000 FriskesSite.wsgi либо gunicorn FriskesSite.wsgi:application --bind 0.0.0.0:8000

посетите http://<ваш_серверный_ip>:8000/

Итак, нам просто нужна служба для запуска этой команды при запуске сервера. Один из способов сделать это - использовать systemd

CTRL+C

Настройте systemd для запуска gunicorn с помощью gunicorn.socket файла

su root

Перейдите в директорию: /etc/systemd/system/

Создайте файл с именем: gunicorn.socket

Добавьте в файл следующее и сохраните:

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Создайте gunicorn service для запуска приложения WSGI (приложение django)

Создайте новый файл: gunicorn.service

Добавьте следующее в gunicorn.service и сохраните. Очень важно скопировать это в точности так, как у меня. Также ваша структура каталогов внутри /home/friskes/ должна быть точно такой же, как у меня. В противном случае этот служебный файл не будет знать, о вашем проекте.

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=friskes
Group=www-data
WorkingDirectory=/home/friskes/project/FriskesSite
ExecStart=/home/friskes/project/venv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          FriskesSite.wsgi:application

[Install]
WantedBy=multi-user.target

sudo systemctl start gunicorn.socket

sudo systemctl enable gunicorn.socket

Полезные команды

  1. sudo systemctl daemon-reload
    • Должно быть выполнено, если вы измените gunicorn.service файл.
  2. sudo systemctl restart gunicorn
    • Если вы меняете код в своём проекте, вы должны выполнить это, чтобы увидеть изменения.
  3. sudo systemctl status gunicorn
    • Проверка статуса gunicorn
  4. sudo shutdown -r now
    • полная перезагрузка сервера
    • Важное замечание, команды начинающиеся на sudo может использовать только root пользователь, соответственно сначало надо перейти в root пользователя с помощью команды su root

проверить версию операционной системы сервера ldd --version

возвращаемся в родительскую директорию cd .. либо cd ~

Очистить консоль clear

Настройте Nginx для передачи прокси-сервера(proxy pass) к Gunicorn

Мы будем использовать Nginx в качестве HTTP-прокси. Это помогает защитить наш веб-сайт от злоумышленников. Вы можете прочитать больше об этом здесьhttps://docs.gunicorn.org/en/stable/deploy.html. Нам нужно настроить Nginx и gunicorn для совместной работы.

Перейдите в директорию: /etc/nginx/sites-available

Создайте файл FriskesSite с таким содержимым:

server {
    listen 80;
    server_name <ваш_серверный_ip>;

    location /static/ {
        root /home/friskes/project/FriskesSite;
    }

    location /media/ {
        root /home/friskes/project/FriskesSite;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

Измените пользователя user в самом начале файла /etc/nginx/nginx.conf на созданного нами пользователя friskes это поможет в обнаружении static/media файлов

Настройте брандмауэр (Firewall)

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

sudo nginx -t

sudo systemctl restart nginx

sudo ufw delete allow 8000

sudo ufw allow 'Nginx Full'

sudo systemctl restart gunicorn

(service gunicorn restart Нет никакой разницы между этими двумя командами sudo systemctl restart gunicorn)

Перезапустите сервер: sudo shutdown -r now

посетите: http://<ваш_серверный_ip>/

Дебаг (DEBUGGING)

Вот несколько команд, которые вы можете использовать для просмотра журналов сервера. Эти команды абсолютно необходимо знать. Если ваш сервер случайно не работает в один прекрасный день, это то, что вы используете для начала отладки.

  1. sudo journalctl это место, куда объединяются все журналы. Обычно я проверяю именно там.
  2. sudo tail -F /var/log/nginx/error.log Просмотр последних записей в журнале ошибок
  3. sudo journalctl -u nginx Журналы процессов Nginx
  4. sudo less /var/log/nginx/access.log Журналы доступа Nginx
  5. sudo less /var/log/nginx/error.log Журналы ошибок Nginx
  6. sudo journalctl -u gunicorn журналы приложений gunicorn
  7. sudo journalctl -u gunicorn.socket проверьте журналы сокетов gunicorn

Логи можно промотать в конец с помощью комбинации клавиш Shift+G Листать логи можно с помощью стрелок на клавиатуре

Просмотр лога в режиме реального времени с флагом -f: tail -f file_name.log

Установка и настройка Redis

Redis используется как своего рода "очередь обмена сообщениями" для Django Channels. Подробнее об этом читайте здесь https://channels.readthedocs.io/en/stable/topics/channel_layers.html?highlight=redis#redis-channel-layer

Для исправления ошибки: "redis.exceptions.ConnectionError: Error 111 connecting to 127.0.0.1:6379. 111." введите команду: sudo ufw allow 6379

sudo apt install redis-server

Перейдите в директорию: /etc/redis/

Откройте файл: redis.conf

Нажмите CTRL+F для поиска supervised no в редакторе

Измените supervised no на supervised systemd и сохраните

sudo systemctl restart redis.service

Подтвердите, что Redis запущен по адресу 127.0.0.1. По умолчанию порт должен быть 6379. sudo systemctl status redis

CTRL+C Для выхода из журнала.

sudo apt install net-tools

sudo netstat -lnp | grep redis

sudo systemctl restart redis.service

ASGI для размещения Django Channels в качестве отдельного приложения

Из документации Django channels:

ASGI (Asynchronous Server Gateway Interface) - это спецификация, на основе которой построены каналы, она предназначенна для отсоединения приложений каналов от конкретного сервера приложений и предоставления общего способа написания кода приложений и промежуточного программного обеспечения.

su friskes

Установите владельца файла cat > asgi.py friskes должен быть владельцем этого файла.

Проверить какие файлы находятся в текущей директории ls

введите ls -l чтобы проверить владельца. friskes должен быть владельцем.

Развертывание Django Channels с помощью Daphne & Systemd

Gunicorn - это то, что мы используем для запуска приложения WSGI, которое является нашим приложением Django. Для запуска приложения ASGI нам нужно что-то еще, дополнительный инструмент. Daphne был создан для каналов Django и является самым простым. Мы можем запустить daphne с помощью службы systemd при загрузке сервера, точно так же, как мы запускаем gunicorn, а затем gunicorn запускает приложение django.

Вот несколько ссылок, которые я нашел полезными. Информация по этому поводу скудна:

  1. https://channels.readthedocs.io/en/latest/deploying.html
  2. https://stackoverflow.com/questions/50192967/deploying-django-channels-how-to-keep-daphne-running-after-exiting-shell-on-web

su root

apt install daphne

Перейдите в /etc/systemd/system/

Создайте daphne.service. Обратите внимание, что порт равен 8001. Это тот же порт как и у нашего WebSocket класса в шаблоне.

[Unit]
Description=WebSocket Daphne Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/home/friskes/project/FriskesSite
ExecStart=/home/friskes/project/venv/bin/python /home/friskes/project/venv/bin/daphne -b 0.0.0.0 -p 8001 FriskesSite.asgi:application
Restart=on-failure

[Install]
WantedBy=multi-user.target

systemctl daemon-reload

systemctl start daphne.service

systemctl status daphne.service

CTRL+C

Запуск daphne.service при загрузке сервера

С помощью gunicorn и приложения WSGI мы создали файл gunicorn.socket, который сообщает gunicorn о запуске при загрузке сервера (по крайней мере, я так понимаю). Я не мог понять, как заставить это работать для daphne, поэтому вместо этого я написал сценарий bash, который будет запускаться при загрузке сервера.

Создайте скрипт для запуска daphne

Перейдите в /root

создайте файл boot.sh и сохраните содержимое

#!/bin/sh
sudo systemctl start daphne.service

Возможно, придется включить его запуск как скрипт (не уверен, нужно ли это) chmod u+x /root/boot.sh

Если вы хотите узнать больше о сценариях bash, я нашел это полезным: https://ostechnix.com/fix-exec-format-error-when-running-scripts-with-run-parts-command/.

Сообщите systemd, чтобы он запустил скрипт bash при загрузке сервера

Перейдите в /etc/systemd/system

создайте файл on_boot.service с содержимым:

[Service]
ExecStart=/bin/bash /root/boot.sh

[Install]
WantedBy=default.target

systemctl daemon-reload

запустите

sudo systemctl start on_boot

Включите его для запуска при загрузке

sudo systemctl enable on_boot

Разрешить обслуживание daphne через брандмауэр (firewall)

ufw allow 8001

перезагрузите сервер

sudo shutdown -r now

Проверьте, запустилась ли служба on_boot при запуске сервера:

systemctl status on_boot.service

можно посмотреть логи sudo journalctl -u on_boot.service

Проверьте, запустилась ли служба daphne при запуске сервера:

systemctl status daphne.service

можно посмотреть логи sudo journalctl -u daphne.service

Проверьте, запустилась ли служба gunicorn при запуске сервера:

systemctl status gunicorn.service

Настройка домена

Если вам нужно пользовательское доменное имя (что, вероятно, делают все), в этом разделе вы узнаете, как это сделать.

Купите домен на любом понравившемся сайте.

Подключите DNS в вашем хостинге

A-запись должна быть равна серверному ip

Добавьте домен в хостинг

Обновить конфигурацию Nginx

Ранее мы настроили Nginx на передачу прокси-сервера(proxy pass) в gunicorn. Нам нужно добавить новый домен в эту конфигурацию.

перейдите в директорию /etc/nginx/sites-available

обновите файл FriskesSite

server {
    listen 80;
    server_name <ваш_домен> www.<ваш_домен> <ваш_серверный_ip>;

    location /static/ {
        root /home/friskes/project/FriskesSite;
    }

    location /media/ {
        root /home/friskes/project/FriskesSite;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

sudo systemctl reload nginx

Убедитесь, что конфигурация nginx по-прежнему в порядке. sudo nginx -t

добавьте новые домены в ALLOWED_HOSTS проекта если не сделали этого ранее

Примените изменения service gunicorn restart

ТЕПЕРЬ ПРИШЛО ВРЕМЯ ПОДОЖДАТЬ...

Может потребоваться некоторое время, чтобы ваш веб-сайт стал доступен в пользовательском домене. Я действительно не знаю, сколько времени это на самом деле займет. Я ждал несколько часов, пока у меня не заработало.

Откуда ты знаешь, что это работает?

Посетив свой домен, вы должны увидеть сообщение Welcome to nginx! ИЛИ вы должны увидеть свой проект вживую и работающим

Вообще обычно процесс занимает не более 24-48 часов, время обновления зависит от интернет-провайдера. Чтобы начать работу над сайтом уже сейчас, пропишите для своего компьютера соответствие адреса и домена в файл hosts по этой инструкции.

HTTPS (Если у вас зарегистрирован домен и он работает)

Не выполняйте этот шаг, если только вы не сможете посетить свой веб-сайт, используя пользовательский домен. Посмотрите: Откуда ты знаешь, что это работает?

Установка certbot

HTTPS немного сложнее настроить при использовании Django Channels. Nginx и Daphne требуют некоторой дополнительной настройки.

sudo apt install certbot python3-certbot-nginx

certbot --version

sudo systemctl reload nginx

Убедитесь, что конфигурация nginx по-прежнему в порядке. sudo nginx -t

Разрешить HTTPS через брандмауэр(firewall)

Если вы не выполняли эту команду ранее - выполните sudo ufw allow 'Nginx Full'

sudo ufw delete allow 'Nginx HTTP' Блокировать стандартный HTTP

Получить SSL-сертификат

sudo certbot --nginx -d <ваш_домен> -d www.<ваш_домен>

Состояние службы отвечающей за авто обновление Certbot для проверки сертификата

sudo systemctl status certbot.timer

протестировать процесс обновления

sudo certbot renew --dry-run

Обновить конфигурацию nginx

Нам нужно сообщить nginx, чтобы он разрешил передачу данных websocket через порт 8001. Я действительно не уверен, как это объяснить. Я не понимаю этого сам до конца. Это работает аналогично тому, как мы разрешаем gunicorn передавать прокси-сервер(proxy pass) nginx.

Перейдите в директорию /etc/nginx/sites-available

обновите FriskesSite

# REDIRECT (www or non-www domain) HTTP TRAFFIC to (www or non-www domain) HTTPS protocol
server {
    listen 80;

    server_name www.<ваш_домен> <ваш_домен>;

    return 301 https://$host$request_uri;
}

# REDIRECT (www domain) HTTPS TRAFFIC to (non-www domain) HTTPS protocol
server {
    listen 443 ssl;

    ssl_certificate /etc/letsencrypt/live/<ваш_домен>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<ваш_домен>/privkey.pem;

    server_name www.<ваш_домен>;

    return 301 $scheme://<ваш_домен>$request_uri;
}

# MAIN (non-www domain) HTTPS protocol HANDLER
server {
    listen 443 ssl;

    ssl_certificate /etc/letsencrypt/live/<ваш_домен>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<ваш_домен>/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    server_name <ваш_домен>;

    client_max_body_size 10M;

    location /static/ {
        root /home/friskes/project/FriskesSite;
    }

    location /media/ {
        root /home/friskes/project/FriskesSite;
    }

    location / {
#        https://stackoverflow.com/a/22027177/19276507
        proxy_set_header Host $host;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass http://unix:/run/gunicorn.sock;
    }

    location /ws/ {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_redirect off;

        proxy_pass http://127.0.0.1:8001;
    }
}

Обновить daphne.service

Расскажите daphne, как получить доступ к нашему сертификату https.

Перейдите в директорию /etc/systemd/system

обновите файл daphne.service

[Unit]
Description=WebSocket Daphne Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/home/friskes/project/FriskesSite
ExecStart=/home/friskes/project/venv/bin/python /home/friskes/project/venv/bin/daphne -e ssl:8001:privateKey=/etc/letsencrypt/live/<ваш_домен>/privkey.pem:certKey=/etc/letsencrypt/live/<ваш_домен>/fullchain.pem FriskesSite.asgi:application
Restart=on-failure

[Install]
WantedBy=multi-user.target

Установка Celery

официальная документация

Обновить установщик apt sudo apt update

Установить celery sudo apt -y install celery

Создать файл celery.service /etc/systemd/system/celery.service

С содержимым:

[Unit]
Description=Celery Service
After=network.target

[Service]
Type=forking
User=friskes
Group=www-data
EnvironmentFile=/etc/conf.d/celery
WorkingDirectory=/home/friskes/project/FriskesSite
ExecStart=/bin/sh -c '${CELERY_BIN} multi start ${CELERYD_NODES} \
  -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \
  --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
ExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait ${CELERYD_NODES} \
  --pidfile=${CELERYD_PID_FILE}'
ExecReload=/bin/sh -c '${CELERY_BIN} multi restart ${CELERYD_NODES} \
  -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \
  --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
Restart=always

[Install]
WantedBy=multi-user.target

Создать директорию conf.d и файл celery внутри /etc/conf.d/celery

С содержимым:

CELERY_APP="FriskesSite"

CELERY_BIN="/home/friskes/project/venv/bin/celery"

CELERYD_NODES="w1"

CELERYD_MULTI="multi"

CELERYD_OPTS="--time-limit=300 --concurrency=8"

CELERYD_PID_FILE="/var/run/celery/%n.pid"

CELERYD_LOG_FILE="/var/log/celery/%n%I.log"

CELERYD_LOG_LEVEL="INFO"


CELERYBEAT_SCHEDULE_FILE="/var/run/celery/celerybeat-schedule"

CELERYBEAT_PID_FILE="/var/run/celery/beat.pid"

CELERYBEAT_LOG_FILE="/var/log/celery/beat.log"


CELERY_FLOWER_URL_PREFIX="flower"

CELERY_FLOWER_LOG_FILE="/var/log/celery/flower.log"

CELERY_FLOWER_ADDRESS="127.0.0.1"

CELERY_FLOWER_PORT="5555"

Создать файл celery.conf /etc/tmpfiles.d/celery.conf

С содержимым:

d /var/run/celery 0755 friskes www-data -
d /var/log/celery 0755 friskes www-data -

Общие команды для Celery, Beat, Flower служб: После изменения файла необходимо перезапустить демона sudo systemctl daemon-reload Установить авто запуск после каждой перезагрузки сервера systemctl enable <название_службы>.service Отключить авто запуск после каждой перезагрузки сервера sudo systemctl disable <название_службы>.service Посмотреть лог sudo journalctl -u <название_службы>.service Проверить состояние sudo systemctl status <название_службы> Остальные команды: sudo systemctl start <название_службы> sudo systemctl stop <название_службы> sudo systemctl restart <название_службы>

Установка Celery Beat

Создать файл celerybeat.service /etc/systemd/system/celerybeat.service

С содержимым:

[Unit]
Description=Celery Beat Service
After=network.target

[Service]
Type=simple
User=friskes
Group=www-data
EnvironmentFile=/etc/conf.d/celery
WorkingDirectory=/home/friskes/project/FriskesSite
ExecStart=/bin/sh -c '${CELERY_BIN} -A ${CELERY_APP} beat \
  -s ${CELERYBEAT_SCHEDULE_FILE} \
  --pidfile=${CELERYBEAT_PID_FILE} \
  --logfile=${CELERYBEAT_LOG_FILE} \
  --loglevel=${CELERYD_LOG_LEVEL}'
Restart=always

[Install]
WantedBy=multi-user.target

Установка Celery Flower

Создать файл celeryflower.service /etc/systemd/system/celeryflower.service

С содержимым:

[Unit]
Description=Flower Celery Service
After=network.target

[Service]
User=friskes
Group=www-data
EnvironmentFile=/etc/conf.d/celery
WorkingDirectory=/home/friskes/project/FriskesSite
ExecStart=/bin/sh -c '${CELERY_BIN} -A ${CELERY_APP} flower \
  --url_prefix=${CELERY_FLOWER_URL_PREFIX} --port=${CELERY_FLOWER_PORT} \
  --address=${CELERY_FLOWER_ADDRESS} \
  --log-file-prefix=${CELERY_FLOWER_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL}'
Restart=on-failure
Type=simple

[Install]
WantedBy=multi-user.target

Создание суперпользователя

Перед тестированием сервера необходимо создать суперпользователя.

su friskes

cd /home/friskes/project/

source venv/bin/activate

cd FriskesSite

python manage.py createsuperuser

Перезагрузите сервер и зайдите на свой веб-сайт, чтобы опробовать его. Теперь все должно работать.

Спасибо за чтение и не стесняйтесь вносить свой вклад в этот документ, если у вас есть лучший способ объяснить происходящее. Я ни в коем случае не являюсь веб-экспертом.

FAQ

Вот некоторые вещи, которые я хотел бы знать, когда делал это в первый раз.

Если вы изменяете файл или обновляете код в проекте, нужно ли вам что-либо делать?

Да.

Если вы изменяете только код, который не связан с django channels, то вам нужно запустить только: service gunicorn restart

Но если вы измените какой-либо код, связанный с django channels, тогда вы также должны перезапустить службу daphne: service daphne restart

На всякий случай я всегда просто запускаю и то, и другое. Это не может повредить.

Команды для проверки статусов сервисов

На протяжении всего этого документа мы периодически проверяем статус настроенных нами сервисов. Такие вещи, как:

  1. sudo systemctl status gunicorn
  2. sudo systemctl status redis
  3. systemctl status daphne.service
  4. systemctl status on_boot.service
  5. sudo systemctl status certbot.timer

Команды NGINX

Посмотреть статус nginx

  1. sudo systemctl status nginx Остановить nginx (до первой перезагрузки сервера)
  2. sudo systemctl stop nginx Запустить nginx
  3. sudo systemctl start nginx Автоматическая остановка а затем запуск nginx
  4. sudo systemctl reload nginx

Отключить автоматический запуск nginx после перезагрузки сервера

  1. sudo systemctl disable nginx Включить автоматический запуск nginx после перезагрузки сервера
  2. sudo systemctl enable nginx

Если что-либо из этого не сработает, значит, вы сделали что-то не так. Наиболее распространенная проблема заключается в том, что структура каталогов не совпадает. Например, вы могли бы использовать /home/friskes/project/неправильное_название_проекта/ вместо /home/friskes/project/FriskesSite/. Вам нужно очень внимательно изучить структуру ваших каталогов и убедиться, что все названия указаны правильно и соотносятся с .service файлами, которые вы создали.

Когда вы вносите изменения в .service файл, Всегда выполняйте команду sudo systemctl daemon-reload. Или на всякий случай просто перезапустите этот чертов сервер sudo shutdown -r now. Перезапуск сервера - это безопасный способ, но и самый медленный.

Получить информацию об оперативной памяти

Команда: free -h Вызвать программу диспетчер задач инструкция Команда открытия диспетчере: top Выйти кнопкой q Команды Shift + < и Shift + > меняют столбец по которому сортируются строки в диспетчере

Покажет использование памяти процессами: ps aux | awk '{print $6/1024 " MB\t\t" $11}' | sort -n

References

  1. https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-18-04
  2. https://channels.readthedocs.io/en/latest/
  3. https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-20-04
  4. https://www.digitalocean.com/community/tutorials/how-to-set-up-object-storage-with-django
  5. https://stackoverflow.com/questions/61101278/how-to-run-daphne-and-gunicorn-at-the-same-time
  6. conda-forge/pygridgen-feedstock#10
  7. https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04