Dzień dobry, smacznego, dobry wieczór i dobranoc (w zależności o jakiej porze czytasz te bzdury). Dawno nic nie pisałem, tym bardziej cieszę się zaprezentować coś choć w części interesującego. Zajmę się dość ciekawą kombinacją – Apache + mod_rewrite + cgiwrap.
Wymagania
Ponieważ używam standardowej konfiguracji PLD-Linux, jeśli chodzi o użytkowników, równie standardowa będzie konfiguracja Apache (co zarazem znaczy, że jest to bardzo specyficzna konfiguracja i wiem, że z inną konfiguracją poniższy opis nie będzie funkcjonować).
Wymagane są następujące komponenty:
- Apache 2.2 + mod_rewrite
- cgiwrap-4.1 + ten patch (lub jeśli używamy PLD-Linux – cgiwrap-4.1-4.*.rpm)
- konta użytkowników w /home/users
- strony użytkowników w /home/users/*/public_html
- zdrowy, nie przepity, nie zaćpany rozum i chęć zrozumienia idei
- dobra znajomość mod_rewrite (bo nie wszystko chce mi się tłumaczyć)
Apache + vhosty za pomocą mod_rewrite
Dlaczego nie po prostu mod_vhost_alias? W sumie tylko z dwóch powodów:
1. Po każdym wpisie nowego virtualhosta trzeba restartować Apache
2. Wpis
Reasumując plusy dodatnie i plusy ujemne tego przedsięwzięcia, mamy taką oto listę.
Plusy:
- nie trzeba restartować Apache po dodaniu nowego vhosta
- krótkie wpisy = mało zmarnowanego czasu
- cachowanie vhostów – Apache mod_rewrite potrafi automatycznie cachować zmapowane rewrity by działać szybciej
- użytkownik może sam sobie dodawać vhosty jeśli da mu się odpowiednie prawa/udostępni odpowiednią automatykę
Minusy:
- brak wildcardów (niektórzy powiedzą, że to plus), czyli wpisów z gwiazdką ‘*’
- niektóre niedogodności lub banalne ustawienia w mod_vhost_alias trzeba obchodzić kolejnymi zagmatwanymi rewritami
- rewrite sam w sobie, można się pogubić :-)
- wywołania http://domena.pl/~user nie działają (co dla niektórych też jest plusem)
Ulubionym edytorem tekstu edytujemy plik /etc/httpd/httpd.conf/00_mod_rewrite.conf i dodajemy następujące wpisy:
RewriteEngine On RewriteMap lowercase int:tolower RewriteMap vhost txt:/etc/virtualhosts.map RewriteCond %{REQUEST_URI} !^/icons/ RewriteCond %{REQUEST_URI} !^/error/ RewriteCond %{REQUEST_URI} !^/cgi-bin/ RewriteCond ${lowercase:%{HTTP_HOST}} ^domena.pl$ RewriteRule ^/~(([a-z])[a-z0-9-]+)(.*) http://$1.domena.pl$3 [R,L] RewriteCond %{REQUEST_URI} !^/icons/ RewriteCond %{REQUEST_URI} !^/error/ RewriteCond %{REQUEST_URI} !^/cgi-bin/ RewriteCond ${lowercase:%{HTTP_HOST}} ^(.+)$ RewriteCond ${vhost:%1} ^(/.*)$ RewriteRule ^/(.*)$ %1/$1 [E=VHOST:${lowercase:%{HTTP_HOST}}]
Krótkie wytłumaczenie. RewriteMap (/etc/virtualhosts.map) zawiera wpisy w formacie:
user.domena.pl /home/users/user/public_html domena2.com /home/users/user150/public_html itd...
Jaki typ RewriteMap wybierzemy jest obojętne. Ja wybrałem “txt” bo automat dodaje mi vhosty użytkowników. Dodatkowo nie pozwalamy nadpisywać aliasów dla ikon, stron z błędami oraz globalnego katalogu cgi-bin. Ponieważ URLe http://domena.pl/~user nie działają, a niektórzy na pewno będą próbowali się tak odwoływać do własnej strony, to przepisujemy te adresy na adresy typu http://user.domena.pl (pierwszy RewriteRule). Następnie już tylko mapujemy odpowiedni vhost do jemu przyporządkowanego (w RewriteMapie) katalogu.
Od tej pory mamy działające virtualhosty i możemy je używać bez problemu z mod_php.
CGIWrap – czyli php wykonywane z prawami użytkownika
Przypominam, że CGIWrap z patchem, którego udostępniam działa tylko z taką konfiguracją. Jest to spowodowane tym, że obliczam w CGIWrapie użytkownika na podstawie jego katalogu domowego i edytuje odpowiednio zmienne środowiskowe PATH_INFO oraz PATH_TRANSLATED.
Ulubionym edytorem tekstu edytujemy plik /etc/httpd/httpd.conf/01_mod_cgid.conf i dopisujemy następujące linie:
ScriptAlias /cgi-bin/ "/home/services/httpd/cgi-bin/" <Directory /home/services/httpd/cgi-bin\> Options FollowSymLinks ExecCGI </Directory\> Action _phpwrap /cgi-bin/php-cgiwrap AddHandler _phpwrap .php .php4 .php5
Jeśli ktoś nie chce odinstalować mod_php, to nie musi. Wystarczy, że odbierze mod_php przywiązanie do plików o typach zdefiniowanych dla _phpwrap.
Następnie dobieramy się po raz kolejny do pliku /etc/httpd/httpd.conf/00_mod_rewrite.conf i dodajemy:
RewriteMap cgi txt:/etc/cgi.map <Files ~ "\.php$"> #CGIWrap RewriteCond %{REQUEST_URI} ^/ RewriteCond %{REQUEST_URI} !^/icons/ RewriteCond %{REQUEST_URI} !^/error/ RewriteCond %{REQUEST_URI} !^/cgi-bin/ RewriteCond ${lowercase:%{HTTP_HOST}} ^(.+)$ RewriteCond ${cgi:%1} ^(/.*)$ RewriteRule ^/(.*)$ %1/$1 [PT,E=REDIRECT_STATUS:200] </Files>
Jeśli Apache wypluje nam coś o tym, że cgi nie działa ponieważ REDITECT_STATUS nie jest poprawnie ustawiony, to należy dodać go analogicznie do poprzedniego RewriteRule.
/etc/cgi.map zawiera wpisy w formacie:
user.domena.pl /cgi-bin/php-cgiwrap/ domena2.pl /cgi-bin/php-cgiwrap/ itd...
To chyba wszystko co należy skonfigurować. W razie problemów włączamy sobie:
RewriteLog /var/log/httpd/rewrite_log RewriteLogLevel 9
i oglądamy sobie co jest nie tak, jeśli problem jest w mod_rewrite. Jeśli problem jest w CGIWrapie, to jako handlera wybieramy np. php-cgiwrapd
– wtedy dostaniemy output z debugiem.
Mam nadzieję, że o niczym nie zapomniałem, bo wpis ten traktuję głównie jako notkę do siebie ;-) Korzystając z okazji pragnę podziękować za pomoc zbyniowi i sparkiemu.
Bijcie!