MAATRIX / Блог / Jekyll: статический сайт на VPS

Jekyll: статический сайт на VPS

Jekyll: статический сайт на VPS

MAATRIX

Если вы пишете на Ruby или просто привыкли к Jekyll ещё со времён GitHub Pages, переносить блог на генератор посерьёзнее не обязательно — Jekyll прекрасно живёт и на собственном VPS, без ограничений бесплатного хостинга GitHub. Ниже — рабочая последовательность: от установки Ruby до отдачи готового сайта через Nginx, с реальными командами и конфигами, которые можно скопировать и подставить свои значения.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое Jekyll и кому он подходит

Jekyll — генератор статических сайтов на Ruby, изначально написанный именно под GitHub Pages: там он до сих пор собирается автоматически при пуше в репозиторий. Но это не единственный сценарий — на своём VPS вы получаете полный контроль: любые плагины (в том числе те, что GitHub Pages запрещает из соображений безопасности), собственные версии гемов, произвольную структуру, и сайт не привязан к лимитам GitHub (10 сборок в час, 1 ГБ репозитория).

Jekyll — разумный выбор, если вы уже держите блог на Ruby-стеке, привыкли к синтаксису Liquid, или просто хотите готовую экосистему тем и плагинов (jekyll-seo-tag, jekyll-sitemap, jekyll-feed закрывают почти все базовые задачи блога из коробки). Если вы начинаете с нуля и скорость сборки критична — присмотритесь к Hugo, у него уже есть отдельный разбор в блоге: Hugo: установка и деплой. Ниже — честно про разницу.

Устанавливаем Ruby и Jekyll

Jekyll тянет за собой Ruby и Bundler, поэтому первый шаг — поднять актуальный Ruby, а не системный (в репозиториях Ubuntu/Debian он часто устаревший и без нужных заголовков для сборки нативных гемов).

Через rbenv (рекомендуемый способ, не трогает системный Ruby):

sudo apt update
sudo apt install -y git curl build-essential zlib1g-dev libssl-dev libreadline-dev libyaml-dev

curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-installer | bash
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
source ~/.bashrc

rbenv install 3.3.5
rbenv global 3.3.5
ruby -v

Дальше ставим Jekyll и Bundler через gem:

gem install jekyll bundler
jekyll -v

Если система ругается на права при gem install, не запускайте это через sudo с системным Ruby — это верный способ получить конфликт версий. Правильный путь — именно rbenv (или rvm), где gem-ы ставятся в домашнюю директорию пользователя.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Создаём новый сайт: структура проекта

Новый сайт создаётся одной командой:

jekyll new myblog
cd myblog
bundle install

Jekyll сгенерирует стандартную структуру:

myblog/
├── _config.yml       # глобальные настройки сайта
├── _posts/           # посты в формате YYYY-MM-DD-title.md
├── _layouts/          # HTML-шаблоны (Liquid)
├── _includes/         # переиспользуемые фрагменты (шапка, футер)
├── _sass/              # SCSS-стили
├── _site/              # сюда попадает результат сборки (не редактируется руками)
├── assets/             # css, images, js
├── Gemfile
└── index.md

Ключевой файл — _config.yml, там задаются url, title, description, плагины, и permalink-схема для постов:

title: Мой блог
description: Заметки про сервера и код
url: "https://example.com"
permalink: /:year/:month/:day/:title/

plugins:
  - jekyll-feed
  - jekyll-seo-tag
  - jekyll-sitemap

Важный нюанс: _config.yml читается только при старте jekyll build/jekyll serve — если вы меняете конфиг во время работы jekyll serve, нужно перезапускать процесс вручную, автоперезагрузка на изменения конфига не сработает (в отличие от постов и шаблонов).

Посты и Front Matter: Markdown + Liquid

Посты лежат в _posts/, имя файла обязано соответствовать шаблону ГОД-МЕСЯЦ-ДЕНЬ-название.md — из имени файла Jekyll берёт дату публикации. Каждый пост начинается с front matter — YAML-блока между ---:

---
layout: post
title: "Настройка Nginx под статику"
date: 2026-08-20 10:00:00 +0300
categories: [nginx, devops]
tags: [nginx, статика, vps]
---

Текст поста в Markdown. Можно вставлять Liquid-теги,
например {% raw %}{{ site.title }}{% endraw %} подставит заголовок сайта из _config.yml.

Liquid — движок шаблонов Jekyll, им написаны все _layouts и _includes. Синтаксис простой: {{ переменная }} для вывода значения, {% тег %} для логики (циклы, условия, include). Например, вывести последние 5 постов на главной:

<ul>
{% for post in site.posts limit: 5 %}
  <li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}
</ul>

Если раньше не работали с Liquid — на старте это непривычнее, чем шаблонизаторы Hugo (Go templates) или Astro/Eleventy, но зато документация Jekyll и готовые темы почти всегда рассчитаны именно на Liquid, так что копипастить чужие сниппеты просто.

Сборка сайта: jekyll build и jekyll serve

Для локальной разработки — jekyll serve, он поднимает встроенный веб-сервер с автообновлением при изменении файлов:

bundle exec jekyll serve --host 0.0.0.0 --port 4000

Флаг --host 0.0.0.0 нужен, если вы работаете прямо на VPS и хотите открыть страницу превью в браузере с другого устройства (не забудьте на время открыть порт в файрволе или пробросить через SSH-туннель — постоянно держать порт разработки открытым наружу не стоит).

Для продакшена нужна не превью-версия, а статическая сборка:

bundle exec jekyll build --destination /var/www/myblog

Команда генерирует чистый HTML/CSS/JS в указанную папку — никакого Ruby-процесса в продакшене не остаётся, отдавать будет обычный веб-сервер. Это и есть главное преимущество статического генератора: сайт не падает от нагрузки на бэкенд, потому что бэкенда для отдачи страниц просто нет.

Здесь стоит сказать честно: Jekyll заметно медленнее Hugo на сборке, особенно на больших сайтах с сотнями постов — Hugo написан на Go и собирает сайты практически мгновенно, а Jekyll на Ruby ощутимо уступает по скорости билда. Для блога на десятки-сотни постов разница на практике не критична (сборка на VPS с современным CPU выполняется за разумное время), но если у вас тысячи страниц или сборка запускается очень часто — это тот случай, когда стоит присмотреться к Hugo или хотя бы протестировать оба варианта на своих данных перед выбором.

Отдаём сайт через Nginx

Nginx для статики — самый простой и предсказуемый вариант: никакого проксирования, только отдача файлов с диска. Базовый конфиг:

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/myblog;
    index index.html;

    location / {
        try_files $uri $uri/ $uri.html =404;
    }

    location = /404.html {
        internal;
    }

    error_page 404 /404.html;

    gzip on;
    gzip_types text/css application/javascript application/json image/svg+xml;

    location ~* \.(css|js|jpg|jpeg|png|gif|svg|woff2?)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

Проверяем конфиг и перечитываем Nginx:

sudo nginx -t
sudo systemctl reload nginx

HTTPS сюда добавляется отдельно через Let's Encrypt — этот шаг разобран детально в статье Let's Encrypt SSL на VPS, для Jekyll ничего специфичного там нет — сертификат вешается на тот же server-блок, что и статика.

Автодеплой: обновляем сайт одной командой

Собирать сайт руками после каждой правки поста неудобно. Рабочая схема — bare git-репозиторий на сервере с post-receive хуком, который при git push автоматически делает bundle exec jekyll build:

# на сервере
mkdir -p ~/myblog.git && cd ~/myblog.git
git init --bare
# ~/myblog.git/hooks/post-receive
#!/bin/bash
GIT_WORK_TREE=/home/deploy/myblog-src git checkout -f main
cd /home/deploy/myblog-src
bundle install --quiet
bundle exec jekyll build --destination /var/www/myblog
chmod +x ~/myblog.git/hooks/post-receive

Локально добавляете remote и пушите:

git remote add prod deploy@your-server:~/myblog.git
git push prod main

Хук выполняет checkout, ставит зависимости и пересобирает сайт — через несколько секунд после push изменения уже в /var/www/myblog, и Nginx их сразу отдаёт (перезагружать сам Nginx не нужно, он просто читает файлы с диска при каждом запросе). Если хотите более гибкий вариант с очередью сборок, вебхуками из GitHub и логами деплоя — посмотрите общий разбор в статье автодеплой из Git на VPS, принцип тот же, меняется только команда сборки.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Jekyll работает на Windows?

Официально не поддерживается напрямую, но работает через WSL2 (Windows Subsystem for Linux) — там Ruby и Jekyll ставятся так же, как на Linux. Для продакшена это не важно: сайт всё равно собирается и отдаётся с Linux-сервера.

Можно ли обойтись без rbenv и ставить Ruby из apt?

Технически да, но версия в репозиториях Ubuntu/Debian обычно старая, и некоторые современные гемы (в том числе плагины Jekyll) требуют более новый Ruby. rbenv или rvm избавляют от этой головной боли и позволяют держать нужную версию без риска сломать системные Ruby-зависимости.

Почему jekyll build падает с ошибкой по гему?

Чаще всего не хватает системных библиотек для сборки нативных расширений (nokogiri и подобные тянут libxml2, libssl-dev). Установите build-essential, zlib1g-dev, libssl-dev из первого раздела и повторите bundle install.

Нужен ли Ruby-процесс на сервере после сборки?

Нет. jekyll build создаёт чистые HTML/CSS/JS файлы, Ruby и Jekyll нужны только на этапе сборки. В продакшене Ruby можно даже не запускать — Nginx отдаёт готовые файлы.

Что делать, если сайт собрался, но Nginx отдаёт 404 или старую версию?

Проверьте, что --destination в jekyll build действительно указывает на root из конфига Nginx, и что кэш браузера/CDN не подсовывает старую страницу. Если проблема глубже — общий разбор типовых ошибок статики есть в статье статический сайт на сервере: частые ошибки.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →