Pull to refresh

Динамические поддомены с использованием nginx+apache

Reading time 3 min
Views 28K
Этот топик — очередной топик про реализацию динамических поддоменов на сайте, коих много в интернете и даже есть пара топиков на хабре.

Проблема в том, что этот вопрос везде освещается только с точки зрения перенаправления с поддомена в папку и вся динамичность поддомена заключается в том, что ты создал папку — поддомен у тебя заработал.

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

Например, у нас есть готовый сайт, на котором работают профили по такому url: www.example.com/users/username, и есть всякие дополнительные возможности (например www.example.com/users/username/contact и другие страницы, связанные с этим юзером).

И мы теперь хотим вынести все, что связано с юзером, на поддомен, например username.example.com, username.example.com/contact и т.д.)

Решения, которые были найдены в интернете, меня не удовлетворили по 2 причинам:
  • Не нашел решения как заставить ее работать, сохранив работоспособность домена www.example.com
  • Все найденные решения подходят только для перенаправления в папку и не работают если дальше должны работать какие то правила


На нашем сайте стоит nginx над апачем (как и на многих других), поэтому пришлось изобретать велосипед самому, используя эту связку (nginx+ apache, благо сейчас почти на всех крупных сайтах стоит проксирующий nginx над апачем)



В общем то решение простое — т.к. на сайте уже налажена через mod_rewrite работоспособность ссылок вида www.example.com/users([a-zA-Z_]+) то было принято решение делать рерайт поддоменов через nginx.

Дополнительное условие — наш сайт работает только как ww.example.com, а example.com редиректит на www.

Соответственно осталось просто написать правило в конфиге nginx для рерайта поддоменов. Правило получилось такое это решение — не верное, использовать его не рекомендуется:
                location / {
                        proxy_pass http://11.22.33.44:8080;
                        proxy_redirect http://www.example.com:8080/ /;
                        proxy_set_header Host $host;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header X-Real-IP $remote_addr;

                        # учитываем что обязательно нужен www
                        set $uid "www";
                        # берем uid из поддомена
                        if ($host ~* "^(([a-z0-9\-]+)\.example\.com)$") {
                                set $uid $2;
                        }
                        # рерайтить нужно только если uid не www, на www работает весь сайт
                        if ($uid !~ "^(www)$") {
                                rewrite ^(.*)$ /users/$uid$1 break;
                        }
                }

upd После публикации топика BlackWizard подсказал лучшее решение, которое отвечает всем изначальным условиям:
server {
    server_name   www.example.com;

    location / {
         proxy_pass 11.22.33.44:8080;
    }
}

server {
    server_name   ~^(?<user>[a-z0-9\-]+)\.example.com$;

    location / {
        proxy_pass 11.22.33.44:8080/users/$user$uri$is_args$args;
    }
}


Таким образом, если посетитель зашел на поддомен то nginx это определяет и запрашивает из апача уже адрес вида www.example.com/users/username, а апач уже дальше разбирает все в соотвествии со своими правилами mod_rewrite.

Полученное в итоге решение обладает следующими плюсами:
  • Нет проблемы с www
  • Легко внедряется на любом сайте с уже готовой системой ссылок (не будем рассматривать процесс измененения ссылок на самом сайте)
  • Работает как для папок, так и для url, которые используют mod_rewrite


Минусы:
  • Требуется проксирующий nginx


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

UPDкак сделать чтобы username.example.com работал без указания всех возможных доменов в конфиге веб-сервера
Чтобы сервер корректно обрабатывал динамические поддомены, необходимо добавить одну маленькую запись в настройки DNS. Это можно сделать, используя панель управления сервером.
Просто добавьте следующую запись формата A («A record» в англоязычной версии):
*.example.com

Запись нужно добавлять после всех поддоменов (mail, smtp и т.д.)
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+48
Comments 50
Comments Comments 50

Articles