mod: update README and remove legacy deploy docs
This commit is contained in:
233
README.md
233
README.md
@@ -1,91 +1,188 @@
|
|||||||
# Сайт CADpoint.ru
|
# CADpoint.ru
|
||||||
|
|
||||||
Сайт с новостями (блог о 3D-печать и Систем Автоматизированного Проектирования) на Django со
|
Сайт CADpoint.ru — это Django-проект, который сейчас живёт в Docker.
|
||||||
встроенными свистелками-перделками:
|
|
||||||
* медиа-библиотека (filer);
|
|
||||||
* HTML-редактор на обычной textarea в админке;
|
|
||||||
* типограф [etpgrf](https://typograph.cube2.ru/);
|
|
||||||
* теги новостей (taggit).
|
|
||||||
|
|
||||||
[Инструкция по развертыванию на хостинге DreamHost.com](deploy_to_dreamhost.md)
|
Кратко о схеме:
|
||||||
|
|
||||||
Для локальной и продовой настройки используй файл `.env` в корне проекта.
|
- сам Django запускается в контейнере `cadpoint-backend`;
|
||||||
Шаблон для него лежит в `.env.sample`.
|
- локально используется `docker-compose.local.yml`;
|
||||||
|
- на проде используется `docker-compose.prod.yml`;
|
||||||
|
- внешний `nginx` стоит на хосте и проксирует запросы в контейнер;
|
||||||
|
- конфигурация и секреты лежат в `.env`;
|
||||||
|
- медиа, статика и SQLite-база живут в проектных каталогах и монтируются в контейнер.
|
||||||
|
|
||||||
Набор базовых переменных:
|
## Что есть в проекте
|
||||||
|
|
||||||
* `DJANGO_SECRET_KEY`
|
- `cadpoint/` — Django-проект, приложения, шаблоны, management commands.
|
||||||
* `DJANGO_DEBUG`
|
- `public/static/` — исходная статика проекта.
|
||||||
* `DJANGO_ALLOWED_HOSTS`
|
- `public/media/` — загруженные файлы и служебные error-assets.
|
||||||
* `DJANGO_ADMINS`
|
- `database/` — SQLite-база и дампы.
|
||||||
* `DJANGO_CSRF_TRUSTED_ORIGINS`
|
- `config/nginx/` — конфиг внешнего `nginx` для прод-хоста.
|
||||||
* `DJANGO_INTERNAL_IPS`
|
- `frontend-assembly/` — сборка CodeMirror 6 для админки.
|
||||||
* `DJANGO_SQLITE_NAME`
|
- `Dockerfile` — финальный образ приложения.
|
||||||
* `ADMIN_URL`
|
- `docker-compose.local.yml` — локальный запуск.
|
||||||
* `DJANGO_EMAIL_HOST`
|
- `docker-compose.prod.yml` — prod-запуск.
|
||||||
* `DJANGO_EMAIL_PORT`
|
|
||||||
* `DJANGO_EMAIL_HOST_USER`
|
|
||||||
* `DJANGO_EMAIL_HOST_PASSWORD`
|
|
||||||
* `DJANGO_EMAIL_FROM`
|
|
||||||
|
|
||||||
Для логического бэкапа базы через Django используй команду:
|
## Быстрый старт
|
||||||
|
|
||||||
|
### 1. Подготовить `.env`
|
||||||
|
|
||||||
|
Скопируй шаблон и заполни значения:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd cadpoint
|
|
||||||
python manage.py backup_db
|
|
||||||
```
|
|
||||||
|
|
||||||
По умолчанию файл дампа сохраняется в `database/backups/`. Восстановление делается обычной командой
|
|
||||||
`python manage.py loaddata <fixture>.json` в пустую базу после `python manage.py migrate`.
|
|
||||||
|
|
||||||
## Замена старых Joomla-ссылок в контенте
|
|
||||||
|
|
||||||
Для массовой замены старых внутренних ссылок в HTML-контенте используй management command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd cadpoint
|
|
||||||
python manage.py replace_legacy_links
|
|
||||||
```
|
|
||||||
|
|
||||||
По умолчанию команда работает в режиме `dry-run`: она только показывает, какие поля и записи
|
|
||||||
будут изменены. Чтобы записать изменения в базу, добавь флаг:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd cadpoint
|
|
||||||
python manage.py replace_legacy_links --apply
|
|
||||||
```
|
|
||||||
|
|
||||||
Сейчас команда чинит только кросс-ссылки на статьи. Ссылки на картинки и прочие медиа пока
|
|
||||||
оставлены как есть.
|
|
||||||
|
|
||||||
Для нового окружения на Poetry:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
poetry install --with dev
|
|
||||||
cp .env.sample .env
|
cp .env.sample .env
|
||||||
poetry run python cadpoint/manage.py migrate
|
|
||||||
poetry run python cadpoint/manage.py runserver
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Для разработки медиа-файлы и статика лежат в `public/media` и `public/static`.
|
Основные переменные:
|
||||||
`django-debug-toolbar` показывается только при `DJANGO_DEBUG=true` и заходе с локального
|
|
||||||
адреса (`127.0.0.1` / `localhost`); если нужно, свои IP можно добавить в `DJANGO_INTERNAL_IPS`.
|
|
||||||
|
|
||||||
## Сборка CodeMirror 6
|
- Общие:
|
||||||
|
- `DJANGO_SECRET_KEY` — секрет Django для подписи сессий, CSRF-токенов, password reset и других подписанных данных. Должен быть уникальным и храниться только в `.env`.
|
||||||
|
- `DJANGO_DEBUG` — включает режим отладки Django. Для локальной разработки обычно `True`, для прода — `False`.
|
||||||
|
- `DJANGO_ALLOWED_HOSTS` — список доменов и IP, с которых Django принимает запросы. Значения перечисляются через запятую.
|
||||||
|
- `DJANGO_ADMINS` — список админов для email-уведомлений о критических ошибках. Формат: `Имя:email@domain` (несколько значений через запятую).
|
||||||
|
- `DJANGO_CSRF_TRUSTED_ORIGINS` — список доверенных origin для CSRF. Нужен для доменов, с которых разрешены POST-запросы.
|
||||||
|
- `DJANGO_INTERNAL_IPS` — внутренние IP для `debug_toolbar` в dev-режиме. Обычно достаточно `127.0.0.1` и `::1`.
|
||||||
|
- `DJANGO_SQLITE_NAME` — имя файла SQLite-базы внутри каталога `database/`. Полный путь собирается через `BASE_DIR.parent / 'database'`.
|
||||||
|
- `ADMIN_URL` — относительный URL админки. По умолчанию `admin/`, можно заменить на любой другой сегмент вроде `a-d-m-i-n/`.
|
||||||
|
- `DJANGO_EMAIL_HOST` — SMTP-хост почтового сервера.
|
||||||
|
- `DJANGO_EMAIL_PORT` — SMTP-порт.
|
||||||
|
- `DJANGO_EMAIL_HOST_USER` — логин для SMTP.
|
||||||
|
- `DJANGO_EMAIL_HOST_PASSWORD` — пароль или токен для SMTP.
|
||||||
|
- `DJANGO_EMAIL_FROM` — адрес отправителя писем. Если не задан, берётся из `DJANGO_EMAIL_HOST_USER`.
|
||||||
|
- Специфичные для продакшена:
|
||||||
|
- `HOST_PROJECT_PATH` — полный путь к проекту на прод-хосте. Используется при генерации nginx-конфига, чтобы подставить правильный `alias` для media-файлов.
|
||||||
|
- `REPO_USER` / `REPO_PASS` — логин и токен/пароль для доступа к приватному registry, откуда Watchtower подтягивает новый образ.
|
||||||
|
|
||||||
Когда появится фронтенд-часть CodeMirror 6 админки, её можно пересобирать скриптом
|
Для ориентира:
|
||||||
`frontend-assembly/build-codemirror6.sh`.
|
|
||||||
|
|
||||||
Скрипт создаёт временную рабочую папку, ставит зависимости через `npm ci`, собирает
|
- `DJANGO_DEBUG` управляет самим Django.
|
||||||
минимизированный бандл и затем сам удаляет временные `src/` и `node_modules/`.
|
- `DEBUG` в `docker-compose.local.yml` — это служебная переменная контейнера, но в проекте используется именно `DJANGO_DEBUG`.
|
||||||
В проекте остаётся только готовая статика:
|
- `DJANGO_SETTINGS_MODULE` и `PYTHONUNBUFFERED` задаются в Docker Compose и обычно не трогаются вручную.
|
||||||
|
|
||||||
* `public/static/codemirror/editor.js`
|
### 2. Локальная разработка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.local.yml up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
После старта сайт будет доступен на:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://127.0.0.1:8055
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Продакшен на сервере
|
||||||
|
|
||||||
|
На сервере должен быть:
|
||||||
|
|
||||||
|
- установлен Docker;
|
||||||
|
- настроен внешний `nginx` на хосте;
|
||||||
|
- подготовлен `.env`;
|
||||||
|
- доступен приватный registry с образом проекта.
|
||||||
|
- в корне проекта на хосте заранее созданы каталоги `database/`, `config/` и `media/` — они монтируются в контейнер как bind-mount'ы.
|
||||||
|
|
||||||
Запуск:
|
Запуск:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Backend в контейнере слушает только localhost хоста:
|
||||||
|
|
||||||
|
```text
|
||||||
|
127.0.0.1:8050
|
||||||
|
```
|
||||||
|
|
||||||
|
А уже внешний `nginx` проксирует домен на этот порт.
|
||||||
|
|
||||||
|
## Где лежат данные
|
||||||
|
|
||||||
|
- `public/static/` — исходники статики.
|
||||||
|
- `public/staticfiles/` — результат `collectstatic`.
|
||||||
|
- `public/media/` — загруженные файлы и служебные error-pages.
|
||||||
|
- `database/` — SQLite-файл и бэкапы.
|
||||||
|
|
||||||
|
## Основные команды
|
||||||
|
|
||||||
|
### Миграции
|
||||||
|
|
||||||
|
Локально:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.local.yml exec web python manage.py migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
На проде:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml exec web python manage.py migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Django shell
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.local.yml exec web python manage.py shell
|
||||||
|
```
|
||||||
|
|
||||||
|
### Логи
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml logs -f web
|
||||||
|
```
|
||||||
|
|
||||||
|
### Бэкап базы
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml exec web python manage.py backup_db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Восстановление fixture
|
||||||
|
|
||||||
|
После `migrate` в пустую базу:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml exec web python manage.py loaddata <fixture>.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Замена старых Joomla-ссылок
|
||||||
|
|
||||||
|
Для массовой замены старых внутренних ссылок в HTML-контенте есть management command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml exec web python manage.py replace_legacy_links
|
||||||
|
```
|
||||||
|
|
||||||
|
По умолчанию команда работает в режиме `dry-run`.
|
||||||
|
|
||||||
|
Чтобы применить изменения:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml exec web python manage.py replace_legacy_links --apply
|
||||||
|
```
|
||||||
|
|
||||||
|
Сейчас команда чинит только кросс-ссылки на статьи. Ссылки на картинки и прочие медиа пока остаются как есть.
|
||||||
|
|
||||||
|
## CodeMirror 6 в админке
|
||||||
|
|
||||||
|
Редактор админки собирается отдельно из npm-части.
|
||||||
|
|
||||||
|
Исходники и скрипт сборки лежат в `frontend-assembly/`.
|
||||||
|
|
||||||
|
Сборка:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash ./frontend-assembly/build-codemirror6.sh
|
bash ./frontend-assembly/build-codemirror6.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Результат сборки — только готовый бандл:
|
||||||
|
|
||||||
|
```text
|
||||||
|
public/static/codemirror/editor.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## Заметки по развертыванию
|
||||||
|
|
||||||
|
- Главный источник правды по запуску — `docker-compose.local.yml` и `docker-compose.prod.yml`.
|
||||||
|
- Секреты не храним в репозитории: используем `.env`.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,189 +0,0 @@
|
|||||||
## Установка (компиляция) версии Python 3.8.6
|
|
||||||
|
|
||||||
Проект создан на версии Python 3.8.6. Скомпилируем необходимую версию Python.
|
|
||||||
|
|
||||||
1. ВХОДИМ ЧЕРЗ SSH ЧЕРЕЗ LOGIN/PWD СВОЕГО АККАУНТА.
|
|
||||||
2. Создадим папку `tmp` (скорее всего уже создана)
|
|
||||||
3. Перейдем в эту папку
|
|
||||||
4. Скачаем tgz-архив с исходными файлами Python
|
|
||||||
5. Распакуем архив с помощью `tar`
|
|
||||||
6. Перейдем в папку `Python-3.8.6`, созданную при разархивации.
|
|
||||||
7. Сконфигурируем будущую компиляцию на размещение готовой версии Python в папку `~/opt/python-3.8.6`
|
|
||||||
8. Компилируем Python (в том числе будут запущены тесты)
|
|
||||||
9. Устанавливаем Python 3.8.6
|
|
||||||
Контакт для уведомлений: <notification_email>
|
|
||||||
|
|
||||||
```
|
|
||||||
cd ~
|
|
||||||
mkdir tmp
|
|
||||||
cd tmp
|
|
||||||
wget https://www.python.org/ftp/python/3.8.6/Python-3.8.6.tgz
|
|
||||||
tar zxvf Python-3.8.6.tgz
|
|
||||||
cd Python-3.8.6
|
|
||||||
./configure --prefix=$HOME/opt/python-3.8.6 --enable-optimizations
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
```
|
|
||||||
|
|
||||||
В результате установлена нужная нам версия python установлена в папку `~/<site_root>` (`/home/<hosting_user>/opt/python-3.8.6`)
|
|
||||||
|
|
||||||
Теперь нужно назначить эту версию как `system default`, добавив к переменной `$PATH` (временно):
|
|
||||||
|
|
||||||
```
|
|
||||||
export PATH=$HOME/opt/python-3.8.6/bin:$PATH
|
|
||||||
```
|
|
||||||
|
|
||||||
------------------------------
|
|
||||||
_Также можно добавить эту строку в файл `.bashrc` и/или `.bash_profile` в домашней директории `/home/<hosting_user>`. Это нужно, чтобы сделать так, чтобы этот python всегда заменял версию которая есть на сервере._
|
|
||||||
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
Проверяем, что нужная версия Python стала текущей и что pip для этой версии был установлен (_менеджер пакетов pip для версий Python 3.x входит в поставку... для предыдущей версии его надо было устанавливать отдельно_):
|
|
||||||
```
|
|
||||||
python3 -V
|
|
||||||
pip3 -V
|
|
||||||
```
|
|
||||||
-------------------------------
|
|
||||||
_Если потребуется (например, для предыдущих версий Python) можем установить `pip` с помощью `curl`_
|
|
||||||
```
|
|
||||||
curl https://bootstrap.pypa.io/get-pip.py > ~/tmp/get-pip.py
|
|
||||||
python ~/tmp/get-pip.py
|
|
||||||
```
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
## Настройка виртуального окружения проекта
|
|
||||||
|
|
||||||
Чтобы "заморозить" установленную версию Python в виртуальном окружении `virtualenv`:
|
|
||||||
|
|
||||||
```
|
|
||||||
pip3 install virtualenv
|
|
||||||
```
|
|
||||||
|
|
||||||
Через панель управления хостингом __Domains -> Manage Domains -> Add Hosting to a Domain/Sub-Domain__ создадим поддомен __cadpoint.ru__ (без создания нового пользователя). В нашем домашнем каталоге будет создана папка `~/<site_root>`. В этой папке будет лежать `passenger_wsgi.py`, также есть папка `public` в которой будут лежать статичные файлы не требующие обработки CGI (media, static и пр.)
|
|
||||||
|
|
||||||
Теперь создадим виртуальное окружение в папке нашего сайта (`$HOME/<site_root>`):
|
|
||||||
```
|
|
||||||
virtualenv -p python3 $HOME/<site_root>/env
|
|
||||||
```
|
|
||||||
|
|
||||||
Активируем созданное виртуальное окружение:
|
|
||||||
```
|
|
||||||
source $HOME/<site_root>/env/bin/activate
|
|
||||||
```
|
|
||||||
|
|
||||||
Проверить, что теперь мы работаем в виртуальном окружении можно дав команды:
|
|
||||||
```
|
|
||||||
python -V
|
|
||||||
pip -V
|
|
||||||
```
|
|
||||||
|
|
||||||
Мы увидим, что срабатывают нужные нам версии (т.е. не надо использовать `python3` и `pip3`).
|
|
||||||
|
|
||||||
## Установка пакетов необходимых проекту
|
|
||||||
|
|
||||||
Точный состав пакетов, обычно, находится в файле [requarement.txt](dicquo/requarement.txt). Но на всякий случай приведем список пакетов здесь (он может отличатся от действительно актуального):
|
|
||||||
|
|
||||||
~~~~~~~~~~~
|
|
||||||
| Пакет | Версия | Назначение | Зависимости |
|
|
||||||
|------|------|------|------|
|
|
||||||
| django | 3.1.3 | Фреймворк Django | притащит с собой пакеты: __asgiref-3.3.0__, __pytz-2020.4__, __sqlparse-0.4.1__
|
|
||||||
| django-taggit | 1.3.0 | Система тегов для Django | нет
|
|
||||||
| pillow | 8.0.1 | Пакет работы с графическими файлами
|
|
||||||
| pytils | 0.4.4 | Пакет рускоязычной транслитерации, работы с числительными, склонениями числительных и временными диаппазонами (для Python 3.x) | нет
|
|
||||||
| typus | 0.2.2 | типограф | нет
|
|
||||||
| urllib3 | 1.25.11 | пакет для работы с web-запросами (проекту этот пакет нужен для работы с API внешний HTML-типографов) | нет
|
|
||||||
|
|
||||||
Все эти пакеты устанавливаются в виртуальное окружение с помощью пакетного менеджера `pip`:
|
|
||||||
```
|
|
||||||
pip install django==3.1.3
|
|
||||||
pip install django-taggit==1.3.0
|
|
||||||
pip install pillow==8.0.1
|
|
||||||
pip install pytils==0.4.4
|
|
||||||
pip install typus==0.2.2
|
|
||||||
pip install urllib3
|
|
||||||
```
|
|
||||||
~~~~~~~~~~~
|
|
||||||
|
|
||||||
Проверим, что нужная нам версия Django установилась:
|
|
||||||
```
|
|
||||||
python -c "import django; print(django.get_version())"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Копируем проект на хостинг
|
|
||||||
|
|
||||||
На момент написания данной документации структура файлов и каталогов проекта в папке `cadpoint.ru` выглядела примерно так:
|
|
||||||
```
|
|
||||||
.
|
|
||||||
|-- passenger_wsgi.py
|
|
||||||
|-- cadpoint
|
|
||||||
| |-- db.sqlite3
|
|
||||||
| |-- manage.py
|
|
||||||
| |-- cadpoint
|
|
||||||
| | |-- __init__.py
|
|
||||||
| | |-- asgi.py
|
|
||||||
| | |-- my_secret.py # хранится только локально, в Git не коммитится
|
|
||||||
| | |-- settings.py
|
|
||||||
| | |-- urls.py
|
|
||||||
| | `-- wsgi.py
|
|
||||||
| |-- templates
|
|
||||||
| | |-- base.html
|
|
||||||
| | |-- blocks
|
|
||||||
| | | `-- tecnical_info.html
|
|
||||||
| | `-- index.html
|
|
||||||
| `-- web
|
|
||||||
|-- public
|
|
||||||
`-- tmp
|
|
||||||
`-- restart.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
Далее нам надо скопировать статические файлы админки Django в папку статических файлов хостинга:
|
|
||||||
```
|
|
||||||
cd ~/<site_root>/dicquo
|
|
||||||
python manage.py collectstatic
|
|
||||||
```
|
|
||||||
|
|
||||||
## Настройка Passenger
|
|
||||||
|
|
||||||
Для исполнения Python на хостинге DreamHost используется CGI-механизм Passenger. Чтобы его настроить для нашего проекта в папке сайта `~/cadpoint.ru` нужно разметить файл `passenger_wsgi.py` следующего содержания ([см. документацию DreamHost](https://help.dreamhost.com/hc/en-us/articles/360002341572-Creating-a-Django-project)):
|
|
||||||
|
|
||||||
```python
|
|
||||||
#!/home/<hosting_user>/<site_root>/env/bin/python3
|
|
||||||
|
|
||||||
import sys, os
|
|
||||||
INTERP = "/home/<hosting_user>/<site_root>/env/bin/python3"
|
|
||||||
#INTERP is present twice so that the new python interpreter
|
|
||||||
#knows the actual executable path
|
|
||||||
if sys.executable != INTERP:
|
|
||||||
os.execl(INTERP, INTERP, *sys.argv)
|
|
||||||
|
|
||||||
cwd = os.getcwd()
|
|
||||||
sys.path.append(cwd)
|
|
||||||
sys.path.append(cwd + '/cadpoint') #You must add your project here
|
|
||||||
|
|
||||||
sys.path.insert(0,cwd+'/env/bin')
|
|
||||||
# sys.path.insert(0,cwd+'/env/lib/python3.8/site-packages/django')
|
|
||||||
sys.path.insert(0,cwd+'/env/lib/python3.8/site-packages')
|
|
||||||
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = "cadpoint.settings"
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
|
||||||
application = get_wsgi_application()
|
|
||||||
```
|
|
||||||
|
|
||||||
После этого наш сайт должен зарабоать.
|
|
||||||
|
|
||||||
Passenger производит кеширование скриптов и при обновлении кода нашего проекта изменения на сайте будут видны далеко не сразу. Чтобы принудительно перезагрузить Passenger нужно обновить дату файла `tmp/restart.txt` в папке нашего проекта ([см. документацию DreamHost](https://help.dreamhost.com/hc/en-us/articles/216385637-How-do-I-enable-Passenger-on-my-domain-)).
|
|
||||||
|
|
||||||
Сначала создадим соответствующий каталог:
|
|
||||||
```
|
|
||||||
cd ~/cadpoint.ru
|
|
||||||
mkdir -p tmp
|
|
||||||
```
|
|
||||||
|
|
||||||
Обновлять `restart.txt` можно командой:
|
|
||||||
```
|
|
||||||
touch ~/cadpoint.ru/tmp/restart.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
## Дополнительно
|
|
||||||
|
|
||||||
Стоит включить ssl-сертификат для сайта. В панели управления DreamHost __Domains --> SSL/TLS Certificates__
|
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user