{"id":17005954,"url":"https://github.com/friskes/frishub","last_synced_at":"2025-04-19T15:17:35.803Z","repository":{"id":191384864,"uuid":"638678425","full_name":"Friskes/Frishub","owner":"Friskes","description":"Тренировочный Python-Django проект использующий: WebSocket, Celery, Redis, PostgreSQL на бэке и много JavaScript на фронте.","archived":false,"fork":false,"pushed_at":"2024-04-06T10:06:10.000Z","size":10785,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-21T05:44:57.779Z","etag":null,"topics":["celery","django","javascript","postgresql","python","redis","websocket"],"latest_commit_sha":null,"homepage":"https://frishub.ru","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Friskes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-05-09T21:41:58.000Z","updated_at":"2024-06-25T22:32:27.000Z","dependencies_parsed_at":"2023-10-26T15:01:59.134Z","dependency_job_id":"344a1f82-db25-43b7-a171-c098b6faf52d","html_url":"https://github.com/Friskes/Frishub","commit_stats":null,"previous_names":["friskes/frishub"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Friskes%2FFrishub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Friskes%2FFrishub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Friskes%2FFrishub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Friskes%2FFrishub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Friskes","download_url":"https://codeload.github.com/Friskes/Frishub/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226986659,"owners_count":17713649,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["celery","django","javascript","postgresql","python","redis","websocket"],"created_at":"2024-10-14T05:04:37.451Z","updated_at":"2024-11-28T21:04:13.334Z","avatar_url":"https://github.com/Friskes.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e-\u003e \u003ca href=\"https://frishub.ru\" target=\"_BLANK\"\u003efrishub\u003c/a\u003e \u003c-\u003c/h1\u003e\n\n## Запуск проекта локально без докера\n\n#### 1) Необходим установленный и запущенный \u003ca href=\"https://github.com/tporadowski/redis\" target=\"_BLANK\"\u003eREDIS\u003c/a\u003e сервер на пк.\n\n#### 2) Загрузите репозиторий с помощью команды:\n    git clone https://github.com/Friskes/Frishub.git\n\n#### 3) Создайте виртуальное окружение (необходим Python==3.8 на пк):\n    py -3.8 -m venv venv\n\n#### 4) Обновите установщик pip:\n    python.exe -m pip install --upgrade pip\n\n#### 5) Установите зависимости необходимые для работы проекта:\n    pip install -r requirements.txt\n\n#### 6) Сгенерируйте статические файлы:\n    python manage.py collectstatic\n\n#### 7) Создайте миграции:\n    python manage.py makemigrations\n\n#### 8) Выполните миграцию:\n    python manage.py migrate\n\n#### 9) Создайте супер пользователя:\n    python manage.py createsuperuser\n\n#### 10) Для запуска проекта, в первой консоли, выполните команду:\n    python manage.py runserver\n\n#### 11) Для запуска CELERY необходимого для полноценной работы проекта, во второй консоли, выполните команду:\n    python manage.py runcelery\n\n#### 12) Откройте в браузере проект по адресу:\n    http://127.0.0.1:8000/\n\n#### Для остановки программы нажмите сочетание клавиш CTRL+C в обеих консолях.\n\n## Запуск проекта локально с докером\n\n#### 1) Загрузите репозиторий с помощью команды:\n    git clone https://github.com/Friskes/Frishub.git\n\n#### 2) Необходимо создать файл `.env` в корне проекта с содержимым:\n\n```\n# IF DEPLOY OR DEV WITH DOCKER MUST BE TRUE ELSE FALSE\nRUN_DEV_SERVER_WITH_DOCKER=1\n\nPROJECT_NAME=FriskesSite\n\nPOSTGRES_DB=db\nPOSTGRES_USER=db\nPOSTGRES_PASSWORD=db\nPOSTGRES_HOST=postgres\nPOSTGRES_PORT=5432\n\nREDIS_HOST=redis\nREDIS_PORT=6379\n\nCELERY_APP=FriskesSite\nCELERY_FLOWER_URL_PREFIX=flower\nCELERY_FLOWER_ADDRESS=celery-flower\nCELERY_FLOWER_PORT=5555\n\nSERVER_HOST=0\nSERVER_IP=0\n```\n\n#### 3) Запустите Docker Desktop на пк.\n\n#### 4) Создайте образ и запустите контейнер:\n    docker compose up --build\n\n#### 5) Создайте супер пользователя (для этого остановите контейнер):\n    docker compose run wsgiserver python manage.py createsuperuser\n\n#### 6) Снова запустите контейнер:\n    docker compose up\n\n#### 7) Откройте в браузере проект по адресу:\n    http://127.0.0.1:8000/\n\n#### Для остановки программы нажмите сочетание клавиш CTRL+C\n\u003cbr\u003e\n\n\u003e # Развёртывание проекта на удаленном сервере:\n\n1. [О чём говорится в этом документе](#О-чём-говорится-в-этом-документе)\n1. [Создание SSH ключа](#Создание-SSH-ключа)\n1. [Установка серверных зависимостей](#Установка-серверных-зависимостей)\n1. [Публикация проекта на Github](#Публикация-проекта-на-Github)\n1. [Развёртывание github репозитория на сервере](#Развёртывание-github-репозитория-на-сервере)\n1. [Создание systemd socket и service файлов для Gunicorn](#Создание-systemd-socket-и-service-файлов-для-Gunicorn)\n1. [Дебаг (DEBUGGING)](#Дебаг-(DEBUGGING))\n1. [Установка и настройка Redis](#Установка-и-настройка-Redis)\n1. [ASGI для размещения Django Channels в качестве отдельного приложения](#ASGI-для-размещения-Django-Channels-в-качестве-отдельного-приложения)\n1. [Развертывание Django Channels с помощью Daphne \u0026 Systemd](#Развертывание-Django-Channels-с-помощью-Daphne-\u0026-Systemd)\n1. [Запуск daphne.service при загрузке сервера](#Запуск-daphne.service-при-загрузке-сервера)\n1. [Настройка домена](#Настройка-домена)\n1. [Установка Celery](#Установка-Celery)\n1. [Установка Celery Beat](#Установка-Celery-Beat)\n1. [Установка Celery Flower](#Установка-Celery-Flower)\n1. [Создание суперпользователя](#Создание-суперпользователя)\n1. [FAQ](#FAQ)\n1. [References](#References)\n\n# О чём говорится в этом документе\nОбо всём, что связано с публикацией веб-сайта django, оснащенного WebSockets, с использованием Django Channels,\nа так же о celery, celery beat, celery flower.\n\n# Создание SSH ключа\n#### SSH key\nОбязательно выберите SSH-ключ для аутентификации вместо пароля. В противном случае хакеры могут взломать пароли для входа на ваш сервер. Использование SSH-ключа намного безопаснее.\n\nЧтобы сгенерировать SSH-ключ откройте командную строку в windows и выполните команду `ssh-keygen`, вам будет предложено ввести путь по которому будет сохранён сгенерированный ключ, после нажмите enter один раз. **Обязательно сохраните резервную копию приватного и публичного ключа**.\n\n#### IP адрес вашего сервера\nЗапишите где-нибудь IP-адрес вашего сервера. Берётся он на хостинге где вы арендуете сервер. Он понадобится вам в дальнейшем для входа на ваш сервер.\n\n# Войдите на сервер с помощью SSH и FTP\nЛично мне нравится использовать программу [MobaXterm](https://mobaxterm.mobatek.net/) для входа на серверы (она бесплатная). Это здорово, потому что вы можете использовать SSH и FTP из одного окна. Это очень удобно.\n\n#### SSH Настройки\n1. Установите IP-адрес сервера\n1. Установите `root` в качестве имени пользователя\n1. Под \"Advanced SSH settings\":\n    1. кликните \"use private key\" и выберите место, где вы сохранили свой приватный SSH ключ.\n\n# Установка серверных зависимостей\nЗапустите эти команды в SSH-терминале.\n\n`passwd` Установка пароля для root пользователя.\n\n`sudo apt update`\n\n`sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl`\n\n`sudo -u postgres psql` Войти в командную строку БД\n\n`CREATE DATABASE frishub_db;`\n\n`CREATE USER friskes WITH PASSWORD 'пароль';`\n\n`ALTER ROLE friskes SET client_encoding TO 'utf8';`\n\n`ALTER ROLE friskes SET default_transaction_isolation TO 'read committed';`\n\n`ALTER ROLE friskes SET timezone TO 'UTC';`\n\n`GRANT ALL PRIVILEGES ON DATABASE frishub_db TO friskes;`\n\n`\\q` Выйти из командной строки БД\n\n`sudo -H pip3 install --upgrade pip`\n\n`sudo -H pip3 install virtualenv`\n\n`sudo apt install git-all`\n\n`sudo apt install libgl1-mesa-glx` Устранить проблему с \"cv2\"\n\n`adduser django`\n\nУстановка другой версии Python\n(\n`sudo apt-get install -y make build-essential libssl-dev zlib1g-dev`\n\n`sudo apt-get install -y libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm`\n\n`sudo apt-get install -y libncurses5-dev  libncursesw5-dev xz-utils tk-dev`\n\n`su root`\n\n`cd /opt`\n\n`wget https://www.python.org/ftp/python/3.8.9/Python-3.8.9.tgz`\n\n`tar xzvf Python-3.8.9.tgz`\n\n`cd Python-3.8.9`\n\n`./configure --enable-optimizations`\n\n`make`\n\n`sudo make install`\n)\n\n(проверить какой текущий пользователь можно с помощью команды): `id`\n\nпереходим с root пользователя на friskes\n`su friskes`\n\n`cd /home/friskes/`\n\n`mkdir project`\n\n`cd project`\n\nПроверить версию Python в OS\n`python3 -V`\n\n(\nУстановить Python самой последней версии которая установлена на сервере в виртуальное окружение\n`virtualenv venv`\n\nЛибо\n\nУстановить Python конкретной версии которая установлена на сервере в виртуальное окружение\n`python3.8 -m venv venv`\n)\n\n`source venv/bin/activate`\nВ случае необходимости деактивация виртуального окружения происходит с помощью команды: `deactivate`\n\n\n# Публикация проекта на Github\n1. Войдите в Github.com\n1. Создайте новый репозиторий [https://github.com/new](https://github.com/new)\n1. Откройте терминал в вашем локальном каталоге проекта\n\nВыполните эти команды:\n`git init`\n\n`git add .`\n\n`git commit -m \"init repo\"`\n\n`git remote add origin https://github.com/Friskes/Frishub.git`\n\n`git push -u origin master`\n\n#### Создайте файл .env в корневом каталоге проекта\n```\nWINDOWS_REDIS_INSTALLED=0\n# IF DEPLOY OR DEV WITH DOCKER MUST BE TRUE ELSE FALSE\nRUN_DEV_SERVER_WITH_DOCKER=1\n\nSECRET_KEY=\u003cсекретный_ключ\u003e\n\n# IF LOCAL IP EXISTS THEN START LOCAL SERVER ONLY WITH IT\nMY_LOCAL_IPV4_ADDRESS=\u003cваш_локальный_ip_(не_обязательная_настройка)\u003e\n\nPROJECT_NAME=FriskesSite\n\nPOSTGRES_DB=\u003cназвание бд\u003e\nPOSTGRES_USER=\u003cникнейм в бд\u003e\nPOSTGRES_PASSWORD=\u003cпароль в бд\u003e\nPOSTGRES_HOST=postgres\nPOSTGRES_PORT=5432\n\nREDIS_HOST=redis\nREDIS_PORT=6379\n\nCELERY_APP=FriskesSite\nCELERY_FLOWER_URL_PREFIX=flower\nCELERY_FLOWER_ADDRESS=celery-flower\nCELERY_FLOWER_PORT=5555\n\nSERVER_HOST=\u003cхост сервера\u003e\nSERVER_IP=\u003cайпи сервера\u003e\n```\n\n#### Обновите код в Github после добавления нового файла\n`git add .`\n`git commit -m \"add .env\"`\n`git push origin master`\n\n# Развёртывание github репозитория на сервере\nОткройте MobaXterm и войдите на свой сервер через SSH.\n\nИнициализируйте git в директории в которой будет находится проект\n`git init`\n\nЗагрузите проект в текущую директорию\n`git pull https://github.com/Friskes/Frishub.git prod`\n\nпопросит ввести github никнейм владельца репозитория (Friskes) и токен в качестве пароля\n(при создании токена необходимо указать права для Repository permissions -\u003e Contents -\u003e Read-only) иначе будет выдавать ошибку\nТокен создаётся здесь: https://github.com/settings/tokens?type=beta\nТокен надо сохранить куда нибудь локально т.к. он будет требоватся часто\n\nПотребуется залогинится в гите с помощью данных команд\n`git config --global user.name \"your_github_username\"`\n\n`git config --global user.email \"your_github_email\"`\n\nМожно сохранить логин + пароль(токен) в store чтобы не вводить их каждый раз заного. [источник](https://stackoverflow.com/questions/68775869/message-support-for-password-authentication-was-removed-please-use-a-personal`)\nНеобходимо единоразово ввести команду перед исполнением git pull\n`git config --global credential.helper store`\nВ будущем этот store можно удалить командами\n`git config --local --unset credential.helper`\n`git config --global --unset credential.helper`\n`git config --system --unset credential.helper`\nПринтануть store: `git config credential.helper`\n\nПроверить версию пакетного менеджера pip\n`pip -V`\n\nОбновляем пакетный менеджер pip\n`pip install --upgrade pip`\n\nНеобходимо обязательно удалить файл local_settings.py\nНа сервере должен оставатся только prod_settings.py\nНа локальной машине могут оставатся оба файла.\n\nНе забываем добавить в requirements.txt пару библиотек перед установкой если их нету\n`psycopg2-binary`\n`gunicorn`\n\nПереходим в директорию с проектом\n`cd FriskesSite`\n\nпосмотреть список библиотек из файла requirements.txt\n`cat requirements.txt`\n\nперед установкой необходимо проверить, если присутствует библиотека\n`twisted-iocpsupport`\nеё необходимо убрать перед установкой на линуксе.\nhttps://stackoverflow.com/questions/66428469/twisted-iocpsupport-error-when-using-pip-on-ubuntu-debian-io-h-missing\n\nУстанавливаем библиотеки\n`pip install -r requirements.txt`\n\nДля работы вебсокета дополнительно необходимо установить библиотеки\n`pip install -U 'Twisted[tls,http2]'`\n\nСоздаём пустую папку для медиа файлов если она ещё не создана\n`mkdir media`\n\n## Проверьте, можете ли вы запустить свой проект (Тестовый запуск)\n`su root`\n\n`sudo ufw allow 8000`\n\n`su friskes`\n\n`source venv/bin/activate`\n\n`cd FriskesSite`\n\n`python manage.py makemigrations`\n\n`python manage.py migrate`\n\n`python manage.py runserver 0.0.0.0:8000`\n\nпосетите [http://\u003cваш_серверный_ip\u003e:8000/](http://\u003cваш_серверный_ip\u003e:8000/)\n\nОстановить сервер\n`CTRL+C`\n\nМожет быть такая проблема что не будет нормально грузить static либо media\nдля этого надо выполнить эти команды для диреторий static и media соответственно\n`sudo chown -R www-data:www-data /home/friskes/project/FriskesSite/static`\n\n`sudo chown -R www-data:www-data /home/friskes/project/FriskesSite/media`\n\n`sudo chmod -R 777 /home/friskes/project/FriskesSite/static`\n\n`sudo chmod -R 777 /home/friskes/project/FriskesSite/media`\n\n`sudo usermod -a -G www-data $(whoami)`\n\n# Создание systemd socket и service файлов для Gunicorn\nМы провели тест, чтобы узнать, запустится ли приложение, если мы запустим его вручную, но мы хотим, чтобы приложение автоматически запускалось / перезапускалось, когда это необходимо. Например, когда мы перезапускаем сервер или он по какой-то причине выходит из строя.\n\nОдин из способов сделать это - с помощью gunicorn. Запустив эту команду, вы увидите, что gunicorn может запускать приложение:\n`gunicorn --bind 0.0.0.0:8000 FriskesSite.wsgi`\nлибо\n`gunicorn FriskesSite.wsgi:application --bind 0.0.0.0:8000`\n\nпосетите [http://\u003cваш_серверный_ip\u003e:8000/](http://\u003cваш_серверный_ip\u003e:8000/)\n\nИтак, нам просто нужна служба для запуска этой команды при запуске сервера. Один из способов сделать это - использовать [systemd](https://en.wikipedia.org/wiki/Systemd)\n\n`CTRL+C`\n\n#### Настройте systemd для запуска gunicorn с помощью `gunicorn.socket` файла\n\n`su root`\n\nПерейдите в директорию: `/etc/systemd/system/`\n\nСоздайте файл с именем: `gunicorn.socket`\n\nДобавьте в файл следующее и сохраните:\n\n```\n[Unit]\nDescription=gunicorn socket\n\n[Socket]\nListenStream=/run/gunicorn.sock\n\n[Install]\nWantedBy=sockets.target\n```\n\n#### Создайте gunicorn service для запуска приложения WSGI (приложение django)\nСоздайте новый файл: `gunicorn.service`\n\nДобавьте следующее в `gunicorn.service` и сохраните. **Очень важно скопировать это в точности так, как у меня. Также ваша структура каталогов внутри /home/friskes/ должна быть точно такой же, как у меня. В противном случае этот служебный файл не будет знать, о вашем проекте.**\n\n```\n[Unit]\nDescription=gunicorn daemon\nRequires=gunicorn.socket\nAfter=network.target\n\n[Service]\nUser=friskes\nGroup=www-data\nWorkingDirectory=/home/friskes/project/FriskesSite\nExecStart=/home/friskes/project/venv/bin/gunicorn \\\n          --access-logfile - \\\n          --workers 3 \\\n          --bind unix:/run/gunicorn.sock \\\n          FriskesSite.wsgi:application\n\n[Install]\nWantedBy=multi-user.target\n```\n\n`sudo systemctl start gunicorn.socket`\n\n`sudo systemctl enable gunicorn.socket`\n\n#### Полезные команды\n1. `sudo systemctl daemon-reload`\n    - Должно быть выполнено, если вы измените `gunicorn.service` файл.\n1. `sudo systemctl restart gunicorn`\n    - Если вы меняете код в своём проекте, вы должны выполнить это, чтобы увидеть изменения.\n1. `sudo systemctl status gunicorn`\n    - Проверка статуса gunicorn\n1. `sudo shutdown -r now`\n    - полная перезагрузка сервера\n    - Важное замечание, команды начинающиеся на sudo может использовать только root пользователь, соответственно сначало надо перейти в root пользователя с помощью команды `su root`\n\nпроверить версию операционной системы сервера\n`ldd --version`\n\nвозвращаемся в родительскую директорию\n`cd ..`\nлибо\n`cd ~`\n\nОчистить консоль\n`clear`\n\n#### Настройте Nginx для передачи прокси-сервера(proxy pass) к Gunicorn\n\u003e Мы будем использовать Nginx в качестве HTTP-прокси. Это помогает защитить наш веб-сайт от злоумышленников. Вы можете прочитать больше об этом здесь[https://docs.gunicorn.org/en/stable/deploy.html](https://docs.gunicorn.org/en/stable/deploy.html). Нам нужно настроить Nginx и gunicorn для совместной работы.\n\nПерейдите в директорию: `/etc/nginx/sites-available`\n\nСоздайте файл `FriskesSite` с таким содержимым:\n\n```\nserver {\n    listen 80;\n    server_name \u003cваш_серверный_ip\u003e;\n\n    location /static/ {\n        root /home/friskes/project/FriskesSite;\n    }\n\n    location /media/ {\n        root /home/friskes/project/FriskesSite;\n    }\n\n    location / {\n        include proxy_params;\n        proxy_pass http://unix:/run/gunicorn.sock;\n    }\n}\n```\n\nИзмените пользователя `user` в самом начале файла `/etc/nginx/nginx.conf` на созданного нами пользователя friskes\nэто поможет в обнаружении static/media файлов\n\n\n#### Настройте брандмауэр (Firewall)\n`sudo ln -s /etc/nginx/sites-available/FriskesSite /etc/nginx/sites-enabled`\n\n`sudo nginx -t`\n\n`sudo systemctl restart nginx`\n\n`sudo ufw delete allow 8000`\n\n`sudo ufw allow 'Nginx Full'`\n\n`sudo systemctl restart gunicorn`\n\n(`service gunicorn restart` Нет никакой разницы между этими двумя командами `sudo systemctl restart gunicorn`)\n\nПерезапустите сервер: `sudo shutdown -r now`\n\nпосетите: [http://\u003cваш_серверный_ip\u003e/](http://\u003cваш_серверный_ip\u003e/)\n\n# Дебаг (DEBUGGING)\nВот несколько команд, которые вы можете использовать для просмотра журналов сервера. **Эти команды абсолютно необходимо знать.** Если ваш сервер случайно не работает в один прекрасный день, это то, что вы используете для начала отладки.\n1. `sudo journalctl` это место, куда объединяются все журналы. Обычно я проверяю именно там.\n1. `sudo tail -F /var/log/nginx/error.log` Просмотр последних записей в журнале ошибок\n1. `sudo journalctl -u nginx` Журналы процессов Nginx\n1. `sudo less /var/log/nginx/access.log` Журналы доступа Nginx\n1. `sudo less /var/log/nginx/error.log` Журналы ошибок Nginx\n1. `sudo journalctl -u gunicorn` журналы приложений gunicorn\n1. `sudo journalctl -u gunicorn.socket` проверьте журналы сокетов gunicorn\n\nЛоги можно промотать в конец с помощью комбинации клавиш Shift+G\nЛистать логи можно с помощью стрелок на клавиатуре\n\nПросмотр лога в режиме реального времени с флагом `-f`:\n`tail -f file_name.log`\n\n\n# Установка и настройка Redis\nRedis используется как своего рода \"очередь обмена сообщениями\" для Django Channels. Подробнее об этом читайте здесь [https://channels.readthedocs.io/en/stable/topics/channel_layers.html?highlight=redis#redis-channel-layer](https://channels.readthedocs.io/en/stable/topics/channel_layers.html?highlight=redis#redis-channel-layer)\n\nДля исправления ошибки: \"redis.exceptions.ConnectionError: Error 111 connecting to 127.0.0.1:6379. 111.\" введите команду:\n`sudo ufw allow 6379`\n\n`sudo apt install redis-server`\n\nПерейдите в директорию: `/etc/redis/`\n\nОткройте файл: `redis.conf`\n\nНажмите `CTRL+F` для поиска `supervised no` в редакторе\n\nИзмените `supervised no` на `supervised systemd` и сохраните\n\n`sudo systemctl restart redis.service`\n\nПодтвердите, что Redis запущен по адресу 127.0.0.1. По умолчанию порт должен быть 6379.\n`sudo systemctl status redis`\n\n`CTRL+C` Для выхода из журнала.\n\n`sudo apt install net-tools`\n\n`sudo netstat -lnp | grep redis`\n\n`sudo systemctl restart redis.service`\n\n# ASGI для размещения Django Channels в качестве отдельного приложения\nИз документации Django channels:\n\u003e ASGI (Asynchronous Server Gateway Interface) - это спецификация, на основе которой построены каналы, она предназначенна для отсоединения приложений каналов от конкретного сервера приложений и предоставления общего способа написания кода приложений и промежуточного программного обеспечения.\n\n`su friskes`\n\nУстановите владельца файла\n`cat \u003e asgi.py`\nfriskes должен быть владельцем этого файла.\n\nПроверить какие файлы находятся в текущей директории\n`ls`\n\nвведите `ls -l` чтобы проверить владельца. friskes должен быть владельцем.\n\n# Развертывание Django Channels с помощью Daphne \u0026 Systemd\n\u003e Gunicorn - это то, что мы используем для запуска приложения WSGI, которое является нашим приложением Django. Для запуска приложения ASGI нам нужно что-то еще, дополнительный инструмент. **[Daphne](https://github.com/django/daphne)** был создан для каналов Django и является самым простым. Мы можем запустить daphne с помощью службы systemd при загрузке сервера, точно так же, как мы запускаем gunicorn, а затем gunicorn запускает приложение django.\n\nВот несколько ссылок, которые я нашел полезными. Информация по этому поводу скудна:\n1. [https://channels.readthedocs.io/en/latest/deploying.html](https://channels.readthedocs.io/en/latest/deploying.html)\n1. [https://stackoverflow.com/questions/50192967/deploying-django-channels-how-to-keep-daphne-running-after-exiting-shell-on-web](https://stackoverflow.com/questions/50192967/deploying-django-channels-how-to-keep-daphne-running-after-exiting-shell-on-web)\n\n`su root`\n\n`apt install daphne`\n\nПерейдите в `/etc/systemd/system/`\n\nСоздайте `daphne.service`. Обратите внимание, что порт равен `8001`. Это тот же порт как и у нашего `WebSocket` класса в шаблоне.\n\n```\n[Unit]\nDescription=WebSocket Daphne Service\nAfter=network.target\n\n[Service]\nType=simple\nUser=root\nWorkingDirectory=/home/friskes/project/FriskesSite\nExecStart=/home/friskes/project/venv/bin/python /home/friskes/project/venv/bin/daphne -b 0.0.0.0 -p 8001 FriskesSite.asgi:application\nRestart=on-failure\n\n[Install]\nWantedBy=multi-user.target\n```\n\n`systemctl daemon-reload`\n\n`systemctl start daphne.service`\n\n`systemctl status daphne.service`\n\n`CTRL+C`\n\n# Запуск daphne.service при загрузке сервера\n\u003e С помощью gunicorn и приложения WSGI мы создали файл `gunicorn.socket`, который сообщает gunicorn о запуске при загрузке сервера (по крайней мере, я так понимаю). Я не мог понять, как заставить это работать для daphne, поэтому вместо этого я написал сценарий bash, который будет запускаться при загрузке сервера.\n\n#### Создайте скрипт для запуска daphne\nПерейдите в `/root`\n\nсоздайте файл `boot.sh` и сохраните содержимое\n\n```\n#!/bin/sh\nsudo systemctl start daphne.service\n```\n\nВозможно, придется включить его запуск как скрипт (не уверен, нужно ли это)\n`chmod u+x /root/boot.sh`\n\nЕсли вы хотите узнать больше о сценариях bash, я нашел это полезным:\n[https://ostechnix.com/fix-exec-format-error-when-running-scripts-with-run-parts-command/](https://ostechnix.com/fix-exec-format-error-when-running-scripts-with-run-parts-command/).\n\n#### Сообщите systemd, чтобы он запустил скрипт bash при загрузке сервера\n\nПерейдите в `/etc/systemd/system`\n\nсоздайте файл `on_boot.service` с содержимым:\n\n```\n[Service]\nExecStart=/bin/bash /root/boot.sh\n\n[Install]\nWantedBy=default.target\n```\n\n`systemctl daemon-reload`\n\n##### запустите\n`sudo systemctl start on_boot`\n\n##### Включите его для запуска при загрузке\n`sudo systemctl enable on_boot`\n\n##### Разрешить обслуживание daphne через брандмауэр (firewall)\n`ufw allow 8001`\n\n##### перезагрузите сервер\n`sudo shutdown -r now`\n\n##### Проверьте, запустилась ли служба on_boot при запуске сервера:\n`systemctl status on_boot.service`\n\nможно посмотреть логи\n`sudo journalctl -u on_boot.service`\n\n##### Проверьте, запустилась ли служба daphne при запуске сервера:\n`systemctl status daphne.service`\n\nможно посмотреть логи\n`sudo journalctl -u daphne.service`\n\n##### Проверьте, запустилась ли служба gunicorn при запуске сервера:\n`systemctl status gunicorn.service`\n\n# Настройка домена\nЕсли вам нужно пользовательское доменное имя (что, вероятно, делают все), в этом разделе вы узнаете, как это сделать.\n\n#### Купите домен на любом понравившемся сайте.\n\n#### Подключите DNS в вашем хостинге\nA-запись должна быть равна серверному ip\n\n#### Добавьте домен в хостинг\n\n#### Обновить конфигурацию Nginx\nРанее мы настроили Nginx на передачу прокси-сервера(proxy pass) в gunicorn. Нам нужно добавить новый домен в эту конфигурацию.\n\nперейдите в директорию `/etc/nginx/sites-available`\n\nобновите файл `FriskesSite`\n\n```\nserver {\n    listen 80;\n    server_name \u003cваш_домен\u003e www.\u003cваш_домен\u003e \u003cваш_серверный_ip\u003e;\n\n    location /static/ {\n        root /home/friskes/project/FriskesSite;\n    }\n\n    location /media/ {\n        root /home/friskes/project/FriskesSite;\n    }\n\n    location / {\n        include proxy_params;\n        proxy_pass http://unix:/run/gunicorn.sock;\n    }\n}\n```\n\n`sudo systemctl reload nginx`\n\nУбедитесь, что конфигурация nginx по-прежнему в порядке.\n`sudo nginx -t`\n\n### добавьте новые домены в `ALLOWED_HOSTS` проекта если не сделали этого ранее\n\nПримените изменения\n`service gunicorn restart`\n\n## ТЕПЕРЬ ПРИШЛО ВРЕМЯ ПОДОЖДАТЬ...\n\u003e Может потребоваться некоторое время, чтобы ваш веб-сайт стал доступен в пользовательском домене. Я действительно не знаю, сколько времени это на самом деле займет. Я ждал несколько часов, пока у меня не заработало.\n\n#### Откуда ты знаешь, что это работает?\nПосетив свой домен, вы должны увидеть сообщение `Welcome to nginx!` **ИЛИ вы должны увидеть свой проект вживую и работающим**\n\nВообще обычно процесс занимает не более 24-48 часов, время обновления зависит от интернет-провайдера.\nЧтобы начать работу над сайтом уже сейчас, пропишите для своего компьютера соответствие адреса и домена в файл hosts по этой [инструкции](https://beget.com/ru/kb/how-to/sites/kak-dobavit-sootvetstvie-ip-adresa-i-domena-sajta-v-fajl-etc-hosts?_ga=2.217897046.1912125031.1673476626-1439285939.1671724688).\n\n# HTTPS (Если у вас зарегистрирован домен и он работает)\n**Не выполняйте этот шаг, если только вы не сможете посетить свой веб-сайт, используя пользовательский домен.** Посмотрите: [Откуда ты знаешь, что это работает?](#Откуда-ты-знаешь,-что-это-работает?)\n\n#### Установка certbot\nHTTPS немного сложнее настроить при использовании Django Channels. Nginx и Daphne требуют некоторой дополнительной настройки.\n\n`sudo apt install certbot python3-certbot-nginx`\n\n`certbot --version`\n\n`sudo systemctl reload nginx`\n\nУбедитесь, что конфигурация nginx по-прежнему в порядке.\n`sudo nginx -t`\n\n#### Разрешить HTTPS через брандмауэр(firewall)\n\nЕсли вы не выполняли эту команду ранее - выполните\n`sudo ufw allow 'Nginx Full'`\n\n`sudo ufw delete allow 'Nginx HTTP'` Блокировать стандартный HTTP\n\n#### Получить SSL-сертификат\n\n`sudo certbot --nginx -d \u003cваш_домен\u003e -d www.\u003cваш_домен\u003e`\n\n#### Состояние службы отвечающей за авто обновление Certbot для проверки сертификата\n`sudo systemctl status certbot.timer`\n\n#### протестировать процесс обновления\n`sudo certbot renew --dry-run`\n\n## Обновить конфигурацию nginx\nНам нужно сообщить nginx, чтобы он разрешил передачу данных websocket через порт 8001. Я действительно не уверен, как это объяснить. Я не понимаю этого сам до конца. Это работает аналогично тому, как мы разрешаем gunicorn передавать прокси-сервер(proxy pass) nginx.\n\nПерейдите в директорию `/etc/nginx/sites-available`\n\nобновите `FriskesSite`\n\n```\n# REDIRECT (www or non-www domain) HTTP TRAFFIC to (www or non-www domain) HTTPS protocol\nserver {\n    listen 80;\n\n    server_name www.\u003cваш_домен\u003e \u003cваш_домен\u003e;\n\n    return 301 https://$host$request_uri;\n}\n\n# REDIRECT (www domain) HTTPS TRAFFIC to (non-www domain) HTTPS protocol\nserver {\n    listen 443 ssl;\n\n    ssl_certificate /etc/letsencrypt/live/\u003cваш_домен\u003e/fullchain.pem;\n    ssl_certificate_key /etc/letsencrypt/live/\u003cваш_домен\u003e/privkey.pem;\n\n    server_name www.\u003cваш_домен\u003e;\n\n    return 301 $scheme://\u003cваш_домен\u003e$request_uri;\n}\n\n# MAIN (non-www domain) HTTPS protocol HANDLER\nserver {\n    listen 443 ssl;\n\n    ssl_certificate /etc/letsencrypt/live/\u003cваш_домен\u003e/fullchain.pem;\n    ssl_certificate_key /etc/letsencrypt/live/\u003cваш_домен\u003e/privkey.pem;\n    include /etc/letsencrypt/options-ssl-nginx.conf;\n    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;\n\n    server_name \u003cваш_домен\u003e;\n\n    client_max_body_size 10M;\n\n    location /static/ {\n        root /home/friskes/project/FriskesSite;\n    }\n\n    location /media/ {\n        root /home/friskes/project/FriskesSite;\n    }\n\n    location / {\n#        https://stackoverflow.com/a/22027177/19276507\n        proxy_set_header Host $host;\n\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n\n        proxy_pass http://unix:/run/gunicorn.sock;\n    }\n\n    location /ws/ {\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        proxy_redirect off;\n\n        proxy_pass http://127.0.0.1:8001;\n    }\n}\n```\n\n\n## Обновить `daphne.service`\nРасскажите daphne, как получить доступ к нашему сертификату https.\n\nПерейдите в директорию `/etc/systemd/system`\n\nобновите файл `daphne.service`\n\n```\n[Unit]\nDescription=WebSocket Daphne Service\nAfter=network.target\n\n[Service]\nType=simple\nUser=root\nWorkingDirectory=/home/friskes/project/FriskesSite\nExecStart=/home/friskes/project/venv/bin/python /home/friskes/project/venv/bin/daphne -e ssl:8001:privateKey=/etc/letsencrypt/live/\u003cваш_домен\u003e/privkey.pem:certKey=/etc/letsencrypt/live/\u003cваш_домен\u003e/fullchain.pem FriskesSite.asgi:application\nRestart=on-failure\n\n[Install]\nWantedBy=multi-user.target\n```\n\n\n# Установка Celery\n\n[официальная документация](https://docs.celeryq.dev/en/latest/userguide/daemonizing.html#usage-systemd)\n\nОбновить установщик apt\n`sudo apt update`\n\nУстановить celery\n`sudo apt -y install celery`\n\nСоздать файл celery.service\n`/etc/systemd/system/celery.service`\n\nС содержимым:\n```\n[Unit]\nDescription=Celery Service\nAfter=network.target\n\n[Service]\nType=forking\nUser=friskes\nGroup=www-data\nEnvironmentFile=/etc/conf.d/celery\nWorkingDirectory=/home/friskes/project/FriskesSite\nExecStart=/bin/sh -c '${CELERY_BIN} multi start ${CELERYD_NODES} \\\n  -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \\\n  --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'\nExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait ${CELERYD_NODES} \\\n  --pidfile=${CELERYD_PID_FILE}'\nExecReload=/bin/sh -c '${CELERY_BIN} multi restart ${CELERYD_NODES} \\\n  -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \\\n  --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n```\n\nСоздать директорию conf.d и файл celery внутри\n`/etc/conf.d/celery`\n\nС содержимым:\n```\nCELERY_APP=\"FriskesSite\"\n\nCELERY_BIN=\"/home/friskes/project/venv/bin/celery\"\n\nCELERYD_NODES=\"w1\"\n\nCELERYD_MULTI=\"multi\"\n\nCELERYD_OPTS=\"--time-limit=300 --concurrency=8\"\n\nCELERYD_PID_FILE=\"/var/run/celery/%n.pid\"\n\nCELERYD_LOG_FILE=\"/var/log/celery/%n%I.log\"\n\nCELERYD_LOG_LEVEL=\"INFO\"\n\n\nCELERYBEAT_SCHEDULE_FILE=\"/var/run/celery/celerybeat-schedule\"\n\nCELERYBEAT_PID_FILE=\"/var/run/celery/beat.pid\"\n\nCELERYBEAT_LOG_FILE=\"/var/log/celery/beat.log\"\n\n\nCELERY_FLOWER_URL_PREFIX=\"flower\"\n\nCELERY_FLOWER_LOG_FILE=\"/var/log/celery/flower.log\"\n\nCELERY_FLOWER_ADDRESS=\"127.0.0.1\"\n\nCELERY_FLOWER_PORT=\"5555\"\n```\n\nСоздать файл celery.conf\n`/etc/tmpfiles.d/celery.conf`\n\nС содержимым:\n```\nd /var/run/celery 0755 friskes www-data -\nd /var/log/celery 0755 friskes www-data -\n```\n\nОбщие команды для Celery, Beat, Flower служб:\nПосле изменения файла необходимо перезапустить демона\n`sudo systemctl daemon-reload`\nУстановить авто запуск после каждой перезагрузки сервера\n`systemctl enable \u003cназвание_службы\u003e.service`\nОтключить авто запуск после каждой перезагрузки сервера\n`sudo systemctl disable \u003cназвание_службы\u003e.service`\nПосмотреть лог\n`sudo journalctl -u \u003cназвание_службы\u003e.service`\nПроверить состояние\n`sudo systemctl status \u003cназвание_службы\u003e`\nОстальные команды:\n`sudo systemctl start \u003cназвание_службы\u003e`\n`sudo systemctl stop \u003cназвание_службы\u003e`\n`sudo systemctl restart \u003cназвание_службы\u003e`\n\n\n# Установка Celery Beat\n\nСоздать файл celerybeat.service\n`/etc/systemd/system/celerybeat.service`\n\nС содержимым:\n```\n[Unit]\nDescription=Celery Beat Service\nAfter=network.target\n\n[Service]\nType=simple\nUser=friskes\nGroup=www-data\nEnvironmentFile=/etc/conf.d/celery\nWorkingDirectory=/home/friskes/project/FriskesSite\nExecStart=/bin/sh -c '${CELERY_BIN} -A ${CELERY_APP} beat \\\n  -s ${CELERYBEAT_SCHEDULE_FILE} \\\n  --pidfile=${CELERYBEAT_PID_FILE} \\\n  --logfile=${CELERYBEAT_LOG_FILE} \\\n  --loglevel=${CELERYD_LOG_LEVEL}'\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n```\n\n\n# Установка Celery Flower\n\nСоздать файл celeryflower.service\n`/etc/systemd/system/celeryflower.service`\n\nС содержимым:\n```\n[Unit]\nDescription=Flower Celery Service\nAfter=network.target\n\n[Service]\nUser=friskes\nGroup=www-data\nEnvironmentFile=/etc/conf.d/celery\nWorkingDirectory=/home/friskes/project/FriskesSite\nExecStart=/bin/sh -c '${CELERY_BIN} -A ${CELERY_APP} flower \\\n  --url_prefix=${CELERY_FLOWER_URL_PREFIX} --port=${CELERY_FLOWER_PORT} \\\n  --address=${CELERY_FLOWER_ADDRESS} \\\n  --log-file-prefix=${CELERY_FLOWER_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL}'\nRestart=on-failure\nType=simple\n\n[Install]\nWantedBy=multi-user.target\n```\n\n\n# Создание суперпользователя\nПеред тестированием сервера необходимо создать суперпользователя.\n\n`su friskes`\n\n`cd /home/friskes/project/`\n\n`source venv/bin/activate`\n\n`cd FriskesSite`\n\n`python manage.py createsuperuser`\n\nПерезагрузите сервер и зайдите на свой веб-сайт, чтобы опробовать его. Теперь все должно работать.\n\nСпасибо за чтение и не стесняйтесь вносить свой вклад в этот документ, если у вас есть лучший способ объяснить происходящее. Я ни в коем случае не являюсь веб-экспертом.\n\n# FAQ\nВот некоторые вещи, которые я хотел бы знать, когда делал это в первый раз.\n\n### Если вы изменяете файл или обновляете код в проекте, нужно ли вам что-либо делать?\nДа.\n\nЕсли вы изменяете только код, который *не связан с django channels*, то вам нужно запустить только:\n`service gunicorn restart`\n\nНо если вы измените какой-либо код, связанный с django channels, **тогда вы также должны перезапустить службу daphne**:\n`service daphne restart`\n\nНа всякий случай я всегда просто запускаю и то, и другое. Это не может повредить.\n\n### Команды для проверки статусов сервисов\nНа протяжении всего этого документа мы периодически проверяем статус настроенных нами сервисов. Такие вещи, как:\n1. `sudo systemctl status gunicorn`\n1. `sudo systemctl status redis`\n1. `systemctl status daphne.service`\n1. `systemctl status on_boot.service`\n1. `sudo systemctl status certbot.timer`\n\n### Команды NGINX\nПосмотреть статус nginx\n1. `sudo systemctl status nginx`\nОстановить nginx (до первой перезагрузки сервера)\n1. `sudo systemctl stop nginx`\nЗапустить nginx\n1. `sudo systemctl start nginx`\nАвтоматическая остановка а затем запуск nginx\n1. `sudo systemctl reload nginx`\n\nОтключить автоматический запуск nginx после перезагрузки сервера\n1. `sudo systemctl disable nginx`\nВключить автоматический запуск nginx после перезагрузки сервера\n1. `sudo systemctl enable nginx`\n\nЕсли что-либо из этого не сработает, значит, вы сделали что-то не так. Наиболее распространенная проблема заключается в том, что структура каталогов не совпадает. Например, вы могли бы использовать `/home/friskes/project/неправильное_название_проекта/` вместо `/home/friskes/project/FriskesSite/`. Вам нужно очень внимательно изучить структуру ваших каталогов и убедиться, что все названия указаны правильно и соотносятся с `.service` файлами, которые вы создали. \n\n\u003e Когда вы вносите изменения в `.service` файл, **Всегда выполняйте команду `sudo systemctl daemon-reload`**. Или на всякий случай просто перезапустите этот чертов сервер `sudo shutdown -r now`. Перезапуск сервера - это безопасный способ, но и самый медленный.\n\n\n### Получить информацию об оперативной памяти\nКоманда: `free -h`\nВызвать программу диспетчер задач [инструкция](https://zalinux.ru/?p=1811)\nКоманда открытия диспетчере: `top` Выйти кнопкой `q`\nКоманды `Shift + \u003c` и ` Shift + \u003e` меняют столбец по которому сортируются строки в диспетчере\n\nПокажет использование памяти процессами:\n`ps aux | awk '{print $6/1024 \" MB\\t\\t\" $11}' | sort -n`\n\n\n# References\n1. [https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-18-04](https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-18-04)\n1. [https://channels.readthedocs.io/en/latest/](https://channels.readthedocs.io/en/latest/)\n1. [https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-20-04](https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-20-04)\n1. [https://www.digitalocean.com/community/tutorials/how-to-set-up-object-storage-with-django](https://www.digitalocean.com/community/tutorials/how-to-set-up-object-storage-with-django)\n1. [https://stackoverflow.com/questions/61101278/how-to-run-daphne-and-gunicorn-at-the-same-time](https://stackoverflow.com/questions/61101278/how-to-run-daphne-and-gunicorn-at-the-same-time)\n1. [https://github.com/conda-forge/pygridgen-feedstock/issues/10](https://github.com/conda-forge/pygridgen-feedstock/issues/10)\n1. [https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffriskes%2Ffrishub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffriskes%2Ffrishub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffriskes%2Ffrishub/lists"}