После того как я сделал свой мини блог на Hugo, я решил что было бы круто сделать автодеплой. Ведь зачем мне каждый раз заходить на сервер и делать git pull
?
План как все должно работать
Что мы имеем изначально
Hugo прекрасный генератор статических сайтов. Написан на go, работает быстро, имеет хорошую документацию и большое комьюнити, контент удобно писать в markdown. Но есть одно но: много ручной работы. Например, чтобы опубликовать новый пост, нужно сделать следующее:
- Сбилдить проект
- Закомитить изменения
- Запушить их в удаленный репозиторий (я использую github)
- Зайти на сервер
- Сделать
git pull
Что мы хотим
Минимум ручной работы. Я хочу чтобы после того как я написал пост и закоммитил его, он сам опубликовался на сайте.
Что нам для этого нужно
- Первым делом я оплатил себе сервер на DigitalOcean, я взял один из недорогих планов, за 6 долларов в месяц. 1 Гб оперативной памяти, 25 Гб диска, 1 процессор. Думаю этого должно хватить
- Купил себе домен godevcraft.com
- Накатил на сервер nginx, настроил его так чтобы он отдавал статику из моего проекта и указал пути до сертификатов
server {
listen 443 ssl;
keepalive_timeout 30;
ssl_certificate /local/cert_chain.crt;
ssl_certificate_key /local/godevcraft.key;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
server_name godevcraft.com;
root /root/godevcraft/;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Поднял на этом же сервере self hosted github runner. Это нужно что бы он мог делать pull, да и минутки в CI не бесконечные
Настроил github actions. Вот так выглядит мой workflow:
name: Build and Deploy Hugo Site
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: self-hosted
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
- name: Update submodules
run: git submodule update --init --recursive
- name: Install Hugo modules
run: hugo mod get -u
- name: Build the website
run: hugo --gc --minify
- name: Deploy to external repo
if: success()
env:
TARGET_REPO: ${{ secrets.TARGET_REPO }} # Add this secret in your repository settings
TARGET_TOKEN: ${{ secrets.TARGET_TOKEN }} # Add this secret in your repository settings
TARGET_BRANCH: main # Or any other branch you want to push to
run: |
cd public
git init
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
git commit -m "Deploy Hugo site"
git push --force "https://x-access-token:${{ env.TARGET_TOKEN }}@github.com/${{ env.TARGET_REPO }}.git" master:${{ env.TARGET_BRANCH }}
- name: Mark directory as safe
run: git config --global --add safe.directory /local/godevcraft
- name: Git pull
run: cd /local/godevcraft/ && git fetch --all && git reset --hard origin/main
Таким образом при пуше в мастера, github actions посылает задачу на моего воркера, который забирает проект с гитахаба, обновляет все темы и модули, билдит проект (с минификацией и сборкой мусора), и пушит результат в отдельный репозиторий. После этого он делает git pull
и все обновляется. Отдельный репозиторий я выбрал осознанно, что бы не хранить рядом сгенерированный фронтенд и исходники в markdown. Кажется от этого репозиторий может стать довольно тяжелым.
Минутка безопасности
- Все секреты я решил хранить в Github Secrets. Это удобно и безопасно.
- Оба репозитория приватные
- На сервере отключен вход по паролю, только по ssh ключу
- Общение сервера с гитхабом тоже происходит по ssh ключу
- Для воркера я создал отдельного пользователя, который не имеет прав на выполнение команд от имени root. Воркер использует токен для доступа к репозиторию, который я всегда могу отозвать
Подключаем телеграм
Что бы быть модным, стильным и молодежным, я подключил telegram app. Это делается довольно легко, через @BotFather. Теперь мой блог доступен как через браузер, так и как приложение в телеграме. Под мобилку hugo отлично адаптируется, даже тему можно поменять на светлую или темную.
Выводы
Мне достаточно поменять что либо в ide и нажать push, или поменять сразу на github через web интерфейс, и через 2 мин изменения появятся на сайте. Звучит удобнее чем деплоиться руками. Еще можно докрутить например нотификацию в телегу при удачном деплое, но это уже совсем другая история.