Полное руководство по виртуальным хостам Nginx: от первого сайта до продвинутой оптимизации (2026) | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Полное руководство по виртуальным хостам Nginx: от первого сайта до продвинутой оптимизации (2026)

04 мая 2026 12 мин. чтения
Содержание статьи

Nginx - это высокопроизводительный веб-сервер и обратный прокси, который стал стандартом для современных веб-приложений. Его событийно-ориентированная архитектура эффективно обрабатывает тысячи одновременных соединений с минимальным потреблением памяти. Виртуальные хосты (server блоки) - это фундаментальный механизм Nginx для размещения нескольких независимых сайтов или приложений на одном сервере. Это руководство предоставляет полный набор проверенных на практике конфигураций, от базового статического сайта до сложных сценариев с балансировкой нагрузки. Все примеры актуальны для 2026 года и готовы к применению в рабочей среде Ubuntu/Debian.

Базовый каркас: структура конфигов и ваш первый виртуальный хост

После установки Nginx из официальных репозиториев система конфигурации организуется вокруг нескольких ключевых директорий и файлов. Основной конфигурационный файл /etc/nginx/nginx.conf включает в себя глобальные настройки. Для управления сайтами используются директории /etc/nginx/sites-available/ (здесь хранятся все конфигурации) и /etc/nginx/sites-enabled/ (сюда добавляются символические ссылки на активные конфигурации). Эта структура позволяет легко включать и отключать сайты без удаления их конфигурационных файлов.

Готовая конфигурация виртуального хоста (с комментариями)

Создайте файл конфигурации для вашего первого сайта, например, /etc/nginx/sites-available/my-site.conf. Вот минимальный рабочий шаблон для статического сайта с подробными комментариями.

server {
    # Сервер слушает входящие HTTP-запросы на порту 80 для всех сетевых интерфейсов.
    listen 80;
    # Указываем доменное имя, для которого работает этот server блок.
    # Можно перечислить несколько имен через пробел: server_name example.com www.example.com;
    server_name my-site.local;

    # Корневая директория, откуда Nginx будет отдавать файлы сайта.
    # Убедитесь, что у пользователя, от имени которого работает Nginx (обычно www-data или nginx),
    # есть права на чтение файлов в этой директории.
    root /var/www/my-site/html;
    # Список индексных файлов, которые Nginx будет искать при обращении к директории.
    index index.html index.htm;

    # Блок location для обработки всех запросов ( / ).
    location / {
        # Пытается найти запрошенный URI как файл, затем как директорию,
        # и если ничего не найдено, отдает индексный файл.
        try_files $uri $uri/ =404;
    }

    # Блок для логирования. Рекомендуется настраивать отдельные логи для каждого сайта.
    access_log /var/log/nginx/my-site.access.log;
    error_log /var/log/nginx/my-site.error.log;
}

После создания файла активируйте сайт, создав символическую ссылку, и проверьте синтаксис конфигурации.

sudo ln -s /etc/nginx/sites-available/my-site.conf /etc/nginx/sites-enabled/
sudo nginx -t  # Проверка синтаксиса
sudo systemctl reload nginx  # Применение конфигурации без простоя

Разграничение окружений: разработка (dev) vs продакшен (prod)

Для предотвращения ошибок при переносе настроек между средами используйте отдельные конфигурационные файлы или управляйте параметрами через переменные окружения. Простой подход - создание шаблонных конфигураций с последующим включением окружения.

1. Создайте базовый конфиг /etc/nginx/sites-available/my-site-base.conf:

server {
    listen 80;
    server_name my-site.local;
    root /var/www/my-site/html;
    index index.html;

    # Включаем файл с настройками окружения
    include /etc/nginx/conf.d/my-site-environment.conf;

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

2. Создайте конфигурацию для разработки /etc/nginx/conf.d/my-site-dev.conf:

# Dev-окружение: отладочный режим, отключенное кэширование для разработчика.
client_max_body_size 50M;  # Разрешаем загрузку больших файлов
# Отключаем кэширование статики в браузере для удобства разработки
add_header Cache-Control "no-cache, no-store, must-revalidate";
# Включаем подробное логирование
access_log /var/log/nginx/my-site-dev.access.log;

3. Создайте конфигурацию для продакшена /etc/nginx/conf.d/my-site-prod.conf:

# Prod-окружение: безопасность и производительность.
# Включаем кэширование статики на 30 дней
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}
# Базовые заголовки безопасности
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
# Ограничиваем размер тела запроса
client_max_body_size 10M;

Символическую ссылку для my-site-environment.conf можно менять в зависимости от среды, используя скрипты развертывания (CI/CD). Для более комплексного подхода к настройке продакшн-окружения изучите полное руководство по настройке Nginx для production-среды.

Обработка динамического контента: интеграция с бэкендами

Nginx сам не выполняет код PHP, Python или JavaScript. Его роль - принимать запросы от клиентов и передавать их специализированным процессам бэкенда по протоколам FastCGI или HTTP (проксирование). Это разделение обязанностей повышает безопасность и производительность.

Оптимальная конфигурация для PHP-FPM

Для работы с PHP используется менеджер процессов PHP-FPM. Nginx передает запросы к .php файлам через протокол FastCGI. Вот стандартный и надежный блок location для обработки PHP.

server {
    ... # Базовые настройки server_name, root и т.д.

    location ~ \.php$ {
        # Пытаемся найти и передать скрипт. Если файл не существует - 404.
        try_files $uri =404;
        # Разделитель для FastCGI. В конце должен быть /, даже если путь пустой.
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        # Защита от попыток выполнения произвольного кода.
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        # Указываем, куда передавать запрос. Можно использовать сокет или TCP.
        # Сокет (рекомендуется для одного сервера):
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        # TCP (подходит для распределенных систем):
        # fastcgi_pass 127.0.0.1:9000;

        # Включаем стандартные параметры FastCGI
        include fastcgi_params;
        # Устанавливаем таймауты для предотвращения 502 ошибок при долгих запросах.
        fastcgi_read_timeout 60;
        fastcgi_send_timeout 60;
    }

    # Важно: запрещаем прямой доступ к другим .php файлам, например, конфигурационным.
    location ~ /(config|system|vendor)/.*\.php$ {
        deny all;
        return 403;
    }
}

Убедитесь, что пользователь www-data (или nginx) имеет права на чтение сокета PHP-FPM. Обычно это регулируется параметром listen.owner и listen.group в конфигурационном файле пула PHP-FPM (например, /etc/php/8.3/fpm/pool.d/www.conf).

Проксирование к Node.js и Python приложениям

Приложения на Node.js (Express, Nest.js) или Python (Django, Flask, FastAPI) часто запускаются как отдельные сервисы, слушающие localhost на определенном порту (например, 3000 или 8000). Nginx выступает в роли обратного прокси, перенаправляя запросы клиентов к этим сервисам.

Конфигурация для Node.js приложения (localhost:3000):

server {
    listen 80;
    server_name api.my-site.local;

    location / {
        # Адрес бэкенд-приложения.
        proxy_pass http://127.0.0.1:3000;
        # Критически важно передавать оригинальные заголовки, особенно Host.
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # Таймауты для долгих операций (загрузка файлов, long polling).
        proxy_connect_timeout 75s;
        proxy_send_timeout 3600s;
        proxy_read_timeout 3600s;
    }

    # Поддержка WebSocket соединений (для реального времени, чатов).
    location /ws/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

Конфигурация для Python приложения (Gunicorn/Uvicorn на сокете):

server {
    listen 80;
    server_name app.my-site.local;

    location / {
        # Проксирование на Unix-сокет, который создает Gunicorn/Uvicorn.
        proxy_pass http://unix:/run/gunicorn/myapp.sock;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Статические файлы Django/Flask лучше отдавать напрямую через Nginx.
    location /static/ {
        alias /var/www/myapp/static/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
    location /media/ {
        alias /var/www/myapp/media/;
        expires 7d;
        add_header Cache-Control "public";
    }
}

Для получения большего количества готовых шаблонов конфигураций, включая сложные сценарии с Docker, обратитесь к нашей коллекции практических шаблонов Nginx.

Безопасность: контроль доступа, SSL/TLS и защита от атак

Базовая безопасность виртуального хоста включает обязательное использование HTTPS, контроль доступа к чувствительным разделам и защиту от распространенных векторов атак. Эти меры должны применяться ко всем production-окружениям.

Автоматическое получение и обновление SSL-сертификатов Let's Encrypt

Certbot - стандартный инструмент для автоматизации работы с Let's Encrypt. Установите его и настройте для Nginx.

sudo apt update
sudo apt install certbot python3-certbot-nginx
# Получение сертификата для домена с автоматической настройкой Nginx
sudo certbot --nginx -d my-site.local -d www.my-site.local

Certbot автоматически изменит конфигурацию вашего виртуального хоста, добавив блок listen 443 ssl и необходимые директивы для SSL. Он также настроит автоматическое обновление сертификатов через системный таймер. В конфигурации появится редирект с HTTP на HTTPS.

server {
    listen 80;
    server_name my-site.local www.my-site.local;
    # Принудительный редирект всех HTTP-запросов на HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2; # HTTP/2 работает только поверх HTTPS
    server_name my-site.local www.my-site.local;

    # Пути к сертификатам, сгенерированные Certbot
    ssl_certificate /etc/letsencrypt/live/my-site.local/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/my-site.local/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    ... # остальная конфигурация сайта
}

Блокировка и разрешение доступа по IP-адресам

Используйте директивы allow и deny внутри блоков location для ограничения доступа к административным интерфейсам или staging-окружениям.

# Разрешаем доступ к панели администратора только с офисного IP и localhost.
location /admin/ {
    allow 192.168.1.0/24;  # Локальная сеть
    allow 203.0.113.5;     # Конкретный публичный IP
    allow 127.0.0.1;       # Localhost
    deny all;              # Запрет для всех остальных
    ... # proxy_pass или fastcgi_pass для бэкенда
}

# Защита WordPress wp-admin (в дополнение к сильным паролям).
location ~* ^/wp-admin/ {
    allow 192.168.1.0/24;
    deny all;
    try_files $uri $uri/ /index.php$is_args$args;
}

# Защита API-эндпоинта от публичного доступа.
location /api/v1/internal/ {
    allow 10.0.0.0/8;  # Разрешаем только из внутренней сети
    deny all;
    return 403;
}

Важно: этот метод неэффективен для пользователей с динамическими IP-адресами или при использовании CDN. В таких случаях необходима аутентификация на уровне приложения или с помощью базовой аутентификации Nginx (auth_basic).

Оптимизация производительности и удобства

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

Сжатие контента и кеширование (gzip, brotli, proxy_cache)

Сжатие Gzip и Brotli: Brotli обеспечивает лучшее сжатие, чем gzip, особенно для текстовых ресурсов. Настройте оба алгоритма.

# В контексте http (внутри nginx.conf или отдельного include-файла)
gzip on;
gzip_vary on;
gzip_min_length 1024;  # Сжимаем файлы больше 1 КБ
# Типы файлов для сжатия
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
# Уровень сжатия gzip (1-9). 6 - оптимальный баланс скорости и степени сжатия.
gzip_comp_level 6;

# Brotli сжатие (требует отдельной сборки Nginx с модулем или установки пакета nginx-extras).
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;

Кэширование статики в браузере: Укажите браузеру кэшировать статические ресурсы на длительный срок.

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

Кэширование прокси (proxy_cache): Кэширует ответы от бэкенда (например, от API или CMS) непосредственно на диске Nginx.

# Определяем зону кэша в контексте http.
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;

server {
    ...
    location /api/ {
        proxy_pass http://backend;
        # Включаем кэш для этого location.
        proxy_cache my_cache;
        # Ключ кэша: по умолчанию $scheme$proxy_host$request_uri.
        proxy_cache_key "$host$request_uri$cookie_user";
        # Кэшируем ответы с кодом 200 на 10 минут.
        proxy_cache_valid 200 10m;
        proxy_cache_valid 404 1m;
        # Добавляем заголовок в ответ, чтобы видеть, попал ли ответ из кэша (HIT/MISS/BYPASS).
        add_header X-Cache-Status $upstream_cache_status;
    }
}

Чистые URL и перенаправления

Директива rewrite изменяет URI запроса внутри Nginx. Используйте ее осторожно, так как избыточные rewrite-правила усложняют отладку.

# Убираем расширение .php из URL (пример для PHP-сайта).
# Запрос /about будет внутренне обработан как /about.php
location / {
    try_files $uri $uri/ @rewrite;
}
location @rewrite {
    rewrite ^/(.*)$ /$1.php last;
}

# Редирект с www на non-www (или наоборот). Делается на уровне server блока.
server {
    listen 80;
    server_name www.my-site.local;
    return 301 $scheme://my-site.local$request_uri;
}

# Постоянный редирект (301) при переезде страницы.
location = /old-page.html {
    return 301 /new-page;
}

# Редирект всех запросов со старого домена на новый.
server {
    listen 80;
    server_name old-domain.local;
    return 301 https://new-domain.local$request_uri;
}

Для глубокого понимания всех возможностей структуры конфигурации Nginx и тонкой настройки параметров performance ознакомьтесь с полным разбором структуры nginx.conf.

Логирование и диагностика для каждого виртуального хоста

Настройка отдельных логов для каждого сайта - обязательная практика. Это позволяет быстро изолировать проблему, не фильтруя общий файл /var/log/nginx/access.log.

Настройка отдельных логов и их анализ

Укажите пути к лог-файлам внутри каждого server блока.

server {
    server_name my-site.local;
    # Лог доступа в формате combined с буферизацией (32k буфер, сброс при заполнении).
    access_log /var/log/nginx/my-site.access.log combined buffer=32k flush=5m;
    # Лог ошибок с уровнем предупреждений warn.
    error_log /var/log/nginx/my-site.error.log warn;
    ...
}

Анализ error.log:

  • connect() failed (111: Connection refused) - Nginx не может подключиться к бэкенду (PHP-FPM, Node.js). Проверьте, запущен ли сервис бэкенда.
  • primary script unknown - Ошибка в директиве fastcgi_param SCRIPT_FILENAME. Убедитесь, что путь к файлу корректен.
  • open() "/var/www/..." failed (13: Permission denied) - Проблема с правами доступа к файлам сайта.
  • no live upstreams while connecting to upstream - Все серверы в блоке upstream отмечены как нерабочие.

Базовая статистика (stub_status): Включите модуль для мониторинга базовых метрик. Добавьте в конфигурацию:

location /nginx_status {
    stub_status;
    # Обязательно ограничьте доступ к этой статистике!
    allow 127.0.0.1;
    allow 192.168.1.0/24;
    deny all;
}

Запрос к http://my-site.local/nginx_status вернет данные в формате:

Active connections: 3
server accepts handled requests
 100 100 200
Reading: 0 Writing: 1 Waiting: 2

Ротация логов: Пакет logrotate обычно уже настроен для Nginx. Конфигурация находится в /etc/logrotate.d/nginx. Она обеспечивает ежедневный ротат логов, их сжатие и удаление старых файлов.

Продвинутые сценарии и лучшие практики

Для сложных проектов с высокими требованиями к доступности и производительности Nginx предоставляет инструменты для балансировки нагрузки, гибкой маршрутизации и автоматизации управления конфигурациями.

Балансировка нагрузки и отказоустойчивость (upstream)

Блок upstream определяет группу серверов бэкенда, между которыми Nginx распределяет запросы.

# Определяем группу бэкендов для нашего приложения.
upstream backend_cluster {
    # Балансировка по умолчанию - round-robin.
    # least_conn; # Можно раскомментировать для балансировки по наименьшему числу соединений.
    server 10.0.1.10:3000 weight=3; # У этого сервера в 3 раза больше «веса»
    server 10.0.1.11:3000;
    server 10.0.1.12:3000 backup;   # Резервный сервер, используется, если оба основных недоступны.
    # Пассивные health checks: сервер временно исключается после ошибок соединения/таймаута.
}

server {
    location / {
        proxy_pass http://backend_cluster;
        # Активные health checks (требуют отдельного коммерческого модуля или Nginx Plus).
        # health_check interval=5s fails=3 passes=2;
    }
}

При падении одного из серверов Nginx автоматически перенаправит трафик на остальные рабочие инстансы. Для реализации сложных сценариев высокой доступности, включая активные health checks и graceful shutdown, изучите продвинутое руководство по настройке Nginx как балансировщика нагрузки.

Резервное копирование и управление конфигами

Конфигурации Nginx - это инфраструктурный код. Относитесь к ним соответственно: храните в Git, проводите code review, используйте CI/CD для развертывания.

Скрипт для быстрого бэкапа конфигов:

#!/bin/bash
BACKUP_DIR="/backup/nginx/$(date +%Y%m%d_%H%M%S)"
mkdir -p $BACKUP_DIR
cp -r /etc/nginx $BACKUP_DIR/
# Также можно архивировать логи на момент бэкапа
tar -czf $BACKUP_DIR/nginx_backup.tar.gz /etc/nginx
find /backup/nginx -type d -mtime +30 -exec rm -rf {} \; # Удаляем бэкапы старше 30 дней

Использование Git: Инициализируйте репозиторий в /etc/nginx/ (или в отдельной директории с вашими конфигами из sites-available). Добавьте .gitignore, чтобы не отслеживать симлинки из sites-enabled, сертификаты Let's Encrypt и временные файлы. Это позволяет отслеживать изменения, откатываться к предыдущим версиям и автоматически развертывать конфигурации на несколько серверов.

Для сравнения архитектурных решений и выбора оптимального веб-сервера под конкретный проект рекомендуем ознакомиться с практическим сравнением Nginx и Apache в 2026 году.

Эффективная работа с современными технологиями часто требует интеграции с инструментами искусственного интеллекта для автоматизации рутинных задач, анализа логов или генерации кода. Для удобного и безопасного доступа к множеству AI-моделей через единый API, оплачиваемый в рублях, вы можете рассмотреть сервис AiTunnel. Он агрегирует более 200 моделей, включая GPT, Gemini и Claude, и позволяет управлять бюджетами и ключами в одном интерфейсе.

Поделиться:
Сохранить гайд? В закладки браузера