Hugo — генератор статических сайтов, написанный на Go. Он берёт Markdown-файлы, шаблоны и тему, а на выходе получается набор HTML-страниц, которые отдаёт любой веб-сервер. Здесь нет базы данных и PHP: меньше точек отказа, выше скорость отдачи и проще резервное копирование. Для блога, документации или лендинга этого обычно достаточно. Ниже — маршрут от установки до публикации.
Кому подходит Hugo
Статический подход выигрывает там, где контент меняется редко, а читателей много. Страница собирается заранее, поэтому серверу не нужно выполнять код при каждом запросе. Ограничения тоже есть: комментарии, поиск и формы подключаются отдельными сервисами.
- Блог или журнал с большим архивом материалов.
- Документация проекта, которая лежит рядом с кодом.
- Лендинг без сложной авторизации и личного кабинета.
Установка и проверка окружения
В репозиториях Debian и Ubuntu пакет hugo есть, но версия может отставать от upstream. Для простой темы это не критично. Расширенная сборка Extended нужна для Sass/SCSS и части тем: в выводе hugo version должно быть слово extended. Если его нет, возьмите готовый .deb со страницы релизов проекта и установите через dpkg.
sudo apt update
sudo apt install hugo
hugo version
which hugo
Не смешивайте пакет из репозитория и бинарник в /usr/local/bin.
Создание сайта и структура каталогов
Создайте проект в отдельном каталоге и сразу инициализируйте git: так проще откатывать правки и публиковать сайт.
hugo new site mysite --format yaml
cd mysite
git init
find . -maxdepth 2 -type d | sort
В корне появятся archetypes с шаблонами front matter, content для материалов, layouts для переопределений, static для файлов без обработки и themes. Каталог public создаётся при сборке и в git не нужен. Конфигурация хранится в hugo.yaml.
Конфигурация и подключение темы
Минимальный конфиг задаёт адрес сайта, язык, тему и поведение Markdown. От baseURL зависят ссылки, карта сайта и канонические адреса.
baseURL: "https://example.com/"
languageCode: "ru-ru"
title: "Мой сайт"
theme: "PaperMod"
enableRobotsTXT: true
markup:
goldmark:
renderer:
unsafe: false
params:
description: "Заметки о Linux и инфраструктуре"
ShowReadingTime: true
Тему удобно держать git-сабмодулем: обновление сводится к переключению на новый коммит. Для PaperMod команды такие.
git submodule add https://github.com/adityatelange/hugo-PaperMod themes/PaperMod
git submodule update --init --recursive
git commit -m "init hugo site"
Первый материал
Hugo создаёт файл по архетипу и подставляет дату. В свежих версиях используется подкоманда new content.
hugo new content posts/pervaya-zametka.md
Внутри файла важен корректный front matter. Пока стоит draft: true, материал не попадёт в продакшен-сборку, но будет виден на локальном сервере с флагом -D.
---
title: "Первая заметка"
date: 2026-11-05
draft: false
tags: ["linux", "hugo"]
---
Текст заметки в Markdown.
Локальный сервер и сборка
Во время работы удобно держать запущенным hugo server: он пересобирает страницы при изменении файлов и автоматически обновляет браузер. Флаг --bind 0.0.0.0 нужен, если смотреть сайт с другой машины в локальной сети.
hugo server -D --bind 0.0.0.0 --port 1313
hugo --minify --gc
du -sh public
Флаг --minify сжимает HTML, CSS и JS, а --gc удаляет неиспользуемый кеш. Перед публикацией собирайте сайт без -D: посетители увидят именно этот результат.
Публикация на своём сервере
Самый простой вариант — отдать каталог public через nginx. Заливка через rsync передаёт только изменения и умеет удалять файлы, которых больше нет в сборке. Флаг --delete применяйте только к отдельному каталогу сайта, иначе легко стереть лишнее.
rsync -avz --delete public/ user@server:/var/www/example/
ssh user@server "sudo nginx -t && sudo systemctl reload nginx"
Конфигурация nginx для статики минимальна. Отдельный блок для ассетов с длинным кешем снижает нагрузку и ускоряет повторные загрузки.
server {
listen 80;
server_name example.com;
root /var/www/example;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location ~* \.(css|js|woff2|png|jpg|svg)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
Автоматизация сборки
Ручная заливка быстро надоедает. Минимальный workflow в GitHub Actions собирает сайт при каждом push в основную ветку. Важно включить рекурсивную загрузку сабмодулей, иначе тема не попадёт в сборку.
name: build
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: peaceiris/actions-hugo@v3
with:
hugo-version: "latest"
extended: true
- run: hugo --minify
- uses: burnett01/rsync-deployments@7.0.1
with:
switches: -avzr --delete
path: public/
remote_path: /var/www/example/
remote_host: ${{ secrets.HOST }}
remote_user: ${{ secrets.USER }}
remote_key: ${{ secrets.SSH_KEY }}
Секреты храните в настройках репозитория, а не в YAML. Для домашнего сервера можно собирать сайт локально, но проверка сборки тогда ложится на вашу машину.
Диагностика типичных проблем
Большая часть жалоб связана не с Hugo, а с окружением и путями.
- Пустая страница или 404. Проверьте
baseURL, имя каталога вcontentи то, что материал не помечен черновиком. - Тема не применяется. Убедитесь, что каталог существует, имя в конфиге совпадает, а сабмодуль действительно загружен.
- Ссылки работают локально, но не на сервере. Linux чувствителен к регистру:
Post.mdиpost.md— разные файлы. - Сборка падает на шаблоне. Запустите
hugo --printPathWarningsи посмотрите первую ошибку, а не последнюю.
hugo list drafts
hugo list future
hugo config | grep -E "baseURL|theme"
hugo --printPathWarnings
Если страница собирается, но выглядит без стилей, откройте инструменты разработчика и проверьте путь к CSS. Чаще всего он указывает на localhost из-за неверного baseURL или на старую версию файла в кеше браузера.
Чек-лист перед публикацией
- Сборка проходит без предупреждений, черновики не попадают в
public. - Проверены заголовки, описание и картинки для соцсетей.
- Настроены HTTPS, редирект с HTTP и корректный 404.
- Есть резервная копия контента и конфигурации в git.
- Проверена скорость на мобильном соединении.
Итог
Hugo хорош предсказуемостью: один бинарник, понятная структура, быстрая сборка и статический результат, который легко обслуживать. Начать можно с трёх команд и готовой темы, а по мере роста добавить CI, кеширование и мониторинг. Главное — не тащить в статический сайт динамические задачи, для которых он не предназначен, и держать контент в git.