# Деплой 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 /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 # backup → сборка → миграции → перезапуск ``` `deploy.sh up` **обязательно** делает backup перед обновлением. Если backup завершился ошибкой, деплой прерывается. Миграции БД (Flyway) применяются автоматически при старте сервисов. ## 8. Резервное копирование Полная инструкция — [`BACKUP.md`](BACKUP.md). Кратко: ```bash ./deploy/backup.sh backup # БД + решения + материалы ./deploy/backup.sh list ./deploy/backup.sh verify ./deploy/backup.sh restore # destructive, требует ввода RESTORE ``` Backup включает `pg_dump` БД, volume решений и volume материалов, контрольные суммы и manifest. По умолчанию хранится 14 дней (`LMS_BACKUP_KEEP_DAYS`), каталог — `/opt/lms/backups` (`LMS_BACKUP_DIR`). Ежедневное расписание: ```bash sudo cp deploy/systemd/lms-backup.service deploy/systemd/lms-backup.timer /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now lms-backup.timer ``` Backup на том же сервере — не единственная защита: настройте выгрузку на отдельный хост и периодически проверяйте восстановление на staging. ## 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.