Files
LMS/deploy/DEPLOY.md
Vladislav Kopnin d04207302a 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

6.3 KiB
Raw Blame History

Деплой 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

curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker "$USER"   # перелогиньтесь, чтобы работать без sudo
docker compose version            # нужна версия v2

2. Получить код

sudo mkdir -p /opt/lms && sudo chown "$USER" /opt/lms
git clone <URL-репозитория> /opt/lms
cd /opt/lms

3. Настроить окружение

cp .env.prod.example .env.prod
nano .env.prod

Обязательно задайте надёжный LMS_DB_PASSWORD. Остальные значения по умолчанию подходят.

4. Собрать и запустить

./deploy/deploy.sh up

Скрипт соберёт образы (первый раз ~5–15 минут: скачиваются Gradle и зависимости) и поднимет контейнеры. Проверка:

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

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. Файлы со списками студентов и выгрузками паролей — персональные данные, держите их вне репозитория.

7. Обновление версии

cd /opt/lms
git pull
./deploy/deploy.sh up        # пересоберёт изменённые образы и перезапустит

Миграции БД (Flyway) применяются автоматически при старте сервисов.

8. Резервное копирование

# БД
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. Диагностика

./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.