From 8584fc225b90e6af3ab0e15399423c5a63752470 Mon Sep 17 00:00:00 2001 From: Dmitry Dementev Date: Tue, 4 Aug 2026 10:01:58 -0400 Subject: [PATCH] =?UTF-8?q?docs(project):=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D1=81=D0=BF=D0=B5=D1=86=D0=B8=D1=84?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BF=D1=83=D0=B1=D0=BB?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D0=B8=20=D1=81=D0=B0=D0=B9=D1=82?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Зачем: - нужен согласованный вариант публикации сайта без зависимости от GitHub Pages. - Что: - описан контур Gitea Actions, host runner, nginx и резерв на GitHub Pages. - в архитектурный документ добавлена ссылка на новую спецификацию. - Проверка: - git diff --cached --check. --- project/ADR.md | 3 + .../2026-08-04-gitea-vps-site-publishing.md | 114 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 project/specs/2026-08-04-gitea-vps-site-publishing.md diff --git a/project/ADR.md b/project/ADR.md index 3292cd4..2cbe409 100644 --- a/project/ADR.md +++ b/project/ADR.md @@ -1,6 +1,9 @@ # ADR: Архитектура сайта de-roadmap > Архитектурный документ. Проектные цели и требования — в [PRD](./PRD.md). +> Решения о публикации и custom domain заменены спецификацией +> [«Публикация сайта через Gitea Actions и VPS»](./specs/2026-08-04-gitea-vps-site-publishing.md). +> Решения о MkDocs, структуре файлов и ссылках остаются актуальными. --- diff --git a/project/specs/2026-08-04-gitea-vps-site-publishing.md b/project/specs/2026-08-04-gitea-vps-site-publishing.md new file mode 100644 index 0000000..e70f104 --- /dev/null +++ b/project/specs/2026-08-04-gitea-vps-site-publishing.md @@ -0,0 +1,114 @@ +# Публикация сайта через Gitea Actions и VPS + +Статус: согласовано 2026-08-04; механизм синхронизации GitHub-резерва +требует отдельного решения после восстановления доступа к GitHub. + +## Проблема + +Сайт `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/`. +- Добавление динамического приложения, авторизации или серверной базы данных. + +## Текущее состояние + +- 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 + +После восстановления доступа к GitHub существующий GitHub workflow продолжает собирать сайт из GitHub-репозитория. Чтобы резерв оставался актуальным, изменения из основной Gitea должны автоматически синхронизироваться с GitHub. Предпочтительный кандидат — встроенный Gitea push mirror; окончательный механизм и его права будут согласованы отдельно после восстановления учётной записи. Резерв доступен по стандартному адресу GitHub Pages, но основной домен направлен на VPS. + +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 служит ручным резервом после восстановления GitHub | +| После переключения DNS HTTPS ещё не готов | DNS TTL уменьшается заранее; Certbot запускается сразу после подтверждения публичного HTTP; короткий перерыв принят как допустимый | +| Сертификат GitHub Pages не готов во время аварии | Допускается задержка; на время восстановления используется стандартный адрес GitHub Pages | +| GitHub-резерв отстаёт от Gitea | После восстановления GitHub настраивается автоматическая синхронизация; до выбора механизма резерв не считается тёплым | + +## Проверка реализации + +- 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 остаются актуальными. + +После реализации нужно обновить `AGENTS.md`, `project/PRD.md` и `project/TODO.md`, чтобы они описывали фактический основной контур публикации. Ссылку на исходный репозиторий в `mkdocs.yml` следует направить на Gitea; ссылку на GitHub можно сохранить как дополнительную после восстановления доступа. + +## Открытый вопрос + +После восстановления GitHub нужно окончательно выбрать способ автоматической синхронизации резервного репозитория. Базовый кандидат — Gitea push mirror с синхронизацией при каждом push; GitHub при этом становится read-only зеркалом, поскольку mirror перезаписывает расходящиеся изменения. -- 2.54.0