Как же меня бесят статьи в духе “Как всего за 139 рублей в месяц развернуть свой сайт-визитку на vps”. Какие 139 рублей за сайт-визитку, совсем уже стыд потеряли?!
В этой статье я вам пошагово расскажу и покажу как бесплатно разместить и вести ваш личный сайт(блог, cv, wiki). Вам даже отдельный домен не нужен (всё будет “из коробки”), хотя в последнем шаге мы и его прикрутим. От вас нужны будут базовые знания git и просто уметь работать с markdown.
Краткий план наш будет такой: создаем специальную репку, ставим локально генератор статических сайтов и генерим странички, немного магии github actions и профит! В основе всего будет GitHub Pages - бесплатный хостинг статических сайтов, который позволяет автоматически публиковать сайт из репозитория GitHub.
Я буду поднимать персональный блог с CV. И я хочу чтобы мой сайт был доступен по красивому адресу https://itcaat.github.io. Тут надо понимать, что занять вы можете адрес только с именем вашего аккаунта, т.е. your_account_name.github.io
.
Шаг 1. Создание и настройка репозитория
Создаем новый репозиторий c именем itcaat.github.io. Важно чтобы он имел именно формат: ACCOUNT_
NAME.github.io
, чтобы хост itcaat.github.io смотрел именно на этот репозиторий. Далее выставляем в настройках репозитория Settings->Pages->Source=Github Actions
. Больше никакие настройки не трогаем. На данном этапе у нас будет просто пустой репозиторий без файлов и бранчей.

Шаг 2. Создание базовой структуры
Ставим генератор статических сайтов hugo и создаем базовую структуру.
# https://gohugo.io/installation/ - здесь можете выбрать под свою OS
brew install hugo
# Создаем новый сайт
hugo new site itcaat.github.io
Давайте сразу добавим эти файлы в созданный репозиторий и зальем их. Так нам будет проще видеть историю изменений. Заранее создадим .gitignore.
cd itcaat.github.io
cat <<EOF >.gitignore
public
EOF
git init
git add .
git commit -m "mvp"
git branch -M main
git remote add origin git@github.com:itcaat/itcaat.github.io.git
git push -u origin main
Шаг 3. Подключение темы hugo
Теперь заглянем в магазин тем https://themes.gohugo.io и выберем ту тему что вам подходит. Мне нравится минимализм, поэтому я остановился на https://github.com/athul/archie. Подключим репозиторий с темой как сабмодуль.
git submodule add https://github.com/athul/archie.git themes/archie
Шаг 4. Перенос настроек из темы
Почти все темы содержат пример сайта со всеми необходимыми параметрами для корректной работы темы. Давайте перенесем контент и настройки из exampleSite
в корень нашего репозитория.
cp -R themes/archie/exampleSite/* ./
Обычно в exampleSite
основные настройки лежат в config.toml. Поэтому нам надо переложить их в hugo.toml чтобы генератор всё подхватил.
mv ./config.toml ./hugo.toml
git add . && git commit -m "added theme athul archie" && git push
Поздравлю, мы уже можем сгенерировать сайт локально и посмотреть что у мы имеем на данный момент. Тут важно понимать что сервер поднимается просто для локального тестирования - он просто собирает всё воедино из css, тем и md-файлов.
hugo server --buildDrafts
# Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
# Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
# Press Ctrl+C to stop

Открываем http://localhost:1313/ и смотрим что всё корректно работает. “Но тут же чужие посты и контакты!” скажете вы. Cейчас это поправим. За то что мы видим на сайте отвечают файлы внутри content
и файл конфигурации hugo.toml. Я не хочу подробно тут останавливаться на hugo.toml - там всё интуитивно понятно. У меня будет примерно будет так:
baseURL = "https://itcaat.github.io"
title = "ItCaat personal blog and CV"
....
[[params.social]]
name = "GitHub"
icon = "github"
url = "https://github.com/itcaat"
[[params.social]]
name = "Twitter"
icon = "twitter"
url = "https://x.com/itcaat"
....
Шаг 5. Наполняем сайт
Тут надо понимать две простые вещи: всё содержимое вашего сайта находится в каталоге content
и всё содержимое это обычные md-файлы из которых в дальнейшем генерируется сайт. Мы можем отредактировать, создать и удалить текущие посты как нам нравится. Ну и отредактировать about.md
. Новые посты рекомендуется создавать через команду hugo new
это позволит создать draft пост с необходимыми полями. Когда пост будет финально готов - то просто удалите draft: true, а также можно дополить description
и tags
. Но в целом можно и просто вручную создавать файлы.
hugo new posts/kak-kakat.md

Мы подошли к финалу - публикация нашего сайта. Давайте запустим его, проверим что нам всё нравится и зальем финальные правки.
hugo server --buildDrafts
git add . && git commit -m "ready for release" && git push

Про структуру и картинки
На самом деле не обязательно хранить ваши md файлы в content/posts
- можно делать каталоги с именем поста и внутри делать index.md.

Это довольно удобно, ведь часто мы оформляем свои посты с картинками и будет классно хранить картинки прямо рядом с текстом.
Шаг 6. Публикация
Доверим всю работу по публикации github actions. Для этого просто закинем в .github/workflows/hugo.yml
содержимое ниже и commit push. Данный файл сделает всю грязную работу и опубликует наш сайт.
# .github/workflows/hugo.yml
name: Deploy Hugo site to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
# Default to bash
defaults:
run:
shell: bash
jobs:
# Build job
build:
runs-on: ubuntu-latest
env:
HUGO_VERSION: 0.145.0
steps:
- name: Install Hugo CLI
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb
- name: Install Dart Sass
run: sudo snap install dart-sass
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
- name: Install Node.js dependencies
run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
- name: Build with Hugo
env:
HUGO_CACHEDIR: ${{ runner.temp }}/hugo_cache
HUGO_ENVIRONMENT: production
run: |
hugo \
--minify \
--baseURL "${{ steps.pages.outputs.base_url }}/"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./public
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Заливаем правки по github actions и дожидаемся публикации нашего сайта. Обратите внимание на env переменную HUGO_VERSION: 0.145.0
. Посмотрите локальную версию с помощью команды hugo version
и пропишите такую же чтобы не было различий. Заливаем правки.
git add . && git commit -m "github actions" && git push

Поздравляю, у нас полностью бесплатный, с версионированием, без бекендов и баз данных сайт https://itcaat.github.io. Для тех кому лень разбираться в деталях и вы хотите такой же сайт в таком же исполнении - просто форкайте репу https://github.com/itcaat/itcaat.github.io и наполняйте своим контентом.

В принципе этого уже будет достаточно и всё будет работать на бесплатных инструментах. Но если у вас лишние пара сотен рублей и вы хотите подключить свой красивый домен, то надо сделать последний шаг.
Шаг 7. Собственный домен
Давайте прикрутим собственный домен к нашему сайту. Для этого:
1. Нужно прописать A-записи на сервера, которые есть в официальной документации github.

2. Выставить настройку Custom domain
в Pages
(обязательно выставьте Enforce HTTPS
чтобы получить сертификат).

Процесс валидации довольно быстрый, но в некоторых случаях может занимать какое то время. После проверки ваш сайт будет доступен по указанному вами домену.
А на этом у меня всё - всем спасибо и хороших выходных.
Комментарии (18)
Nill-Ringil
24.05.2025 09:01Предлагаю следующей статьей написать про Cloudflare Pages для тех же целей. С тем же HugoCMS у него интеграция из коробки, как и с десятком других cms генерящих статичные сайты. Главный плюс CF в том, что он раздает это все со своих CDN-серверов, то есть каждый посетитель будет получать с ближайшего к нему. У самого визитка так сделана(ссылку давать в комменте не буду, что бы не выглядело рекламой)
CoolCmd
24.05.2025 09:01Доверим всю работу по публикации github actions. Для этого просто закинем в .github/workflows/hugo.yml содержимое ниже и commit push. Данный файл сделает всю грязную работу и опубликует наш сайт.
можно объяснить в двух словах, зачем нужны github actions, что за грязную работу они делают? с hugo я не работал.
itcaat Автор
24.05.2025 09:01После пуша github actions пнет hugo чтобы тот из md файлов собрал вам статичный сайт, который будет содержать связанные html страницы, картинки, js и тд. Те по сути готовый статичный сайт. И далее actions опубликует его в pages
CoolCmd
24.05.2025 09:01как я понял из статьи, hugo уже стоит на компе и собирает сайт для предварительного просмотра. почему не собрать им же окончательную версию, зачем поручать это гитхабу?
itcaat Автор
24.05.2025 09:01Примерно по той же причине почему мы не собираем локально программы и не выкладываем их руками.
Но вы можете делать так как вам нравится и все выкладывать руками. Я предпочитаю вариант когда все собралось и выложилось, а вариант локального запуска оставить для отладки
13werwolf13
24.05.2025 09:011) потому что так принято - да звучит странно, но это так
2) потому что в дальнейшем вообще не обязательно иметь установленный hugo, достаточно редактировать md файлы любым текстовым редактором хоть на телефоне
3) потому что человеческий фактор - если hugo на этапе сборки вернёт отличный от нуля код возврата то CI не сделает релиз, а замыленный глаз или кривонаписанная автоматизация могут это и упуститьNill-Ringil
24.05.2025 09:01в дальнейшем вообще не обязательно иметь установленный hugo, достаточно редактировать md файлы любым текстовым редактором хоть на телефоне
Я на визитке и на блоге порой вообще в браузере лезу в гитхаб или гитлаб(один там, другой там) и правлю файлы, то есть локально не то что hugo может не быть, но и md-файлов
AlexJameson
24.05.2025 09:01Один из бонусов в том, что вы можете внезапно понять, что в статье, которую вы опубликовали в конце рабочего дня, есть битая ссылка или досадная опечатка, и вы можете зайти с телефона и поправить что-то прямо в исходниках на гитхабе. Сайт после этого сразу пересоберется без дополнительных действий.
fosihas
24.05.2025 09:01Человек платит:
Какие 139 рублей за сайт-визитку, совсем уже стыд потеряли?!
Чтобы никогда заниматься вот этим
2. Выставить настройку
Custom domain
вPages
(обязательно выставьтеEnforce HTTPS
чтобы получить сертификат).ps:
сделайте сервис за "адекватную" цену. А мы разберем почему она "неправильная"itcaat Автор
24.05.2025 09:01Я не очень понял, Вас напугало выставление галочки? Или вы решили что за 139 у вас будет штат инженеров, которые решат все вопросики, включая настройку сертификатов. Поищите статьи которые рассказывают как настроить сайты-визитки на их vps серваках и вы очень удивитесь насколько там все сложнее описано. Но мы то знаем зачем они гонят туда народ ;)
fosihas
24.05.2025 09:01Я о том что у разных человеков, разный набор знаний. И можно не знать, а купить уже готовый продукт.
А вопрос цены, это другая категория
Mr_Boshi
24.05.2025 09:01За такие деньги обычно продают самый базовый VPS без домена, без сертификатов, даже без панелей, одна голая консоль. Не очень понятно чем этот готовый продукт лучше (или требует принципиально других знаний), чем тоже готовый вариант из статьи.
souls_arch
24.05.2025 09:01Помимо других мест для статики есть еще несколько ресурсов, где можно и динамику с бэкендом, бд, кафкой, бассейном, преферансом и кокотками. Просто про все, в том числе про хостинг единственного персонального для аккаунта на гитхабе, уже не раз писали.
MountainGoat
Как говорил один советский иллюзионист, показывая опустевшую коробку: "Только что было - только что нет!"