Windows, Linux, КПК и немного ещё.

Деплой Hugo на GitHub Pages из приватного репозитория

en: Deploy Hugo to GitHub Pages from a Private Repository

Хотите опубликовать свой сайт на GitHub Pages из приватного репозитория, но не хотите покупать Pro подписку на GitHub? Можно сделать так, что бы сайт жил в публичном репозитории и деплоился автоматически при каждом пуше, а исходники при этом оставались в приватном. Расскажу, как настроил у себя — заодно и шпаргалка получится.

Разумеется, не подойдет, если вы храните что-то важное за UUID (или вообще просто случайными) ссылками, которые не должны быть публичными.

Способ работает без персональных токенов (PAT), которые имеют неприятное свойство истекать. SSH-ключи бессрочны, и GitHub официально рекомендует их для деплоя во внешние репозитории.


Публичный репозиторий — будущий дом сайта

Создаём на GitHub новый публичный репозиторий. Назовём его, скажем, username.github.io (для пользовательского сайта) или username/public-repo-name (для проектного). Это будет «лицевая» часть — сюда экшен будет закидывать сгенерированный public/.


Генерируем SSH-пару

На своей машине делаем ключ специально для этого деплоя:

bash
ssh-keygen -t rsa -b 4096 -C "for github pages deploy" -f gh-pages -N ""

Флаги:
-t rsa -b 4096 — надёжный ключ,
-C — любой комментарий,
-f gh-pages — файлы назовутся gh-pages (приватный) и gh-pages.pub (публичный),
-N "" — пустой пароль, иначе в GitHub Actions придётся вводить его интерактивно, что не работает.

Приватный gh-pages — никому не показываем. Публичный gh-pages.pub — пойдёт в публичный репозиторий.


Публичный ключ в публичный репозиторий

В только что созданном публичном репозитории: Settings → Deploy keys → Add deploy key. Заголовок любой, например GH Actions Deploy Key. Вставляем содержимое gh-pages.pub.
Важно: ставим галочку Allow write access — без неё экшен не сможет пушить.

скриншот добавления публичного ключа

Жмём Add key. Готово, публичный репозиторий теперь доверяет нашему ключу.


Приватный ключ — в секреты приватного репозитория

Переходим в репозиторий с исходниками Hugo (тот, что приватный): Settings → Secrets and variables → Actions → New repository secret.

Имя: ACTIONS_DEPLOY_KEY Значение: весь приватный ключ целиком, со строками

-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----

скриншот добавления приватного ключа

Сохраняем. Теперь у экшена есть доступ к деплою.


Workflow — собираем и пушим

В приватном репозитории создаём .github/workflows/deploy.yml:

yaml
name: Deploy Hugo site to public repo

on:
  push:
    branches: [ master ]
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout source
        uses: actions/checkout@v4
        with:
          submodules: true
          fetch-depth: 0

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v3
        with:
          hugo-version: 'latest'

      - name: Build site
        run: hugo --minify

      - name: Deploy to public repository
        uses: peaceiris/actions-gh-pages@v4
        with:
          deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
          external_repository: username/public-repo-name
          publish_branch: master
          publish_dir: ./public

На что обратить внимание:

  • external_repository — пропишите свой публичный репозиторий
  • publish_branch — та ветка, которую указали в Pages (обычно master или main)
  • submodules: true — если тему подключали как сабмодуль
  • fetch-depth: 0 — нужен, чтобы Hugo корректно работал с датами (lastmod и т.п.)

Включение Pages

Пушим в master приватного репозитория. Заходим во вкладку Actions — должен запуститься workflow. В публичном репозитории должен появиться сгенерённый сайт.

В настройках публичного репозитория включаем Pages: Settings → Pages → Source: Deploy from a branch, бранч master (или main, если вы на предыдущем шаге использовали его).

скриншот включения Pages


Проверяем

  • https://username.github.io/public-repo-name/ — для проектного
  • https://username.github.io/ — если репозиторий username.github.io

Скриншот работающего сайта


Custom domain — свой домен вместо github.io

Хотите blog.example.com вместо username.github.io? Делается за пару минут.

  1. В публичном репозитории: Settings → Pages → Custom domain — вписываете свой домен (например, blog.example.com), жмёте Save. GitHub создаст файл CNAME в ветке публикации.

  2. У вашего DNS-провайдера добавляете записи:

    • Для поддомена (blog.example.com) — CNAME на username.github.io
    • Для домена (example.com) — A записи на IP GitHub Pages:
      code
      185.199.108.153
      185.199.109.153
      185.199.110.153
      185.199.111.153
  3. После распространения DNS (обычно пару минут) в настройках Pages появится галочка Enforce HTTPS — включите её. GitHub сам выдаст и обновит Let’s Encrypt сертификат.

Важно: если используете Cloudflare, проксируйте (оранжевое облачко) только после того, как HTTPS заработает — иначе проверка домена может не пройти.


Альтернатива: Personal Access Token (PAT)

Если по каким-то причинам SSH не вариант — можно использовать классический PAT.

  1. Создайте токен: Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token. Выдайте права repo (полный доступ к репозиториям).
  2. Добавьте его как секрет в приватный репозиторий: имя PAGES_DEPLOY_TOKEN, значение — сам токен.
  3. В workflow замените deploy_key на personal_token:
yaml
- name: Deploy to public repository
  uses: peaceiris/actions-gh-pages@v4
  with:
    personal_token: ${{ secrets.PAGES_DEPLOY_TOKEN }}
    external_repository: username/public-repo-name
    publish_branch: master
    publish_dir: ./public

Но SSH-ключи предпочтительнее: PAT истекает, его нужно периодически обновлять, а ключ — поставил и забыл.


Нюансы, на которые стоит обратить внимание

  • GITHUB_TOKEN не работает с другими репозиториями — только с тем, где запускается экшен. Поэтому SSH-ключ или PAT обязательны.
  • PAT удобен для разовых задач, но он истекает. SSH-ключ — поставь и забудь.
  • Если тема Hugo — сабмодуль, не забудьте submodules: true в checkout, иначе сборка упадёт с пустым themes/.
  • Hugo версии latest в экшене — удобно, но для продакшена лучше зафиксировать версию (hugo-version: '0.165.0'), чтобы не сломалось неожиданно.

Теперь при каждом пуше в master сайт сам соберётся и обновится. Исходники — у вас в приватном, публичная часть — чистая и быстрая. Удобно, надёжно, и главное — раз настроил, больше не думаешь.


comments powered by Disqus