Hugo позволяет легко и быстро получить красивый статический веб-сайт. Однако, веб-сайт бесполезен, если его никто не видит.

В этой статье, Я расскажу о том, как разместить свой собственный статический веб-сайт в российском сервисе - Яндекс Облако. И не просто разместить вручную, Я расскажу о том, как настроить автоматический CD пайплайн в GitHub, дабы каждое изменение, сделанное в проекте сайта, автоматически развёртывалось в сети Интернет.

Инструкции в статье, прежде всего, относятся к веб-сайтам, созданным с помощью Hugo. Однако, работа с Яндекс Облаком отношения к Hugo - не имеет. Вы вольны разместить в Облаке статический веб-сайт, созданный абсолютно любым способом.

Прежде, чем начать

Для выполнения инструкции, нам потребуются:

  • свой собственный Hugo сайт

  • учётная запись в GitHub и приватный репозиторий, в котором этот сайт хранится

  • и учётная запись в сервисе Яндекс Облако

О создании собственного сайта на Hugo, Я уже рассказывал тут, а так же, создал целый образовательный курс.

Учётную запись в GitHub можно завести на сайте проекта. Размещение сайта в приватном репозитории не является частью этой статьи, но Вы без проблем сможете это сделать, следуя инструкциям самого GitHub'а.

Ну и наконец, завести учётную запись в инфраструктурном сервисе Вы сможете перейдя на сайт Яндекс Облака.

Готовим облака

В Яндекс Облако нас интересует сервис под названием - Object Storage. Это полный аналог Amazon AWS S3. Сервис предназначен для хранения статических данных малых и больших объёмов, с разным уровнем доступа к ним. Сервис позволяет конфигурировать доступ к данным, в том числе, позволяет открывать доступ к содержимому хранилища, под сгенерированным доменным именем. Именно это нас и интересует.

Прежде чем наш веб-сайт станет доступен нашим клиентам, его нужно где-то в Интернете разместить. Для этого мы воспользуемся бакетами Object Storage.

Создание бакета

Что такое бакет? Бакет - это способ организации хранения данных в Object Storage сервисе. Другими словами, это единое адресное пространство или аналог диска в файловой системе, который создаётся для проекта.

Каждый бакет имеет имя, а так же ряд других настроек.

Рисунок 1. Создание нового бакета
Рисунок 1. Создание нового бакета

Если Вы не хотите читать справку по каждой из настроек - ничего страшного. Можно создать бакет как есть. Достаточно, отметить Доступ на чтение объектов, как Публичный. Остальные настройки по умолчанию отлично подходят для статического веб-сайта.

Единственное, о чём следует сразу же подумать, так это о том, будете ли Вы, в дальнейшем размещать веб-сайт под своим собственным доменным именем. Если да, то имя бакета должно быть полным доменным именем Вашего веб-сайта. Например, на примере Выше, Я подразумеваю, что будущий веб-сайт, размещённый в Яндекс Облаке будет доступен под доменным именем plan.ru.

В данной статье, мы НЕ будем заниматься настройкой доступа к сайту по произвольному доменному имени. Однако, если для Вас это важно - то требование к названию бакета стоит иметь ввиду.

Публикация сайта вручную

После создания бакета, Вы увидите следующую страницу:

Рисунок 2. Пустой бакет
Рисунок 2. Пустой бакет

Внимательный читатель обратит внимание на кнопку Загрузить объекты. С помощью этой кнопки, мы можем загрузить наш веб-сайт в бакет.

Эксперимента ради, Я загружу основной index.html файл своего веб-сайта.

Рисунок 3. Первая публикация
Рисунок 3. Первая публикация

Готово. Наш сайт (точнее, один его файл) лежит в Яндекс Облаке, и всё, что нам нужно сделать, чтобы к нашему сайту можно было обратиться, это настроить Яндекс Облако, на работу в режиме хостинга статических сайтов. Как это сделать?

Всё предельно просто.

Там же, в Object Storage, в меню, есть пункт Веб-сайт. Именно там, нужно выставить режим Хостинг, настроить отображение главной страницы и страницы ошибок и сохранить изменения.

Рисунок 4. Подключаем хостинг
Рисунок 4. Подключаем хостинг

Обратите внимание, там же, Object Storage подсказывает нам, по какому именно адресу будет доступен наш веб-сайт в сети Интернет. Впрочем, уже сейчас, после этих действий, если перейти по указанному в Вашем Object Storage адресу, Вы увидите главную страницу Вашего сайта. Её отображение будет поломано - это нормально.

Последние шаги

Чтобы Ваш веб-сайт нормально отображался, нужно проделать три вещи.

Указать публичный адрес Вашего сайта из Object Storage в качестве baseUrl в конфигурации Вашего Hugo веб-сайта

Делается это путём добавления следующей настройки в config-файл Вашего Hugo веб-сайта. В моём случае, это будет выглядеть вот так:

baseUrl: 'http://plan.ru.website.yandexcloud.net'

Пересобрать веб-сайт

Хорошей практикой является пересборка сайта вместе с минификацией ресурсов и скриптов. Минификация это процесс упразднения ненужных вещей из сборки, в целях экономии занимаемого пространства и ускорения подгрузки ресурсов.

В Hugo подготовка веб-сайта к использованию в продакшн окружении делается с помощью команды:

hugo --minify

В результате её выполнения, в папке public Вашего Hugo проекта будет актуальное и готовое к использованию состояние Вашего сайта.

Загрузка файлов веб-сайта в облако

Всё содержимое папки public необходимо загрузить в бакет Яндекс Облака.

Результат

После всех этих действий, Ваш веб-сайт станет полностью доступен по адресу, указанному в Object Storage.

В случае, если Вам потребуется изменить содержимое веб-сайта, потребуется пересборка сайта и перезагрузка всех его файлов в бакет.

Вручную, делать это не особо радостное занятие, согласитесь? И поэтому, далее, поговорим о автопубликации Вашего сайта.

Автопубликация

Под автопубликацией, Я имею ввиду механизм, который на каждый коммит в репозиторий Вашего проекта, будет выполнять ряд действий за Вас, а именно - сборку наиболее актуальной версии проекта и загрузку всего сайта в Ваш бакет.

В профессиональной разработке, этот подход называется CD или Continious Deployment и он экономит массу времени разработчиков.

Для автопубликации, нам потребуются несколько вещей:

API ключи для клиентских приложений Object Storage

API ключи - это сгенерированные самим Яндекс Облаком токены (проще говоря - специальные строки), посредством которого, клиентские приложения, обращаясь в API Object Storage подтверждают то, что они имеют право работать с бакетами, загружать и удалять данные в них.

Для генерации API ключа, необходимо:

  1. Перейти на страницу Дашборда Яндекс Облака

  2. Перейти в пункт Сервисные аккаунты

  3. Нажать Создать сервисный аккаунт

В появившемся окне, необходимо задать название сервисного аккаунта. Чтобы не запутаться в будущем с сервисными аккаунтами, Я крайне рекоммендую указывать в названии принадлежность к репозиторию и проекту. Например, если бы у меня был репозиторий под названием plan.ru на GitHub, то название сервисного аккаунта, стоило бы выставить как github-plan-ru.

Рисунок 5. Создание сервисного аккаунта
Рисунок 5. Создание сервисного аккаунта
  1. На странице нового сервисного аккаунта, необходимо нажать Создать новый ключ-> Создать статический ключ доступа -> Создать

Рисунок 6. Создание нового ключа
Рисунок 6. Создание нового ключа
  1. И наконец, в появившемся окне, Вам будут выданы данные ключа - его идентификатор и секретный ключ. Эти данные нам понадобятся далее, поэтому сохраните их куда-нибудь.

Рисунок 7. Данные ключа
Рисунок 7. Данные ключа

Секреты для GitHub Action'а

Теперь, когда мы сгенерировали новый API-ключ для нашей автопубликации, нам необходимо отдать его нашей клиентскому приложению, которое и будет выполнять сборку и загрузку новых версий нашего веб-сайта. Этим приложением является - GitHub Workflow, который мы создадим в следующем пункте. Для его работы, нам необходимо задать секреты.

Что такое секреты в GitHub? Это приватная информация, которая не может присутствовать явно в коде, в репозитории, но необходима для работы, например, GitHub Action'ов. Для того, чтобы такие чувствительные данные использовать без их разглашения, и существуют секреты.

Нам понадобятся три секрета:

  • BUCKET - его значением должно быть полное название бакета, в который наш GitHub Action будет загружать файлы веб-сайта. В моём случае, это будет plan.ru

  • ACCESS_KEY_ID - его значением должен стать идентификатор сгенерированного ключа. Ещё точнее - сюда нужно скопировать первое значение формы, изображённой на Рисунке 7.

  • SECRET_ACCESS_KEY - и наконец, его значением должен стать, как несложно догадаться, секретный ключ Вашего сгенерированного API-ключа. Ещё точнее - сюда нужно скопировать второе значение формы, изображённой на Рисунке 7.

Указанные секреты, можно создать в настройках репозитория на GitHub: Settings -> Secrets -> Actions.

Рисунок 8. Настройка секретов в GitHub
Рисунок 8. Настройка секретов в GitHub

GitHub Workflow

Ну и наконец, заключительный шаг - добавление нового GitHub Workflow'а в Ваш проект.

Для того, чтобы добавить GitHub Workflow с Action'ами, в корне Вашего проекта, необходимо создать файл .github/workflows/yandex-cloud-object-storage.yml (на самом деле название самого yml файла не имеет никакого значения. Важны путь и содержимое файла):

 name: Deploy

on:
    push:
        branches:
            - main

jobs:
    deploy:
        runs-on: ubuntu-latest
        
        steps:
            
            - uses: actions/checkout@v2
              with:
                submodules: true  # Fetch Hugo themes (true OR recursive)
                fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

            - name: Setup Hugo
              uses: peaceiris/actions-hugo@v2
              with:
                hugo-version: '0.112.7'
                extended: true

            - name: Build
              run: hugo --minify

            - name: Deploy
              uses: nekitcorp/yandex-storage-website-action@v1
              with:
                  accessKeyId: ${{ secrets.ACCESS_KEY_ID }}
                  secretAccessKey: ${{ secrets.SECRET_ACCESS_KEY }}
                  bucket: ${{ secrets.BUCKET }}
                  path: "./public"
                  clear: true

Этот workflow содержит несколько шагов, и два GitHub Action'ов, которые делают автоматическую публикацию для нас. Давайте разберём особо важные части конфигурации workflow:

- name: Setup Hugo
  uses: peaceiris/actions-hugo@v2
  with:
    hugo-version: '0.112.7'
    extended: true

- name: Build
  run: hugo --minify

Первый шаг - Setup Hugo отвечает за настройку Hugo в окружении. Грубо говоря, после его работы, в последующих шагах, мы вольны использовать команды Hugo. Второй шаг - Build, содержит уже знакомую нам команду hugo --minify. Благодаря этим двум шагам, наш Hugo веб-сайт собирается для работы в продакшн окружении и результат сборки публикуется в папку public. Всё как обычно.

- name: Deploy
              uses: nekitcorp/yandex-storage-website-action@v1
              with:
                  accessKeyId: ${{ secrets.ACCESS_KEY_ID }}
                  secretAccessKey: ${{ secrets.SECRET_ACCESS_KEY }}
                  bucket: ${{ secrets.BUCKET }}
                  path: "./public"
                  clear: true

Следующий шаг, использует специальный GitHub Action - nekitcorp/yandex-storage-website-action@v1 для загрузки данных Вашего сайта в Яндекс Облако. Если взглянуть на его конфигурацию в пункте with, можно заметить знакомые названия - наименования секретов указывают на то, значения каких именно секретов и куда будут подставлены. Ну а path: "./public" указывает action'у содержимое какой конкретно папки будет использовано для загрузки в Object Storage. Последняя опция clear: true означает на то, что перед загрузкой новой версии сайта в бакет, старая будет полностью вычищена.

Автопубликация в действии

После всех этих действий, автопубликация настроена и будет происходит автоматически после каждого коммита. Если совсем быть точным - после каждого коммита в репозиторий, GitHub будет автоматически стартовать испонение настроенного ранее Workflow.

Если Вы всё настроили верно, то после того, как Вы закоммитили Workflow, первый же следующий коммит должен привести к автопубликации. Увидеть запуск workflow можно на вкладке Actions в GitHub. Перейдя на страницу Action'ов Вы увидите историю запусков Вашего workflow, а так же удобную цветовую индикацию статусов запусков:

Рисунок 9. История запусков workflow
Рисунок 9. История запусков workflow

Ну и наконец, если последний запуск workflow был завершён успешно, по указанному в Object Storage адресу, Вы сможете найти свой сайт:

Рисунок 10. Веб-сайт Hugo, задеплоенный автоматически
Рисунок 10. Веб-сайт Hugo, задеплоенный автоматически

Заключение

Статья получилась объёмной, и, возможно даже, для кого-то - сложной. Однако, достаточно потратить один вечер, для того, чтобы настроить автоматическую публикацию сайта в Яндекс Облако, чтобы больше никогда не возвращаться к этому вопросу и заниматься только разработкой сайта.

Список материалов

Дополнительные материалы

Комментарии (4)


  1. valery1707
    20.06.2023 13:40

    Action nekitcorp/yandex-storage-website-action рекомендуют использовать вот так:

    - uses: nekitcorp/yandex-storage-website-action@v2
      with:
    	  access-key-id: ${{ secrets.ACCESS_KEY_ID }}
    	  secret-access-key: ${{ secrets.SECRET_ACCESS_KEY }}
    	  bucket: ${{ secrets.BUCKET }}
    	  working-directory: build
    	  clear: true
    

    а в статье это блок выглядит поломанным:


    1. anverbogatov Автор
      20.06.2023 13:40

      Валерий, действительно. Не очень аккуратно перенёс статью со своего сайта. Не обратил внимания. Большое спасибо за замечание. Исправил ????


  1. anti4ek
    20.06.2023 13:40

    А зачем вы везде пишете "Я" с большой буквы?


    1. anverbogatov Автор
      20.06.2023 13:40

      Статья скопирована из моего личного блога, где я имею подобную привычку. Не волнуйтесь - это не мания величия ????