↓ Перейти к основному содержимому
  1. Posts/
  2. Self-Hosting/

Когда проще - не значит лучше. Возвращаюсь на два репозитория Forgejo

·1182 слов·6 минут· loading · loading · ·
Stilicho2011
Автор
Stilicho2011
Пишу о homelab, self-hosting, автоматизации и open-source решениях
Оглавление
Автоматизация публикации ProHomelab - This article is part of a series.
Part : This Article

Итог статьи 3 - и первые сомнения
#

В третьей статье цикла я объединил два репозитория - prohomelab-content и prohomelab-site - в один репозиторий prohomelab-pages-new, поставил self-hosted GitHub Actions раннер прямо на LXC, и в итоге весь цикл - от заметки в Obsidian до опубликованной статьи - заработал полностью автоматически. На бумаге это было улучшением. Вроде бы. Один репозиторий вместо двух, никакого workflow_dispatch-моста между ними.

На практике за один вечер я получил: self-hosted раннер, который отказывается стартовать от root; путаницу между встроенным Jekyll-автосборщиком GitHub и своим workflow; проблему в самом Hugo с полем published; и - самое неприятное - NTFS junction, который Obsidian просто не показывает, из-за чего на несколько минут мне показалось, что пропали все статьи. Ничего не потерялось безвозвратно (git-история никуда не девается), но эмоционально это была самая нервная часть всего цикла.

Когда все заработало, я честно спросил себя: а стоило ли оно того? Сравнил оба варианта по пунктам:

Вариант 3 (статья): self-hosted GH Actions, один репозиторийВариант 2 (статьи 1-2): два репозитория на Forgejo
Репозитории1 (prohomelab-pages-new)2 (prohomelab-content, prohomelab-site)
Кто собираетself-hosted раннер на LXC, зарегистрированный в GitHubforgejo-runner на том же LXC, другой процесс
Безопасность раннерариск через PR у публичных репо (у меня нет pull_request-триггера, но все-таки)Forgejo приватный - риска с публичными форками нет
Obsidiansparse-checkout, лишний уровень вложенности content/postsобычный клон, плоская структура, без вложенности
Проверено в боюда, но всего один вечерда, это ровно то, что уже стабильно работало раньше
Хрупкие местаPAT-токены на Windows, systemd-сервис раннера, TOML рукамиworkflow_dispatch между репозиториями, git push из CI в GitHub Pages

Вывод получился не в пользу нового варианта. Он дал заметно скромный выигрыш (один репозиторий вместо двух) ценой ощутимо большего числа мест, которые могут сломаться. Старая схема надежнее.

Возвращаем контент в Forgejo
#

Первая проблема отката - за время эксперимента я продолжал писать в Obsidian, и весь новый контент (правки в доброй паре десятков статей, черновики «Docker vs Podman vs Kubernetes», «Quadlets vs Podlets», вторая статья цикла, исправленная дата в посте про Arcane) существовал только в prohomelab-pages-new на GitHub - в prohomelab-content на Forgejo его не было.

Решение - обычный rsync без флага --delete, чтобы гарантированно ничего не стереть, только добавить:

cd /home/prohomelab
git pull github main

cd /home
git clone https://forgejo.stilicho.ru/stilicho/prohomelab-content.git prohomelab-content-sync

rsync -av /home/prohomelab/content/posts/ /home/prohomelab-content-sync/
cd /home/prohomelab-content-sync
git status

git status перед коммитом - обязательный шаг, а не формальность. В моем случае он показал не только ожидаемые правки, но и пару неожиданностей - задвоенные файлы с суффиксом " 1" (похоже на типичное поведение Obsidian при конфликте одной и той же заметки в двух местах) и лишнюю вложенную папку. Ничего критичного, но все-таки лучше увидеть это до коммита, чем после.

Раннер и деплой - проблема в старом workflow
#

Включил forgejo-runner обратно (systemctl enable/start) - и он тут же сработал сам, по старому межрепозиторному триггеру, который все это время оставался живым на стороне Forgejo.

Дальше начал править .forgejo/workflows/deploy.yml, готовясь заменить FTP-деплой на git push - и обнаружил, что деплой уже был переделан на git push в GitHub Pages еще раньше, до всей этой истории с третьей статьей. Просто указывал на prohomelab-pages (без -new) - тот самый репозиторий, который я удалил в самом начале эксперимента с self-hosted раннером. Отсюда и была самая первая ошибка сегодняшнего дня: repository 'prohomelab-pages.git' not found.

Смержил обе версии workflow (у меня в локальной копии была свежая с git push, на Forgejo - старая, тоже с git push, но в другой репозиторий и с деплоем в main, а не в отдельную ветку). Итоговый шаг деплоя:

- name: Deploy to GitHub Pages
  env:
    GH_PAGES_TOKEN: ${{ secrets.GH_PAGES_TOKEN }}
  run: |
    cd public
    git init -q
    git checkout -q -b gh-pages
    git -c user.name="prohomelab-bot" -c user.email="bot@prohomelab.com" add -A
    git -c user.name="prohomelab-bot" -c user.email="bot@prohomelab.com" commit -q -m "Deploy $(date -u +%Y-%m-%dT%H:%M:%SZ)"
    git push --force "https://stilicho2011:${GH_PAGES_TOKEN}@github.com/stilicho2011/prohomelab-pages-new.git" gh-pages:gh-pages

Один нюанс, который я не сразу заметил. Шаг сборки в моем собственном примере выше - hugo -D --minify. Флаг -D («build drafts») заставляет Hugo включать в сборку все статьи с draft: true, независимо от buildDrafts = false в конфиге - флаг командной строки перебивает настройку конфига. То есть с этим флагом любой черновик, лежащий в репозитории, тут же публикуется на живом сайте. Убрал -D из реального workflow, как только заметил:

sed -i 's/hugo -D --minify/hugo --minify/' .forgejo/workflows/deploy.yml

Мелочь, но именно из таких мелочей и складывается ощущение «вроде все работает, но как-то не так» - сайт собирался и деплоился без единой ошибки, просто заодно публиковал то, что публиковаться не должно.

Ключевое решение - деплоить именно в отдельную ветку gh-pages, не в main: в main prohomelab-pages-new теперь лежат исходники Hugo (тема, конфиг), а не собранный сайт. Затереть их собранным HTML было бы шагом назад.

Секрет GH_PAGES_TOKEN пришлось пересоздать - старый был выдан под удаленный репозиторий и не годился. В Forgejo секреты нельзя отредактировать на месте, только удалить и создать заново с тем же именем.

GitHub Pages. Снова путаница с Source
#

После первого успешного деплоя зашел в Settings → Pages - и увидел то же самое «currently being built from the main branch», что и в начале истории с self-hosted раннером. Выпадающий список веток при сохранении почему-то не подхватил gh-pages, оставшись на дефолтной main. Пришлось выбрать явно. Мелочь, но второй раз за один цикл статей наступить на одни и те же грабли с source-настройками - забавное совпадение.

Obsidian. Назад к плоской структуре
#

Финальный шаг - вернуть Obsidian к обычному клону prohomelab-content, без sparse-checkout и без вложенности:

Rename-Item Prohomelab Prohomelab-github-experiment-backup
git clone https://forgejo.stilicho.ru/stilicho/prohomelab-content.git Prohomelab

Тут я поймал еще один мелкий, но раздражающий баг - Windows Credential Manager закэшировал refresh_token для forgejo.stilicho.ru, который к этому моменту протух, и Git тихо подставлял его вместо того, чтобы спросить заново. Симптом - Authentication failed, при том что сам токен для ручного использования был рабочим. Вылечил точечным удалением конкретной записи:

cmdkey /list | Select-String "forgejo"
cmdkey /delete:LegacyGeneric:target=git:https://refresh_token.forgejo.stilicho.ru

После этого клонирование прошло с первого раза, структура вернулась ровно такой, какой была до всех экспериментов - категории статей прямо в корне Prohomelab, без content/posts.

Итоговая схема
#

Obsidian (Windows) → push
        │
        ▼
Forgejo: prohomelab-content
        │  workflow_dispatch (notify.yml)
        ▼
Forgejo: prohomelab-site
        │  forgejo-runner (LXC)
        │  checkout → sync-content.sh → hugo --minify → git push (gh-pages)
        ▼
GitHub: prohomelab-pages-new, ветка gh-pages
        │  Pages Source: Deploy from a branch
        ▼
prohomelab.com

Внешне это почти то же самое, с чем цикл начинался в первой и второй статьях - только вместо FTP на smartape деплой идет git push собранного сайта в отдельную ветку GitHub-репозитория. Self-hosted раннер, объединенный репозиторий и sparse-checkout из статьи 3 оставлены как пройденный, задокументированный, но не выбранный для продакшена путь.

Стоило ли вообще пробовать
#

Ну скорее да, чем нет - при том что закончилось все откатом. Телодвижения, описанные в статье 3, не были ошибкой. Без них я бы не узнал, что self-hosted раннер требует непривилегированного пользователя, что Obsidian не переваривает NTFS junction, и что published в Hugo - заминированное поле. Эти находки остаются полезными сами по себе, независимо от того, какая архитектура в итоге прижилась. Ну то есть знания точно обогатил. Но как постоянная схема для личного блога - два скучных репозитория на Forgejo с проверенным git push оказались правильнее одного модного self-hosted GitHub Actions. По крайней мере для меня это оказался в итоге самый оптимальный вариант.

Автоматизация публикации ProHomelab - This article is part of a series.
Part : This Article

Related

Убираем лишнее звено: переезжаем со своего Forgejo-раннера на self-hosted GitHub Actions

·1832 слов·9 минут· loading · loading
Как я перевел сборку и деплой ProHomelab с самодельного Forgejo-раннера на self-hosted GitHub Actions runner прямо на своем LXC, объединил content и site в один репозиторий - и что из этого пошло не по плану.

ProHomelab: автоматизация публикации статей через Forgejo

·4948 слов·24 минут· loading · loading
Полностью автоматизирую публикацию ProHomeLab: пишу статью в Obsidian, изменения автоматически попадают в Forgejo, Forgejo Actions запускает сборку Hugo на Blowfish LXC, а готовый сайт без ручного участия загружается на хостинг от Smartape.

Установка Hugo + тема Blowfish с нуля: подробная инструкция

··2434 слов·12 минут· loading · loading
Разворачиваю Hugo Extended и тему Blowfish с чистого листа: от подготовки LXC и установки Hugo до создания сайта, подключения темы, настройки структуры контента и первой production-сборки.