Этот топик — очередной топик про реализацию динамических поддоменов на сайте, коих много в интернете и даже есть пара топиков на хабре.
Проблема в том, что этот вопрос везде освещается только с точки зрения перенаправления с поддомена в папку и вся динамичность поддомена заключается в том, что ты создал папку — поддомен у тебя заработал.
Иногда же требуется решение другой проблемы — например вынос на поддомен профиля пользователя и всего функционала, который с ним связан.
Например, у нас есть готовый сайт, на котором работают профили по такому url: www.example.com/users/username, и есть всякие дополнительные возможности (например www.example.com/users/username/contact и другие страницы, связанные с этим юзером).
И мы теперь хотим вынести все, что связано с юзером, на поддомен, например username.example.com, username.example.com/contact и т.д.)
Решения, которые были найдены в интернете, меня не удовлетворили по 2 причинам:
На нашем сайте стоит nginx над апачем (как и на многих других), поэтому пришлось изобретать велосипед самому, используя эту связку (nginx+ apache, благо сейчас почти на всех крупных сайтах стоит проксирующий nginx над апачем)
В общем то решение простое — т.к. на сайте уже налажена через mod_rewrite работоспособность ссылок вида www.example.com/users([a-zA-Z_]+) то было принято решение делать рерайт поддоменов через nginx.
Дополнительное условие — наш сайт работает только как ww.example.com, а example.com редиректит на www.
Соответственно осталось просто написать правило в конфиге nginx для рерайта поддоменов. Правило получилось такое это решение — не верное, использовать его не рекомендуется:
upd После публикации топика BlackWizard подсказал лучшее решение, которое отвечает всем изначальным условиям:
Таким образом, если посетитель зашел на поддомен то nginx это определяет и запрашивает из апача уже адрес вида www.example.com/users/username, а апач уже дальше разбирает все в соотвествии со своими правилами mod_rewrite.
Полученное в итоге решение обладает следующими плюсами:
Минусы:
В целом решение мне показалось довольно неплохим, готов выслушать рекомендации и критику от гуру, потому что сам я в деле настройки веб-серверов новичек, и возможно решение пригодится новичкам вроде меня.
UPDкак сделать чтобы username.example.com работал без указания всех возможных доменов в конфиге веб-сервера
Чтобы сервер корректно обрабатывал динамические поддомены, необходимо добавить одну маленькую запись в настройки DNS. Это можно сделать, используя панель управления сервером.
Просто добавьте следующую запись формата A («A record» в англоязычной версии):
*.example.com
Запись нужно добавлять после всех поддоменов (mail, smtp и т.д.)
Проблема в том, что этот вопрос везде освещается только с точки зрения перенаправления с поддомена в папку и вся динамичность поддомена заключается в том, что ты создал папку — поддомен у тебя заработал.
Иногда же требуется решение другой проблемы — например вынос на поддомен профиля пользователя и всего функционала, который с ним связан.
Например, у нас есть готовый сайт, на котором работают профили по такому 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 и т.д.)