Установка
Страница для того, кто ставит коробку на сервер. Она честнее обычной инструкции в одном: установка дважды проходила на живом сервере, и всё, что там сломалось, описано здесь, а не сглажено.
Главное правило: чек-лист ниже проходится до установки. Каждый его пункт стоит десяти минут, а найденный после установки — нескольких часов.
Что нужно от сервера #
| Минимум | Комфортно | |
|---|---|---|
| Ядра | 2 | 4 |
| Память | 4 ГБ | 8 ГБ |
| Свободный диск | 20 ГБ | 40 ГБ |
| ОС | Ubuntu 22.04 / 24.04, Debian 12 | — |
| Docker | 24+ с плагином compose v2 | 29+ |
Память — про сборку, а не про работу. Работающая установка укладывается примерно в 1,5 ГБ. Сборка образа съедает 2–3 ГБ разом: если на сервере уже что-то живёт, сборка на нём — самый быстрый способ уронить соседей.
Чек-лист до установки #
1. Время синхронизировано #
timedatectl
Нужно System clock synchronized: yes. Это не формальность: одноразовые коды
двухфакторной защиты ломаются при расхождении больше 30 секунд — владелец
не сможет войти в собственную админку. Плюс от часов сервера считаются сроки
доступа и отложенные события, а Let's Encrypt не выпустит сертификат при заметном
расхождении.
Синхронизация может быть настроена и при этом не работать. На сервере первой установки служба была активна, а стандартные серверы времени с этой машины не отвечали вовсе. Лечится указанием доступного:
mkdir -p /etc/systemd/timesyncd.conf.d
printf '[Time]\nNTP=time.cloudflare.com\n' > /etc/systemd/timesyncd.conf.d/10-reachable-ntp.conf
systemctl restart systemd-timesyncd
timedatectl timesync-status
Часовой пояс сервера при этом значения не имеет: приложение работает в UTC и показывает даты в поясе школы. Обязательна именно синхронность.
2. Место и память #
df -h /
free -h
20 ГБ свободных. И решите здесь же, собирается образ на этом сервере (нужно ещё 3 ГБ памяти) или переносится готовым с другой машины.
3. Порты #
ss -ltnp | grep -E ':(80|443|5432|6379|3000)\b'
- 80 и 443 нужны, если установка ставит свой прокси. Заняты чужим прокси — это отдельный сценарий, см. ниже.
- 5432 и 6379 наружу не нужны вообще: PostgreSQL и Redis живут во внутренней сети Docker и портов на хост не публикуют. Если 5432 занят чужой базой — это нам не мешает.
4. Домен #
A-запись домена должна указывать на этот сервер до установки: без этого сертификат не выпустится.
getent hosts school.example.com
curl -s https://ifconfig.me
Два адреса должны совпасть. Домен за проксирующим DNS или CDN — выпуск сертификата пойдёт иначе, и это надо решить заранее, а не в момент установки.
5. Исходящая связь #
curl -s -o /dev/null -w '%{http_code}\n' https://api.resend.com
timeout 6 bash -c '</dev/tcp/smtp.yandex.ru/587' && echo "587 открыт" || echo "587 закрыт"
Закрытый исходящий SMTP — норма, а не поломка. У многих хостеров порты 25, 465, 587 и 2525 закрыты по умолчанию и открываются по заявке. На сервере первой установки закрыты были все четыре, до всех проверенных провайдеров, при работающем исходящем HTTPS. Если письма нужны — либо открывайте порт заявкой хостеру, либо берите провайдера, который принимает письма по HTTPS.
6. Откуда ставится #
Из чистого клона репозитория, а не из папки, где кто-то пишет код. Рабочая копия
содержит свой .env, свои node_modules и незакоммиченные правки: установка
перепишет первое и споткнётся о третьем. Проверено дорогой ценой на первой же
установке.
Установка за уже работающим прокси #
Отдельный сценарий, и он не автоматизирован. Если 80 и 443 уже занял чужой Traefik, Nginx или Caddy, автоматический установщик неприменим: он рассчитывает, что порты его. Порядок в этом случае ручной — коробка поднимается без своего прокси, а маршрут к ней добавляется в уже стоящий.
Это ровно тот случай, который встретился на первой установке, и он оказался не редким: сервер, где живёт только школа и больше ничего, — исключение, а не правило.
Первая проверка #
Убедиться, что встало верно, можно не заводя ни одного ученика:
- страница входа открывается по вашему домену, сертификат настоящий;
http://отдаёт перенаправление наhttps://, а не страницу;- владелец вошёл и настроил двухфакторную защиту сам — см. предупреждение ниже;
- в админке видно состояние очередей и фоновых задач;
- создался тестовый курс с одним уроком, и урок открывается.
Предупреждение, которое дороже остальных #
Кто первым вошёл — тот и владеет школой. Первый вход настраивает двухфакторную защиту на себя, и перенастроить её на другого человека средствами продукта сейчас нельзя: войти по паролю можно, а перепривязать второй фактор — нет.
Практически это значит: первый вход делает тот, кто останется владельцем школы, а не подрядчик, который ставит. Школа, у которой уволился техспециалист, настроивший двухфакторку на себя, останется без доступа к собственной админке.
Это находка первой установки, она известна и чинится. Пока не починена — порядок входа решает всё.
Обновление #
Раздел не написан, и это не забывчивость.
Порядок обновления работающей установки с данными ещё не проверен: второй заход установки — обновление поверх непустой базы — в паузе. Описывать желаемый порядок вместо проверенного нельзя: обновление важнее установки, потому что ставят один раз, а обновляют десятки.
Что известно точно уже сейчас:
- обновление — ваше событие, а не наше: оно не приходит само;
- миграции базы генерируются, а не пишутся руками, и применяются отдельным шагом;
- перед обновлением снимается резервная копия, и её восстановимость надо проверить, а не предположить.
Когда порядок будет пройден на живой установке с данными, здесь появятся шаги с замерами простоя и поведением при упавшей на середине миграции.