apache i mod_perl

marzec 14th, 2007

Ostatnio zmuszony byłem do uruchomienia dość dużej ilości domen i serwisów www. Coś a’la hosting. Niestety znalezione panele były i są zdecydowanie niedostosowane do moich potrzeb. Użyłbym lighthttpd, ale nie tam żadnego modułu limitowania pasma per serwis. Ale od czego jest stary dobry apache.

Aby wszystko działało musiałem doinstalować kilka modułów apache
apache-mod_cband
apache-mod_dbi_pool
apache-mod_dbi_pool-devel
apache-mod_env
apache-mod_perl
apache-mod_perl-devel

Konieczne należy także pamiętać o odpowiednich bibliotekach perl

Teraz opis jak to ma działać :) Wszystkie informacje przechowywane są w bazie danych, a konfiguracja jest dynamicznie generowana przy każdym przeładowaniu usługi. Zwykłe moduły vhost_mysql umożliwiają tylko przechowywanie danych nt. DocumentRoot oraz ServerName czyli niedużo, oraz nie można połączyć tego z cband.

Masshosting, czyli wykorzystanie %0 także jest średnim pomysłem ze względu na fakt, że apache-core będzie widział tylko %0 jako Virtual Host.

Pozostaje także problem z logowaniem ale wystarczy apache-mod_log_sql i nie ma problemu.

A teraz przepis jak zrobić aby i wilk syty (wydajność) i owca cała (wygoda). Należy wykorzystać wstawki perl. Edytujemy plik httpd.conf:

LoadModule perl_module modules/mod_perl.so
NameVirtualHost *:80

#!/usr/bin/perl
use DBI;
use Apache2::PerlSections();
#
my $www_skel_dir = “/home/services/hosting/skel/websites/domain.foo”;
#
my ($query1, $dbase, $server_name, $server_root, $user_id, $server_admin, $log_level, $score_board, $band_limit, $band_speed, $band_period);
$dbase = DBI->connect(”dbi:mysql:test:localhost”,”test”,”test”);
$query1 = $dbase->prepare(”SELECT ServerName, ServerRoot, User, ServerAdmin, LogLevel, ScoreBoard, CBandLimit, CBandSpeed, CBandPeriod FROM v_vhosts_nossl”);
$query1->execute();
#
while (($server_name, $server_root, $user_id, $server_admin, $log_level, $score_board, $band_limit, $band_speed, $band_period ) = $query1->fetchrow_array()) {
print STDERR “Building Virtual Host for $server_name ($server_root)\n”;
#
unless (-d “$server_root”){
mkdir -p (”$server_root”, 0755);
my $line=”cp -Rf $www_skel_dir/* $server_root/”;
chown -R “$user_id” “$server_root”;
}
#
push @{ $VirtualHost{’*:80′} },
{
ServerName => $server_name,
ServerAlias => “www.$server_name”,
ServerAdmin => $server_admin,
LogLevel => $log_level,
CustomLog => “\”|/usr/sbin/rotatelogs $server_root/logs/access_%Y%m%d.log 100M\” combined”,
ErrorLog => “\”|/usr/sbin/rotatelogs $server_root/logs/error_%y%m%d.log 100M\”",
DocumentRoot => “$server_root/htdocs”,
ScriptAlias => [
[’/cgi-bin/’,”$server_root/cgi-bin/”],
[’/cgi/’,”$server_root/cgi-bin/”]
],
Alias => [
[’/icons/’,”$server_root/icons/”],
[’/error/’,”$server_root/error/”]
],
ServerSignature => ‘Off’,
RewriteEngine => ‘On’,
RewriteOptions => ‘inherit’,
#
CBandLimit => $band_limit,
CBandSpeed => “$band_speed 50 20″,
CBandPeriod => $band_period,
CBandScoreboard => “/home/services/hosting/status/scoreboard”,
CBandExceededURL => ‘http://hosting.eqax.pl/error-pages/bandwidth_exceeded.html’,
CBandRemoteSpeed => “$band_speed 10 5″,
CBandScoreFlushPeriod => “15″,
CBandClassRemoteSpeed => “googlebot_class 10kb/s 2 3″,
#
Directory => {
“$server_root/htdocs” => {
Options => ‘Indexes MultiViews SymLinksIfOwnerMatch’,
AllowOverride => ‘None’,
FilesMatch => {
‘.(jpg|jpeg|gif|png|bmp|swf|avi)$’ => {
SetEnvIf => [
[’Referer’, “^http://?$server_name/”, ‘local_referal’],
[’Referer’, ‘^$’, ‘local_referal’]
],
Order => ‘Deny,Allow’,
Deny => ‘from all’,
Allow => ‘from env=local_referal’,
}
},
Order => ‘Allow,Deny’,
Allow => ‘from all’,
},
# cgi-bin
“$server_root/cgi-bin” => {
Options => ‘Indexes MultiViews SymLinksIfOwnerMatch ExecCGI’,
AllowOverride => ‘All’,
SetHandler => ‘cgi-script’,
Order => ‘Allow,Deny’,
Allow => ‘from all’,
},
# icons
“$server_root/icons” => {
Options => ‘Indexes MultiViews’,
AllowOverride => ‘None’,
Order => ‘Allow,Deny’,
Allow => ‘from all’,
},
# error
“$server_root/error” => {
Options => ‘IncludesNoExec’,
AllowOverride => ‘None’,
AddOutputFilter => ‘Includes html’,
AddHandler => ‘type-map var’,
Order => ‘Allow,Deny’,
Allow => ‘from all’,
LanguagePriority => ‘pl en de es fr it cs ja ko nl pt-br ro sv tr’,
ForceLanguagePriority => ‘Prefer Fallback’,
}
}
}

}
$query1->finish();
$dbase->disconnect();

Oto całość :) Co dziwniejsze nawet działa i to wydajnie. Oczywiście każdy musi zmodyfikować stosownie do swoich potrzeb zarówno baze mysql jak i zapytanie. Pozwolę sobie zasugerować jednak wykorzystanie relacyjnej bazy danych i dodanie widoków, co bardzo ułatwi zarządzanie i przejrzystość.

W podobny sposób można zrealizować obsługę domen z wykorzystaniem mod_ssl

2 Responses to “apache i mod_perl”

  1. 1 życzliwy Mareczek
    marzec 30th, 2007 at 3:10 pm

    Otóż pozwolę sobie wpisać pewien komentarz a raczej uzupełnić pewną nieścisłość:

    “Użyłbym lighttpd, ale nie tam żadnego modułu limitowania pasma per serwis. Ale od czego jest stary dobry apache.”

    Chyba nie przeczytałeś do końca manuala… To zdanie jest nie prawdziwe limitowanie pasma/połączeń/pasma peer połączenie itd oraz wszystkie inne ustawienia związane z wirtualkami dostępne są poprzez moduł simple-vhost

    Pozdrawiam wszystkich

  2. 2 daniel
    marzec 30th, 2007 at 5:25 pm

    okej może nieco “poniosło” mnie :) wszystkie informacje odnośnie vhost’a przechowywane są w SQL (PostgreSQL lub MySQL), więc simple-vhost raczej średnio użyteczny

Leave a Reply