Apache HTTP Server 2.4 版
本文件描述如何使用 Apache HTTP Server 有效服務任意數量的虛擬主機。另一份文件 探討使用 mod_rewrite
建立動態大量虛擬主機。
如果您 httpd.conf
的許多 <VirtualHost>
區段基本上相同,例如
<VirtualHost 111.22.33.44> ServerName customer-1.example.com DocumentRoot "/www/hosts/customer-1.example.com/docs" ScriptAlias "/cgi-bin/" "/www/hosts/customer-1.example.com/cgi-bin" </VirtualHost> <VirtualHost 111.22.33.44> ServerName customer-2.example.com DocumentRoot "/www/hosts/customer-2.example.com/docs" ScriptAlias "/cgi-bin/" "/www/hosts/customer-2.example.com/cgi-bin" </VirtualHost> <VirtualHost 111.22.33.44> ServerName customer-N.example.com DocumentRoot "/www/hosts/customer-N.example.com/docs" ScriptAlias "/cgi-bin/" "/www/hosts/customer-N.example.com/cgi-bin" </VirtualHost>
我們想以一種可以動態計算的機制取代這些多個 <VirtualHost>
區段。這具有許多優點:
主要缺點是每個虛擬主機無法擁有不同的記錄檔;但是,如果您有許多虛擬主機,這樣做可能是個壞主意,因為所需的檔案描述符數量。更好的方法是 記錄到管線或 fifo,並安排另一端的程序將記錄檔分割成每個虛擬主機一份。您可以從 split-logfile 工具程式中找到這樣的程序範例。
虛擬主機由兩項資訊定義:其 IP 位址和 HTTP 要求中 Host:
標頭的內容。在此使用的動態大量虛擬主機技術,是基於自動將此資訊插入用於滿足要求的文件路徑名稱中。最容易做到這一點的方法,是搭配 Apache httpd 使用 mod_vhost_alias
。或者,也可以使用 mod_rewrite。
這兩個模組預設都是停用的;如果您要使用這項技術,您必須在組態和建置 Apache httpd 時啟用其中一個。
需要從要求中決定幾件事,才能讓動態虛擬主機看起來像一般的。最重要的就是伺服器名稱,伺服器用它來產生自參考 URL 等。它使用 ServerName
指令來組態,而且 CGI 可以透過 SERVER_NAME
環境變數存取它。執行期間使用的實際值,由 UseCanonicalName
設定控制。如果 UseCanonicalName Off
,伺服器名稱來自要求中 Host:
標頭的內容。如果 UseCanonicalName DNS
,則會從虛擬主機 IP 位址的反向 DNS 查詢中擷取。前者設定用於基於名稱的動態虛擬主機,而後者用於基於 IP 的主機。如果 httpd 無法找出伺服器名稱,是因為沒有 Host:
標頭,或 DNS 查詢失敗,則改用設定在 ServerName
中的值。
另一件要決定的事項是文件根目錄(使用 DocumentRoot
組態,並且可以透過 DOCUMENT_ROOT
環境變數讓 CGI 腳本存取)。在一般的組態中,核心模組使用它在比對 URI 到檔案名稱時使用,但是當伺服器組態為動態虛擬主機時,該工作必須由另一個模組(mod_vhost_alias
或 mod_rewrite
)接手,它有不同的比對方式。這兩個模組都不負責設定 DOCUMENT_ROOT
環境變數,所以如果任何 CGI 或 SSI 文件使用它,它們會得到誤導性的值。
從 httpd.conf
擷取的這段內容,實作在 動機 區段中所概述的虛擬主機安排,方法是使用 mod_vhost_alias
。
# get the server name from the Host: header UseCanonicalName Off # this log format can be split per-virtual-host based on the first field # using the split-logfile utility. LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon CustomLog "logs/access_log" vcommon # include the server name in the filenames used to satisfy requests VirtualDocumentRoot "/www/hosts/%0/docs" VirtualScriptAlias "/www/hosts/%0/cgi-bin"
只要將 UseCanonicalName Off
改成 UseCanonicalName DNS
,這個組態就可以變成一個基於 IP 的虛擬主機解決方案。插入到檔案名稱中的伺服器名稱接著會從虛擬主機的 IP 位址派生而來。變數 %0
參考要求的伺服器名稱,如 Host:
標頭中所指示。
請參閱 mod_vhost_alias
文件,以取得更多使用範例。
這是針對 ISP 的 web 托管伺服器調整上述系統而成。使用 %2
,我們可以在檔案名稱中選取伺服器名稱的子字串來使用,例如:www.user.example.com
的文件位於 /home/user/www
。它使用單一的 cgi-bin
目錄,而不是每個虛擬主機一個。
UseCanonicalName Off LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon CustomLog "logs/access_log" vcommon # include part of the server name in the filenames VirtualDocumentRoot "/home/%2/www" # single cgi-bin directory ScriptAlias "/cgi-bin/" "/www/std-cgi/"
mod_vhost_alias
文件中提供更複雜的 VirtualDocumentRoot
設定範例。
使用更複雜的設定,你可以使用 httpd 的一般 <VirtualHost>
指令來控制多個虛擬主機組態的範圍。例如,你可以為一般客戶的主頁設定一個 IP 位址,並為企業客戶設定另一個 IP 位址,使用以下設定。這可以與傳統的 <VirtualHost>
組態區段結合起來,如下所示。
UseCanonicalName Off LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon <Directory "/www/commercial"> Options FollowSymLinks AllowOverride All </Directory> <Directory "/www/homepages"> Options FollowSymLinks AllowOverride None </Directory> <VirtualHost 111.22.33.44> ServerName www.commercial.example.com CustomLog "logs/access_log.commercial" vcommon VirtualDocumentRoot "/www/commercial/%0/docs" VirtualScriptAlias "/www/commercial/%0/cgi-bin" </VirtualHost> <VirtualHost 111.22.33.45> ServerName www.homepages.example.com CustomLog "logs/access_log.homepages" vcommon VirtualDocumentRoot "/www/homepages/%0/docs" ScriptAlias "/cgi-bin/" "/www/std-cgi/" </VirtualHost>
如果第一個 VirtualHost 區塊不包含 ServerName
指令,系統將使用相關 IP 的反向 DNS。如果你不想使用該伺服器名稱,可以加入一個虛假條目 (例如:ServerName none.example.com
) 來解決此問題。
建議的組態變更會將 第一個範例 轉為基於 IP 的虛擬主機設定,會造成一個效率不高的設定。每一個要求都需要一個新的 DNS 查詢。為了避免這個額外的負擔,檔案系統可以調整為對應 IP 位址,而不是主機名稱,從而消除對 DNS 查詢的需求。記錄也將必須調整以符合這個系統。
# get the server name from the reverse DNS of the IP address UseCanonicalName DNS # include the IP address in the logs so they may be split LogFormat "%A %h %l %u %t \"%r\" %s %b" vcommon CustomLog "logs/access_log" vcommon # include the IP address in the filenames VirtualDocumentRootIP "/www/hosts/%0/docs" VirtualScriptAliasIP "/www/hosts/%0/cgi-bin"
大量的虛擬主機也可以使用 mod_rewrite
來完成,使用簡單的 RewriteRule
指令,或使用更複雜的技術,例如將 vhost 定義儲存在外部,並透過 RewriteMap
來存取它們。這些技術在 rewrite 文件 中有討論。
動態生成的虛擬主機的另一個選項是 mod_macro
,你可以使用它來建立一個虛擬主機範本,並對多個主機名稱呼叫它。模組文件的用法區段中提供了這方面的範例。