Chỉ sử dụng VirtualDocumentRoot * nếu một tài liệu gốc phù hợp tồn tại


8

Tôi muốn thiết lập một môi trường nơi các máy chủ ảo Apache có thể được tạo động mà không cần tải lại cấu hình.

Tôi có thể làm điều này với mod_vhost_alias , tôi thiết lập máy chủ ảo mặc định của mình một cái gì đó như thế này

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

Điều đó chỉ hoạt động tốt, nhưng nếu một yêu cầu được thực hiện cho một tên máy chủ hiện không được thiết lập, tôi gặp lỗi 404 Không tìm thấy.

Những gì tôi muốn thực sự muốn làm là chỉ có VirtualHost đá này trong chỉ nếu các tài liệu gốc tồn tại, nếu không có nó cố gắng để phù hợp với vhost khác (nói cách khác, làm cho sự hiện diện của các VirtualDocumentRoot làm việc trong cùng một cách như sử dụng một Máy chủ)

Tôi đã thử biến nó thành vhost thứ hai, với vhost đầu tiên chỉ xử lý tất cả các yêu cầu, nhưng điều này không hoạt động - các yêu cầu cho các miền nơi VirtualDocumentRoot được cấu hình rơi vào vhost mặc định.

Vì vậy, làm thế nào tôi có thể có các vhost được cấu hình động, nhưng với một dự phòng cho một vhost khác cho bất kỳ cái nào chưa được cấu hình?

Câu trả lời:


7

Tôi tìm thấy một cách giải quyết phù hợp với tôi.

Tôi có thể sử dụng ErrorDocument để nhận Lỗi 404 trong tập lệnh PHP. Lúc đầu, điều đó có vẻ có vấn đề. Nếu không có DocumentRoot, kịch bản sẽ sống ở đâu?

Tôi có thể sử dụng URL cho thông báo lỗi, được cung cấp từ một tên miền khác. Tuy nhiên, trong thử nghiệm tôi không tìm thấy cách nào để biết tên miền được yêu cầu ban đầu là gì.

Câu trả lời là Alias một thư mục và phục vụ các lỗi trong đó, vì vậy vhost của tôi trông như thế này

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

Bây giờ, khi một tên miền chưa được định cấu hình được yêu cầu, tập lệnh tại /var/www/default/errors/notfound.php được gọi thay thế. Tập lệnh này có thể kiểm tra $ _SERVER ['HTTP_HOST'] để xem tên miền nào được yêu cầu. Nếu nó thực sự được cấu hình, thì chúng ta có 404 thông thường. Nếu nó không được cấu hình, chúng ta có thể hiển thị một số thông báo lỗi thay thế. Trong trường hợp của tôi, đó là nơi tôi hiển thị UI để giúp thiết lập vhost.


Điều đó sẽ không ném 404 làm trạng thái cho mọi yêu cầu về mặc định chứ?
Kyle

1
Trình xử lý lỗi chỉ được gọi nếu VirtualDocumentRoot không tồn tại (hoặc nó thực sự là 404, nhưng notfound.php có thể dễ dàng nhận ra sự khác biệt).
Paul Dixon

3

Tôi tìm thấy câu hỏi của bạn khi Google. Tôi đã có chính xác cùng một vấn đề và áp dụng cách khắc phục như được mô tả trong câu trả lời của Paul . Tuy nhiên, đối với ứng dụng web phức tạp của tôi, tôi không hài lòng với việc định tuyến tất cả các yêu cầu notfound.php.

Cuối cùng, tôi đã cố gắng khắc phục sự cố mà không cần các tập lệnh bên ngoài, chỉ bằng cách chỉnh sửa cấu hình Virtualhost của tôi.

Lúc đầu, Virtualhost của tôi được cấu hình như thế này:

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

Tôi đã có URL như client1.domainname.com, client2.domainname.comwhatever.domainname.com

mà quyết tâm /mnt/ramdisk/www/cms-client1-development/, /mnt/ramdisk/www/cms-client2-development//mnt/ramdisk/www/cms-whatever-development/

Tuy nhiên, một URL như nonexistent.domainname.comsẽ cung cấp cho tôi 404 vì thư mục /mnt/ramdisk/www/cms-nonexistent-development/không tồn tại. Tôi muốn những tên miền phụ này sử dụng thư mục/mnt/ramdisk/www/cms-default-development/

Tôi đã sửa lỗi này bằng cách sử dụng ModRewriteModProxy:

<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>

Điều này làm là: lấy tên miền phụ (phần trước .domainname.com), chèn nó vào đường dẫn (% 1) và yêu cầu proxy đến URL mặc định chỉ khi thư mục không tồn tại.

Bằng cách sử dụng proxy, quy trình này minh bạch và người dùng nghĩ rằng anh ta đang truy cập http://nonexistent.domainname.com , trong khi anh ta thực sự xem nội dung từ http://default.domainname.com/ .


3

Tôi cũng bắt gặp câu hỏi này để tìm kiếm apache2 dự phòng vhost động và câu trả lời của Luc đã giúp tôi rất nhiều trong việc giải quyết vấn đề của mình, nhưng tôi vẫn muốn thể hiện những gì tôi đã làm để đạt được mục tiêu của mình, chủ yếu là vì nó liên quan đến một số công việc phụ và vì tôi nghĩ nó có thể hữu ích cho bất kỳ nhân viên nào trong tương lai ...

Mục tiêu của tôi

  • vhosting động cho tất cả các tên miền và tên miền phụ trỏ vào VPS của tôi
  • foo.com nên phục vụ cùng một nội dung như www.foo.com
  • dự phòng cho các tên miền không xác định với một số loại mặc định
  • dự phòng cho các tên miền phụ chưa biết của foo.comđể www.foo.comtrừ trường hợp wwwkhông có sẵn, dự phòng để mặc định thay vì

DNS

Tôi có một vài tên miền (và tất cả tên miền phụ của chúng) trỏ vào VPS của tôi, ví dụ:

  • foo.com
  • thanh.com
  • foobar.com

Hệ thống tập tin

Tôi có các thư mục sau, tên miền chứa các thư mục có tên của các tên miền phụ có sẵn, thư mục www là bắt buộc, nhưng cấu hình sẽ có thể xử lý tình huống không có. Localhost được sử dụng làm dự phòng mặc định:

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

Xét nghiệm

Chuyển mục tiêu của tôi thành các trường hợp có thể kiểm chứng:

  • foo.com nên được phục vụ từ foo.com/www
  • www.foo.com nên được phục vụ từ foo.com/www
  • bar.foo.com nên được phục vụ từ foo.com/bar
  • foo.foo.com nên được phục vụ từ foo.com/www (foo.com/foo không tồn tại)
  • bar.com nên được phục vụ từ localhost (bar.com/www không tồn tại)
  • www.bar.com phải được phục vụ từ localhost (bar.com/www không tồn tại)
  • foo.bar.com nên được phục vụ từ bar.com/foo
  • bar.bar.com phải được phục vụ từ localhost (bar.com/bar không tồn tại)
  • foobar.com nên được phục vụ từ localhost (foobar.com không tồn tại)
  • www.foobar.com nên được phục vụ từ localhost (foobar.com không tồn tại)
  • foo.foobar.com nên được phục vụ từ localhost (foobar.com không tồn tại)

Giải pháp

Điều này sử dụng : mod_rewrite, mod_proxy_httpvà tất nhiên 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>

Cái này hoạt động ra sao? Có ba máy chủ ảo được xác định:

localhost

Localhost phục vụ như một mặc định. Tất cả các yêu cầu không thể giải quyết được phục vụ bởi localhost. Thiết lập một liên kết tượng trưng từ localhost đến bất kỳ tên miền nào của bạn cũng giống như thiết lập trang web đó làm mặc định.

tên miền phụ

Subhost miền v.d đang lấy tất cả các yêu cầu ở dạng *.*.*. Theo mặc định, tất cả các yêu cầu được phục vụ từ /domain.com/subnhư được xác định bởi VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3.

dự phòng:

Đầu tiên RewriteRulechăm sóc các tên miền không xác định, ví dụ. domain.comthư mục không tồn tại, bằng cách ủy quyền trang web localhost.

Thứ hai RewriteRulecũng ủy nhiệm cho localhost khi cả thư mục domain.com/subdomain.com/wwwthư mục không có mặt.

Các RewriteRuleproxy thứ ba domain.comkhi domain.com/subkhông tồn tại. Chúng tôi biết domain.com/wwwcó tồn tại vì khối viết lại thứ hai.

Bare.domain

Các vhost Bare.domain đang lấy các *.*yêu cầu và phục vụ chúng/domain.com/www

Ở đây RewriteRulesẽ proxy cho localhost khi domain.comhoặc domain.com/wwwkhông tồn tại.

^ $%. * !!!

Tôi đã có một số rắc rối quấn quanh đầu tôi tất cả những $%những dấu hiệu trong RewriteCondRewriteRulevì vậy tôi sẽ giải thích về họ ở đây:

    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]
  • Các *trong ServerAliaschỉ là ký tự đại diện.
  • Các %ntrong VirtualDocumentRootlà từ nội suy tên tài liệu .
  • Cái %nthứ hai RewriteCondđề cập đến các lựa chọn (.*)từ cái thứ nhất RewriteCond, vd. các phần của miền được yêu cầu.
  • Việc %ntrong RewriteRulequá.
  • Các $1trong RewriteRuleđề cập đến việc lựa chọn (.*)ở đầu RewriteRule. Mà nắm bắt mọi thứ từ tên miền cho đến ?trong url yêu cầu. Bất kỳ chuỗi truy vấn được tự động thêm vào url bởi mod_proxy.

1

Chỉ cần ném nó ra khỏi đó, tôi nhận được kết quả tương tự (trừ chuyển hướng localhost) như RemyNL, nhưng cũng bao gồm địa chỉ IP khi kết nối trực tiếp:

<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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.