🖇 Конфиг Nginx для нескольких сайтов

05.06.2022

Возникла необходимость в автоматическом режиме создавать поддомены, но возиться с каждым доменом очень не хотелось, тем более правила работы у всех хостов одинаковые, а значит эти правила можно описать единожды.

Реализовать единый конфиг Nginx для нескольких сайтов можно при помощи масок или регулярных выражений директивы server_name

Один конфиг для всех поддоменов

Недавно я писал про Wildcard сертификат от Let's Encrypt для всех поддоменов, теперь настало время сделать для них единый конфиг.

Стоит учесть что при одном конфиге для всех поддоменов у них будет одна конфигурация и работать они будут по одним и тем же правилам.

В моем случае поддомены должны были работать на PHP и отдавать статику. Это нормальная схема. А вот случай когда один поддомен должен работать с использованием PHP, а другой на Node.js нужно рассматривать с двумя разными конфигами.

Итак, получается вот такой конфиг:

•••
plaintext
server { listen 80; # принимаем все входящие соединения на поддомены byurrer.ru # далее используем переменную $host для обозначени домена server_name *.byurrer.ru; root /var/www/$host/; # если директории виртуального хоста нет, тогда ответ 444 # https://nginx.org/ru/docs/http/request_processing.html if (!-d /var/www/$host) { return 444; } index index.html index.htm index.php; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include /etc/nginx/fastcgi_params; } }

Этот конфиг вводит ряд ограничений правил:

  • директории виртуальных хостов должны быть расположены по заранее выбранному пути, например /var/www/
  • директория виртуального хоста должна иметь имя поддомена
А теперь вариант конфига с использованием Wildcard сертификата:
•••
plaintext
# принимаем все входящие соединения с 80 порта (http) # на все поддомены byurrer.ru и перенаправлем их на https server { listen 80; server_name *.byurrer.ru; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name *.byurrer.ru; root /var/www/$host/; if (!-d /var/www/$host) { return 444; } index index.html index.htm index.php; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include /etc/nginx/fastcgi_params; } ssl_certificate /etc/letsencrypt/live/byurrer.ru/fullchain.pem; ssl_trusted_certificate /etc/letsencrypt/live/byurrer.ru/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/byurrer.ru/privkey.pem; }

Один конфиг для нескольких сайтов

Теперь сделаем конфиг для нескольких сайтов при помощи регулярных выражений.

Реглярные выражения в конфиге Nginx совместимы с PCRE, поэтому можно использовать именованные выделения, типа domain как в примере.

•••
plaintext
server { listen 80; server_name ~^(?<domain>.+)$; if (!-d /var/www/$domain) { return 444; } index index.html index.htm index.php; root /var/www/$domain/; location / { try_files $uri $uri/ =404; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include /etc/nginx/fastcgi_params; } }

Разница между масками и регулярными выражениями в примерах почти незначительна. С масками мы используем переменную host, а с регулярными выражения именнованное выделение domain.

Редиректы и сертификаты для конфига оставлю в качестве домашнего задания, там не сложно догадаться и трудно ошибиться :)

Результат

Как оказалось, при использовании Nginx вовсе необязательно дублировать конфиг виртуального хоста, если правила работы одинаковы.

Догадаться о таком решении при небольшом опыте использвания оказалось не трудно, а тут еще и русскоязычна документация :)