Назад | Перейти на главную страницу

Массовый виртуальный хостинг с Apache 2.4

Я хотел бы использовать значение, установленное VirtualDocumentRoot в RewriteRule.

Апач документация говорит:

Еще одна вещь, которую необходимо определить, - это корень документа (настроенный с помощью DocumentRoot и доступный для сценариев CGI через переменную среды DOCUMENT_ROOT). В нормальной конфигурации это используется основным модулем при сопоставлении URI имен файлов, но когда сервер настроен на динамический виртуальный хостинг, это задание должно быть передано другому модулю (либо mod_vhost_alias, либо mod_rewrite), который имеет другой способ сделать отображение. Ни один из этих модулей не отвечает за установку переменной среды DOCUMENT_ROOT, поэтому, если какие-либо документы CGI или SSI будут использовать ее, они получат неверное значение.

Ссылаясь на документацию, кажется, я не смогу использовать %{DOCUMENT_ROOT} в RewriteRule. Но после поиска альтернативных решений я нашел это проездной билет (заглавие: Переменная среды DOCUMENT_ROOT установлена ​​неправильно с VirtualDocumentRoot), говоря, что это было «исправлено в 2.4.1».

Я использую последнюю (стабильную) версию Apache:

$ httpd -v
Server version: Apache/2.4.9 (Unix)
Server built:   Jun 18 2014 03:07:48

... но, похоже, у меня это не работает. При тестировании %{DOCUMENT_ROOT} имеет значение по умолчанию, установленное DocumentRoot в httpd.conf. Я хотел бы %{DOCUMENT_ROOT} (или любой другой переменной, которую я мог бы использовать) для динамической установки VirtualDocumentRoot.

Вот что я хотел бы использовать в httpd-vhosts.conf:

<VirtualHost *:8080>
    ServerName dev
    ServerAlias *.dev

    VirtualDocumentRoot "/usr/local/var/www/.dev/%-2+"

    RewriteRule ^/(.*\.php(/.*)?)$ "fcgi://127.0.0.1:9000%{DOCUMENT_ROOT}/$1" [P]
</VirtualHost>

Есть решение?

Я сделал это с помощью mod_proxy и mod_proxy_fcgi, отметив "Прокси через обработчик" раздел: https://httpd.apache.org/docs/trunk/mod/mod_proxy_fcgi.html

Мне нужно было запускать PHP 5.6 и PHP 7 на моих локальных сайтах разработчиков, поэтому я установил PHP-FPM как для PHP 5.6, так и для PHP 7 и настроил конфигурацию vhosts следующим образом:

<Virtualhost *:80>
    VirtualDocumentRoot "/Volumes/CODE/projects/%1"
    ServerName sites.hack
    ServerAlias *.hack
    UseCanonicalName Off
    <FilesMatch "\.php$">
        Require all granted
        SetHandler proxy:fcgi://127.0.0.1:9056
    </FilesMatch>
</Virtualhost>

<Virtualhost *:80>
    VirtualDocumentRoot "/Volumes/CODE/projects/%1"
    ServerName php7.php
    Serveralias *.php
    UseCanonicalName off
    <FilesMatch "\.php$">
      Require all granted
      SetHandler proxy:fcgi://127.0.0.1:9070
    </FilesMatch>
</Virtualhost>

Как поясняется в разделе «Прокси через обработчик»:

Когда FastCGI настроен таким образом, сервер может вычислить наиболее точный PATH_INFO.

С этой конфигурацией я могу:

Посетите местный сайт разработчиков http://example.hack и он будет извлечен из корня документа /Volumes/CODE/projects/example и передаваться в мою службу PHP 5.6 PHP-FPM SetHandler proxy:fcgi://127.0.0.1:9056.

Посетите местный сайт разработчиков http://example.php и он будет извлечен из того же корня документа /Volumes/CODE/projects/example но он будет передан моей службе PHP 7 PHP-FPM SetHandler proxy:fcgi://127.0.0.1:9070

У меня с этим пока не было проблем. Все просто и работает.

Посмотрев во многих направлениях с @ Джон Олд (спасибо за ваше время и помощь), я наконец нашел решение. Как я сказал в предыдущий комментарий, он не идеален на 100%, но мне подходит.

Для ясности, вот что я хотел иметь в httpd-vhosts.conf:

<VirtualHost *:8080>
    ServerName dev
    ServerAlias *.dev

    VirtualDocumentRoot "/usr/local/var/www/.dev/%-2+"

    RewriteRule ^/(.*\.php(/.*)?)$ "fcgi://127.0.0.1:9000%{DOCUMENT_ROOT}/$1" [P]
</VirtualHost>

И вот что я придумал:

<VirtualHost *:8080>
    ServerName dev
    ServerAlias *.dev

    VirtualDocumentRoot "/usr/local/var/www/.dev/%-2/%-3"

    RewriteCond %{SERVER_NAME} (?:([^.]+)\.)?([^.]+)\.dev
    RewriteRule ^/(.*\.php(/.*)?)$ "fcgi://127.0.0.1:9000/usr/local/var/www/.dev/%2/${:%1|www}/$1" [P]
</VirtualHost>

я использую RewriteCond захватить части %{SERVER_NAME} и повторно использовать их в RewriteRule.

Есть две группы захвата: субдомен (%1) и домен (%2). Субдомен не является обязательным, поэтому я использую синтаксис ${map:value|default} чтобы установить значение по умолчанию для поддомена, когда оно пусто.

VirtualDocumentRoot имеет собственное значение по умолчанию, когда часть (%N.M) недоступно. Как сказано в документация:

Если N или M больше, чем количество доступных частей, интерполируется одиночное подчеркивание.

Вот почему мне пришлось использовать небольшой "трюк", чтобы заставить его работать с необязательным поддоменом:

ln -sfv /path/to/the/project/www /path/to/the/project/_

Если вы думаете, как это сделать только конфигурация, оставьте комментарий, и я отредактирую свой ответ с вашим вкладом.

Следующее сработало для меня для 2.4

UseCanonicalName Off
<VirtualHost *:80>
  ServerName auto.dev
  ServerAlias *.dev
  VirtualDocumentRoot /Users/yourusername/Sites/auto/%1/public

  <Directory ~ "/Users/yourusername/Sites/auto/.*/public">
    Options Indexes FollowSymlinks MultiViews
    AllowOverride All
    Order allow,deny
    Allow from all
  </Directory>
</VirtualHost>

Обратите внимание, что я подключаюсь к общей папке в корневой папке.

Переменная недоступна в файлах конфигурации apache.

Взгляните на mod_macro, который позволяет использовать переменные в файлах conf.

http://httpd.apache.org/docs/current/mod/mod_macro.html