Apache Web伺服器可以在SAME伺服器上託管多個網站。每個網站不需要單獨的伺服器機器和apache軟體。這可以使用虛擬主機或VHost的概念來實現。
要在Web伺服器上託管的任何域(網站應用)都將在apache配置檔中具有單獨的條目。
Apache虛擬主機類型
Apache虛擬主機類型有兩種 -
- 基於名稱的虛擬主機
- 基於地址或基於IP的虛擬主機。
1. 基於名稱的虛擬主機
基於名稱的虛擬主機用於在單個IP地址上託管多個虛擬站點。
要配置基於名稱的虛擬主機,需要設置要在其上接收所有所需網站的Apache請求的IP地址。可以通過apache配置中的NameVirutalHost指令(即/etc/httpd/conf/httpd.conf
檔)執行此操作。如下所示 -
NameVirtualHost *:80
<VirtualHost 192.168.0.108:80>
ServerAdmin webmaster@xuhuhu.com
DocumentRoot /var/www/html/example1_com_dir
ServerName www.example1.com
</VirtualHost>
<VirtualHost 192.168.0.108:80>
ServerAdmin admin@xuhuhu.com
DocumentRoot /var/www/html/example2_com_dir
ServerName www.example2.com
</VirtualHost>
您可以根據需要添加任意數量的虛擬主機。需要使用以下命令檢查Web配置檔是否有配置錯誤:
[root@115 conf.d]# httpd -t
Syntax error on line 978 of /etc/httpd/conf/httpd.conf:
Invalid command '*', perhaps misspelled or defined by a module not included in the server configuration
如上面顯示的結果可以發現,配置檔存在語法配置錯誤,這時需要根據提示修改配置檔。直到沒有錯誤提示為止。當配置檔有錯誤時,Apache是不能啟動的,這點需要注意。
2. 基於IP的虛擬主機
要設置基於IP的虛擬主機,需要在伺服器上配置多個IP地址。因此,vhost apache的數量取決於伺服器上配置的IP地址數量。如果您的伺服器有10個IP地址,則可以創建10個基於IP的虛擬主機。
在上圖中,兩個網站example1.com
和example2.com
分配了不同的IP並使用基於IP的虛擬主機。
Listen 192.168.0.100:80
<VirtualHost 192.168.10.108:80>
ServerAdmin webmaster@example1.com
DocumentRoot /var/www/html/example1_com_dir
ServerName www.example1.com
</VirtualHost>
<VirtualHost 192.168.10.109:80>
ServerAdmin admin@example2.com
DocumentRoot /var/www/html/example1_com_dir
ServerName www.example2.com
</VirtualHost>
3. 虛擬主機配置示例
這一小節中將列出有關設置虛擬主機的常見問題。這些方案涉及通過基於名稱或基於IP的虛擬主機在單個伺服器上運行的多個網站。
3.1. 在單個IP地址上運行多個基於功能變數名稱的網站
如果伺服器有多個主機名可以解析為單個地址,您希望對www.example.com
和www.example.org
做出不同的回應。
在Apache伺服器上創建虛擬主機配置不會神奇地導致為這些主機名創建DNS條目。您必須擁有DNS中的名稱,解析為您的IP地址,否則其他人都無法訪問您的網站。可以將條目放在
hosts
檔中以進行本地測試,但這僅適用於具有這些主機條目的電腦。
# Ensure that Apache listens on port 80
Listen 80
<VirtualHost *:80>
DocumentRoot "/var/www/example1"
ServerName www.example.com
# Other directives here
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "/var/www/example2"
ServerName www.example.org
# Other directives here
</VirtualHost>
3.2. 多個IP地址上基於名稱的主機
伺服器有兩個(或更多個)IP地址。一個IP地址是:172.20.30.40,我們將服務於“主”伺服器server.example.com
,另一個IP地址是:172.20.30.50,我們將服務兩個或更多虛擬主機。
Listen 80
# This is the "main" server running on 172.20.30.40
ServerName server.example.com
DocumentRoot "/www/mainserver"
<VirtualHost 172.20.30.50>
DocumentRoot "/www/example1"
ServerName www.example.com
# Other directives here ...
</VirtualHost>
<VirtualHost 172.20.30.50>
DocumentRoot "/www/example2"
ServerName www.example.org
# Other directives here ...
</VirtualHost>
對172.20.30.50
以外的地址的任何請求都將從主伺服器提供。將向www.example.com
提供對172.20.30.50
的請求,其中包含未知主機名或無Host:標頭。
3.3. 在不同的IP地址(例如內部和外部地址)上提供相同的內容
伺服器電腦有兩個IP地址(192.168.1.1
和172.20.30.40
)。機器位於內部(Intranet)網路和外部(Internet)網路之間。在網路外部,名稱server.example.com
解析為外部地址(172.20.30.40
),但在網路內部,同一名稱解析為內部地址(192.168.1.1
)。
只需一個<VirtualHost>
部分,就可以使伺服器回應具有相同內容的內部和外部請求。
<VirtualHost 192.168.1.1 172.20.30.40>
DocumentRoot "/www/server1"
ServerName server.example.com
ServerAlias server
</VirtualHost>
3.4. 在不同端口上運行不同的站點
假設您有多個域轉到同一個IP,並且還希望為多個端口提供服務。下麵的示例說明了在確定最佳匹配的IP地址和端口組合之後進行名稱匹配。
Listen 80
Listen 8080
<VirtualHost 172.20.30.40:80>
ServerName www.example.com
DocumentRoot "/www/domain-80"
</VirtualHost>
<VirtualHost 172.20.30.40:8080>
ServerName www.example.com
DocumentRoot "/www/domain-8080"
</VirtualHost>
<VirtualHost 172.20.30.40:80>
ServerName www.example.org
DocumentRoot "/www/otherdomain-80"
</VirtualHost>
<VirtualHost 172.20.30.40:8080>
ServerName www.example.org
DocumentRoot "/www/otherdomain-8080"
</VirtualHost>
3.4. 基於IP的虛擬主機
伺服器有兩個IP地址(172.20.30.40
和172.20.30.50
),分別解析為www.example.com
和www.example.org
。
Listen 80
<VirtualHost 172.20.30.40>
DocumentRoot "/www/example1"
ServerName www.example.com
</VirtualHost>
<VirtualHost 172.20.30.50>
DocumentRoot "/www/example2"
ServerName www.example.org
</VirtualHost>
對於未在其中一個<VirtualHost>
指令中指定的任何地址(例如localhost)的請求將轉到主伺服器(如果有)。
3.5. 基於混合端口和基於IP的虛擬主機
伺服器機器有兩個IP地址(172.20.30.40
和172.20.30.50
),分別解析為www.example.com
和www.example.org
。在每種情況下,都希望在端口80
和8080
上運行主機。
Listen 172.20.30.40:80
Listen 172.20.30.40:8080
Listen 172.20.30.50:80
Listen 172.20.30.50:8080
<VirtualHost 172.20.30.40:80>
DocumentRoot "/www/example1-80"
ServerName www.example.com
</VirtualHost>
<VirtualHost 172.20.30.40:8080>
DocumentRoot "/www/example1-8080"
ServerName www.example.com
</VirtualHost>
<VirtualHost 172.20.30.50:80>
DocumentRoot "/www/example2-80"
ServerName www.example.org
</VirtualHost>
<VirtualHost 172.20.30.50:8080>
DocumentRoot "/www/example2-8080"
ServerName www.example.org
</VirtualHost>
3.6. 混合基於名稱和基於IP的虛擬主機
永遠不會出現在另一個虛擬主機中的虛擬主機參數中提到的任何地址都是嚴格基於IP的虛擬主機。
Listen 80
<VirtualHost 172.20.30.40>
DocumentRoot "/www/example1"
ServerName www.example.com
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot "/www/example2"
ServerName www.example.org
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot "/www/example3"
ServerName www.example.net
</VirtualHost>
# IP-based
<VirtualHost 172.20.30.50>
DocumentRoot "/www/example4"
ServerName www.example.edu
</VirtualHost>
<VirtualHost 172.20.30.60>
DocumentRoot "/www/example5"
ServerName www.example.gov
</VirtualHost>
3.7. Virtual_host和mod_proxy一起使用
以下示例允許前端電腦將虛擬主機代理到另一臺電腦上運行的伺服器。在該示例中,在192.168.111.2
的電腦上配置了同名的虛擬主機。如果我們將多個主機名代理到單個機器,則使用ProxyPreserveHost On
指令以便傳遞所需的主機名。
<VirtualHost *:*>
ProxyPreserveHost On
ProxyPass "/" "http://192.168.111.2/"
ProxyPassReverse "/" "http://192.168.111.2/"
ServerName hostname.example.com
</VirtualHost>
3.8. 使用 default vhosts
default vhosts適用於所有端口
捕獲對任何未指定的IP地址和端口的每個請求,即未用於任何其他虛擬主機的地址/端口組合。
<VirtualHost _default_:*>
DocumentRoot "/www/default"
</VirtualHost>
使用帶有通配符端口的默認虛擬主機可以有效地阻止任何請求進入主伺服器。
默認虛擬主機從不提供發送到用於基於名稱的虛擬主機的地址/端口的請求。如果請求包含未知或無Host:標頭,則始終從基於主名稱的虛擬主機(配置檔中首先出現的該地址/端口的虛擬主機)提供服務。
您可以使用AliasMatch
或RewriteRule
將任何請求重寫到單個資訊頁面(或腳本)。
default vhosts 用於不同的端口
與上面的設置相同,但伺服器偵聽多個端口,我們希望將第二個_default_ vhost
用於端口80
。
<VirtualHost _default_:80>
DocumentRoot "/www/default80"
# ...
</VirtualHost>
<VirtualHost _default_:*>
DocumentRoot "/www/default"
# ...
</VirtualHost>
端口80
的默認虛擬主機(必須出現在具有通配符端口的任何默認虛擬主機之前)會捕獲發送到未指定IP地址的所有請求。主伺服器從不用於提供請求。
default vhosts用於一個端口
我們希望端口80
具有默認虛擬主機,但沒有其他默認虛擬主機。
<VirtualHost _default_:80>
DocumentRoot "/www/default"
...
</VirtualHost>
從默認虛擬主機提供對端口80上未指定地址的請求。從主伺服器提供對未指定地址和端口的任何其他請求。
在虛擬主機聲明中使用*
的優先順序高於_default_
。
3.9. 將基於名稱的虛擬主機遷移到基於IP的虛擬主機
主機名為www.example.org
的基於名稱的虛擬主機(來自我們基於名稱的示例,設置2)應該獲得自己的IP地址。為避免名稱伺服器或緩存基於名稱的虛擬主機的舊IP地址的代理出現問題,我們希望在遷移階段提供這兩種變體。
解決方案很簡單,因為我們可以簡單地將新的IP地址(172.20.30.50
)添加到VirtualHost
指令中。
Listen 80
ServerName www.example.com
DocumentRoot "/www/example1"
<VirtualHost 172.20.30.40 172.20.30.50>
DocumentRoot "/www/example2"
ServerName www.example.org
# ...
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot "/www/example3"
ServerName www.example.net
ServerAlias *.example.net
# ...
</VirtualHost>
現在可以通過新地址(作為基於IP的虛擬主機)和舊地址(作為基於名稱的虛擬主機)訪問虛擬主機。
4.0. 使用ServerPath指令
我們有一個帶有兩個基於名稱的虛擬主機的伺服器。為了匹配正確的虛擬主機,客戶端必須發送正確的Host:頭。舊的HTTP/1.0
客戶端不發送這樣的頭,Apache不知道客戶端試圖訪問什麼虛擬主機(並從主虛擬主機提供請求)。為了提供盡可能多的向後相容性,我們創建了一個主虛擬主機,它返回一個包含帶有URL首碼的鏈接的單個頁面到基於名稱的虛擬主機。
<VirtualHost 172.20.30.40>
# primary vhost
DocumentRoot "/www/subdomain"
RewriteEngine On
RewriteRule "." "/www/subdomain/index.html"
# ...
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot "/www/subdomain/sub1"
ServerName www.sub1.domain.tld
ServerPath "/sub1/"
RewriteEngine On
RewriteRule "^(/sub1/.*)" "/www/subdomain$1"
# ...
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot "/www/subdomain/sub2"
ServerName www.sub2.domain.tld
ServerPath "/sub2/"
RewriteEngine On
RewriteRule "^(/sub2/.*)" "/www/subdomain$1"
# ...
</VirtualHost>
由於ServerPath
指令,始終從sub1-vhost
提供對URL http://www.sub1.domain.tld/sub1/
的請求。
如果客戶端發送了正確的Host:頭,則僅從sub1-vhost
提供對URL http://www.sub1.domain.tld/
的請求。如果沒有發送Host:頭,則客戶端從主要主機獲取資訊頁面。
請注意,有一個奇怪之處:如果客戶端沒有發送Host:頭,則還會從sub1-vhost
提供對http://www.sub2.domain.tld/sub1/
的請求。