Files
LMS/deploy/DEPLOY.md
Vladislav Kopnin cdf4fb0ee0 Phase 7: deployment, data import, UI hardening and security fixes
Docker/prod deployment:
- multi-stage Dockerfile (JDK21 build, JRE21 run), docker-compose.prod.yml,
  nginx config for lms.our-place.ru, deploy.sh; DEPLOY/IMPORT guides (UI flow)
- Fix Docker 401: LMS_JWT_JWK_SET_URI for academic/progress; forward-headers

Variant distribution (lab page only):
- round-robin by student level, shared random queue across selected groups,
  least-used variants, manual pins always preserved; occupied/dup labels
- setup page: single form + one «Сохранить всё», batch level/variant for
  selected students (checkboxes)

Grades, defense, materials:
- publication gate + comment lists; defense CSV import (2/3 cols, quotes)
- additional task after defense ("начать заново"); enroll/unenroll students
  from group page; temporary-password lock (no navigation until changed) and
  persistent "Смена пароля"; forced change once
- chapter page /learn/{c}; header: LMS home, Войти, user -> dashboard,
  compact theme toggle; responsive mobile header
- markdown: single newlines are soft breaks; highlight.js with light/dark themes
- lab/content imports ZIP-only (lab.yaml+README+variants/assets,
  chapters tree+assets); duplicate lab numbers rejected; variant ordering
  and date defaults honored

Fixes:
- 500 on student create (@MapsId set before persist); broken dialogs/JS refs in group page
2026-09-15 00:09:28 +03:00

146 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Деплой LMS на сервер `lms.our-place.ru`
Стек целиком запускается в Docker. **Java на сервере не устанавливается** — приложение
собирается и работает внутри контейнеров (multi-stage `Dockerfile`: сборка на JDK 21,
запуск на JRE 21).
Компоненты:
| Сервис | Контейнер | Наружу |
|---|---|---|
| web (Thymeleaf UI) | `lms-web` | `127.0.0.1:8090` (проксирует nginx) |
| gateway | `lms-gateway` | нет |
| identity / academic / progress | `lms-*` | нет |
| PostgreSQL 18 | `lms-postgres` | нет |
Данные лежат в именованных volume: `lms_pgdata` (БД), `lms_submissions` (решения),
`lms_assets` (картинки материалов).
---
## 0. Что нужно
- Сервер с Ubuntu 22.04/24.04 (или другим Linux с Docker), sudo/root.
- Домен `lms.our-place.ru`, A-запись которого указывает на IP сервера.
- Открытые порты 80 и 443 (443 — если настраиваете HTTPS).
## 1. Установка Docker
```bash
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker "$USER" # перелогиньтесь, чтобы работать без sudo
docker compose version # нужна версия v2
```
## 2. Получить код
```bash
sudo mkdir -p /opt/lms && sudo chown "$USER" /opt/lms
git clone <URL-репозитория> /opt/lms
cd /opt/lms
```
## 3. Настроить окружение
```bash
cp .env.prod.example .env.prod
nano .env.prod
```
Обязательно задайте надёжный `LMS_DB_PASSWORD`. Остальные значения по умолчанию подходят.
## 4. Собрать и запустить
```bash
./deploy/deploy.sh up
```
Скрипт соберёт образы (первый раз ~5–15 минут: скачиваются Gradle и зависимости)
и поднимет контейнеры. Проверка:
```bash
docker compose -f docker-compose.prod.yml --env-file .env.prod ps
curl -fsS http://127.0.0.1:8090/actuator/health # {"status":"UP",...}
```
## 5. Nginx + HTTPS
```bash
sudo apt-get update && sudo apt-get install -y nginx certbot python3-certbot-nginx
sudo mkdir -p /var/www/certbot
sudo cp deploy/nginx/lms.our-place.ru.conf /etc/nginx/sites-available/lms.our-place.ru.conf
sudo ln -sf /etc/nginx/sites-available/lms.our-place.ru.conf /etc/nginx/sites-enabled/lms.our-place.ru.conf
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d lms.our-place.ru --redirect -m admin@our-place.ru --agree-tos
```
`certbot --nginx` сам добавит TLS-блок и редирект с HTTP на HTTPS. Автопродление
уже настроено пакетом (`systemctl status certbot.timer`).
## 6. Первый запуск приложения
Откройте `https://lms.our-place.ru` → откроется `/setup` → создайте администратора.
## 6a. Наполнение данными
Дальше всё через интерфейс: импорт групп (`.xls`), импорт лабораторной ZIP'ом,
раздача вариантов, оценки и защита, материалы. Подробный порядок с проверками —
в [`IMPORT.md`](IMPORT.md). Файлы со списками студентов и выгрузками паролей —
персональные данные, держите их вне репозитория.
## 7. Обновление версии
```bash
cd /opt/lms
git pull
./deploy/deploy.sh up # пересоберёт изменённые образы и перезапустит
```
Миграции БД (Flyway) применяются автоматически при старте сервисов.
## 8. Резервное копирование
```bash
# БД
docker compose -f docker-compose.prod.yml --env-file .env.prod exec -T postgres \
pg_dump -U "$LMS_DB_USER" "$LMS_DB_NAME" | gzip > lms-$(date +%F).sql.gz
# Файлы (решения и материалы)
docker run --rm -v lms_lms_submissions:/sub -v lms_lms_assets:/assets -v "$PWD":/backup alpine \
tar czf /backup/lms-files-$(date +%F).tar.gz -C / sub assets
```
Восстановление БД: `gunzip -c backup.sql.gz | docker compose ... exec -T postgres psql -U lms lms`.
## 9. Диагностика
```bash
./deploy/deploy.sh ps
./deploy/deploy.sh logs web
./deploy/deploy.sh logs gateway
./deploy/deploy.sh logs identity
```
Типичные проблемы:
- **web отдаёт 502 через nginx** — контейнер `web` не поднялся: смотрите `logs web`.
Часто причина — занят порт 8090 или не задан `LMS_DB_PASSWORD` (compose не стартует).
- **Страница входа открывается, но запросы падают** — проверьте `logs gateway` и
`logs identity`; gateway должен получить JWKS от identity.
- **401 на страницах после входа (Docker)** — у backend-сервисов не задан адрес
JWKS: должно быть `LMS_JWT_JWK_SET_URI=http://identity:8081/api/v1/auth/jwks.json`
(уже прописано в `docker-compose.prod.yml` для academic/progress/gateway).
Внутри контейнера `localhost:8081` недоступен, поэтому токен не проверяется.
- **Не проходят загрузки больших ZIP** — увеличьте `client_max_body_size` в nginx
(сейчас 120 МБ) и `spring.servlet.multipart.max-request-size`.
## Замечания по безопасности
- PostgreSQL наружу не публикуется; связь между контейнерами — по внутренней сети `lms`.
- Публикуется только `127.0.0.1:8090`, доступ снаружи — исключительно через nginx/TLS.
- `.env.prod` содержит пароль БД и не коммитится (в `.gitignore`).
- Пароль администратора задаётся вами на шаге 6; хранение — BCrypt.