Denne posten tar for seg oppsett av det som kalles "mass virtual hosting" på Apache.
Det finnes forskjellige måter å gjøre dette på også, og måten jeg gjør det på er sikkert ikke den beste, men det funker for meg og har gjort det lenge.
Min config, som ikke er min i det hele tatt, men tilpasset mine behov basert på en config for et webcluster i en tidligere jobb, benytter seg av Apaches mod_rewrite. Configen ble brukt på Apache 2.0 på webclusteret, og tilpasset Apache 1.3 for min egen server. Etterhvert ble Apache oppgradert til 2.0, 2.2 og sist til 2.4, og configen har blitt tilpasset i takt med oppgraderingene.
Apache har også en egen modul for nettopp dette, mod_vhost_alias, som i følge dokumentasjonen skal gjøre akkurat det samme denne configen gjør, men jeg har ikke blitt helt venner med mod_vhost_alias siden den legger føringer for mappestruktur og ikke fungerer med subdomener. Configen under gir meg helt frie tøyler til å lage akkurat den mappestrukturen jeg vil, og den fungerer med subdomener helt automagisk.
Dette er altså min auto-vhost-config for Apache, som jeg har brukt i 12 år. Den er noe dyr i drift siden den er basert på et lass rewrite-statements, men den funker bra og har blitt oppdatert fra Apache 1.3 til 2.0 til 2.2 til 2.4 gjennom årenes løp.
Siste versjon for Apache 2.4 ser slik ut:
# # Use name-based virtual hosting. # #NameVirtualHost *:80 # Deprecated in Apache 2.4<Virtualhost *:80> <Directory /www/>
AllowOverride FileInfo AuthConfig Limit Indexes Options
AllowOverride All Options MultiViews Includes FollowSymlinks ExecCGI Indexes <Limit GET POST OPTIONS> Require all granted </Limit> <LimitExcept GET POST OPTIONS> Require all granted </LimitExcept> </Directory>
Alias /error/ "/usr/local/www/apache24/error/"
<Directory "/usr/local/www/apache24/error/"> AllowOverride None Options IncludesNoExec AddOutputFilter Includes html AddHandler type-map var Require all granted LanguagePriority en cs de es fr it ja ko nl pl pt-br ro sv tr ForceLanguagePriority Prefer Fallback </Directory>
ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var ErrorDocument 410 /error/HTTP_GONE.html.var ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
Activate the magic
RewriteEngine On
Remove the Vary header for MSIE, since it doesn't support pipelining. Not sure about recent versions, and old versions shouldn't be used. We don't want to support old versions anyway.
Header unset Vary
RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD)$ RewriteRule .* - [F]
We need to force mime types for cgi scripts and php scripts.
We create our own function variable called "lowercase"
RewriteMap lowercase int:tolower
CGI
Deal with CGIs -- force a MIME type
RewriteCond %{REQUEST_URI} ^/cgi-bin/
Remove www. from request
RewriteCond %{HTTP_HOST} ^(www.)?(.+)$ [NC]
Check if there is a symlink for domain in /www
RewriteCond /www/${lowercase:%2} -l
Do the redirect
RewriteRule ^/cgi-bin/(.*)$ /www/${lowercase:%2}/htdocs/cgi-bin/$1 [E=DOCUMENT_ROOT:/www/${lowercase:%2}/htdocs,T=application/x-httpd-cgi,L]
Deal with errors if something isn't found
RewriteCond %{REQUEST_URI} ^/error/
Serve regular files
Remove www from request
RewriteCond %{HTTP_HOST} ^(www.)?(.+)$ [NC]
Check if there is a symlink for domain
RewriteCond /www/${lowercase:%2} -l
Redirect and get files
RewriteRule ^/error/(.*)$ /www/error/$1 [E=DOCUMENT_ROOT:/www/${lowercase:%2}htdocs,L]
PHP handling
Check if the requested file is a PHP file
RewriteCond %{REQUEST_URI} .(php|php3|php4|php5|phtml)
Remove www. from request
RewriteCond %{HTTP_HOST} ^(www.)?(.+)$ [NC]
Check if there is a symlink for domain
RewriteCond /www/${lowercase:%2} -l
Do the redirect
RewriteRule ^/(.*)$ /www/${lowercase:%2}/htdocs/$1 [E=DOCUMENT_ROOT:/www/${lowercase:%2}/htdocs,T=application/x-httpd-php,L]
otherwise
Remove www. from request
RewriteCond %{HTTP_HOST} ^(www.)?(.+)$ [NC]
Check if there is a symlink for domain in /www
RewriteCond /www/${lowercase:%2} -l
Do the redirect
RewriteRule ^/(.*)$ /www/${lowercase:%2}/htdocs/$1 [E=DOCUMENT_ROOT:/www/${lowercase:%2}/htdocs,L]
####### SUBDOMAINS ########
Deal with CGIs -- force a MIME type
RewriteCond %{REQUEST_URI} ^/cgi-bin/
Remove www. from request
RewriteCond %{HTTP_HOST} ^(www.)?(.+?).(.+)$ [NC]
Check if subdomain folder exists
RewriteCond /www/${lowercase:%3}/subdomener/${lowercase:%2} -d
Do the redirect
RewriteRule ^/(.*)$ /www/${lowercase:%3}/subdomener/${lowercase:%2}/$1 [E=DOCUMENT_ROOT:/www/${lowercase:%3}/subdomener/${lowercase:%2},T=application/x-httpd-cgi,L]
Handle errors
RewriteCond %{REQUEST_URI} ^/error/ RewriteCond %{HTTP_HOST} ^(www.)?(.+?).(.+)$ [NC] RewriteCond /www/${lowercase:%3}/subdomener/${lowercase:%2} -d RewriteRule ^/error/(.*)$ /www/error/$1 [E=DOCUMENT_ROOT:/www/${lowercase:%3}/subdomener/${lowercase:%2},L]
PHP, again
Check if the requested file is a PHP file (note the .pthml missing - gotta love consistency. Should be cleaned up further.)
RewriteCond %{REQUEST_URI} .(php|php3|php4|php5)
Remove www. from request
RewriteCond %{HTTP_HOST} ^(www.)?(.+?).(.+)$ [NC]
Check if subdomain folder exists
RewriteCond /www/${lowercase:%3}/subdomener/${lowercase:%2} -d
Do the redirect
RewriteRule ^/(.*)$ /www/${lowercase:%3}/subdomener/${lowercase:%2}/$1 [E=DOCUMENT_ROOT:/www/${lowercase:%3}/subdomener/${lowercase:%2},T=application/x-httpd-php,L]
Remove www. from request
RewriteCond %{HTTP_HOST} ^(www.)?(.+?).(.+)$ [NC]
Check if subdomain folder exists under the main domain name - note: we do NOT
make symlinks for subdomains, they just work automagically!
RewriteCond /www/${lowercase:%3}/subdomener/${lowercase:%2} -d
Do the redirect
RewriteRule ^/(.*)$ /www/${lowercase:%3}/subdomener/${lowercase:%2}/$1 [E=DOCUMENT_ROOT:/www/${lowercase:%3}/subdomener/${lowercase:%2},L]
If nothing else matches, redirect to a default page that has an explanation. Use with care.
RewriteRule ^.*$ https://example.net/error/feil.html [R,L]
</Virtualhost>
Under /www må du opprette symbolske lenker til der webfilene faktisk ligger. Hvor de ligger er uvesentlig så lenge katalogstrukturen under domenenavnet er som følger:
/home/user/www/example.com/htdocs /home/user/www/example.com/subdomener
For å opprette subdomener, bruk følgende struktur:
/home/user/www/example.com/subdomener/ting /home/user/www/example.com/subdomener/jubelDisse vil da nås i en nettleser som følger:
http(s)://example.com http(s)://ting.example.com http(s)://jubel.example.com
Merk at du linker til domene-mappen, ikke htdocs-mappen. Eksempel:
# cd /www # ln -s /home/user/www/example.com example.com
Om du ønsker å bruke andre mappenavn enn htdocs og subdomener kan du endre dem til hva du vil så lenge det oppdateres i configen.