- Зачем: восстановлен доступ к GitHub, изменились учебные стенды и требования к основной программе. - Что: ссылки для менти возвращены на GitHub; ClickHouse, Kafka и курсовая Clickstream включены в основную программу; уточнены подготовка окружения Python, управление памятью, практика Airflow и вход в DEV1. - Что: обновлены описание публикации через Gitea и бэклог; убрана ссылка на неподходящий курс ClickHouse. - Проверка: строгая сборка MkDocs и проверка пробелов прошли; ссылки и задания сверены с учебными репозиториями.
15 KiB
Публикация сайта через Gitea Actions и VPS
Статус: публикация на VPS реализована 2026-08-05. После восстановления
доступа к GitHub выбран встроенный push mirror Gitea для синхронизации
репозиториев; рабочий origin остается в Gitea. Инструкции по
восстановлению и эксплуатации находятся в
project/ops/gitea-vps-site/README.md.
Проблема
Сайт de.dementev.space публиковался через GitHub Actions и GitHub Pages. После блокировки учётной записи GitHub основной домен стал недоступен, хотя исходный Markdown и конфигурация MkDocs сохранились, а основной Git-репозиторий уже размещён в собственной Gitea.
Публикация сайта не должна зависеть от доступности учётной записи GitHub. При этом рабочий процесс из исходной архитектуры сохраняется: изменение попадает в main, сайт собирается и обновляется автоматически без отдельного ручного деплоя.
Цели
- Публиковать
de.dementev.spaceс существующей VPS. - Запускать сборку и публикацию автоматически после push в
mainв Gitea. - Не заменять работающую версию сайта, если получение исходников или строгая сборка MkDocs завершились ошибкой.
- Ограничить права runner каталогами, необходимыми для сборки и публикации сайта.
- Сохранить GitHub Pages как заранее собираемый резерв на случай проблем с VPS.
- Сохранить минимальные накладные расходы и нулевые дополнительные расходы на хостинг.
Не цели
- Автоматическое переключение между VPS и GitHub Pages.
- Жёсткие требования к времени восстановления или высокой доступности.
- Перенос еженедельной проверки внешних ссылок с GitHub Actions в Gitea Actions.
- Изменение существующих файлов в
.github/workflows/. - Добавление динамического приложения, авторизации или серверной базы данных.
Исходное состояние на 2026-08-04
- MkDocs Material собирает статический каталог
site/;site_urlуже равенhttps://de.dementev.space/. - Публичный репозиторий
ddmitry/de-roadmapв Gitea является текущимorigin. - Gitea Actions для репозитория включены, но подходящего runner пока нет.
- Gitea видит существующие GitHub workflows, однако они зависят от GitHub Pages, GitHub-токенов и сторонних actions.
- На VPS, выбранной для сайта, пока нет HTTP-сервера; публично доступен только SSH.
Выбранное решение
Основной контур публикации
Gitea становится источником событий для основной публикации. На VPS с сайтом работает repository-scoped Gitea runner, зарегистрированный только для de-roadmap. Runner использует host mode и отдельную метку, предназначенную только для этого workflow.
Workflow хранится отдельно в .gitea/workflows/deploy-site.yml. Gitea выбирает .gitea/workflows раньше .github/workflows, поэтому GitHub-specific workflows сохраняются в репозитории, но не исполняются Gitea.
Workflow запускается после push в main и вручную. Он получает конкретный commit из публичного Gitea-репозитория обычным Git, создаёт изолированное Python-окружение, устанавливает закреплённые версии зависимостей и выполняет строгую сборку MkDocs. Сторонние uses: не применяются, поэтому сборка не зависит от GitHub Actions Marketplace.
Изоляция runner
Runner работает как отдельный непривилегированный системный пользователь. У него нет sudo, членства в группе docker и доступа на запись к конфигурации nginx, сертификатам или другим сервисам VPS.
Пользователь runner может записывать только в собственный рабочий каталог и каталог релизов сайта. Workflow не запускается для pull request из недоверенных веток. Потребление памяти, CPU и количество процессов ограничиваются средствами менеджера сервисов операционной системы.
Публикация и восстановление после ошибки
Каждая успешная сборка создаёт отдельную версию статического сайта. Новая версия становится активной только после завершения всех проверок. Переключение между версиями выполняется атомарно; частично собранный каталог никогда не становится корнем сайта.
Ошибка получения исходников, установки зависимостей или сборки оставляет активной предыдущую версию. Как минимум одна предыдущая успешная версия сохраняется для быстрого ручного отката.
HTTP и HTTPS
Статические файлы обслуживает штатный nginx из репозитория Ubuntu. Nginx только читает активную версию сайта и не требует перезагрузки при обычной публикации контента.
TLS-сертификат для de.dementev.space получает и продлевает Certbot с интеграцией nginx. Перед переключением проверяются локальная сборка и конфигурация nginx, а DNS TTL заранее уменьшается. Затем DNS направляется на VPS, проверяется публичная доступность по HTTP и выпускается сертификат. Короткий интервал между переключением DNS и готовностью HTTPS допустим, поскольку жёсткого требования к непрерывной доступности нет.
Резерв на GitHub Pages
Изменения из основной Gitea передаются на GitHub встроенным push mirror.
Ссылки для учащихся ведут на GitHub-зеркала, основной домен остается на VPS.
Workflow в .github/workflows/deploy-site.yml сохранен для резервной
публикации. Перед использованием резерва нужно проверить настройки Pages
и успешный деплой: наличие зеркала репозитория само по себе этого не подтверждает.
GitHub Pages считается тёплым резервом контента и холодным резервом домена. При отказе VPS владелец вручную переключает DNS и при необходимости повторно активирует custom domain в настройках GitHub Pages. Допустимы задержка распространения DNS и ожидание выпуска TLS-сертификата; автоматический failover не требуется.
Отклонённые варианты
- Периодический pull с VPS: проще инфраструктурно, но не даёт опыта работы с Gitea runner и менее наглядно связывает push с результатом сборки.
- Runner рядом с Gitea: усложняет доставку результата на VPS и позволяет сборкам влиять на ресурсы Git-сервера.
- Jobs в Docker: дают лучшую изоляцию, но требуют доступа runner к Docker и отдельного механизма передачи результата в каталог nginx. Для одного доверенного репозитория это лишняя сложность.
- Caddy вместо nginx: упрощает автоматический TLS, но штатный nginx лучше соответствует предпочтению владельца и доступен с обновлениями безопасности из основного репозитория Ubuntu. Certbot закрывает задачу TLS отдельно.
- Cloudflare Pages, GitLab Pages или другой внешний Pages-сервис: уменьшают нагрузку на VPS, но добавляют новую внешнюю учётную запись и зависимость, от которой как раз уходим.
- Ожидание разблокировки GitHub: сохраняет старую архитектуру, но оставляет сайт недоступным на неопределённый срок.
Риски и меры
| Риск | Мера |
|---|---|
| Workflow исполняет команды непосредственно на VPS | Repository-scoped runner, отдельный пользователь без sudo и Docker, узкие права на запись, запуск только из main, системные лимиты ресурсов |
| Ошибка сборки ломает опубликованный сайт | Сборка в отдельной версии и атомарное переключение только после успеха |
| Сторонний action выполняет неожиданный код | Workflow состоит из собственных команд и не использует uses: |
| Gitea временно недоступна | Уже опубликованный сайт обслуживается независимо от Gitea |
| VPS недоступна или потеряна | Исходники остаются в Gitea; GitHub Pages служит ручным резервом после проверки резервной публикации |
| После переключения DNS HTTPS ещё не готов | DNS TTL уменьшается заранее; Certbot запускается сразу после подтверждения публичного HTTP; короткий перерыв принят как допустимый |
| Сертификат GitHub Pages не готов во время аварии | Допускается задержка; на время восстановления используется стандартный адрес GitHub Pages |
| GitHub-резерв отстает от Gitea | Проверяем результат push mirror, совпадение коммитов и резервную сборку; до успешной проверки резерв не считается готовым |
Проверка реализации
- Runner после перезагрузки VPS автоматически подключается к Gitea и принимает только jobs с выделенной меткой.
- Push тестового изменения в
mainзапускает ровно один Gitea workflow и публикует соответствующий commit. - Gitea не запускает workflows из
.github/workflows/, а сами файлы остаются без изменений. - Workflow не обращается к GitHub за actions и не требует GitHub-токенов.
- Ошибка
mkdocs build --strictзавершает workflow с ошибкой и не изменяет публичную версию сайта. - Успешная сборка переключает сайт целиком, без периода частично обновлённого содержимого.
- Пользователь runner не может использовать
sudo, Docker или изменять конфигурацию nginx. https://de.dementev.space/отдаёт собранный сайт с действующим сертификатом после переключения DNS.- Nginx и runner восстанавливаются после перезагрузки VPS без ручного запуска.
- После восстановления GitHub и настройки синхронизации резервная сборка получает тот же commit и остаётся доступна по стандартному адресу GitHub Pages.
Влияние на документацию
Эта спецификация заменяет решения о публикации и custom domain из project/ADR.md. Решения того документа о MkDocs Material, структуре файлов и dual-compatible links остаются актуальными.
Документация проекта описывает Gitea Actions и VPS как основной контур
публикации. Ссылки репозитория в mkdocs.yml направлены на GitHub для менти;
рабочий origin остается в Gitea.
Синхронизация GitHub
Способ синхронизации выбран: встроенный Gitea push mirror. Рабочие изменения вносятся в Gitea, GitHub используется как зеркало для чтения и создания учебных форков. Нужно отдельно проверить работу зеркал всех стендов и готовность резервной публикации Pages.