← Blog

Уход от WordPress: миграция моего сайта на Astro и SQLite

DEENESRUUK

Годами andrew.khanoff.com работал на WordPress: PHP-FPM, база данных MySQL, куча плагинов и постоянный фоновый гул «ваш сайт нуждается в обновлении». Это работало — но это было 475 МБ файлов, база данных размером 160 МБ с 301 таблицей и поверхность атаки, о которой я никогда не просил (xmlrpc.php, wp-login.php, плагин недели). Для личного резюме, которое в основном состоит из текста, это слишком много движущихся частей для исправления и беспокойства.

Поэтому я его заменил. Вот почему и как.

Почему уйти от WordPress

  • Поверхность атаки. Статическое резюме не нуждается в форме входа в публичном интернете, системе комментариев или удаленном выполнении кода через плагины.
  • Размер. PHP + MySQL + ядро WordPress + плагины только для отображения страницы, которая меняется несколько раз в год.
  • Контроль. Я хотел, чтобы контент находился в формате, которым я владею, и который рендерится кодом, который я могу прочитать, без панели администратора, доступной из открытого веба.

Замена намеренно мала: одно приложение Astro (с серверным рендерингом, адаптер Node) в одном контейнере Docker, с SQLite как единственным источником истины. Никакого PHP. Никакого MySQL. Админ-панель доступна только по passkey и заблокирована на LAN на обратном прокси. Проекты готовятся через ежедневный конвейер GitHub→локальный LLM, а аналитика основана на данных первой стороны с локальной базой данных GeoIP.

Правило: ничего разрушительного без пути отката

Вся миграция проходила поэтапно, и первый этап был не кодом — это были резервные копии. Прежде чем трогать что-либо:

  1. tar всего корневого каталога WordPress (сжатый на 350 МБ).
  2. mysqldump --single-transaction базы данных WordPress (18 МБ).
  3. Контрольные суммы и тесточная распаковка, чтобы доказать реальность архивов.

Только после этого я построил новый сайт рядом с WordPress, на временном порту, не трогая живой vhost. WordPress продолжал обслуживать домен все время, пока создавалось и наполнялось новым приложением.

Переключение без простоя

Сама смена была изменением обратного прокси, а не миграцией данных. nginx перешел от обслуживания /var/www/andrew.khanoff.com через PHP-FPM к проксированию нового контейнера на 127.0.0.1:8090:

location / {
    proxy_pass http://127.0.0.1:8090;
}

Старый vhost был сначала зарезервирован, nginx -t контролировал перезагрузку, и если что-то выглядело неправильно, откат был одной командой cp старой конфигурации плюс перезагрузка. Файлы и база данных WordPress остались полностью нетронутыми — домен просто перестал на них указывать. Время отката: секунды.

Я запустил новый сайт в рабочем режиме на некоторое время, проверил всё (публичные страницы, вход по passkey, конвейер проектов, экспорт PDF, аналитика), и только после этого удалил базу данных WordPress — после того, как сделал еще один свежий дамп непосредственно перед DROP. 475 МБ файлов WordPress были удалены в последнюю очередь, после повторной проверки резервных копий.

Что стало лучше

  • Безопасность: нет публичного входа, нет PHP, нет плагинов. Админ-панель защищена passkey WebAuthn и правилом allow 10.0.20.0/24 на nginx. Включен HSTS.
  • Производительность: мобильный Lighthouse показал 92 / 96 / 96 / 100 (Performance / Accessibility / Best-Practices / SEO), LCP ~1.4 с. Ответ сервера составляет ~30 мс, потому что нет танца с возвратами данных из базы — только SQLite и Astro.
  • Эксплуатация: весь сайт — один контейнер и один файл SQLite. Резервные копии тривиальны. Интересная автоматизация (GitHub + локальный LLM) живет в офлайн пакетном режиме — если она сломается, сайт об этом не узнает.
  • Владение: контент находится в SQLite и Markdown, в репозитории git, рендерится примерно из 2 тыс. строк кода, который я действительно могу прочитать.

WordPress — отличный инструмент. Просто он был слишком громоздким механизмом для резюме, которое я хочу быстрым, скучным в обслуживании и безопасным для оставления на месяцы. Эта статья и сайт, на котором вы ее читаете, — результат этого процесса.

Прозрачность: большинство постов здесь написаны с помощью ИИ, а неанглийские версии переведены локальной LLM и вычитаны. Заметили ошибку? Напишите мне.