적합한 문서 루트가있는 경우 VirtualDocumentRoot * only * 사용


8

구성을 다시로드하지 않고 Apache 가상 호스트를 동적으로 만들 수있는 환경을 설정하고 싶습니다.

mod_vhost_alias 사용 하여이 작업을 수행 할 수 있습니다. 기본 가상 호스트를 다음과 같이 설정했습니다.

<VirtualHost *>
  UseCanonicalName Off
  VirtualDocumentRoot /var/www/sandboxes/domains/%0
  ServerName catchall.host
</VirtualHost>

잘 작동하지만 현재 설정되어 있지 않은 호스트 이름을 요청하면 404 Not Found 오류가 발생합니다.

내가 정말로 하고 싶은 것은 문서 루트가있는 경우 에만 이 VirtualHost를 시작 하는 것입니다. 그렇지 않으면 다른 호스트와 일치 시키십시오 (즉, VirtualDocumentRoot 가 존재 하는 것과 동일한 방식으로 작동하도록하십시오) ServerAlias)

VirtualHostRoot가 구성된 도메인에 대한 요청이 기본 가상 호스트로 떨어지면서 첫 번째 가상 호스트가 모든 요청을 처리하는 두 번째 가상 호스트로 만들려고 시도했지만 작동하지 않았습니다.

그렇다면 어떻게 가상 호스트를 동적으로 구성 할 수 있지만 아직 구성되지 않은 다른 가상 호스트로 대체 할 수 있습니까?

답변:


7

나는 나를 위해 작동하는 해결 방법을 찾았습니다.

ErrorDocument 를 사용하여 PHP 스크립트에서 404 오류를 선택할 수 있습니다 . 처음에는 문제가있는 것 같습니다. DocumentRoot가 없으면 스크립트는 어디에 있습니까?

다른 도메인에서 제공 한 오류 메시지의 URL을 사용할 수 있습니다. 그러나 테스트에서 원래 요청한 도메인이 무엇인지 알 방법이 없었습니다.

대답은 디렉토리 에 Alias 에게 있었고 오류를 처리했기 때문에 내 호스트는 다음과 같습니다.

<VirtualHost *>
  UseCanonicalName Off
  VirtualDocumentRoot /var/www/sandboxes/domains/%0
  ServerName catchall.host
  Alias /errors /var/www/default/errors/
  ErrorDocument 404 /errors/notfound.php
</VirtualHost>

이제 구성되지 않은 도메인이 요청되면 /var/www/default/errors/notfound.php의 스크립트가 대신 호출됩니다. 이 스크립트는 $ _SERVER [ 'HTTP_HOST']에서 어떤 도메인이 요청되었는지 확인할 수 있습니다. 실제로 구성된 경우 일반 404가 있습니다. 구성되지 않은 경우 대체 오류 메시지가 표시 될 수 있습니다. 제 경우에는 호스트를 설정하는 데 도움이되는 UI를 보여줍니다.


모든 요청의 기본값으로 404를 기본값으로 처리하지 않습니까?
Kyle

1
오류 처리기는 VirtualDocumentRoot가 존재하지 않거나 실제로는 404이지만 notfound.php가 쉽게 차이점을 알 수있는 경우에만 호출됩니다.
Paul Dixon

3

인터넷 검색시 귀하의 질문을 찾았습니다. 나는 정확히 같은 문제가 있었고 Paul의 답변에 설명 된대로 수정 프로그램을 적용했습니다 . 그러나 복잡한 웹 응용 프로그램의 경우 모든 요청을 하나의 단일 경로로 라우팅하는 것에 만족하지 않았습니다 notfound.php.

결국 외부 스크립트 없이도 VirtualHost 구성을 편집하여 문제를 해결할 수있었습니다.

처음에는 내 VirtualHost가 다음과 같이 구성되었습니다.

<VirtualHost *:80>
    Usecanonicalname Off
    Virtualdocumentroot /mnt/ramdisk/www/cms-%-3.0-development/
</VirtualHost>

나는 URL을 좋아했다 client1.domainname.com, client2.domainname.com그리고whatever.domainname.com

이는에 해결 /mnt/ramdisk/www/cms-client1-development/, /mnt/ramdisk/www/cms-client2-development/그리고/mnt/ramdisk/www/cms-whatever-development/

그러나 같은 nonexistent.domainname.com디렉토리 /mnt/ramdisk/www/cms-nonexistent-development/는 디렉토리 가 없기 때문에 404를 제공 합니다. 이 하위 도메인이 디렉토리를 사용하기를 원했습니다/mnt/ramdisk/www/cms-default-development/

나는 ModRewriteand 를 사용하여 이것을 고쳤다 ModProxy.

<VirtualHost *:80>
    Usecanonicalname Off
    Virtualdocumentroot /mnt/ramdisk/www/cms-%-3.0-development/
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^(.*)\.domainname\.com$ [NC]
    RewriteCond /mnt/ramdisk/www/cms-%1-development/ !-d
    RewriteRule (.*) http://default.domainname.com/$1 [P,L]
</VirtualHost>

이것이하는 것 : 하위 도메인 (이전 부분 .domainname.com)을 가져 와서 경로 (% 1)에 삽입 하고 디렉토리가 존재하지 않는 경우에만 기본 URL에 프록시 요청을 합니다.

프록시를 사용하면 프로세스가 투명 해지고 사용자는 자신이 http://nonexistent.domainname.com을 방문 하고 실제로 http://default.domainname.com/ 의 컨텐츠를 보는 것으로 생각합니다 .


3

나는 또한 apache2 dynamic vhost fallback에 대한이 질문을 발견 했으며 Luc의 대답은 문제를 해결하는 데 많은 도움이되었지만 여전히 목표를 달성하기 위해 무엇을했는지 보여주고 싶습니다. 주로 추가 작업이 필요하고 생각하기 때문입니다. 미래의 모든 Google 직원에게 도움이 될 수 있습니다 ...

내 목표

  • VPS를 가리키는 모든 도메인 및 하위 도메인에 대한 동적 vhosting
  • foo.com 와 동일한 콘텐츠를 제공해야합니다 www.foo.com
  • 알려지지 않은 도메인을 기본으로 대체
  • 의 알 수없는 하위 도메인에 대한 폴백 (fallback) foo.comwww.foo.com(가)하지 않는 한 www대체 대신 기본값으로, 사용할 수 없습니다

DNS

VPS를 가리키는 몇 개의 도메인 (및 모든 하위 도메인)이 있습니다. 예를 들면 다음과 같습니다.

  • foo.com
  • bar.com
  • foobar.com

파일 시스템

다음 디렉토리가 있습니다. 도메인에는 사용 가능한 하위 도메인의 이름을 가진 디렉토리가 있습니다. www 디렉토리는 필요하지만 구성은 존재하지 않는 상황을 처리 할 수 ​​있어야합니다. 로컬 호스트는 기본 폴백으로 사용됩니다.

/var
  /www
    /localhost
    /foo.com
       /www
       /bar
    /bar.com
       /foo

테스트

목표를 테스트 가능한 사례로 변환 :

  • foo.comfoo.com/www 에서 제공해야합니다.
  • www.foo.comfoo.com/www 에서 제공해야합니다.
  • bar.foo.comfoo.com/bar 에서 제공해야합니다.
  • foo.foo.comfoo.com/www 에서 제공해야합니다 (foo.com/foo는 존재하지 않습니다)
  • bar.comlocalhost 에서 제공해야합니다 (bar.com/www는 존재하지 않습니다)
  • www.bar.comlocalhost 에서 제공해야합니다 (bar.com/www는 존재하지 않습니다)
  • foo.bar.combar.com/foo 에서 제공해야합니다.
  • bar.bar.comlocalhost 에서 제공해야합니다 (bar.com/bar는 존재하지 않음)
  • foobar.comlocalhost 에서 제공해야합니다 (foobar.com은 존재하지 않습니다)
  • www.foobar.comlocalhost 에서 제공해야합니다 (foobar.com은 존재하지 않습니다)
  • foo.foobar.comlocalhost 에서 제공해야합니다 (foobar.com은 존재하지 않습니다)

해결책

이 용도 : mod_rewrite, mod_proxy_http그리고 당연히 mod_vhost_alias.

ServerName my.domain
ServerAdmin admin@my.domain

<VirtualHost *:80>
    ServerName localhost
    VirtualDocumentRoot /var/www/localhost
</VirtualHost>

<VirtualHost *:80>
    ServerName sub.domain
    ServerAlias *.*.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3

    RewriteEngine on

    RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
    RewriteCond /var/www/%2.%3 !-d
    RewriteRule (.*) http://localhost/$1 [P]

    RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
    RewriteCond /var/www/%2.%3/%1 !-d
    RewriteCond /var/www/%2.%3/www !-d
    RewriteRule (.*) http://localhost/$1 [P]

    RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
    RewriteCond /var/www/%2.%3/%1 !-d
    RewriteRule (.*) http://%2.%3/$1 [P]
</VirtualHost>

<VirtualHost *:80>
    ServerName bare.domain
    ServerAlias *.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/www

    RewriteEngine on

    RewriteCond %{HTTP_HOST} ^(.*)\.(.*)$ [NC]
    RewriteCond /var/www/%1.%2 !-d [OR]
    RewriteCond /var/www/%1.%2/www !-d
    RewriteRule (.*) http://localhost/$1 [P]
</VirtualHost>

이것은 어떻게 작동합니까? 세 개의 가상 호스트가 정의되어 있습니다.

localhost

로컬 호스트는 기본값으로 사용됩니다. 해결할 수없는 모든 요청은 localhost에 의해 제공됩니다. localhost에서 도메인으로 심볼릭 링크를 설정하는 것은 해당 사이트를 기본값으로 설정하는 것과 같습니다.

하위 도메인

하위 도메인 가상 호스트는의 형식으로 모든 요청을 *.*.*받습니다. 기본적으로 모든 요청은에서 /domain.com/sub정의한대로 제공 됩니다 VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3.

폴백 :

첫 번째 RewriteRule는 알려지지 않은 도메인을 처리합니다. domain.comlocalhost 웹 사이트를 프록시하여 디렉토리가 존재하지 않습니다.

두 번째 RewriteRule는 또한 디렉토리 domain.com/subdomain.com/www디렉토리가 모두 없을 때 localhost에 프록시합니다 .

세 번째 RewriteRule로 프록시 domain.comdomain.com/sub존재하지 않습니다. 우리 domain.com/www는 두 번째 다시 쓰기 블록으로 인해 존재한다는 것을 알고 있습니다.

bare.domain

bare.domain 가상 호스트가 *.*요청 을 받아 처리합니다./domain.com/www

여기에 RewriteRule의지 프록시 때 로컬 호스트 domain.com또는 domain.com/www존재하지 않습니다.

^ $ %. * !!!

나는 모든 주위에 내 머리를 감싸는 몇 가지 문제가 있었다 $%의 징후 RewriteCondRewriteRule나는 여기에 대해 설명 할 것 정도 :

    ServerAlias *.*.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3
    RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
    RewriteCond /var/www/%2.%3/%1 !-d
    RewriteRule (.*) http://%2.%3/$1 [P]
  • *에있는 ServerAlias와일드 카드입니다.
  • %n에서는 VirtualDocumentRoot으로부터 있습니다 문서 이름 보간 .
  • %n에서 두 번째 RewriteCond선택 사항을 참조 (.*)처음부터 RewriteCond예. 요청 된 도메인의 일부
  • %n에는 RewriteRule너무 않습니다.
  • $1에서이 RewriteRule선택에 의미 (.*)의 시작 부분에 RewriteRule. 도메인 ?에서 요청 URL 까지 모든 것을 캡처합니다 . 모든 querystring은에 의해 url에 자동으로 추가됩니다 mod_proxy.

1

그냥 버리고 RemyNL과 동일한 결과 (로컬 호스트 리디렉션 제외)를 얻지 만 직접 연결할 때 IP 주소도 포함합니다.

<VirtualHost _default_:80>
    RewriteEngine On
    RewriteCond %{HTTPS} Off [OR] 
    RewriteCond %{HTTP:X-Forwarded-Proto} !https
    RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R=301,L]
</VirtualHost>

<VirtualHost _default_:443>
    ServerName a.b.c.d
    ServerAlias *.*.*.*
    VirtualDocumentRoot /var/www/%0
</VirtualHost>

<VirtualHost _default_:443>
    ServerName a.b.c
    ServerAlias *.*.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3
</VirtualHost>

<VirtualHost _default_:443>
    ServerName a.b
    ServerAlias *.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/www
</VirtualHost>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.