Category Archives: Linux

Hacking as game

Recently I’ve been interested in several different areas of computer science, one of which is web/system security. I am not trying to join Anonymous or something ;), but You can never have enough knowledge. Due to that fact I’ve stumbled upon a nice page, with some kind of CTF-like games or tasks, which can greatly increase Your knowledge about linux, web and security. I have not ended all tasks but it can be really fun. Here is the page – http://overthewire.org/.

Advertisements

NetworkManager w KUbuntu

Dzisiaj będzie trochę o czymś innym i do tego krótko. Mam laptopa z zainstalowanym KUbuntu. Laptop ma o tyle niefajnie, że raz podłączam go pod kabelek, czasem pod WiFi sąsiada, a czasem pod swoje własne 😉 Do tego łączę się z niego poprzez VPNa do sieci firmowej, ale przy okazji na komputerze przez który idzie łącze ‘kabelkowe’ też czasem odpalam drugiego VPNa. Dlaczego o tym piszę? Gdyż gdzieś w tym galimatiasie linux po prostu staje dęba i nie wie czego konkretnie używać do połączenia z internetem.

Zazwyczaj w KDE mamy takie coś jak NetworkManager. Z tym tylko, że dość często po uruchomieniu systemu klikając na ikonkę w zasobniku dostaję piękne zdalnie ‘NetworkManager disabled’. Khem. Rozwiązanie jest dość banalne, ale trzeba wiedzieć co z czym i po kolei. Dokładny opis znaleźć można pod tym linkiem. Ja tylko o tym piszę bo może komuś się przydać i oszczędzić nerwów.

Instalujemy PostgreSQL na Debianie Lenny

Odgrażałem się chyba z 10 razy, że w końcu zainstaluję PostgreSQL, aby podpiąć pod ten system bazodanowy swoje aplikacje. Lata płyną 🙂 zaś PostgreSQL ani widu, ani słychu. Przy okazji tworzeniu nowego projektu i zabaw z Mavenem przyszedł czas i na bazę.

Mój VPS posiada zainstalowanego MySQLa, który służy nie tylko do obsługi moich aplikacji, ale też trzymania wiki, czy Kulturalnego Chlebika. W tym wpisie opiszę jak przebiega instalacja oraz konfiguracja PostgreSQL na serwerze z Debianem Lenny i jak to poskładać do kupy, aby dobrze działało. Wpierw rzecz jasna trzeba odpowiedzieć sobie na pytanie jaką wersję RDBMSa instalujemy. W sumie najbardziej “nową” wersją jest ta oznaczona numerkiem 8.4. Jednakże moja polityka dotycząca nowych wersji jest powszechnie znana, a co więcej, w tym przypadku jest wspierana tym, iż w repozytoriach Debiana znalazłem gotowy pakiet z wersją 8.3. Po części system zadecydował za mnie. Uruchamiamy zatem apta:

sudo apt-get install postgresql-8.3

Apt pomieli swoje i na końcu całego listingu zobaczyłem takie oto dobre rzeczy:

Creating new cluster (configuration: /etc/postgresql/8.3/main, data: /var/lib/postgresql/8.3/main)…
Moving configuration file /var/lib/postgresql/8.3/main/postgresql.conf to /etc/postgresql/8.3/main…
Moving configuration file /var/lib/postgresql/8.3/main/pg_hba.conf to /etc/postgresql/8.3/main…
Moving configuration file /var/lib/postgresql/8.3/main/pg_ident.conf to /etc/postgresql/8.3/main…
Configuring postgresql.conf to use port 5432…
Starting PostgreSQL 8.3 database server: main.

Informacje o utworzeniu nowego klastra plus pojawienie się plików konfiguracyjnych są bardzo dobre – w necie znalazłem informacje, że zdarzały się przypadki ‘niepełnej’ instalacji z paczek, co skutkowało koniecznością dziwnych zabaw z samą bazą i jej skryptami konfiguracyjnymi lub uruchomieniowymi. W moim przypadku jak widać wszystko poszło OK i serwer PostgreSQL został uruchomiony. Wypada przyjrzeć się choć trochę konfiguracji – otwieramy plik postgresql.conf, który znajdziemy w katalogu wskazanym przy instalacji (u mnie jest to /etc/postgresql/8.3/main ). Jest on dość duży i rozbudowany, ale ten wpis nie jest o tuningowaniu PostgreSQL dlatego na razie odpuścimy sobie większość rzeczy poza wartościami zmiennych timezone oraz datastyle. Zgodnie z zaleceniami powinny one wyglądać tak:

datestyle = 'European, German'
timezone = Poland

Choć to w sumie duperel. Istotne jest to, aby móc łączyć się z bazą z dowolnego miejsca. W pliku konfiguracyjnym odnajdujemy zmienną listen_addresses i jeśli jest inaczej to ustawiamy jej wartość na ‘*’ (czyli na wszystkie możliwe interfejsy). Zamykamy plik. PostgreSQL domyślnie tworzy użytkownika o nazwie postgres, ale lepiej zostawić go w spokoju, za to do łączenia się z bazą lepiej stworzyć oddzielnego użytkownika, albo użyć jednego z istniejących – głównie dla bezpieczeństwa (ograniczenie dostępu lub różne prawa). Edycji poddajemy plik ph_hba.conf, który znajduje się tam gdzie główny plik konfiguracyjny. Dopisujemy tam następującą linijkę:

host all chlebik 0.0.0.0 0.0.0.0 password

Co oznacza tyle, że można połączyć się z serwerem bazy danych spoza serwera macierzystego używając do zalogowania użytkownika o nazwie chlebik. Dla łatwości również stworzymy nową bazę danych dla tych połączeń:

su
su postgres
createuser -a -d -P -e -W chlebik
createdb -e -E UTF-8 -O chlebik chlebik

Restartujemy serwer. Teraz wypadałoby sprawdzić czy nasze zabiegi przyniosły jakikolwiek efekt:

su
su postgres
psql template1
\du

I powinniśmy zobaczyć chlebika jako jednego z użytkowników bazy. Skoro tak to pewnie dałoby się zalogować jako chlebik i przy okazji zobaczyć co tam słychać w naszej bazie (pamiętajmy, że utworzyliśmy właśnie nową dla tego użytkownika ).

psql -U chlebik -h localhost chlebik

Logujemy się jako user chlebik do bazy danych o nazwie również ‘chlebik’ znajdującej się na lokalnej maszynie. Zostaniemy poproszeni o hasło. Jeśli wszystko jest OK to zostaniemy zalogowani do konsoli psql-a, gdzie możemy dla przykładu wydać takie polecenie:

\dt

Co powinno doprowadzić do pojawienia się komunikatu No relations found. Trudno by cokolwiek znaleziono – w końcu baza danych jest czysta jak pierwszy śnieg. Jednakże proces logowania przebiegł pomyślnie i wypada się z tego cieszyć. Jednakże to jeszcze nie koniec – połączenie z serwera jest dobre – na pewno nasze aplikacje na nim wdrożone uruchomią się bez problemów. Jednakże ustawialiśmy możliwość łączenia się z bazą spoza serwera. Teraz przetestujemy tę możliwość – ja wybralem do tego program PgAdmin, który mam na dysku, gdyż lokalnie na maszynie developerskiej posiadam zainstalowanego PostgreSQL. Wpisujemy dane i oto mamy:

SVN w Debianie bo ile można nosić kod ze sobą

Posiadanie własnego serwera daje szereg możliwości. Jedną z nich jest jedno miejsce ze wszystkimi usługami, do którego możemy dostać się zewsząd. W przypadku programisty to chyba jego kod jest najbardziej pożądanym dobrem – zatem jego dostępność jest sprawą nie do przecenienia.

By nie komplikować za bardzo postanowiłem postawić repozytorium SVN – bardzo popularnego systemu kontroli wersji, dobrze obsługiwanego zarówno pod Windowsem jak i linuxem. W związku z tym, iż pracuję na tych dwóch systemach możliwość łatwej obsługi jest dla mnie szczególnie istotna. Zatem w konsoli klepiemy:

sudo apt-get install subversion

I po chwili możemy cieszyć się naszym systemem kontroli wersji. Dostęp do niego zapewnimy sobie przez natywny protokół SVN. Teraz musimy umieścić gdzieś nowe zupełnie repozytorium, a także nadać prawa do korzystania z niego. W sumie jestem jedynym użytkownikiem serwera, zatem mógłbym zainstalować repozytorium w swoim katalogu domowym. Jednakże nie jest to dobre rozwiązanie – bezpieczniej byłoby stworzyć oddzielnego użytkownika tylko dla dostępu do repozytorium. Bezpieczniej i w sumie wygodniej. Lecimy zatem:

adduser svn

Automatycznie jest tworzony użytkownik oraz grupa o takiej samej nazwie. Repozytorium zainstalujemy w katalogu domowym usera svn, jednakże to za chwilkę. Należy zastanowić się nad dość istotną rzeczą. Otóż póki co zamierzamy wysłać do repozytorium kod źródłowy, który znajduje się na razie na moim dysku twardym. Czyli nie jest to plik WAR, ani nawet rozpakowane na serwerze pliki – muskmy wrzucić całość projektu Netbeans, który mamy u nas na serwerze. Zasadniczo byłoby najwygodniej po prostu przekopiować zawartość katalogu z projektem na serwer, ale trochę to takie… nieeleganckie 🙂 Zresztą jak się okazuje, nasze IDE z taką sytuacją upora się dość szybko i łatwo.

W katalogu usera svn tworzymy katalog, w którym będziemy trzymać nasz kod.


mkdir repos
cd repos
mkdir programbash
svnadmin create /home/svn/repos/programbash

Rzecz jasna najlepiej tego typu zabiegi dokonywać kiedy jesteśmy zalogowani jako użytkownik user. W przeciwnym razie czeka nas rekursywne nadanie uprawnień do katalogu repos/programbash właśnie temu użytkownikowi. Kiedy mamy katalog, który docelowo ma trzymać nasze (tutaj konkretne dla projektu) repozytorium należałoby je skonfigurować. Przechodzimy do naszego utworzonego repozytorium i zaglądamy do katalogu conf. Należy poddać edycji plik conf/svnserver.conf:

anon-access = none # tylko zalogowani userzy moga laczyc sie z repo
auth-access = write # userzy moga szalec
password-db = passwd # czyli dostep dla par user-haslo

Zgodnie z ostatnim zapisem w tym pliku poddajemy teraz edycji plik passwd w tym samym katalogu:

[svn] = [nasze_tajne_haslo]

I tyle konfiguracji. Należy omówić teraz budowę repozytorium – głównym jego katalogiem jest trunk, gdzie leży główna część naszego kodu. Do tego elementami repozytorium SVN są katalogi branches oraz tags. Przynajmniej taką strukturę zaleca nam dokumentacja SVNa i akurat tutaj zgódźmy się na takie rozwiązanie. Jednakże katalogi te nie są tworzone automatycznie przez SVNa zatem musimy dodać je sami. By to osiągnąć należy przejść do katalogu /tmp (wybrałem go tylko dlatego, że na pewno jest tam dostęp i potem będziemy mogli jego zawartość wyczyścić) i wydać takie polecenie:

svn co file:///home/svn/repos/programbash

I powinniśmy otrzymać następujący komunikat:

Checked out revision 0.

Konkretnie w tej chwili stworzyliśmy obraz repozytorium w wybranej przez nas lokalizacji. Dzięki temu na spokojnie dodamy wskazane katalogi:

mkdir trunk
mkdir tags
mkdir branches
svn add trunk
svn add tags
svn add branches

W ten sposób utworzone katalogi zostały wybrane do włączenia ich do systemu kontroli wersji. Teraz wypadałoby je do niego wysłać:

svn commit -m "Pierwszy commit - dodanie katalogow repozytorium"

I możemy sobie obejrzeć efekt:

Adding branches
Adding tags
Adding trunkCommitted revision 1.

Nasz pierwszy commit zakończył się powodzeniem (katalog w /tmp możemy usunąć). W naszym repozytorium istnieje już odpowiednia struktura katalogów i czeka na wypełnienie treścią. By to osiągnąć musimy udostępnić nasze repozytorium na zewnątrz. Istnieje kilka możliwości – udostępnianie poprzez protokół HTTP (do tego potrzebne jest dokonfigurowanie serwera WWW), posługiwanie się protokołem SSH (również konfiguracja), albo też natywnym protokołem dla SVN i to rozwiązanie zastosujemy. Za komunikację po ww. protokole odpowiada demon (program może być uruchomiony jako demon) o nazwie svnserve. Jest on automatycznie instalowany wraz z SVN, zatem nie trzeba instalować nic dodatkowego. Demon ten nasłuchuje domyślnie na porcie 3690. Uruchamiamy go w ten sposób:

svnserve -d -r /home/svn/repos

Wskazujemy, że działamy jako demon (-d), a także wskazujemy na roboczy katalog. Dzięki wskazaniu na repos nasz demon obsłuży wszystkie repozytoria jakie kiedykolwiek przyjdzie nam do głowy dodać. Rzecz jasna przydałoby się dodać uruchamianie tego demona przy starcie systemu poprzez edycję skryptów startowych. Na razie jednakże skupmy się na zaimportowaniu plików do repozytorium. Uruchamiamy Netbeans (zakładam, że pluginy do obsługi SVN zostały zainstalowane) i klikamy prawym przyciskiem myszy na projekcie, który zamierzamy wysłać do repozytorium, po czym wybieramy Versioning -> Import into Subversion repository tak jak poniżej:

W pojawiąjacym się okienku wpisujemy:

svn://chlebik.pl/programbash/trunk

Wpisujemy też rzecz jasna użytkownika i hasło po czym klikamy na Next i następuje (powinno 🙂 połączenie z serwerem. Przy naszej strukturze repozytorium (każdy projekt będzie posiadał oddzielny katalog) katalog trunk jest głównym, zatem to właśnie jego wskazujemy jako cel importu. Musimy również wpisać komunikat związany z tym importem i klikamy Next.

Po chwili powinniśmy zobaczyć taki ekran:

I ostatecznie nacisnąć na przycisk Finish. Akurat Programbash trochę waży, zatem w zależności od szybkości łącza internetowego wysłanie wszystkich plików na serwer może trochę potrwać. Ostatecznie w zakładce Output otrzymałem taki komunikat:

Transmitting file data ...
Committed revision 2.
update D:/Java/programbash2 -r HEAD --depth=files --force
At revision 2.
==[IDE]== 2010-02-15 01:14:21 Committing... finished.

Czyli zasadniczo wszystko OK. Sprawdźmy czy wszystko jest na pewno w porządku. Użyłem do tego Eclipse, aby nie mieszać w Netbeans. Odpalamy IDE, tworzymy nowy projekt, wybieramy jako typ SVN -> Checkout project , dodajemy nową lokację repozytorium, podajemy stosowne dane i Eclipse uruchamia kreatora projektu. Zakładam rzecz jasna, że nasz Eclipse posiada plugin do obsługi SVNa – polecam Subclipse. U mnie projekt zaimportował się bez najmniejszych przeszkód i tym samym dowiodłem, że repozytorium działa 🙂

Rzecz na koniec dość istotna – do repozytorium dodałem z premedytacją pliki projektu Netbeans. Standardowo nie robi się tego w ten sposób – jakiekolwiek szczegóły deploymentu aplikacji powinny zostać pominięte w repozytorium. Dzięki temu nie śmiecimy w nim plikami potencjalnie różnymi u każdego programisty. Jednakże zasady tutaj panujące powinny być uzgodnione przez użytkowników repozytorium. W tym przypadku ja będę jedynym, zatem pozwoliłem sobie na taką małą frywolność 🙂

Debian jako serwer Javy – podstawy systemu

Poprzedni wpis (będący jednocześnie pierwszym) na temat wykorzystania Debiana jako serwera dla aplikacji Java skupiał się wyłącznie na uruchomieniu usług, które miały po prostu działać. Dziś skupimy się bardziej na samym systemie.

Użytkownicy systemów Windows są przyzwyczajeni do konieczności poinstalacyjnych operacji związanych ze ściąganiem olbrzymiej liczby poprawek połączonych z restartami systemu. W przypadku linuxa jest lepiej – cała operacja aktualizacji systemu przebiega bardzo sprawnie i nie wymaga spędzenia przy komputerze kilku godzin.

Zanim jednakże weźmiemy się do pracy kilka słów wyjaśnienia. Zakładam, iż czytelnik ma rozeznanie w podstawowych komendach w systemach linuxowych. Jeśli takowego brak (w co wątpię) wówczas można zajrzeć pod ten adres, gdzie można znaleźć szybką ściągawkę z podstawowych komend oraz ich parametrów. Zakładam również, że posiadamy na danym serwerze prawa ROOTa – mowa o konfiguracji serwera zatem oczywistym powino być, że mamy pełną kontrolę nad systemem.

Aktualizacje

Podstawową rzeczą w systemie jest jego ciągła aktualizacja. Na pewno zaś przynajmniej aktualizacje bezpieczeństwa, które niemożliwiają skorzystanie w naszym systemie z odkrytych w oprogramowaniu luk. Rzecz jest zatem bardzo istotna, ale tym samym diablo nudna i rutynowa. Potencjalna ilość aktualizacji codziennie dołączanych do dystrybucji jest bardzo duża. Dlatego też rzecz jasna cały proces trzeba zautomatyzować. Od wydania wersji Debian Woody sugerowanym rozwiązaniem jeśli chodzi o zarządzanie oprogramowaniem w systemie jest program apt. Po części to właśnie on stał się powodem olbrzymiej popularności Ubuntu. Klepiemy linijkę kodu i oto mamy zainstalowane oprogramowanie. To właśnie wzięło się z Debiana i jest jego olbrzymią siłą. Pełną dokumentację narzędzia apt warto przeczytać, zaś znaleźć można ją pod tym adresem.

Zaraz po instalacji najlepiej w konsoli wydać takie oto polecenia:

apt-get update <-- Co zaktualizuje liste pakietow
apt-get upgrade <-- Wprowadzi zmiany w systemie

Co sprawi, że wszystkie pakiety zainstalowane wraz z systemem zostaną zastąpione ich nowszym wersjami (jeśli takowe w ogóle istnieją). W przypadku zwykłego systemu serwerowego, który bynajmniej nie posiada serwera Xów, ani dużej ilości oprogramowania wchodzącego w skład KDE czy Gnome procesy akutalizacji są szybkie i nie wymagają ściągania olbrzymich ilości danych. Zasadniczo nie ma opcji by system automatycznie ściągał poprawki i je instalował – mogłoby to spowodować prawdziwą katastrofę w przypadku zwłaszcza serwera produkcyjnego. Dlatego praktyką jest automatyczne pobieranie aktualizacji, ale decyzja czy je zainstalować jest pozostawiana administratorowi. Można to osiągnąć instalując narzędzie cron-apt, które zgodnie z nazwą cyklicznie dokonuje aktualizacji pakietów. Mamy też możliwość dość solidnej konfiguracji tego narzędzia – w sumie dość profesjonalnym jest otrzymywanie mejli za każdym razem kiedy coś pójdzie nie tak. Wstęp do instalacji tego narzędzia i jego używania można znaleźć pod tym adresem. W związku z tym, iż posiadam tylko jeden serwer pozwoliłem sobie zostawić na razie ręczne akutalizowanie systemu. Na razie 🙂

Ekran logowania

Kolejna rzecz jest kosmetyką, ale dość istotną jeśli mamy raptem 1 serwer. Otóż istnieje możliwość własnego zdefiniowania bannera, który pojawi się przy zalogowaniu się do systemu przez SSH. By osiągnąć taki efekt musimy poddać edycji plik /etc/ssh/sshd_config i w nim odkomentować stosowną linijkę:

Banner /etc/issue.net

Dzięki temu w pliku wskazanym (tutaj /etc/issue.net) możemy wkleić swój komunikat. Restartujemy demona SSH i oto mamy efekt – mała rzecz, a jak cieszy.

Co w procesach piszczy

Przy starcie każdego sytemu operacyjnego po załadowaniu podstawowych rzeczy składających się na sam system, rozpoczyna się sekwencyjne uruchamianie procesów. Jeśli uruchamiamy linuxa choćby na komputerze lokalnym wówczas mamy możliwość zobaczenia komunikatów o startowaniu kolejnych programów/demonów. Tym samym uruchamiane są kolejne procesy. Proces to nic innego jak pewne działanie, które jest wykonywane na serwerze. Każdy z procesów jest identyfikowany jednoznaczenie przez swój PID, czyli ID procesu. By zobaczyć działające w systemie procesy wydajemy w konsoli polecenie top lub htop (to troche ladniejsze i bardziej rozbudowane narzędzie). U mnie wygląda to tak:

Zasadniczo nie ma tam nic podejrzanego. Mamy i procesy Javy, mamy serwer WWW, działa też PHP i kilka podstawowych dla systemu rzeczy. Najistotniejszą rzeczą jest proces o nazwie init:

1 root 20 0 1988 528 496 S 0 0.1 0:00.56 init

Jest to pierwszy proces odpalany w systemie. Powoduje on zainicjalizowanie systemu, a następnie tenże system przechodzi po kolei po wszystkich skryptach znajdujących się w katalogach rcX.d, gdzie X to kolejne cyfry oznaczające tzw. runlevel. Dla nas interesujące są te z przedziału 2-5, gdyż oznaczają one normalne działanie systemu (w sensie uruchamiania). Level 0 to zamykanie systemu, zaś 6 to jego restart. Warto pochodzić po tychże katalogach i zobaczyć co z czym. U mnie dla przykładu katalog rc2.d wygląda tak:

drwxr-xr-x 2 root root 4096 Jan 31 20:48 .
drwxr-xr-x 74 root root 4096 Jan 31 21:18 ..
-rw-r--r-- 1 root root 556 Aug 12 2008 README
lrwxrwxrwx 1 root root 17 Dec 13 10:08 S10rsyslog -> ../init.d/rsyslog
lrwxrwxrwx 1 root root 14 Dec 13 10:17 S12dbus -> ../init.d/dbus
lrwxrwxrwx 1 root root 22 Dec 13 10:18 S14avahi-daemon -> ../init.d/avahi-daemon
lrwxrwxrwx 1 root root 13 Dec 13 10:08 S16ssh -> ../init.d/ssh
lrwxrwxrwx 1 root root 23 Dec 13 11:46 S17mysql-ndb-mgm -> ../init.d/mysql-ndb-mgm
lrwxrwxrwx 1 root root 19 Dec 13 11:46 S18mysql-ndb -> ../init.d/mysql-ndb
lrwxrwxrwx 1 root root 15 Dec 13 11:46 S19mysql -> ../init.d/mysql
lrwxrwxrwx 1 root root 18 Dec 21 12:04 S20lighttpd -> ../init.d/lighttpd
lrwxrwxrwx 1 root root 15 Dec 13 10:45 S20nginx -> ../init.d/nginx
lrwxrwxrwx 1 root root 23 Dec 13 10:08 S20openbsd-inetd -> ../init.d/openbsd-inetd
lrwxrwxrwx 1 root root 17 Dec 13 10:08 S20postfix -> ../init.d/postfix
lrwxrwxrwx 1 root root 18 Jan 31 20:48 S20startphp -> ../init.d/startphp
lrwxrwxrwx 1 root root 13 Dec 19 09:57 S21fam -> ../init.d/fam
lrwxrwxrwx 1 root root 13 Dec 13 10:08 S89atd -> ../init.d/atd
lrwxrwxrwx 1 root root 14 Dec 13 10:08 S89cron -> ../init.d/cron
lrwxrwxrwx 1 root root 17 Dec 13 11:08 S91apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 Dec 13 10:26 S92tomcat6 -> ../init.d/tomcat6
lrwxrwxrwx 1 root root 18 Dec 13 10:08 S99rc.local -> ../init.d/rc.local
lrwxrwxrwx 1 root root 19 Dec 13 10:08 S99rmnologin -> ../init.d/rmnologin
lrwxrwxrwx 1 root root 23 Dec 13 10:08 S99stop-bootlogd -> ../init.d/stop-bootlogd

Jak zatem widać wszystko co się znajduje w tym katalogu (i w pozostałych też) to zasadniczo dowiązania symboliczne do skryptów z katalogu /etc/init.d. W ten sposób startują wszystkie nasze usługi i demony – poprzez dowiązanie symboliczne do skryptu. Istnieje też plik/skrypt o nazwie rc.local, w którym powinny znaleźć się nasze skrypty, które mają być uruchamiane po każdorazowym starcie systemu. Jednakże u mnie to rozwiązanie nie zadziałało (użyłem tego pliku do wrzucenia startu PHP ). I potem dziwiłem się czemu za każdym restartem (w sumie raptem 2 do tej pory, no ale zawsze) nie działały mi aplikacje PHP. Odpowiedź na ten problem znajduje się nawet w oficjalnej dokumentacji Debiana (punkt 10.6). By zatem wystartować PHP podczas startu systemu trzeba zrobić następujące czynności:

  • Tworzymy plik w katalogu /etc/init.d. Ja nadałem mu nazwę startphp.
  • Jego zawartość jest krótka
    /usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www-data -g www-data -f /usr/bin/php5-cgi -P /var/run/fastcgi-php.pid -C 12
  • Informujemy system o fakcie istnienia takiego skryptu. W tym celu użyjemy narzędzia update-rc.d, które to trzeba wywołać z odpowiednimi parametrami. Ja zrobiłem to dość skromnie:
    update-rc.d /etc/init.d/startphp defaults
    I teraz skrypt ten będzie uruchamiał się podczas startu systemu (w runlevelach 2-5). Więcej na temat tego narzędzia oraz jego parametrów można znależć na stronach dokumentacji systemowej.

Rzecz jasna w ten sam sposób moglibyśmy podpiąć do wykonywania plik rc.local, ale po namyśle doszedłem do wniosku, że rozdzielenie skryptów będzie bardziej czytelne. Choć tutaj już każdy musi podjąć decyzję, co mu bardziej pasuje. Podobną decyzję trzeba też podjąć jeśli chodzi o procesy już uruchamiane. Przykładem jest choćby demon avahi, który jest dostarczany wraz z instalacją systemu i automatycznie uruchamiany. Co ten konkretny demon robi można przeczytać tutaj, zaś dyskusję na temat jego pozostawienia i używania tutaj. Mi jakoś specjalnie do niczego potrzebne to nie będzie, zatem trzeba temat wyrzucić. Komenda:

update-rc.d -f /etc/init.d/avahi-daemon remove

I po restarcie mamy nadzieję, że demon już nie powstaje. Niestety jest to nadzieja płonna – albowiem taki trick w Debianie bynajmniej nie wystarcza. Należy jeszcze edycji poddać plik /etc/default/avahi-daemon i tam dopisać linijkę z dyrektywą:

AVAHI_DAEMON_START

I ustawić jej wartość na 0. Reboot i w procesach już Avahi nie ma.

Co słychać w portach

Poza procesami warto też przyjrzeć się otwartym portom i usługom na nich działającym. Pomoże nam w tym taka instrukcja:

netstat -nlp

Pokaże ona interesujące nas rzeczy.

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:869 0.0.0.0:* LISTEN 693/famd
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 663/php5-cgi
tcp 0 0 94.23.178.117:3306 0.0.0.0:* LISTEN 792/mysqld
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 308/portmap
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 557/nginx
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 414/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 653/master
tcp6 0 0 :::8080 :::* LISTEN 740/jsvc
tcp6 0 0 :::22 :::* LISTEN 414/sshd
udp 0 0 0.0.0.0:111 0.0.0.0:* 308/portmap

Portmapper to demon, który jest potrzebny do działania RPC, zatem zostawiamy go póki co sobie. Ciekawym z kolei jest pierwszy wiesz, czyli port 693 i działający tam demon famd. Szybka wycieczka do wujka googla i dowiadujemy się, iż jest to demon, którego celem jest monitorowanie zmian w systemie plików. Więcej na ten temat pod tym adresem no i co istotne – zalecana jest jego zamiana na demona gamin. Lecimy zaptem:

apt-get install gamin

I dostajemy w odpowiedzi:

chlebik@chlebik:~$ sudo apt-get install gamin
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
libgamin0
The following packages will be REMOVED:
fam libfam0
The following NEW packages will be installed:
gamin libgamin0
0 upgraded, 2 newly installed, 2 to remove and 54 not upgraded.
Need to get 102kB of archives.
After this operation, 65.5kB disk space will be freed.
Do you want to continue [Y/n]? Y
Get:1 http://ftp.debian.org lenny/main libgamin0 0.1.9-2 [37.8kB]
Get:2 http://ftp.debian.org lenny/main gamin 0.1.9-2 [64.0kB]
Fetched 102kB in 0s (558kB/s)
(Reading database ... 24203 files and directories currently installed.)
Removing fam ...
Stopping file alteration monitor: FAM.

dpkg: libfam0: dependency problems, but removing anyway as you request:
lighttpd depends on libfam0.
Removing libfam0 ...
Processing triggers for man-db ...
Selecting previously deselected package libgamin0.
(Reading database ... 24181 files and directories currently installed.)
Unpacking libgamin0 (from .../libgamin0_0.1.9-2_i386.deb) ...
Selecting previously deselected package gamin.
Unpacking gamin (from .../gamin_0.1.9-2_i386.deb) ...
Setting up gamin (0.1.9-2) ...
Setting up libgamin0 (0.1.9-2) ...

I po reboocie jest już lepiej:

tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 636/php5-cgi
tcp 0 0 94.23.178.117:3306 0.0.0.0:* LISTEN 784/mysqld
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 308/portmap
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 561/nginx
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 414/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 628/master
tcp6 0 0 :::8080 :::* LISTEN 694/jsvc
tcp6 0 0 :::22 :::* LISTEN 414/sshd
udp 0 0 0.0.0.0:111 0.0.0.0:* 308/portmap

Ciekawe też rzeczy może nam pokazać znany pogram nmap, ale tutaj zainteresowanych odsyłam na stronę domową nmapa.

Chcę oglądać twoje logi

Zasadniczo wszystkie aplikacje pozostawiają po sobie jakieś logi. Jest to dość naturalne – jak inaczej sprawdzić czy z naszymi programami wszystko porządku jeśli nie podsłuchując co do nas mówią. Problemem jednakże stają się przestarzałe artefakty – kiedy nagle kilkaset MB dysku jest zajętych przez stare pliki z logami. Możnaby rzecz jasna napisać własny skrypt powłoki, który usuwałby wskazane pliki (i najlepiej podpiąć go do crontaba i byłby spokój). Jednakże jest to rozwiązanie dość toporne. Rzecz jasna problem nie pojawił się wczoraj i powstały stosowne narzędzia dla uporania się z tym problemem. Jednym z nich jest logrotate. U mnie ta aplikacyjka była już zainstalowana i działała całkiem sprawnie. W katalogu /etc/logrotate.d/ znalazły się informacje o logach ngixa, lightiego, mysqla i kilku innych. Nie grozi mi zatem wyczerpanie miejsca na dysku 🙂
Pomijając usuwanie starych logów, warto też czasem zajrzeć do /var/log/syslog by wiedzieć co pod obudową się dzieje.

Zakończenie

Przedstawiłem dość podstawowe rzeczy dotyczące administracji serwerem opartym na Debianie. Rzecz jasna codzienna praktyka z pewnością będzie bardziej skomplikowana, coś pewnie nie raz się zepsuje i nie będzie działać tak jak powinno. Jeśli znalazłeś jakiś błąd w tekście, albo też masz pomysł, co by tu jeszcze dopisać proszę pisz śmiało.

Debian jako serwer Javy – Serwery, bazy i routing

Po przygodach z przenoszeniem aplikacji z Jetty na Tomcata serwer ostatecznie stoi. Jest to całkowicie mój VPSik. Pierwotnie działał na nim Gentoo, jednakże nigdy nie bawiłem się z tą dystrybucją w związku z czym trochę szkoda mi było kilku tygodni na rozkminienie o co w tym wszystkim chodzi. Dlatego też decyzja o zainstalowaniu na nim Debiana, dystrybucji dojrzałej, sprawdzonej i szeroko znanej. No i jak wiadomo – support dla niej to cała rzesza linuxowych geeków.

Wstęp

Cel był prosty – stworzyć system, na którym będą działały moje aplikacyjki. Nie wymaga on zatem tuningowania jak wielkie produkcyjne serwisy, ale podstawowe kwestie dotyczące stabilności oraz bezpieczeństwa wypadałloby na nim zrobić. Docelowo na serwerze miały działać następujące usługi:

  • Apache Tomcat
  • bazy danych (MySQL na start, potem doinstaluję Postgresa)
  • języki skryptowe – choćby do wygodnego używania PHPMyAdmin, czy tego typu rozwiązań
  • no i jakiś serwer WWW, by te języki skryptowe mogły gdzieś śmigać

To był plan 0. Otrzymałem Debiana z już zainstalowanym SKD dla Javy, a także ze śmigającym Tomcatem. Instalacja samego kontenera nie jest specjalnie skomplikowana – po prostu ściągamy go poprzez apta i tyle. Jeżeli jednak musimy zaczynać z “gołym” systemem to z pewnością ten link będzie bardzo pomocny. UWAGA!!! Dodam tylko, że występuje tam mały błąd – po instalacji SDK w pliku /etc/profile należy dopisać:

export $JAVA_HOME

Zaś na listingu występuje zapis bez znaczka $. Bez tego nasze aplikacyjki dostarczone z Tomcatem nie ruszą. Wypadałoby też zobaczyć czy na pewno używamy Javy 6. W konsoli:

java -version

Jeśli mamy tam jakieś wersje <1.6 to znaczy, że można też odwiedzić wątek na pewnym forum. Na chwilę obecną zakładam, że wszystko jest dobrze poinstalowane plus używamy najnowszej wersji Javy.

W zależności od potrzeby serwer obsługujemy poleceniami:

/etc/init.d/tomcat-6 start|stop|restart

Konkretna nazwa skryptu może się różnić (w podanym przeze mnie linku jest to /etc/init.d/tomcat). Domyślnie nasz kontener działa na porcie 8080 – jego zmianą zajmiemy się za chwilkę. Uruchamiamy kontener i powinniśmy pod adresem http://localhost:8080 zobaczyć taką oto stronę:

Tomcat jest dostarczany bynajmniej nie jako ‘out-of-the-box’ i trzeba trochę pogrzebać w plikach konfiguracyjnych, aby spełniał w pełni swoją rolę. Domyślnie też jest dostarczany z 2 aplikacjami, które umożliwiają zarządzanie serwerem poprzez interfejs WWW. Pozostawianie ich dostępnych na serwerze produkcyjnym nie jest zbyt dobrym pomysłem (z powodów bezpieczeństwa), ale na etapie stawiania systemu mogą okazać się bardzo przydatne. By jednakże otrzymać do nich dostęp należy edytować plik /var/lib/tomcat6/conf/tomcat-users.xml. U mnie wygląda on tak:

<tomcat-users>
 <role rolename="manager"/>
 <role rolename="admin"/>
 <user username="nasztajnylogin" password="mojetajnehaslo" roles="admin,manager"/>
</tomcat-users>

Oczywiście user i hasło są zmyślone 🙂 W tym pliku XML mamy taki kontenerowy ACL – tworzymy jednocześnie zarówno role jak i użytkowników. Dzięki temu uzyskujemy dostęp do 2 aplikacji zarządzających kontenerem. Są one o tyle istotne na etapie tworzenia serwera, że można szybko i wygodnie poprzez stronę WWW zarządzać serwerkiem. Ja jednakże postanowiłem pobawić się plikami konfiguracyjnymi, zatem usunąłem dostęp do tych aplikacji, a je same wyrzuciłem z serwera.

Baza danych MySQL

Podstawą dla wszystkich aplikacji sieciowych jest baza danych. HowToJava powstała z użyciem MySQLa, podobnie póki co jest i z ProgramBash. Wypadało zatem zainstalować ten RDBMS by mieć na czym operować. W pakietach Debiana znajduje się najnowsza (w miarę) wersja zatem wystarczy użyć apta i jesteśmy w domu. Problemy mogą wystąpić przy próbie połączenia z bazą z zewnątrz – dla przykładu z naszego lokalnego komputera. W moim przypadku Hibernate rzucał wyjątkiem o niemożliwości połączenia się z powodu Connection refused. Innymi słowy – już sam serwer nie chciał mojego requestu. Rozwiązanie jest proste – należy edycji poddać plik /etc/mysql/my.cnf i parametrowi bind-address nie nadawać wartości localhost lub 127.0.0.1, ale IP naszego serwera. Wtedy bez najmniejszych problemów będzie można połączyć się z lokalnej maszyny. Nalezy także pamiętać o utworzeniu użytkownika z odpowiednimi prawami (łączącego się z określonego hosta). Na koniec zabaw ze zmianą uprawnień wydajemy polecenie:

flush privilages;

Bez tego można kląć na potęgę dlaczego nasze zmiany w uprawnieniach nie są widoczne.

Routing lub też proxy jak kto woli

Domyślnie Tomcat (choć dotyczy to w sumie wszystkich serwerów/kontenerów Javy z jakimi miałem okazję pracować) działa na porcie 8080 lub okolicach. Rzecz jasna w przypadku podpinania domeny pod nasz serwer takie rozwiązanie nie za bardzo wchodzi w grę – wszak nie można ustawić w routingu domen docelowego portu. Przyjęło się, że w użyciu mamy port 80 – tam przeglądarki standardowo wysyłają swoje żądania. Cóż zatem zrobić, aby wykupiona domena wskazywała na nasze pliki z aplikacjami Javy (u mnie to WARy) i wyglądało to transparentnie? Mamy kilka rozwiązań:

  • ustawienie portu w konfiguracji Tomcata na numer 80. Proste, ale absolutnie niezalecane ze względów bezpieczeństwa!!!
  • forwardować ruch poprzez odpowiednią konfigurację firewalla. Iptables to dobre narzędzie do tego.
  • postawić nasz serwer/kontener Javowy za zwykłym serwerem WWW, który będzie działał jako proxy.

Powyższe rozwiązania zostały dokładnie omówione w tym miejscu, a i z pomocą Gogla, można dowiedzieć się wszystkiego. Ja również pierwotnie myślałem o postawieniu Apache i zastosowaniu connectorów, jednakże moi mili admini wyperswadowali mi takowy pomysł i stanęło na podobnym rozwiązaniu, ale w oparciu o szybki serwer WWW – nginx. Oficjalna stronka znajduje się pod adresem http://nginx.org/. Sam serwer ma swoje plusy i minusy, by się z nimi zapoznać zapraszam do artykułu w Wikipedii. Sam serwer posłuży też do obsługi PHP – konkretniej do narzędzi zarządzających bazą danych (wygodny jestem), a także być może w przyszłości hostowania tego bloga.

Instalacja nginxa jest banalnie prosta:

sudo apt-get install nginx

I nasz serwerek jest już zainstalowany. Całkiem przyzwoity materiał o tym serwerze można znaleźć u Riklaumina, ja ograniczę się na razie do pierwszego jego uruchomienia. Tuningiem i bliższym poznaniem zajmę się w kolejnych artykułach. Przede wszystkim należy przejśc do katalogu /etc/nginx/conf.d. Cokolwiek znajdzie się w tym katalogu zostanie domyślnie potraktowane jako plik konfiguracyjny. Należy utworzyć nasz podstawowy plik konfiguracyjny:

cd /etc/nginx/conf.d
touch default.conf

Edytujemy stworzony plik i wrzucamy w niego na przykład taki oto kod:

 server {
        listen       80;
        server_name  WPISUJEMY_NASZE_IP DOMENA1 DOMENA2 DOMENA3;

        # Main location
        location / {
            proxy_pass         http://127.0.0.1:8080/;
            proxy_redirect     off;

            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

            client_max_body_size       52m;
            client_body_buffer_size    128k;

            proxy_connect_timeout      3600;
            proxy_send_timeout         3600;
            proxy_read_timeout         90;

            proxy_buffer_size          4k;
            proxy_buffers              4 32k;
            proxy_busy_buffers_size    64k;
            proxy_temp_file_write_size 64k;
            proxy_cache_valid 5m;
        }
    }

To baaaaardzo podstawowa konfiguracja. Ale na pewno osiągnęliśmy jedno – wszystkie requesty domyślnie lecące na port 80 zostaną przekierowane na port 8080, gdzie będzie na nie już oczekiwał nasz Tomcat. Można odpalić nginxa poleceniem:

/etc/init.d/ngninx start

Być może trzeba będzie po raz pierwszy zrobić to z poziomu konta administratora. Jak widać sam serwer zainstalował skrypt, ktory uruchamia go przy starcie systemu (w katalogu /etc/init.d/).

Tomcata musimy odpowiednio poinformować o istnieniu czegoś takiego jak subdomeny. I tutaj właśnie pobawimy się plikami konfiguracyjnymi (choć będzie to dość szybka zabawa). Docelowo mój serwerek zainstalował się w katalogu /var/lib/tomcat6/. W tymże katalogu znajduje się również podstawowy katalog dla naszych aplikacji – webapps. Dla naszych aplikacji, które zamierzamy wdrożyć należy przygotować pliki dystrybucyjne – ja pozostaję od samego początku wierny plikom WAR. Teraz musimy wyedytować plik konfiguracyjny Tomcata. W naszym ulubioym edytorku bierzemy na tapetę plik /var/lib/tomcat6/conf/server.xml.

 <Host name="SUBDOMENA_Z_DOMENA" appBase="webapps/NAZWA_SUBDOMENY" unpackWARs="true" autodeploy="true"></Host>

Restart Tomcata i należy udać się pod powyżej wpisany adres. Oczywiście serwer nie znalazł ani katalogu, ani pliku o wskazanej nazwie (jeszcze nic nie wysłaliśmy na serwer), zatem przekierował nas na główną stronę w domenie. Jednakże póki co wszystko działa poprawnie – nie dostaliśmy od serwerów po drodze błędu 404. Do testów maszyny najlepiej na szybko stworzyć maksymalnie prosty projekt w Javie (ja użyłem przykładowego projektu JSF). Generujemy dla niego plik WAR i łączymy się z serwerem dowolnym klientem FTP/SCP/SSH (w zależności co lubimy i co mamy/odpaliilśmy na serwerze). Przesyłamy do katalogu webapps nasz plik WAR i tworzymy dla niego katalog. Dla ułatwienia stworzyłem subdomenę example.chlebik.pl jak i odpowiedni katalog. Do niego wrzuciłem plik WAR. Uwaga!!! Można naciąć się na uprawnieniach do katalogów lub plików. Podążając tropem aktywności mojego Tomcata wszystkie pliki i katalogi przypisuję do użytkownika tomcat6 oraz grupy o tej samej nazwie. Przynajmniej nie dostaję ukochanego komunikatu – Permission denied.

Powyżej w pliku server.xml ustawiliśmy, że ta konkretna aplikacja ma być deployowana na starcie serwera, a także ma mieć rozpakowany plik WAR (dla zwiększenia szybkości działania). Ponownie odwiedzamy adres naszej subdomeny – i nic. Dalej jesteśmy przekierowywani na główną stronę domeny. Cóż się stało? Ano taka dziwna cecha Tomcata – wystarczy nasz plik WAR znajdujący się (u mnie) w katalogu webapps/example/, przemianować na webapps/example/ROOT.war. Restart serwera i co? Hip-Hop, hurrra. Dostajemy miły komunikat od JSF i Facelets, że nasza aplikacja działa. Można z ciekawości zajrzeć do tego katalogu – został tam rozpakowany w podkatalog o takiej samej nazwie jak plik WAR cały kod naszej aplikacji. Dlaczego w ten sposób? Uważam, że w katalogu z aplikacjami powinny być inne katalogi, a nie stado plików WAR lub inszych, które zaciemniają obraz. Każda aplikacja ma swój katalog i niech w nim dzieje się co chce.

PHP i Fast-CGI

Na koniec został mi do zainstalowania PHP. O ile w przypadku pierwotnie planowanego Apache rzecz jest banalna, o tyle nginx wymaga trochę zabawy. Należy bowiem doinstalować specjalny moduł do obsługi języków skryptowych poprzez Fast-CGI. Tutaj korzysta się z dobroci serwera lighttpd, ale o tym można już poczytać sobie w artykule. Dodam tylko by odpowiednio skroić nasz plik default.conf z nginxa – można połączyć konfig FCGI z PHP z istniejącą konfiguracją, ale można też zastosować podejście opisane w powyższym tutorialu. Co więcej – nginx jest tak fajnym narzędziem, że przy restarcie waliduje swoje pliki konfiguracyjne – jeśli coś jest nie tak wówczas od razu zostaniemy o tym poinformowani bez konieczności przeglądania logów serwera.

Co dalej?

Mam nadzieję, iż trochę ułatwiłem początkującym adminom życie (jakbym ja miał 10 lat doświadczenia :). W ramach możliwości postaram się kontynuować tak mile rozpoczęty cykl wpisów o administracji serwerem dla programistów. Jeśli znalazłeś jakikolwiek błąd w powyższym materiale lub masz jakieś sugestie – rzecz jasna zapraszam do kontaktu lub komentowania. Gdyby ktoś był zainteresowany VPSem lub hostingiem tam gdzie ja to należy pisać na ten adres email. Przy okazji możecie wspomnieć, że to dzięki mnie wiecie o usłudze 🙂

Tak na koniec

Na sam koniec dobra rada dla wszystkich programisto-administratorów 🙂 Jakiekolwiek operacje na sewerze (dedyku, VPSie czy w ogóle czymkolwiek) lepiej wpierw przetestować na VirtualBoxie. Produkt firmy SUN świetnie się do tego nadaje. Nie będę opisywał tutaj procesu instalacji i tak dalej, dam tylko kilka szybkich rad dla uruchamiania wirtualizacji systemu w Windows XP:

1. Używana przestrzeń dyskowa na system linuxowy powinna być wrzucona na partycję z systemem plików innym niż FAT32!! Inaczej dostaniemy błędy podczas instalacji, albo użytkowania, gdyż ten format nie obsługuje istnienia plików powyżej 2 GB.
2. W świetle powyższego – skonfigurować wirtualną maszynę by miała rozszerzalne miejsce na partycji. Często coś tam się doinstaluje, odinstaluje lub chce pobawić i nagle BUM – nie ma miejsca.
3. Jeżeli naszego linuxa instalujemy wraz ze środowiskiem graficznym należy ściągnąć VBoxLinuxAdditions. Jest to obraz płyty, który po instalacji naszego systemu należy podpiąć i następnie uruchomić z poziomu linuxa. U mnie wymagało to doinstalowania kilku rzeczy (nagłówków jądra linuxa i czegoś jeszcze). Kiedy to wszystko już zrobimy uruchamiamy po prostu skrypt .sh dla linuxa i stosownej architektury. Dzięki temu będziemy mogli rozszerzać ekran z wirtualizowanym systemem, grafika przestanie się ciąć i w ogóle będzie lepiej.
4. RZECZ BARDZO ISTOTNA!!! Dość często ludziom zdaża się, że uruchomienie VBoxa nawet z czystą konsolą (bez fajerwerków KDE czy GNOME) powoduje zżarcie przez VBoxa jakiś 50-90% procesora. Strasznie to wkurzające – dzieje się tak niezależnie od przydzielonej ilości RAMu. Rozwązaniem jest wyłączenie antywirusa!! U mnie działa darmowy AVG – jego wyłączenie automatycznie zredukowało zasobożerność VBoxa. Domyślam się, że chodzi o monitorowanie wirtualnego połączenia internetowego. Z tego co wyczytałem w sieci również niektóre fiewalle zachowują się w podobny sposób.