Deploy MkDocs to VPS / deploy (push) Successful in 7s
- Зачем: восстановлен доступ к GitHub, изменились учебные стенды и требования к основной программе. - Что: ссылки для менти возвращены на GitHub; ClickHouse, Kafka и курсовая Clickstream включены в основную программу; уточнены подготовка окружения Python, управление памятью, практика Airflow и вход в DEV1. - Что: обновлены описание публикации через Gitea и бэклог; убрана ссылка на неподходящий курс ClickHouse. - Проверка: строгая сборка MkDocs и проверка пробелов прошли; ссылки и задания сверены с учебными репозиториями.
127 lines
15 KiB
Markdown
127 lines
15 KiB
Markdown
# Публикация сайта через Gitea Actions и VPS
|
||
|
||
Статус: публикация на VPS реализована 2026-08-05. После восстановления
|
||
доступа к GitHub выбран встроенный push mirror Gitea для синхронизации
|
||
репозиториев; рабочий origin остается в Gitea. Инструкции по
|
||
восстановлению и эксплуатации находятся в
|
||
[`project/ops/gitea-vps-site/README.md`](../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.
|