Урок 04

Virtual hosts и server-блоки

Что такое virtual host

Virtual host — отдельный сайт на одном сервере. Один Nginx может обслуживать десятки доменов: example.com, api.example.com, nobleweb.ru.

Nginx определяет, какой сайт отдавать, по server_name (домену).

Простой server-блок

Файл /etc/nginx/sites-available/example.com:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/example/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
}

Разбор

listen 80; — слушать порт 80 (HTTP).

listen [::]:80; — то же для IPv6.

server_name example.com www.example.com; — для каких доменов.

root /var/www/example/public; — корневая папка с файлами.

index index.php index.html; — файл по умолчанию.

location / — что делать для всех URL.

try_files $uri $uri/ /index.php?$query_string; — если файл существует — отдать, иначе — в index.php (Laravel).

Стандартный конфиг для Laravel

server {
    listen 80;
    listen [::]:80;
    server_name example.com;

    root /var/www/skills/api/public;
    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.5-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Ключевые моменты Laravel

root .../public; — важно: корень — папка public, не корень проекта. Иначе .env доступен снаружи.

try_files — Laravel использует фронт-контроллер public/index.php. Все запросы идут туда.

location ~ \.php$ — обработка PHP через fastcgi_pass на PHP-FPM.

fastcgi_pass unix:/var/run/php/php8.5-fpm.sock; — сокет PHP-FPM. Проверь свою версию:

ls /var/run/php/
# php8.5-fpm.sock

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; — путь к PHP-файлу. $realpath_root защищает от path traversal через симлинки.

location ~ /\.(?!well-known).* — запрет доступа к скрытым файлам (.env, .git). (?!well-known) — исключение для .well-known/acme-challenge (нужен для Let's Encrypt).

Включение сайта

1. Создай конфиг:

sudo nano /etc/nginx/sites-available/example.com

2. Симлинк в sites-enabled:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

3. Проверь:

sudo nginx -t

4. Перезагрузи:

sudo systemctl reload nginx

5. Проверь:

curl -I http://example.com
# HTTP/1.1 200 OK

Удаление default-конфига

Nginx по умолчанию отдаёт страницу приветствия. Убери:

sudo rm /etc/nginx/sites-enabled/default
sudo systemctl reload nginx

Иначе если server_name не совпадёт — Nginx отдаст эту страницу.

Проверка server_name

Если домен не совпадает с server_name, Nginx отдаёт первый server-блок из конфига. Это может быть чужой сайт.

Проверь:

curl -I http://wrong-domain.com

Если это не 404, а чужой сайт — значит default не удалён или порядок server-блоков неверный.

Поддомены

Для api.example.com:

server {
    listen 80;
    server_name api.example.com;
    root /var/www/skills/api/public;
    # ...
}

Каждый поддомен — свой server-блок.

Wildcard

Для всех поддоменов одного домена:

server_name *.example.com;

Для любых доменов (для default-блока):

server_name _;

Проверка текущего server-блока

Полезная команда:

nginx -T | grep -A 20 "server_name example.com"

Покажет весь блок.

Итог

Алгоритм:

  1. Создать конфиг в sites-available/
  2. Симлинк в sites-enabled/
  3. nginx -t
  4. systemctl reload nginx

Для Laravel: корень — public/, PHP — через fastcgi_pass.

Дальше — reverse proxy для Laravel.