# Переезд блога с WordPress на Hugo: 13 лет заметок в статику вместо PHP

Источник: https://blog.xsk.in/it/pereezd-bloga-s-wordpress-na-hugo/
Опубликовано: 2026-11-02 · Рубрики: IT, Linux


Этот блог жил активной жизнью с 2013 по 2018 год, за это время в нём накопилось 120 заметок про Linux, nginx, OpenWRT и Zabbix. Далее мне было недосуг обновлять его содержимое, поэтому следующие 8 лет он просто существовал, продолжая всё это время работать на древнющей виртуалке с Debian 6 и таким же старым WordPress. В целом, я понимал, что это бомба замедленного действия. Но недавно оно стало тикать неприлично громко. Ниже о том, как это было и на что я наступил.

## Откуда переезжали

В октябре вышли CVE с удалённым выполнением кода в PHP. Старый сервер блога работал на PHP 5.6, для которого исправлений уже не будет, поэтому блог срочно превратили в статику: WordPress уехал в закрытый контур, плагин Simply Static выгружал HTML, а скрипт заливал его в бакет S3 и раздавал как статику. Не то, чтобы это плохо работало, но держать ради одной заметки за восемь лет PHP, MariaDB и какие-то когнитивные знания про деплой - не наш путь. Да и нужна где-то пошаренная база знаний в наше время.

## Куда

Сравнивал Hugo, Zola, Astro и Eleventy. У бакета нет серверной логики, и Hugo закрывает то, что из-за этого нужно: адреса постов задаются в front matter (`url:`), старые слаги идут в `aliases`, RSS можно положить по старому адресу `/feed/`, а у каждой страницы может быть вторая версия в виде сырого markdown.

Hugo к тому же один бинарник без npm-дерева, и блогу без интерактивности ежегодные мажоры Node ни к чему. Тему выбирал из трёх, собрав на них свои же посты, и остановился на PaperMod: в ней главное текст, и она не требует обложек, которых у меня нет. Весь сайт собирается меньше чем за секунду.

## Конвертер

Готовый `wp2hugo` запускать не стал, не хотелось тащить чужой бинарник ради одного прогона. Свой конвертер из выгрузки WordPress (WXR) вышел на 360 строк Python без зависимостей. Простой HTML он переводит в markdown, а таблицы и списки определений оставляет HTML-вставками, потому что в markdown их только испортишь. Многострочные `<code>`, которыми я в 2013-м оформлял команды, превращаются в нормальные блоки кода. Переносы строк внутри абзаца сохраняет `hardWraps` в goldmark, как раньше это делал `wpautop`.

## Чтобы не сломались адреса

Все старые адреса вида `/it/<слаг>/<ID>` остались прежними, но у s3 бакета свои особенности.

- На адрес без слэша бакет отвечает 302 на адрес со слэшем, а WordPress ссылался как раз без него. Поэтому каждая страница заливается ещё и ключом без слэша, и ответ сразу 200.
- Параметры запроса бакет игнорирует, а 301 по ним делать не умеет. Старые ссылки вида `/?p=57` ловит маленький скрипт на главной, карта «ID в адрес» строится из front matter при сборке.
- GUID в RSS я оставил в формате WordPress (`?p=ID`) просто в угоду обратной совместимости (ну или потому что клод предложил).
- На несуществующий адрес сайт отвечает честным 404 с поиском по блогу. Если человек ничего не делает, через семь секунд его уводит на главную.

После выката проверил 230 адресов, со слэшем и без, и все ответили 200.

## Для людей и для ИИ

У каждой статьи теперь есть markdown-версия (`…/index.md`), у сайта есть `llms.txt`, а под каждым постом стоит блок «Прочитать с ИИ». Он копирует промпт со ссылкой на статью или открывает её сразу в ChatGPT или Claude. Идею подсмотрел у [pimenov.ai](https://pimenov.ai/articles/sait-teper-mozhno-chitat-s-ii/). Промпт просит не пересказать текст, а применить его к своей задаче. Главная кнопка копирует промпт, потому что параметр `q` у ChatGPT и Claude не документирован и может перестать работать.

## Комментарии: что пропало и что нашлось

Комментарии у блога лежали в трёх местах. В самом WordPress не нашлось ничего, кроме спама. С 2017 года работал isso на старом сервере, и тут фейл: его база лежала в `/var/lib/isso`, а при архивации сервера я сохранил `/etc`, `/home`, `/var/www` и дампы MySQL. Сервер на днях выключили и удалили, вместе с ним пропали комментарии isso. Не помню там полезных комментов, так что не жалко. Зато Disqus, где комментарии жили в 2013–2016 годах, отдал выгрузку целиком: 68 живых комментариев, и все нашли свои посты.

Новые комментарии теперь в Remark42 на своём сервере: войти можно через Telegram, GitHub или анонимно, уведомления приходят в Telegram. Импорт из Disqus у Remark42 штатный, но комментарии он привязывает к адресу из выгрузки, а там перемешаны адреса трёх эпох блога. Перед импортом их переписывает небольшой скрипт, сопоставляя посты по заголовку.

## Что убрал

Статистики посещений не было три года: старый Google Analytics перестал принимать данные ещё в 2023-м. По Вебмастеру Яндекса и Search Console блог держится в основном на OpenWRT (клонирование MAC, UCI, перенос системы на флешку). Удалять почти нечего, старые заметки просто получат плашку «архив».

Удалил только серию «Я был Стигом». Это любительский перевод глав чужой книги, поисковики её не показывали, а вопрос прав никуда не делся. Заодно ушли реклама, лайтбокс, jQuery и плагин для Твиттера.

## Что вынес

1. Архив сервера не заканчивается на `/etc` и базах. Всё, что приложения складывают в `/var/lib`, тоже данные.
2. Пока бэкап ни разу не восстанавливали, неизвестно, есть ли он.
3. DNS, сертификат, выкат комментариев и бэкап у меня теперь - честный IaC. Через полгода я не вспомню, что делал руками. А ИИ найдёт по контексту.

Комментарии снова работают, они ниже.

*Черновик подготовлен с помощью ИИ по материалам переезда и почти целиком переписан автором.*

