Конкурс инструкций

GitHub Actions: Простой способ развернуть множество стендов фронтенд-приложения

Деплоим с поддержкой ветвления без навыков DevOps на примере Vue

Грубо говоря, GitHub Actions – это написанные пользователем сценарии, выполнение которых можно затриггерить по определенным действиям в репозитории (например, новый коммит).

Можно выделить следующие преимущества GitHub Actions среди других CI инструментов:

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

  1. Пользователь вносит изменения в ветку
  2. Автоматически запускается отвечающий за сборку скрипт
  3. Собранное приложение доставляется на сервер и доступно по адресу <имя_ветки>.app.example.ru

Подготовка сервера

Все действия будут выполнены на OC Ubuntu 20.04. Также нам понадобится доступ к NS-записям домена.

Подойдет cамая минимальная конфигурация, достаточная для раздачи статики. Остальную работу на себя возьмут серверы Гитхаба.

P.S.: Читателям статьи VScale предоставили купон VCGUIDE на 250 рублей.

Авторизуемся сгенерированным паролем с помощью командной строки или любого SSH клиента:

ssh root@<ip вашего сервера>

Установка необходимых пакетов

Установим nginx – он будет отвечать за раздачу файлов приложения:

apt update && apt install nginx -y

Далее создадим SSH-ключ, который понадобится нам для деплоя приложения на сервер:

ssh-keygen -t rsa -b 4096 -f deploy

Нам будет предложено задать секретный пароль, пропустим этот шаг (Enter).

Добавим ключ в доверенные:

cat ~/deploy.pub >> ~/.ssh/authorized_keys

И перезапустим сервис sshd для применения изменений:

service sshd reload

Настройка репозитория

Secrets (Settings > Secrets)

Подходит для хранения приватной информации – например, нашего SSH-ключа. Значения этих переменных будут скрыты из вывода в консоль и будут доступны только нам.

Задаем следующие переменные в настройках:

  • DEPLOY_SERVER_HOST – IP вашего сервера
  • DEPLOY_SERVER_PORT – SSH порт (по умолчанию 22)
  • DEPLOY_SERVER_USERNAME – Имя пользователя (по умолчанию root)
  • DEPLOY_SERVER_KEY – Секретная часть сгенерированного ранее ключа (посмотреть можно командой cat ~/deploy)

Github Actions: Создаем Workflow

Создадим в нашем репозитории шаблон для задачи, отвечающей за деплой:

Следующего содержания:

name: CI on: [push] env: DEPLOY_PATH: /var/www/app # В теории можно собрать не только Vue-приложение, так как принцип сборки мало где отличается BUILD_SCRIPT: npm run build BUILD_SCRIPT_OUTPUT: dist jobs: deploy: runs-on: ubuntu-latest steps: # Делаем checkout текущей ветки - uses: actions/checkout@v2 # Устанавливаем Node.JS для сборки приложения - uses: actions/setup-node@v1 with: node-version: '14' # Записываем в переменные окружения имя текущей ветки # Чтобы избежать конфиликтов с URL, меняем точки на _, а слеши на минусы - name: Get branch name shell: bash run: echo "::set-env name=BRANCH_NAME::$(echo ${GITHUB_REF#refs/heads/} | sed 's/\//-/g' | sed 's/\./_/g')" # Устанавливаем зависимости для сборки - name: Install Dependencies run: npm i # Собираем приложение - name: Build Appliction run: $BUILD_SCRIPT # Доставляем собранное приложение на сервер - name: Deploy to Server uses: appleboy/scp-action@master with: host: ${{ secrets.DEPLOY_SERVER_HOST }} port: ${{ secrets.DEPLOY_SERVER_PORT }} username: ${{ secrets.DEPLOY_SERVER_USERNAME }} key: ${{ secrets.DEPLOY_SERVER_KEY }} source: ${{ env.BUILD_SCRIPT_OUTPUT }} target: ${{ env.DEPLOY_PATH }}/${{ env.BRANCH_NAME }} strip_components: 1 - name: Print Info run: echo "Deployed at https://${BRANCH_NAME}.app.example.ru/"

В примере выше используется созданный пользователем пакет appleboy/scp-action, выполняющий функцию архивирования файлов, передачу созданного архива по SSH и его распаковку на удаленном сервере.

Возле последнего коммита отображается статус последнего workflow

Настройка фронтенда

Автообновляемые бесплатные SSL-сертификаты

Для начала нужно привязать имеющийся домен к серверу.

В панеле управления доменом зададим DNS-серверы/NS-записи ns1.vscale.io и ns2.vscale.io

В настройках домена добавим новую запись *.example.ru, указывающую на IP нашего сервера:

Пример настроенных записей

Установим клиент ACME.sh для работы с Let's Encrypt:

curl https://get.acme.sh | sh && source ~/.bashrc

Для получения и продления wildcard-сертификатов нужно добавлять специальную текстовую запись для домена. Создадим API токен с полными правами, чтобы не делать это каждый раз вручную.

Инструкция для других поддерживаемых провайдеров.

Добавим полученный токен в переменные окружения сервера:

export VSCALE_API_KEY=<ваш токен>

Следующая команда инициирует создание сертификатов для доменов *.example.ru и *.app.example.ru соответственно:

acme.sh --issue --dns dns_vscale -d *.example.ru -d *.app.example.ru --key-file /etc/ssl/privkey.pem --fullchain-file /etc/ssl/fullchain.pem --reloadcmd "service nginx force-reload"

Ждем окончания проверки, в случае успеха получаем такое сообщение:

-----END CERTIFICATE----- [Mon Sep 14 10:03:50 UTC 2020] Your cert is in /root/.acme.sh/*.example.ru/*.example.ru.cer [Mon Sep 14 10:03:50 UTC 2020] Your cert key is in /root/.acme.sh/*.example.ru/*.example.ru.key [Mon Sep 14 10:03:50 UTC 2020] The intermediate CA cert is in /root/.acme.sh/*.example.ru/ca.cer [Mon Sep 14 10:03:50 UTC 2020] And the full chain certs is there: /root/.acme.sh/*.example.ru/fullchain.cer [Mon Sep 14 10:03:50 UTC 2020] Installing key to:/etc/ssl/privkey.pem [Mon Sep 14 10:03:50 UTC 2020] Installing full chain to:/etc/ssl/fullchain.pem [Mon Sep 14 10:03:50 UTC 2020] Run reload cmd: service nginx force-reload [Mon Sep 14 10:03:50 UTC 2020] Reload success

Настройка nginx

При каждом коммите в ветку, GitHub Action собирает приложение и отправляет его в директорию /var/www/app/<branch_name>/ у нас на сервере.

Нужно настроить сервер так, чтобы запросы к поддомену <branch_name>.app.example.ru указывали на соответствующую директорию.

Создадим/заменим стандартную конфигурацию nginx (/etc/nginx/sites-available/default):

server { listen 443 ssl; server_name "~^(?<branch>.*)\.app\.example\.ru$"; ssl_certificate /etc/ssl/fullchain.pem; ssl_certificate_key /etc/ssl/privkey.pem; ssl_trusted_certificate /etc/ssl/fullchain.pem; location / { root /var/www/app/$branch; try_files $uri /index.html; } }

С помощью регулярного выражения проверяется директива server_name: при соответствии правилу, значение поддомена подставляется в качестве имени root-директории, в которой находится уже собранное приложение.

Для применения изменений перезагружаем nginx:

nginx -s reload

Проверяем, всё ли получилось:

Также можно дополнить конфигурацию следующим правилом:

server { listen 443 ssl; server_name app.example.ru; ssl_certificate /etc/ssl/fullchain.pem; ssl_certificate_key /etc/ssl/privkey.pem; ssl_trusted_certificate /etc/ssl/fullchain.pem; location / { root /var/www/app/master; try_files $uri /index.html; } }

Теперь app.example.ru будет отображать состояние master-ветки.

0
Комментарии
-3 комментариев
Раскрывать всегда