Гайд 06 · для того, кто выкладывает
Сборка и выкладка
Как собрать сайт для прода, упаковать его в образ и вести несколько сайтов на разных версиях HERON. Для того, кто выкладывает, — человека или агента-сборщика.
Одна и та же папка сайта выходит из HERON либо обычными файлами, либо готовым образом. Здесь — оба пути и проверки, которые проходит сайт перед выкладкой.
Простыми словами
Сборка похожа на выпечку: папка с текстами — тесто, heron build — печь, готовый сайт — хлеб. Хлеб можно отдать как есть — папкой dist/ с готовыми страницами — или упакованным в коробку — образом, который запустит любой сервер с Docker. Эта страница объясняет оба способа и проверки, которые проходят до того, как хлеб покинет кухню.
Что выбрать. Бесплатный хостинг вроде GitHub Pages или обычный тариф хостинга принимает папку. Свой сервер с Docker принимает образ, и обновление превращается в «скачать новый образ и перезапустить». Если сомневаетесь, начните с папки; на странице Публикация способы сравниваются.
Пример. heron build . --env prod --strict делает dist/ со всеми страницами, картой сайта, llms.txt и готовым конфигом nginx. Скопируйте эту папку на хостинг — и сайт в интернете.
Эта страница нужна, когда сайт готов выйти в интернет и когда на одном сервере живут несколько сайтов.
Два выхода: папка или образ
Папка dist/ |
Образ nginx | |
|---|---|---|
| Чем | heron build |
scripts/site.sh САЙТ image |
| Что внутри | HTML, картинки, карты, .heron-nginx.conf |
nginx-unprivileged, статика, конфиг под этот сайт |
| Куда | любой хостинг статики, свой nginx | любой хост с докером, Kubernetes |
| 301, 410, своя 404 | подключить .heron-nginx.conf в свой nginx |
уже включены |
Выход выбирается командой, а не при создании сайта: одна и та же папка собирается и так, и так. Подробно — два выхода в спецификации.
Окружение сайта
Рабочая и боевая сборка — это флаг сборки, а не другой образ HERON:
--env dev (по умолчанию) |
--env prod |
|
|---|---|---|
| индексация | закрыта: noindex и Disallow: / |
открыта |
счётчики из analytics |
нет | есть |
| метка сборки (версия, время, коммит) | тема может показать | не показывается |
--strict превращает предупреждения в ошибки — для прода обязателен. Перебить по отдельности: SITE_INDEXABLE=false, SITE_ANALYTICS=false — прод-подобное превью, закрытое от поисковиков.
Домен по окружению. Рабочая сборка на своём адресе должна ссылаться на себя, а не на боевой домен. Для этого в site.yaml:
site:
domain: example.com # боевой
domains:
dev: dev.example.com # canonical, sitemap, hreflang, robots — на этот адрес в рабочей сборке
Имя окружения то же, что в --env: один рычаг управляет и индексацией, и доменом.
Один сайт
H="docker run --rm -v $PWD:/site -w /site --user $(id -u):$(id -g) ghcr.io/fmstm/heron:prod"
$H build мой-сайт --env prod --strict
мой-сайт/dist/ — готовый сайт. Залейте папку на хостинг статики (тогда 301 и 410 настраиваются средствами хостинга по dist/redirects.map и dist/gone.map) или отдайте своему nginx — ниже.
Свой nginx на сервере
dist/.heron-nginx.conf — готовый блок server {} вместе с картами 301 и 410. Он подключается в контекст http, как любой файл сайта. Пример для Debian или Ubuntu с nginx из apt:
sudo cp -r мой-сайт/dist /var/www/мой-сайт
sudo cp мой-сайт/dist/.heron-nginx.conf /etc/nginx/sites-enabled/мой-сайт.conf
# в файле поправьте root на /var/www/мой-сайт и listen/server_name под свой хост
sudo nginx -t && sudo systemctl reload nginx
Размеры хэшей карт. В начале файла стоят map_hash_bucket_size и map_hash_max_size — HERON посчитал их по самому длинному адресу из redirect_from и gone. Без них длинный кириллический адрес не помещается в корзину размером с кэш-линию процессора, и nginx не стартует: could not build map_hash, you should increase map_hash_bucket_size: 64. Отчёт сборки показывает посчитанные значения.
Если /etc/nginx/nginx.conf хоста уже задаёт эти директивы, повтор в файле сайта даст directive is duplicate. Тогда в site.yaml:
nginx:
hash_sizes: off # auto (по умолчанию) — писать в конфиг сайта; off — их задаёт хост
Отчёт сборки напишет, сколько нужно, — например «картам 301/410 нужен map_hash_bucket_size ≥ 256». Это вписывается в http { … } файла /etc/nginx/nginx.conf:
http {
map_hash_bucket_size 256;
map_hash_max_size 2048;
# … остальное как было
}
Если nginx есть на машине, где идёт сборка, HERON сам прогоняет nginx -t на собранном конфиге и пишет результат в отчёт; не прошёл — предупреждение, при --strict — ошибка.
Посмотреть локально — heron serve мой-сайт: та же 404, что увидит посетитель, сборка во временную папку, папка сайта не пачкается. 301 и 410 serve не изображает — их проверяет smoke на образе.
Образ из репозитория сайта
Сайт обычно живёт в своём репозитории, и клона HERON рядом нет. Образ собирает переиспользуемый workflow HERON — свой Dockerfile писать не нужно:
# .github/workflows/image.yml в репозитории сайта
name: image
on:
push:
branches: [main]
jobs:
image:
uses: FMSTM/HERON/.github/workflows/site-image.yml@prod
permissions:
contents: read
packages: write
with:
env: dev # dev или prod
engine: prod # тег HERON: prod, beta или 0.1.0
Workflow соберёт сайт HERON из образа, упакует dist/ в nginx по рецепту той же версии HERON, поднимет образ, прогонит дымовую проверку и отправит его в ghcr.io/ВЛАДЕЛЕЦ/РЕПОЗИТОРИЙ:ОКРУЖЕНИЕ. Параметры: path — папка сайта внутри репозитория, image и tag — своё имя образа, strict — true или false (по умолчанию строгая только prod), push: false — собрать и проверить без отправки. Пока бета не стала продом, звать @beta с engine: beta.
Несколько сайтов: scripts/site.sh
Из клона репозитория HERON:
git clone https://github.com/FMSTM/HERON.git && cd HERON && HERON_NOTES=ru ./scripts/site.sh мойсайт new ~/sites/мой-сайт
new создаёт папку сайта — в терминале с теми же вопросами, что и heron new, — и заводит env/.env.мойсайт.dev и .prod. Папка может уже существовать и быть под git. Дальше всё — одной командой:
./scripts/site.sh мойсайт check dev # отчёт без сборки
./scripts/site.sh мойсайт build dev # → out/мойсайт-dev
./scripts/site.sh мойсайт serve dev # nginx на localhost:$PORT
./scripts/site.sh мойсайт stop # погасить просмотр
./scripts/site.sh мойсайт build prod
./scripts/site.sh мойсайт image prod # образ IMAGE_NAME:IMAGE_TAG
./scripts/site.sh мойсайт smoke prod # поднять образ, проверить коды
./scripts/site.sh мойсайт push prod # в REGISTRY
./scripts/site.sh мойсайт init # достроить папку после правки site.yaml
Папка контента монтируется только на чтение: всё, что производит сборка, живёт в out/, контент ничем не пачкается.
Настройки сайта — env/.env.САЙТ.ОКРУЖЕНИЕ, в git не попадают. Образец с пояснениями — env/.env.example.
| Переменная | Что задаёт |
|---|---|
SITE_PATH |
путь к папке сайта |
SITE_ENV |
dev или prod — каким будет сайт |
STRICT |
строгая сборка |
ENGINE |
какой версией HERON собирать (ниже) |
IMAGE_NAME, IMAGE_TAG |
имя образа сайта |
REGISTRY, REGISTRY_CONFIG |
реестр для push и докер-конфиг для него; пусто — push запрещён |
PORT |
порт просмотра |
HERON_NOTES |
язык комментариев и записок, которые кладёт init: ru или en |
Секреты форм (SMTP, вебхуки) сюда не кладутся: сборка статическая, всё, что она видит, может оказаться в HTML.
Дымовой прогон
site.sh САЙТ smoke ОКРУЖЕНИЕ поднимает собранный образ и сверяет ответы (саму проверку делает scripts/smoke-site.sh — тот же скрипт зовёт workflow образа сайта):
- корень и
robots.txt— 200, несуществующий адрес — 404; - языковой раздел — 200 и своя 404;
- служебный конфиг рядом со статикой — 404;
- каждый адрес из
redirects.map— 301 туда, куда объявлено; - каждый точный адрес из
gone.map— 410.
Упал — контейнер гасится, логи nginx печатаются. Подробно — проверки и дымовой прогон.
Версии HERON
Сайт закрепляет версию HERON сам — первой строкой site.yaml:
heron: ">=0.1,<0.2"
HERON не из диапазона откажется собирать (E012). Обновление HERON для сайта — смена этой строки, осознанно и по одному сайту.
Какой версией собирает site.sh — ENGINE в env-файле:
| Значение | Когда |
|---|---|
| пусто | точная версия из site.yaml, если она там точная; иначе исходники рядом; иначе :prod |
ghcr.io/fmstm/heron:prod |
стабильный — обычный выбор |
ghcr.io/fmstm/heron:0.1.0 |
закрепиться на версии |
source |
собрать из исходников рядом — только когда правите сам HERON |
Теги образа HERON:
| Тег | Что это |
|---|---|
:X.Y.Z |
точная версия, не меняется никогда |
:prod |
то, на чём стоят сайты |
:beta |
обкатка следующей версии на живых сайтах |
:dev |
разработка HERON; для сайтов не предназначен |
Какой образ на руках, показывает --version: ветка, коммит и время сборки, например heron, version 0.1.0 (beta, 55249f0, 2026-10-08 19:12 UTC). Номер версии один на всю ветку разработки, а по коммиту видно, свежая ли бета. Из исходников — (source, КОММИТ).
Подвижного :X.Y нет намеренно: сайт должен иметь возможность закрепиться на том, что не поедет под ним завтра.
Чек-лист перед выкладкой
- 1
site.yaml
Домен, языки,heron:с диапазоном, счётчики. - 2
Строгая сборка
build --env prod --strictпроходит без ошибок. - 3
Пустые секции
Сводка «Не заполнено» пуста или осознанно принята. - 4
Дымовой прогон
smoke prodзелёный: 200, 404, все 301 и 410. - 5
После выкладки
Карта сайта — в Search Console.
Источник
Эта страница повторяет docs/guide/06-deploy.md из ветки prod. Репозиторий обновляется первым, поэтому там всегда самая свежая версия.
Справочник: спецификации Развёртывание и Поставка.