Сайт клиента: 100 баллов PageSpeed на Docker + nginx + SSL за 1 день
Представьте: к нам в ITFresh обращается крупная юридическая фирма, которая занимает 35 рабочих мест прямо в ЦАО. И что же их беспокоит? Их сайт-визитка еле дотягивал до 38 баллов в Google PageSpeed Insights, картинки загружались по 4 секунды, а маркетолог в отчаянии жаловалась, что Яндекс просто перестал поднимать ресурс в выдаче. Результат нашей работы? Всего один рабочий день нашего инженера — и сайт показывает чистые 100 баллов на десктопе, а на мобильных устройствах — уверенные 99. Как мы это сделали? Ниже я подробно разберу, как устроен наш эталонный nginx-конфиг в Docker, как мы выдаём Let's Encrypt сертификаты без миллисекунды даунтайма и почему один правильно собранный контейнер на голой Ubuntu обходит по скорости любой shared-хостинг.
Откуда взялись 38 баллов и почему сайт «тормозил»
Я хорошо помню, как однажды к нам подошла маркетолог клиента, с глазами полными надежды: «Пожалуйста, посмотрите наш сайт, мне кажется, с ним что-то совсем не так». Конечно, первым делом я открыл PageSpeed Insights. Признаюсь честно, цифры меня, мягко говоря, не обрадовали: всего 38 баллов на десктопе и совершенно удручающие 22 на мобильном. И это были не единственные проблемы. Показатели Core Web Vitals тоже оставляли желать лучшего: Largest Contentful Paint — целых 6.4 секунды, а Time to First Byte — почти две секунды, 1.8. Что сразу бросилось в глаза? Сайт "жил" наshared-хостинге, у одного из тех провайдеров, которые обещают золотые горы за три копейки: 2 ГБ места, общий пул PHP-FPM на две сотни клиентов и, конечно, древний Apache 2.4, который даже HTTP/2 не поддерживал. SSL-сертификат, кстати, у них был. Но работал он через два абсолютно ненужных редиректа: сначала с HTTP на HTTPS, а потом ещё и на www.https. И каждый такой лишний шаг, представьте, отнимал у пользователя по 200 миллисекунд.
Дальше я начал кропотливо составлять целую карту проблем. И вот что обнаружил: все картинки на сайте были в формате PNG, и каждая, внимание, весила по 1.6 МБ! Фавикон размером 32×32 раздавался без каких-либо кэш-заголовков — зачем, спрашивается? CSS-файлы никто и не думал минифицировать, а шрифты тянулись напрямую с Google Fonts, да ещё и с полным набором и кириллицы, и латиницы, хотя, скорее всего, столько символов и близко не требовалось. Один-единственный JS-файл на 240 КБ вообще блокировал рендер страницы. А вишенка на торте? Gzip был отключён на хостинге! И это под предлогом, как они сказали, «снижения нагрузки на CPU». О Brotli там, похоже, даже и не слышали, не то что использовать!
В таких ситуациях мы в ITFresh всегда разделяем всю работу на две большие, чёткие части. Первая — это серверная сторона: всё, что можно быстро настроить буквально за один рабочий день и сразу получить 30-40 дополнительных баллов к скорости. Вторая — контентная часть, которая больше сосредоточена на оптимизации картинок, шрифтов и скриптов; это уже, как правило, задача для верстальщика и занимает 2-3 дня. Сегодня мы подробно расскажем именно о серверной части. Наша команда тратит на неё ровно один человеко-день, и за эти усилия клиент гарантированно видит измеримый и ощутимый рост позиций своего сайта в поисковой выдаче.
Один день — как мы планируем работу
В 10:00 я уже был в офисе клиента, уютно расположенном в районе Чистых прудов. К 18:00 сайт уже полностью "переехал" и уверенно "жил" на нашей новой VM. А вот какой план мы составили:
Утренний блок: подготовка
- 10:00–10:30: Сразу же взял в работу — получил доступы к домену (через учётку регистратора). Что дальше? Быстро скачал весь контент сайта, используя `wget`.
- 10:30–11:00: Не теряя времени, арендовал новенькую VM на Selectel. Конфигурация: 2 vCPU, 4 GB RAM, 40 GB NVMe — всего за 690 рублей в месяц. И, конечно, на ней уже стояла свежая OS Ubuntu 24.04 LTS.
- Мы начали с безопасности, как и полагается. С 11 до 11:30 установили ssh-ключи – это намного надёжнее, чем пароль. Сразу же отключили авторизацию по паролю для пользователя root. А чтобы уж точно никто не пролез, настроили fail2ban, добавили ufw для фаервола, и, разумеется, включили автоматические unattended-upgrades. Всё как по учебнику, но с нашей фирменной заботой о мелочах.
Дневной блок: Docker и nginx
- Сразу после безопасности, с 11:30 до 13:00, перешли к сердцу инфраструктуры — Docker Engine. Мы установили его, настроили docker-compose. Важно было убедиться, что всё готово к работе, поэтому провели тестовую сборку nginx. Уже тогда добавили в неё brotli, чтобы заранее оценить преимущества сжатия. Всё шло по плану, без сучка, без задоринки.
- Целый час, с 13:00 до 14:00, мы уделили ювелирной работе над nginx-конфигом. Что туда вошло? Конечно же, HTTP/2 для быстрой загрузки страниц. Обязательно добавили OCSP stapling, чтобы браузеры пользователей не тратили время на проверку сертификатов. Не забыли про кэш-заголовки – они помогают экономить трафик. Ну и, само собой, включили gzip вместе с brotli. Ведь почему бы не использовать лучшее из двух миров для максимального сжатия? Наша цель — скорость.
- С 14:00 до 15:00 пришло время для SSL-сертификата. Мы использовали Let's Encrypt – отличный выбор для большинства проектов. Получили первый сертификат через webroot-метод. И, что самое приятное, сразу же настроили автоматическое обновление. Клиенту больше не нужно ломать голову над сроками: всё будет продлеваться само, без нашего вмешательства.
- Час с 15:00 до 16:00 мы посвятили миграции статики. Это не просто перенос файлов — здесь важна каждая деталь. Мы внимательно проверяли все пути, чтобы не было битых ссылок. Добавили фавиконы, чтобы сайт выглядел профессионально. И, конечно, не забыли про важные для SEO вещи: корректный robots.txt и актуальный sitemap.xml. Ведь хочется, чтобы поисковики всё индексировали правильно, верно?
Вечерний блок: переключение и контроль
- С 16:00 до 16:30 мы сделали ключевой шаг — обновили A-запись домена, направив её на наш новый, уже настроенный IP-адрес. Установили минимальный TTL, чтобы изменения вступили в силу как можно быстрее. Ну а дальше что? Только ждать. Это всегда самый волнительный момент в миграциях!
- Когда DNS-записи обновились, с 16:30 до 17:30, мы сразу же перешли к замерам. Запустили тесты PageSpeed, чтобы увидеть реальную скорость загрузки. А как же безопасность? Конечно, проверили наш SSL-сертификат на ssllabs.com. И, что самое приятное, получили заслуженную оценку A+. Это значит, что все наши настройки по HTTP/2, OCSP stapling и прочему дали отличный результат. Разве это не здорово?
- Вот и настало время сдачи проекта, с 17:30 до 18:00. Маркетолог получил от нас все свежие замеры скорости и безопасности, чтобы убедиться в качестве нашей работы. А для комфортного использования мы выслали подробную инструкцию по работе с Docker. Чтобы клиент чувствовал себя уверенно и мог самостоятельно управлять новой инфраструктурой. Мы не просто настраиваем, мы передаём знания. Вроде бы, всё, рабочий день закончен, а проект блестит!
В среднем, один такой день работы у нас в ITFresh стоит от 35 до 50 тысяч рублей. А теперь давайте погрузимся в самую интересную часть — техническую. Ведь она, по сути, повторяется практически у каждого клиента из этой категории, и вы сами увидите, почему.
Базовая VM: что должно быть на сервере до Docker
Поскольку мы всегда устанавливаем Docker на свежую Ubuntu 24.04, базовый набор работ для нас — это уже отработанный стандарт. Наш подход исключает любые компромиссы в виде Apache, ISPmanager или Plesk. Мы предпочитаем, чтобы всё было максимально минималистично, настроено вручную, и, что самое важное, полностью под нашим контролем. Это даёт нам гибкость и уверенность в каждом элементе:
# Свежая система
apt update && apt full-upgrade -y
# Базовые утилиты
apt install -y curl wget git ufw fail2ban htop vim ncdu \
unattended-upgrades apt-listchanges
# Часовой пояс — Москва
timedatectl set-timezone Europe/Moscow
# Файрвол: только 22, 80, 443
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
# fail2ban — защита от перебора SSH
systemctl enable --now fail2ban
# Автообновления безопасности
dpkg-reconfigure -plow unattended-upgrades
Дальше — Docker. Мы не идём по пути наименьшего сопротивления, устанавливая его из репозитория Ubuntu, нет. Мы ставим Docker только с официального docker.com. Почему? Потому что там всегда самая свежая версия, и, что критично для наших клиентов, долгая и надёжная поддержка.
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" \
> /etc/apt/sources.list.d/docker.list
apt update
apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
# Проверка
docker run --rm hello-world
Итак, что мы имеем к 11:30? Полностью чистая VM с Docker, надёжным файрволом, доступом по SSH-ключу и настроенными автообновлениями. Пора браться за сам сайт!
Dockerfile: nginx с brotli из исходников
Вы знали, что стандартный nginx, который можно найти в официальном Docker Hub, почему-то не поддерживает brotli "из коробки"? А ведь brotli на обычных HTML/CSS/JS файлах способен обеспечить на 15-25% лучшую компрессию, чем старый добрый gzip! Мы не стали мириться с этим упущением. Именно поэтому мы всегда собираем свой собственный, оптимизированный образ Nginx. Вот, кстати, рабочий Dockerfile, который наша команда постоянно использует для всех наших клиентов:
FROM nginx:1.27-alpine AS builder
ARG NGINX_VERSION=1.27.4
ARG BROTLI_VERSION=v1.0.0rc
RUN apk add --no-cache \
git build-base pcre-dev zlib-dev openssl-dev linux-headers \
&& cd /tmp \
&& wget https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \
&& tar -xf nginx-${NGINX_VERSION}.tar.gz \
&& git clone --recursive https://github.com/google/ngx_brotli.git \
&& cd nginx-${NGINX_VERSION} \
&& ./configure \
--with-compat \
--add-dynamic-module=/tmp/ngx_brotli \
&& make modules \
&& mkdir -p /modules \
&& cp objs/*.so /modules/
FROM nginx:1.27-alpine
COPY --from=builder /modules/ngx_http_brotli_filter_module.so \
/usr/lib/nginx/modules/
COPY --from=builder /modules/ngx_http_brotli_static_module.so \
/usr/lib/nginx/modules/
# Подкатываем нашу конфигурацию
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
# Без рута — security baseline
RUN chown -R nginx:nginx /var/cache/nginx /var/log/nginx /etc/nginx
USER nginx
EXPOSE 80 443
STOPSIGNAL SIGQUIT
CMD ["nginx", "-g", "daemon off;"]
Сборка проходит за 90 секунд на нашем dev-сервере, итоговый образ весит 38 МБ — это меньше, чем стоковый nginx с тяжёлым OpenSSL. Тегаю его как itfresh/nginx-brotli:1.27.4 и кладу в локальный registry.
nginx.conf: реальный референсный конфиг для статики
А вот так выглядит наш главный конфигурационный файл. Конечно, под каждого клиента мы его "подгоняем" и немного правим, но каркас, этот надёжный скелет, остаётся неизменным уже целых пять лет:
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# Базовые
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
types_hash_max_size 2048;
server_tokens off;
client_max_body_size 32M;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Логи
log_format itfresh '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct=$upstream_connect_time';
access_log /var/log/nginx/access.log itfresh buffer=64k flush=5s;
error_log /var/log/nginx/error.log warn;
# Компрессия
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json
application/javascript application/xml+rss
application/atom+xml image/svg+xml;
brotli on;
brotli_comp_level 6;
brotli_static on;
brotli_types text/plain text/css text/xml application/json
application/javascript application/xml+rss
application/atom+xml image/svg+xml;
# SSL общий
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 77.88.8.8 1.1.1.1 valid=300s;
resolver_timeout 5s;
include /etc/nginx/conf.d/*.conf;
}
А вот сайт-специфичный конфиг для домена клиента — отдельный файл в conf.d/zakon-yurist.conf (имя анонимизировано):
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# Только ACME-челлендж и редирект
location ^~ /.well-known/acme-challenge/ {
root /var/www/certbot;
default_type "text/plain";
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name zakon-yurist.ru www.zakon-yurist.ru;
ssl_certificate /etc/letsencrypt/live/zakon-yurist.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/zakon-yurist.ru/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/zakon-yurist.ru/chain.pem;
root /var/www/zakon-yurist;
index index.html;
# Безопасность
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
# Кэш для статики
location ~* \.(?:css|js|woff2|svg|png|jpg|webp|avif|ico)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
try_files $uri =404;
}
# HTML — пусть протухает быстро
location ~* \.html$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
location / {
try_files $uri $uri/ /index.html;
}
location = /robots.txt { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
}
Из тонкостей: я не использую ssl_protocols TLSv1.0 TLSv1.1 даже для совместимости со старыми клиентами. Эти протоколы выкинуты браузерами в 2020 году, и единственные, кому они нужны, — это внутренние корпоративные системы, которым в любом случае не место в публичном вебе. На SSL Labs такая конфигурация даёт A+ без оговорок.
docker-compose: nginx + certbot одной командой
Финальный compose-файл выглядит так. Он живёт в /opt/sites/zakon-yurist/docker-compose.yml:
services:
nginx:
image: itfresh/nginx-brotli:1.27.4
container_name: zakon-nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./conf.d:/etc/nginx/conf.d:ro
- ./www:/var/www/zakon-yurist:ro
- ./certbot/conf:/etc/letsencrypt:ro
- ./certbot/www:/var/www/certbot:ro
- ./logs:/var/log/nginx
networks:
- sitenet
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1/healthz"]
interval: 30s
timeout: 5s
retries: 3
certbot:
image: certbot/certbot:latest
container_name: zakon-certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --webroot -w /var/www/certbot --deploy-hook \"docker kill -s HUP zakon-nginx\"; sleep 12h & wait $${!}; done;'"
networks:
- sitenet
networks:
sitenet:
driver: bridge
Запуск первого сертификата — это отдельный, разовый прогон. Просто и быстро:
docker run --rm \
-v $(pwd)/certbot/conf:/etc/letsencrypt \
-v $(pwd)/certbot/www:/var/www/certbot \
certbot/certbot certonly \
--webroot -w /var/www/certbot \
--email admin@zakon-yurist.ru \
--agree-tos --no-eff-email \
-d zakon-yurist.ru -d www.zakon-yurist.ru
docker compose up -d
В чём красота этого решения? После первоначальной настройки certbot-контейнер автоматически, раз в 12 часов, проверяет, не пора ли продлить сертификат. При обновлении он отправляет специальный HUP-сигнал в nginx — и тот переоткрывает сертификаты без единого рестарта. Результат? Downtime — ноль миллисекунд. Ни секунды простоя!
Картинки и шрифты: 50% PageSpeed-баллов лежат здесь
Итак, только за счёт серверной части мы обычно "выбиваем" стартовые 60-70 баллов. Но разве 60-70 баллов — это предел? Чтобы дойти до заветных 100, нужно быть уверенным, что клиент загружает ровно столько мегабайт, сколько ему действительно необходимо для просмотра главной страницы. Вспомните ту юридическую фирму из ЦАО, о которой мы говорили в самом начале: у них на главной странице висело 14 фотографий, и каждая, представьте, весила по 1.6 МБ в формате PNG! Что мы сделали? Взяли и переконвертировали их все одним махом через cwebp:
# Один проход по всему каталогу: PNG/JPG → WebP с качеством 82
find /var/www/zakon-yurist/img -type f \( -iname "*.png" -o -iname "*.jpg" \) \
| while read f; do
cwebp -q 82 -m 6 "$f" -o "${f%.*}.webp"
done
# Дополнительно — AVIF для современных браузеров (Safari 16.4+, Chrome 85+)
find /var/www/zakon-yurist/img -type f -iname "*.webp" \
| while read f; do
avifenc -s 4 -j 4 -q 60 "$f" "${f%.*}.avif"
done
Размер каталога картинок упал с 23 МБ до 1.8 МБ — то есть в 12 раз. Затем верстальщик перевёл все теги <img> на <picture> с тремя источниками:
<picture>
<source srcset="/img/team-1.avif" type="image/avif">
<source srcset="/img/team-1.webp" type="image/webp">
<img src="/img/team-1.jpg" alt="Команда юристов"
width="600" height="400" loading="lazy" decoding="async">
</picture>
Ещё один важный шаг: мы всегда заменяем шрифты Google Fonts на self-hosted woff2. Зачем так заморачиваться? Это позволяет нам "срезать" целых 200-300 миллисекунд на DNS-запросах и TLS-рукопожатиях к fonts.googleapis.com. Плюс, мы полностью избавляемся от зависимости от внешнего CDN, который, как показывает наша практика, иногда "глючит" или вообще недоступен под санкционным трафиком. Так безопаснее и быстрее!
Замеры до и после: что показал Lighthouse
Чтобы сравнить результаты, мы делали замеры дважды. Первый раз, в 10 утра, когда сайт ещё жил на стареньком shared-хостинге. А потом, к 17:30, уже на новой, мощной VM. Какие же точки контроля мы выбрали?
- Performance (десктоп): 38 → 100;
- Performance (мобайл): 22 → 99;
- Largest Contentful Paint: 6.4 с → 0.8 с;
- First Contentful Paint: 2.1 с → 0.3 с;
- Time to First Byte: 1.8 с → 0.11 с;
- Total Blocking Time: 480 мс → 0 мс;
- Cumulative Layout Shift: 0.18 → 0.00;
- Оцените эту цифру: размер главной страницы с 4.2 МБ ужался до невероятных 240 КБ! Это не просто сокращение — это кардинальное изменение. Ваша страница теперь загружается почти мгновенно, и пользователи скажут вам спасибо. Впечатляет, правда?
- SSL Labs: B → A+;
- securityheaders.com: D → A.
Всего две недели, и что произошло? Яндекс тут же взялся за дело: сайт начал активно подниматься в поиске по запросам вроде «юрист по корпоративным спорам Москва». Представьте, с 18-й позиции он взлетел сразу на 7-ю! Мало того, по паре коммерческих запросов мы вообще увидели его на первой странице. Нет, это не какая-то там прямая магия PageSpeed. Это скорее сигнал от Яндекса: он наконец-то понял, что сайт больше не «медленный», и, как мы между собой говорим, снял с него этот неприятный «дисконт ранжирования».
Что мы делаем потом — мониторинг и регламент
Сайт готов, мы его сдали. Но разве на этом всё? Нет, проект для нас не заканчивается. Следующий шаг — я обязательно настраиваю минимальный мониторинг:
- UptimeRobot или внутренний Uptime Kuma — пинг каждые 60 секунд, алерт в Telegram @ITfresh_Boss при 2 подряд фейлах;
- SSL-monitoring через cron-задачу:
openssl s_client -connect zakon-yurist.ru:443 -servername zakon-yurist.ru— если до истечения меньше 14 дней, мне в Telegram прилетает напоминание; - Чтобы клиент всегда был в курсе происходящего, мы настроили еженедельный парсинг nginx access_log с помощью GoAccess. Все данные по посещаемости, откуда приходят пользователи, какие страницы смотрят — всё это собирается в удобный HTML-отчёт. Так клиент чётко видит, кто, когда и сколько раз заходил на его сайт. Это же ценная информация для бизнеса, не так ли?
- А что с логами Docker? Мы позаботились и об этом! Они пишутся через journald-driver и автоматически ротируются. Это значит, что они не будут бесконтрольно расти и однажды просто 'выжрать' весь диск. Важная мелочь, которая спасает от больших проблем, согласитесь.
- Бэкап содержимого
/opt/sitesраз в сутки на наш FTP-хранилище ITfresh_FTP — это HP DL380 Gen8 с RAID60 и дедупликацией ReFS, держит копии 60 дней.
PageSpeed — не та история, где настроил раз и навсегда. Я всегда перепроверяю показатели, примерно раз в квартал. Почему это так важно? Да очень просто: достаточно одному контент-менеджеру случайно загрузить на сайт какую-нибудь здоровенную картинку в JPG на 3 МБ, и ваши заветные баллы мигом скатятся куда-нибудь в 80-е. Чтобы такие "сюрпризы" не застали нас врасплох, у меня есть специальный Telegram-бот. Он каждую неделю запускает lighthouse-cli и присылает мне прямо в мессенджер подробный PDF-отчёт.
Контр-нарратив: где 100 баллов вредят бизнесу
Послушайте, я вот что скажу, и это, возможно, не всем понравится. Порой, эта дикая гонка за заветными 100 баллами PageSpeed может принести больше вреда, чем пользы. На нашей практике мы видели проекты, где маркетолог буквально выбивал 100/100. И что ради этого делали? Отключали Яндекс.Метрику, GTM, чат поддержки и, представьте, даже видеоблок с обращением главного менеджера! Ну и что в итоге? Поисковик видит красивые 100, но реальная конверсия при этом падает на целую треть. Какая уж тут польза?
Давайте посмотрим правде в глаза: наша настоящая цель — это совсем не какая-то там красивая, круглая цифра. Куда важнее, чтобы LCP укладывался в 2.5 секунды, CLS не полз выше 0.1, а INP оставался меньше 200 мс. Ведь это те самые пороги Core Web Vitals, которые напрямую, без всяких там обходных путей, влияют на ранжирование вашего сайта. Всё, что выше этих значений — это, безусловно, приятный бонус, но не цель ради цели. Если у вас сайт с кучей активных форм, чатов, аналитики, да ещё и видеоконсультаций, то вполне адекватный, реальный потолок — это 90-95 баллов на десктопе и 80-85 на мобильных. И знаете, по-моему, это абсолютно достаточно. И, главное, честно.
FAQ: что чаще всего спрашивают клиенты
Реально ли получить 100 баллов PageSpeed на корпоративном сайте?
Получить сотню? Да, конечно, это вполне реально! Но тут есть один нюанс: ваш сайт не должен сидеть на какой-нибудь неповоротливой CMS, обвешанной десятком плагинов, которые просто не отключить. Для лёгких, статических сайтов, лендингов или проектов на Grav и Hugo — выбить 100 баллов на Docker + nginx — это буквально задача на один день. А вот если у вас WordPress с WooCommerce, то готовьтесь к тому, что реальный максимум будет в районе 90-95 баллов. И, положа руку на сердце, честно говоря, тратить силы на борьбу за эти последние 5 процентов — для бизнеса чаще всего просто не имеет смысла.
Зачем заворачивать nginx в Docker, если можно поставить пакетом?
Нам нужно, чтобы конфиг, SSL-сертификат и контент жили как единое целое, знаете, таким вот атомарным юнитом. Почему это круто? Представьте: накатили вы обновление через `docker compose pull && up -d`, а оно вдруг — бац! — и упало. Что делаем? Спокойно откатываемся на предыдущий тег. И всё это — буквально за 30 секунд! С обычным пакетом из `apt` так не получится: там в случае проблем приходится чуть ли не с лупой рыться в системных директориях. А есть ещё один огромный плюс: на одной нашей VM спокойно размещаются 5-10 контейнерных сайтов для разных клиентов, и никаких тебе конфликтов версий. Разве это не удобно?
Сколько стоит у ITfresh такая разовая оптимизация?
Сколько это будет стоить? Для статического сайта или проектов на Grav/Hugo день работы нашего инженера обойдется в 35-50 тысяч рублей. За эти деньги мы полностью настраиваем Docker, nginx, SSL, brotli, кэширование, проводим полноценный аудит всех изображений, делаем замеры до и после оптимизации, а также предоставляем всю необходимую документацию. С WordPress или Bitrix история другая — там цена стартует от 70 до 120 тысяч. Почему такая разница? Всё просто: с этими CMS добавляется намного больше нюансов и объёмных задач. Например, нужно тонко настраивать плагины кэширования, серьёзно оптимизировать образы в медиабиблиотеке и, конечно, плотно работать с базой данных.
Не сломается ли сайт после Let's Encrypt auto-renew?
«А вдруг что-то сломается?» — часто спрашивают. Отвечаю: нет, абсолютно ничего не сломается, если `certbot` настроен грамотно, через `webroot` или `DNS-01`. И это не всё! Критически важно, чтобы `nginx` умел подхватить новый сертификат без полного перезапуска. Для наших клиентов мы всегда делаем так: создаём специальную `cron`-задачу, которая использует `certbot renew --deploy-hook` и просто отправляет `SIGHUP` прямо в контейнер `nginx`. Что это значит на практике? Никакого даунтайма! Ноль простоев, вообще. И знаете, мы идём дальше: через нашу систему мониторинга мы постоянно следим, чтобы до истечения срока действия сертификата всегда оставалось как минимум две недели. Если вдруг этот срок станет меньше, мне моментально прилетит алерт прямо в Telegram.
Что важнее для PageSpeed — сервер или код сайта?
Знаете, по моему глубокому убеждению, код сайта порой раза в три важнее! Посудите сами: даже если у вас идеальный, вылизанный код, но сервер «хромает», вы вряд ли получите больше 80 баллов. А вот на мощном, идеально настроенном сервере плохой код вообще редко когда перевалит за 50. Однако, есть одно "но". Правильно собранная связка из nginx, brotli, HTTP/2, грамотных кэш-заголовков и SSL (и, что важно, без этих вечных, ненужных редиретов!) — это ваш стартовый бонус. Она сразу добавляет 20-30 баллов сверху, если сравнивать с каким-нибудь дефолтным `apache` из репозитория. И что самое классное? Мы видим реально крутую картину в Lighthouse: ключевые метрики, такие как Largest Contentful Paint и Time to First Byte, значительно падают именно благодаря серверной оптимизации.
Итог
Представьте: всего один день работы инженера, одна скромная VM от Selectel за 690 рублей в месяц, один-единственный контейнер `nginx` с `brotli` и `certbot`. И что в итоге? Помните сайт той самой юрфирмы? Он получил не только заветные 100 баллов PageSpeed, но и оценку A+ на SSL Labs! А главное — всего за две недели он взлетел на целых 11 позиций в Яндексе! Все конфигурации, о которых я рассказывал, абсолютно рабочие: я лично разворачивал их на более чем 30 проектах с 2024 по 2026 годы. Так что, если ваш сайт сейчас где-то в районе 70 баллов или ниже, и вы чувствуете, что теряете клиентов и трафик — не тяните! Смело пишите мне. Я обязательно посмотрю и пришлю вам персональный план работ буквально за один рабочий день.
Похожая задача в вашей компании?
Расскажите, что у вас сейчас — пришлю план работ и оценку в течение рабочего дня.
Написать в Telegram или +7 903 729-62-41
Семёнов Е.С., руководитель ITfresh
