Развёртывание на Debian 12/13: Docker, nginx, работа за обратным прокси
- приложение перенесено в public/, инструкции в docs/ - Dockerfile (nginx без root-прав), docker-compose.yml с ограничениями - deploy/split-trainer.conf: CSP и заголовки безопасности, no-cache по ETag, /healthz, реальный IP из X-Forwarded-For только от частных сетей, редиректы без внутреннего хоста - deploy/install-debian.sh: установка и обновление без Docker - docs/DEPLOY.md: требования, установка, примеры прокси (nginx, Caddy, Traefik), подпуть Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
42b90a056c
commit
e897a6c5eb
+185
@@ -0,0 +1,185 @@
|
||||
# Развёртывание на своём сервере (Debian 12 / 13)
|
||||
|
||||
Сплит-тренер состоит из статических файлов (HTML, CSS, JS) и ничего не хранит на сервере. Нет бэкенда, базы данных, куки и обращений к внешним сайтам. Сервер только отдаёт файлы, поэтому требования минимальные.
|
||||
|
||||
## 1. Минимальные требования
|
||||
|
||||
### Сервер
|
||||
|
||||
| | Минимум | Комментарий |
|
||||
|---|---|---|
|
||||
| ОС | Debian 12 (bookworm) или Debian 13 (trixie), amd64 или arm64 | |
|
||||
| CPU / RAM | 1 vCPU, 128 МБ свободной памяти | nginx в простое занимает 5–10 МБ; для контейнера задан лимит 64 МБ |
|
||||
| Диск | порядка 500 МБ с Docker Engine (сам образ занимает несколько десятков МБ) или ~10 МБ с nginx из пакетов | сам сайт меньше 1 МБ |
|
||||
| Сеть | один TCP-порт; по умолчанию `127.0.0.1:8080` | наружу выставляет обратный прокси |
|
||||
| Исходящий доступ | только на время установки (apt или docker pull) | во время работы сайту интернет не нужен |
|
||||
| ПО (вариант A) | Docker Engine 24+ с плагином Compose v2 | рекомендуется официальный репозиторий: docs.docker.com/engine/install/debian |
|
||||
| ПО (вариант B) | nginx 1.22+ из пакетов Debian (в Debian 12 это 1.22, в 13 это 1.26) | ставится скриптом |
|
||||
| Права | root или sudo на время установки | сайт работает без root-прав |
|
||||
|
||||
Нужно выбрать один вариант: A или B.
|
||||
|
||||
### Домен и HTTPS
|
||||
- Для работы сайта HTTPS **не обязателен**: приложение не использует API, требующие защищённого контекста.
|
||||
- Но на публичном адресе HTTPS нужен: его даёт ваш обратный прокси (раздел 4).
|
||||
|
||||
### Браузеры пользователей
|
||||
Современные: Chrome и Edge 111+, Firefox 113+, Safari 16.2+ (примерно 2023 год и новее). Для работы нужен включённый JavaScript и `localStorage`.
|
||||
|
||||
## 2. Что важно знать про данные
|
||||
|
||||
- Прогресс и статистика хранятся **в браузере пользователя** (`localStorage`), на сервер ничего не отправляется. Резервировать на сервере нечего.
|
||||
- Данные привязаны к адресу сайта (схема + домен + порт). Если сменить домен, пользователи начнут «с нуля»; смена пути (`/trainer/`) прогресс не затрагивает.
|
||||
- Файл раскладки Vial (.vil) читается локально в браузере и никуда не загружается.
|
||||
|
||||
## 3. Установка
|
||||
|
||||
Склонируйте репозиторий на сервер:
|
||||
|
||||
```bash
|
||||
git clone https://gittea.khad1997pav.ru/khadzhibekovpa/split-trainer.git
|
||||
cd split-trainer
|
||||
```
|
||||
|
||||
### Вариант A: Docker (рекомендуется)
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
curl -i http://127.0.0.1:8080/healthz # должно ответить 200 и "ok"
|
||||
```
|
||||
|
||||
- Порт по умолчанию открыт **только на localhost**. Изменить: файл `.env` рядом с `docker-compose.yml`, например `PORT=9000` и/или `BIND=0.0.0.0` (откроет наружу: тогда закройте порт файрволом для всех, кроме прокси).
|
||||
- Контейнер работает без root-прав, с файловой системой «только чтение», без лишних возможностей ядра и с лимитом памяти.
|
||||
- Если прокси тоже в Docker, уберите блок `ports:` и подключите сервис к общей сети прокси: он слушает `8080` внутри контейнера.
|
||||
|
||||
### Вариант B: nginx из пакетов Debian
|
||||
|
||||
```bash
|
||||
sudo ./deploy/install-debian.sh
|
||||
curl -i http://127.0.0.1:8080/healthz
|
||||
```
|
||||
|
||||
Скрипт ставит nginx, копирует файлы в `/var/www/split-trainer` и подключает отдельный конфиг `split-trainer.conf`. Чужие сайты и настройки он не трогает.
|
||||
|
||||
Параметры (переменные окружения):
|
||||
|
||||
| Переменная | По умолчанию | Назначение |
|
||||
|---|---|---|
|
||||
| `LISTEN` | `127.0.0.1:8080` | адрес и порт (или только порт) |
|
||||
| `DOMAIN` | `_` | `server_name`, можно несколько через пробел |
|
||||
| `WEBROOT` | `/var/www/split-trainer` | куда копировать файлы |
|
||||
| `FORCE` | `0` | `1`: разрешить запуск не на Debian 12/13 |
|
||||
|
||||
Без прокси, прямо на порту 80:
|
||||
|
||||
```bash
|
||||
sudo LISTEN=80 DOMAIN=trainer.example.com ./deploy/install-debian.sh
|
||||
```
|
||||
|
||||
Если порт 80 уже занят «сайтом по умолчанию» nginx и вы не задали `DOMAIN`, будет открываться страница «Welcome to nginx»: укажите домен или отключите сайт по умолчанию (`sudo rm /etc/nginx/sites-enabled/default && sudo systemctl reload nginx`).
|
||||
|
||||
### Обновление
|
||||
|
||||
```bash
|
||||
git pull
|
||||
docker compose up -d --build # вариант A
|
||||
# или
|
||||
sudo ./deploy/install-debian.sh # вариант B
|
||||
```
|
||||
|
||||
Браузеры подхватят новую версию сами: сайт отдаётся с `Cache-Control: no-cache`, то есть при каждом открытии версия сверяется по ETag.
|
||||
|
||||
## 4. За обратным прокси
|
||||
|
||||
От прокси ничего особенного не требуется: сайт статический, без WebSocket, без нестандартных заголовков, все ссылки внутри относительные. Достаточно передать запрос на `127.0.0.1:8080`.
|
||||
|
||||
### nginx
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name trainer.example.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/trainer.example.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/trainer.example.com/privkey.pem;
|
||||
|
||||
# HTTPS завершается здесь, поэтому HSTS должен ставить именно прокси
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8080;
|
||||
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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Caddy
|
||||
|
||||
```
|
||||
trainer.example.com {
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
}
|
||||
```
|
||||
|
||||
HTTPS-сертификат Caddy получит сам.
|
||||
|
||||
### Traefik (Docker, метки в `docker-compose.override.yml`)
|
||||
|
||||
```yaml
|
||||
services:
|
||||
split-trainer:
|
||||
ports: !reset []
|
||||
networks: [traefik]
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.trainer.rule=Host(`trainer.example.com`)
|
||||
- traefik.http.routers.trainer.tls.certresolver=letsencrypt
|
||||
- traefik.http.services.trainer.loadbalancer.server.port=8080
|
||||
networks:
|
||||
traefik:
|
||||
external: true
|
||||
```
|
||||
|
||||
Имена сети и резолвера замените на свои. Тег `!reset` требует Docker Compose 2.24 или новее.
|
||||
|
||||
### Под подпутём (`https://example.com/trainer/`)
|
||||
|
||||
Приложение можно отдавать из подкаталога: все пути в нём относительные, свой конфиг менять не нужно. Прокси должен убрать префикс (завершающий `/` в `proxy_pass` обязателен):
|
||||
|
||||
```nginx
|
||||
location = /trainer { return 301 /trainer/; }
|
||||
location /trainer/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; }
|
||||
```
|
||||
|
||||
Для Caddy:
|
||||
|
||||
```
|
||||
example.com {
|
||||
redir /trainer /trainer/
|
||||
handle_path /trainer/* { reverse_proxy 127.0.0.1:8080 }
|
||||
}
|
||||
```
|
||||
|
||||
### Настоящий IP клиента в логах
|
||||
|
||||
Конфиг доверяет заголовку `X-Forwarded-For` только от прокси из частных сетей и localhost (`127.0.0.0/8`, `10/8`, `172.16/12`, `192.168/16`). Если ваш прокси стоит на другом сервере с публичным адресом, добавьте его в `set_real_ip_from` в `deploy/split-trainer.conf` и пересоберите или переустановите.
|
||||
|
||||
## 5. Что отдаёт сервер
|
||||
|
||||
- `GET /healthz` отвечает `200 ok` (для мониторинга и healthcheck).
|
||||
- Заголовки безопасности: строгий `Content-Security-Policy` (только свои скрипты и стили, никаких внешних адресов), `X-Content-Type-Options`, `Referrer-Policy: no-referrer`, `X-Frame-Options`, `Permissions-Policy`.
|
||||
- Файлы сжимаются gzip, скрытые файлы (`.git`, `.env`) не отдаются, версия nginx в ответах скрыта.
|
||||
|
||||
## 6. Если что-то не работает
|
||||
|
||||
| Симптом | Причина и решение |
|
||||
|---|---|
|
||||
| 502 / 504 от прокси | Сайт не запущен или слушает другой порт: `docker compose ps`, `curl http://127.0.0.1:8080/healthz` |
|
||||
| Белая страница под `/trainer/` | Нет завершающего `/` в `proxy_pass` или нет редиректа `/trainer` на `/trainer/` (см. выше) |
|
||||
| После обновления видна старая версия | Обновите страницу с Ctrl+F5; если стоит CDN или кеш на прокси, исключите сайт из кеширования |
|
||||
| Прогресс пропал после смены адреса | `localStorage` привязан к адресу сайта (схема + домен + порт); вернуть старый адрес |
|
||||
| `nginx -t` ругается (вариант B) | Покажите вывод `sudo nginx -t`; чаще всего порт занят другим сайтом |
|
||||
| Нужно изменить текст упражнений | Правьте `public/data.js` и обновите сайт командой из раздела «Обновление» |
|
||||
@@ -0,0 +1,113 @@
|
||||
# Сплит-тренер: как пользоваться
|
||||
|
||||
## 1. Запуск
|
||||
|
||||
1. Откройте файл `public/index.html` двойным кликом (лучше в Chrome или Edge). Если приложение установлено на сервере, откройте его адрес в браузере.
|
||||
2. Ничего устанавливать не нужно. Интернет не нужен.
|
||||
|
||||
Прогресс и статистика хранятся в самом браузере. Не переносите папку с приложением в другое место и не меняйте браузер или адрес сайта, иначе прогресс «потеряется» (он привязан к браузеру и адресу).
|
||||
|
||||
## 2. Главное правило: раскладка Windows
|
||||
|
||||
Тренер читает те символы, которые выдаёт система. Поэтому перед упражнением включите **ту раскладку, на которой печатаете**:
|
||||
|
||||
- русский урок: русская раскладка;
|
||||
- английский урок: английская.
|
||||
|
||||
Переключение: `Win + Пробел` или `Alt + Shift`. Если включена не та, сверху появится жёлтая подсказка, ошибкой это не считается.
|
||||
|
||||
## 3. Как проходит упражнение
|
||||
|
||||
- Сверху текст, ниже экранная клавиатура. Следующая клавиша подсвечена, рядом написано, каким пальцем её нажимать. Если нужен Shift, подсвечивается Shift **противоположной** руки.
|
||||
- Таймер запускается с первой нажатой клавиши.
|
||||
- Неверная клавиша не засчитывается: курсор остаётся на месте, ошибка записывается. Нажмите правильную клавишу, чтобы идти дальше.
|
||||
- `Esc` начинает упражнение заново.
|
||||
- Если включён Caps Lock, тренер предупредит, а не будет считать это ошибками.
|
||||
|
||||
## 4. Разделы
|
||||
|
||||
### Уроки
|
||||
45 уроков для каждого языка, от простого к сложному. Идти лучше по порядку, но открыть можно любой.
|
||||
|
||||
| Раздел | Что тренируем |
|
||||
|---|---|
|
||||
| A. Основной ряд | Исходная позиция, указательные к центру |
|
||||
| B. Верхний ряд | Новые буквы по 2–3 за урок |
|
||||
| C. Нижний ряд | То же для нижней строки |
|
||||
| D. Сплит | Центр на стыке половинок, слова одной рукой, чередование рук, мизинцы и безымянные |
|
||||
| E. Слова | Короткие, средние, длинные |
|
||||
| F. Заглавные | Работа с Shift |
|
||||
| G. Цифры | Ряд цифр, числа, даты, телефоны |
|
||||
| H. Знаки препинания | Точка, запятая, `? ! : ; -`, кавычки, скобки |
|
||||
| I. Символы | `@ # $ % & * [ ] { }` и код (в русской раскладке: `№ % * ?`) |
|
||||
| J. Тексты | Предложения, абзацы, «Марафон» |
|
||||
| K. Слои | Только с загруженной раскладкой Vial (см. раздел 6) |
|
||||
|
||||
**Звёзды:** ★ за точность от 90%; ★★ за точность от 95% и целевую скорость урока; ★★★ за 98% и скорость на 25% выше цели. Кнопка «Продолжить» сверху ведёт к первому непройденному уроку.
|
||||
|
||||
### Практика
|
||||
Собственные упражнения: слова (можно добавить заглавные, цифры, знаки), предложения, абзацы, цифры, символы, режим «Слои» и **свой текст** (вставьте любой, символы, которых нет на раскладке, будут убраны).
|
||||
|
||||
### Статистика
|
||||
- скорость, точность, время, рекорды, графики по последним упражнениям;
|
||||
- **карта клавиш**: красным отмечены клавиши с ошибками (или медленные, если переключить);
|
||||
- кнопка **«Тренировать слабые клавиши»**: тренер соберёт текст из ваших проблемных букв (нужно хотя бы несколько упражнений).
|
||||
|
||||
### Настройки
|
||||
Тема, экранная клавиатура вкл/выкл, цвета пальцев, вид клавиатуры (со сдвигом или ортолинейная), размер текста, звук ошибки.
|
||||
|
||||
## 5. Что означают цифры в результате
|
||||
|
||||
- **Скорость** в знаках в минуту (зн/мин). Слов в минуту = зн/мин ÷ 5.
|
||||
- **Точность**: доля верных нажатий среди всех нажатий.
|
||||
- **Ровность ритма**: насколько ровные паузы между клавишами. Рваный ритм показывает места, которые пальцы ещё не выучили.
|
||||
- **Самые медленные клавиши** и **путаница** («нужно Ф, нажато Ы») подсказывают, что повторять.
|
||||
|
||||
## 6. Ваша клавиатура из Vial и слои
|
||||
|
||||
### Загрузка раскладки
|
||||
1. В программе **Vial**: меню **File → Save current layout**, получится файл `.vil`.
|
||||
2. В тренере откройте раздел **Клавиатура**, выберите файл или перетащите его в окно.
|
||||
3. Проверьте, что слои распознаны. Слои можно переименовать (файл их названий не хранит).
|
||||
|
||||
Настройки на этой странице:
|
||||
- **Использовать в тренировках**: экранная клавиатура рисуется по вашему файлу.
|
||||
- **Расположение клавиш**: «Две половинки» (по умолчанию) или «Один блок», если у вашей модели матрица устроена иначе и схема выглядит неправильно.
|
||||
- **Слой с цифрами**: какой слой тренер будет просить использовать для цифр и символов. По умолчанию определяется сам.
|
||||
|
||||
### Тренировка со слоями
|
||||
- Уроки раздела **К** в списке уроков и режим **Практика → «Слои: текст, числа и формулы»**.
|
||||
- Над клавиатурой видна полоска слоёв: сплошным закрашен слой, на котором тренер **считает**, что вы сейчас, а жёлтой рамкой отмечен нужный для следующего символа.
|
||||
- Если нужно переключить слой, в подсказке написано действие (например, «Включите слой «Цифры»: TG(1)»), а нужная клавиша слоя мигает жёлтым. Дальше подсвечена сама клавиша символа на нужном слое.
|
||||
- Уроки специально заставляют переключаться: цифры и символы нужно набирать через слой «Цифры», хотя на базовом слое есть цифровой ряд. В английских уроках есть символы `[ ] { } \ | = ~`, которых на базовом слое нет.
|
||||
- В результатах появляется блок **«Переключение слоёв»**: число переключений и «цена переключения» (на сколько миллисекунд дольше символ сразу после смены слоя). Её и нужно сокращать.
|
||||
|
||||
### Важно знать
|
||||
- Нажатия клавиш слоёв (`TG`, `MO` и т. п.) обрабатывает прошивка клавиатуры, до тренера они **не доходят**. Тренер проверяет только набранные символы, а выполнение подсказок по слоям остаётся на вас.
|
||||
- Если вы оказались на другом слое, чем думает тренер, нажмите на нужный слой над клавиатурой, и маршрут пересчитается.
|
||||
- Для цифрового блока (`KP_*`) в системе должен быть включён NumLock.
|
||||
|
||||
## 7. Как заниматься
|
||||
|
||||
- Лучше **20 минут каждый день**, чем 2 часа раз в неделю.
|
||||
- **Точность важнее скорости**: печатайте медленнее, чем хочется. Скорость придёт, когда пальцы запомнят путь.
|
||||
- Если на уроке меньше ★: повторите его, а не переходите дальше.
|
||||
- Раз в неделю заглядывайте в «Статистику» и запускайте **слабые клавиши**.
|
||||
- Не смотрите на клавиши клавиатуры: подсказки на экране для этого и сделаны. Когда освоитесь, экранную клавиатуру можно выключить в «Настройках».
|
||||
|
||||
## 8. Если что-то не так
|
||||
|
||||
| Проблема | Что делать |
|
||||
|---|---|
|
||||
| Жёлтая подсказка про раскладку | Переключите раскладку Windows на нужный язык |
|
||||
| Подсказка про Caps Lock | Выключите Caps Lock |
|
||||
| Клавиши не реагируют | Кликните по странице: фокус должен быть в окне приложения, а не в адресной строке |
|
||||
| Уроки К закрыты замком | Загрузите файл `.vil` в разделе «Клавиатура» и включите «Использовать в тренировках» |
|
||||
| Схема клавиатуры выглядит неправильно | В «Клавиатура → Расположение клавиш» выберите «Один блок» |
|
||||
| «Этого символа нет на вашей раскладке» | Такой символ нельзя набрать на вашей клавиатуре; добавьте его в Vial или пропустите упражнение |
|
||||
| Прогресс пропал | Он хранится в браузере: проверьте, тем ли браузером и тем же файлом вы пользуетесь |
|
||||
| Нужно всё обнулить | «Статистика» → «Сбросить все данные» |
|
||||
|
||||
## 9. Файлы приложения
|
||||
|
||||
В папке `public/`: `index.html` (запуск), `app.js` (логика), `vial.js` (чтение Vial и маршруты по слоям), `data.js` (раскладки, слова и тексты упражнений), `styles.css` (оформление). Слова и предложения для упражнений можно править в `data.js`. Установка на сервер описана в `docs/DEPLOY.md`.
|
||||
Reference in New Issue
Block a user