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

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

Хотите опубликовать свой сайт на 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