środa, 19 sierpnia 2009

Domowy serwer na bazie Ubuntu Server Karmic Koala

Wstęp

Jak skonfigurować domowy serwer pełniący funkcje NAT, firewalla, serwera uPNP (do dynamicznego przekierowania portów dla np. Skype czy choćby transferów plików w Gadu-Gadu), serwera iTunes, DHCP, lokalnego przyspieszacza DNS (bind9), przyspieszacza WWW (transparent proxy za pomocą Squid 3), usługi pobierania plików poprzez BitTorrent z możliwością kontroli przez WWW lub aplikację kliencką (dzięki transmission-daemon).

Do tego celu użyję dość przyjemnego w konfiguracji Ubuntu Server, w wersji zwanej kodowo Karmic Koala (wkrótce, już oficjalnie, 9.10).

Zakładam że dostęp do Internetu uzyskujemy przez urządzenie zewnętrzne, dostarczone przez operatora, podłączone za pomocą kabla sieciowego do serwera. Inne konfiguracje, jak np. modem DSL podłączony przez USB, także są możliwe, jednak ich ustawienie zostawiam w gestii czytelnika.

Konfiguracja sprzętowa

Mój serwer to stosunkowo żwawy staruszek o następujących parametrach:

  • Pentium III 933 skręcony na 466MHz - chłodzony pasywnie pióropuszem Zalmana, ogrzane powietrze odciągane przez zasilacz - temperatura 32-36°C, także w gorące dni
  • 512MB RAM (DDR 133)
  • Seagate Barracuda IV 60GB - tu rzecz jasna polecam coś większego
  • dwie karty sieciowe 1Gbps, choć może z jedną nieco przesadziłem, ponieważ i tak łączy się ona z modemem kablowym UPC z prędkością 100Mbps. Z drugiej strony karty gigabitowe nie są znacząco droższe od 100 megabitowych, więc nie stanowi to problemu. Zawsze mamy nieco lepszy sprzęt na wypadek, gdyby operatorzy zaczęli nam wreszcie do domów podpinać gigabitowe łącza światłowodowe. ;)

Na razie jest to lekko chaotyczny zrzut kroków, jakie popełniłem po kolei, by z czystej instalacji stworzyć dość fajnie działający serwerek domowy. Jak czas pozwoli, rozwinę go nieco i uporządkuję.

Gdyby pójść zgodnie z opisem, myślę że skonfigurowanie serwera można zamknąć w dwóch godzinach od zainstalowania.

Pewne elementy konfiguracji powinno dać się jeszcze przyspieszyć, wykorzystując nieco magii uniksowych poleceń grep/sed/awk, jednak nie jestem w nich szczególnie biegły, zatem nie będę ryzykował. ;)

Przy instalacji wybrałem opcje "LAMP", "DNS", "Samba". W razie gdyby czegoś brakowało, a będzie potrzebne przez inne usługi, które będziemy instalować na następnym etapie, zostaną przez Ubuntu doinstalowane.

Uwaga! Przy instalacji Ubuntu Server może być warto wybrać opcję LVM dla dysków, albo zarezerwować sobie nieco miejsca na takie wolumeny na dysku. Dzięki temu w łatwy sposób będzie można stworzyć udziały Windows obsługujące shadow copy, tj. zachowujące historię zmodyfikowanych plików i pozwalające do nich wracać w dowolnym momencie. Funkcja ta istnieje od Windows 2000, serwer Samba obsługuje ją poprzez vfs, za pomocą modułu shadow_copy. Konfiguracja shadow copy jest dość prosta. Póki nie spróbuję samemu i nie udokumentuję, polecam opis wyglądający na dość przyjemny: SambaShadowCopyHowto.

Czego jeszcze w opisie brakuje, to konfiguracja związana z opcjami oszczędności energii. Ze względu na posiadany procesor, usług wykorzystujących Cool'n'Quiet w procesorach AMD czy SpeedStep nie będę konfigurował, ale warto się nimi zainteresować. Procesor w tego typu serwerze mimo wszystko większość czasu będzie się dość nudził, zatem będzie działał na minimalnych przewidzianych przez producenta obrotach.

Można natomiast zająć się ustawieniem chociażby wyłączania dysku/dysków po ustalonym czasie. Gdy nieco ten temat rozpoznam, także pod względem zorientowania się, jak uczynić by Ubuntu jak najrzadziej odwoływał się do dysku by nie budzić go zbyt często, uzupełnię ten opis. Tu można zdziałać z ekstremalnie opóźnionymi zapisami na dysk, przechowywaniem większej ilości danych w pamięci (np. preload.d dla plików uruchamialnych i bibliotek). Szczególnie ciekawą z technicznego punktu widzenia opcją, z jaką się spotkałem, to "położenie" (przy użyciu unionfs) systemu plików trzymanego w pamięci RAM na drzewie katalogów /var/log. W tym wypadku nawet częste zapisy do logów nie wywołują zapisów na dysk, wszystko odbywa się w pamięci. Jednak w razie powieszenia systemu lub awarii zasilania wolę zachować informacje z logów.

Większość opisów instalacji Linuksa na kartach pamięci lub pendrivach te kwestie podejmuje, zatem warto się zainteresować.

Kroki konfiguracji

Pierwsza “paczka”

apt-get install mercurial etckeeper mc linux-igd transmission-cli transmission-daemon squid3 dhcp3-server traceroute

Zauważcie że nigdzie, w przeciwieństwie do innych dokumentów instalacji czy konfiguracji Ubuntu czy innych systemów linuksowych, nie dodaję sudo przed komendami. W takim “ciągu” wydawanych komend administracyjnych wolę odpalić basha z uprawnieniami roota, tj.

sudo bash

Ale oczywiście należy pamiętać, by pracę na koncie administratora zredukować do minimum! Tyczy się to także użytkowania Windows. Gdyby wszyscy tego przestrzegali już od premiery Windows XP, swiat byłby dziś znacznie lepszy. ;)

Etckeeper

Przekonfigurować etckeeper na Mercurial (korzystam z hg na co dzień, zatem dla mnie jest to bardziej znajome narzędzie, niż bzr).

Odkomentować opcję w /etc/etckeeper/etckeeper.conf:

VCS="hg"

zamiast domyślnej

VCS=”bzr”

Serwer DNS

Plik /etc/bind/named.conf.options

Odkomentować forwarders, wstawić adresy ip serwerów DNS dostawcy połączenia internetowego, u mnie:

forwarders {
    62.179.1.63; 62.179.1.62;
};

Restart serwera

/etc/init.d/bind9 restart

(choć może wystarczyłby reload, tę opcję zalecam częściej, by nie przerywać działania usług tylko dla zmiany w pliku konfiguracyjnym. Z tego co wiem, większość usług, przynajmniej tych popularnych, interpretuje wysłanie sygnału SIGHUP jako rozkaz przeładowania konfiguracji)

Resolver

W /etc/resolv.conf dodać serwer lokalny, 127.0.0.1 do DNSów, przed pozostałymi już ustawionymi (w czasie konfiguracji DHCP przy instalacji serwera),

nameserver 127.0.0.1

Sprawdzić działanie forwardowania DNS:

  • Uruchomić komendę dig google.com dwukrotnie
  • Za drugim razem, w odpowiedzi, linijka ;; SERVER: będzie zawierała 127.0.0.1#53. Jeśli nie, coś jest nie tak, RTFM! ;)

Denyhosts

Jeśli nasz serwer jest bombardowany próbami zalogowania na losowe konta poprzez SSH, dobrze jest mieć denyhosts, który automatycznie będzie namolne maszyny blokował po kilku nieudanych próbach.

apt-get install denyhosts

Domyślna konfiguracja jest całkiem w porządku, choć daemon jest ustawiony tak, by monitorować nowych upierdliwych “gości” co 30 sekund. W tym czasie zdąży taki wykonać przynajmniej kilkanaście prób zalogowania, a nie chcemy zaśmiecania logu. W pliku /etc/denyhosts.conf przestawiłem tym samym ten czas na 10 sekund:

DAEMON_SLEEP = 10s

Zakładając że sami nie będziemy próbowali za często logować się na konta które na naszym serwerze nie istnieją, można nieco ostrzej reagować na takie “ataki”, zmniejszając liczbę tolerowanych prób do 2

DENY_THRESHOLD_INVALID = 2

Myślę że kolekcjonować blokowanych adresów na dłużej niż 3 dni nie ma potrzeby:

PURGE_DENY = 3d

Zobaczymy, o ile czystsze logi będą w ciągu tygodnia. :)

Transmission Daemon

Konfigurujemy transmission-daemon. Trzeba upewnić się, że transmission-daemon jest zatrzymany, inaczej nadpisze ustawienia w /etc/transmission-daemon/settings.json

/etc/init.d/transmission-daemon stop

W pliku ustawień:

  1. umożliwiamy ustalanie innych ograniczeń szybkości transferów w dni robocze, gdy nikogo nie ma w domu, by torrentów nie pobierać z pełną prędkością cały dzień, utrudniając działanie innych usług sieciowych
    1. "alt-speed-enabled" na true
  1. "max-peers-global" na 100
  2. "peer-socket-tos" na 32 - później spróbujemy na firewallu ustawiać priorytet pakietów bittorrentowych na niski, by nie zakłócać działania innych usług
  3. "preallocation" na 0 - domyślnie przy pobieraniu torrenta od razu rezerwowane jest miejsce na dysku na całą jego zawartość, ustawiamy na 0, jeśli tego nie chcemy
  4. "rpc-password" na "transmission" - bo nie potrzebujemy mocnych zabezpieczeń, jeśli mamy sterować zdalnie tylko z sieci lokalnej
  5. "speed-limit-down-enabled" na true
  6. "speed-limit-up-enabled" na true
  7. "upload-slots-per-torrent" na 10, albo wedle preferencji

Logowanie startu systemu

W /etc/default/bootlogd opcję BOOTLOGD_ENABLE ustawić na Yes

Może się przydać.

Linux Internet Gateway Daemon

linux-igd to usługa uPNP, umożliwiająca ustawianie przez aplikacje sieciowe przekierowania portów z najbliżej położonej bramki internetowej/firewalla. uPNP wykorzystuje Skype, uTorrent, do ustawiania portów sieciowych dla nasłuchiwania ruchu przychodzącego.

W /etc/default/linux-igd

  • EXTIFACE na interfejs sieciowy zewnętrzny, prowadzący do internetu, u mnie

EXTIFACE=eth0

  • INTIFACE na interfejs sieciowy sieci lokalnej, u mnie

INTIFACE=eth1

Można zrestartować serwer lub przeładować konfigurację:

/etc/init.d/linux-igd restart

Firewall

Korzystamy z domyślnie instalowanego ufw – uncomplicated firewall. Jest prosty w użyciu i jest standardową opcją we wszystkich Ubuntu, to jego dwie niezaprzeczalne zalety.

W pliku /etc/default/ufw - do IPT_MODULES dodać moduł nf_conntrack_netbios_ns, zatem u mnie:

IPT_MODULES="nf_conntrack_ftp nf_nat_ftp nf_conntrack_irc nf_nat_irc nf_conntrack_netbios_ns"

Konfigurujemy NAT wg oficjalnej dokumentacji:

  • w /etc/default/ufw DEFAULT_FORWARD_POLICY na "ACCEPT"
  • odkomentowujemy w /etc/ufw/sysctl.conf linijkę net/ipv4/ip_forward=1
  • odkomentowujemy w /etc/ufw/sysctl.conf linijkę net/ipv6/conf/default/forwarding=1
  • w /etc/ufw/before.rules dodajemy następujący kod, przed sekcją *filter

# nat Table rules
*nat
:POSTROUTING ACCEPT [0:0]
# Forward traffic from eth1 through eth0.
-A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE
# don't delete the 'COMMIT' line or these nat table rules won't be processed
COMMIT

Ta konfiguracja zakłada że chcemy przekierowywać ruch z sieci lokalnej z interfejsu eth1 na interfejs zewnętrzny, eth0.

Maskę adresów ip należy zmienić na odpowiednią, u mnie 192.168.1.0/24.

Otwieramy porty usług

Aby po włączeniu firewalla można było się łączyć na SSH z wewnątrz i zewnątrz:

ufw allow ssh

Odpalamy firewall:

ufw enable

Dodać regułę zezwalającą na wysyłanie zapytań od DNS z sieci lokalnej

ufw allow from 192.168.1.0/24 to any app bind9

Dodać regułę zezwalającą na połączenie SMB komputerów Windows do udziałów udostępnionych na serwerze

ufw allow from 192.168.1.0/24 to any app samba

Otwieramy port do zarządzania transmission-daemonem z zewnątrz

ufw allow from 192.168.1.0/24 to any port 9091

Aplikujemy reguły tradycyjnie komendami:

ufw disable && ufw enable

SQUID

Ustawiamy SQUID jako proxy przezroczysty, tj. przekierowujący każde odwołanie HTTP na port 80 z sieci wewnętrznej na port własny, domyślnie 3128, tym samym przechowując w pamięci podręcznej wszystkie statyczne pliki przychodzące z internetu - przy kilku komputerach w sieci daje to dość zauważalną poprawę szybkości działania odwiedzanych przez domowników stron.

Tutaj edytujemy plik /etc/squid3/squid.conf

W sekcji acl dodajemy:

acl localnet src 192.168.1.0/24

Odkomentowujemy linijkę

http_access allow localnet

Do linijki http_port 3128 dodajemy "transparent", bez znaków cudzysłowia, tj.

http_port 3128 transparent

Linijka cache_dir:

cache_dir aufs /var/spool/squid3 500 16 256

  • aufs to asynchroniczny "system plików", operacje na plikacj pamięci podręcznej nie będą blokowały głównego procesu squid, co może poprawić wydajność
  • 500 - rozmiar pamięci podręcznej w megabajtach
  • 16 i 256 to odpowiednio liczba podkatalogów pierwszego i drugiego poziomu w drzewie katalogów pamięci podręcznej, może tak pozostać, nie ma większego znaczenia w naszych zastosowaniach

maximum_object_size zwiększamy do 30000 KB - w takim maksymalnym dopuszczalnym rozmiarze obiektu przechowywanego zmieszczą się już wszelkie pliki aktualizacji, np. firefoksa, co dla kilku komputerów może znacząco poprawić wydajność sieci

Logformat - parametr ustawiający format, w jakim będzie wypełniany plik log dostępny w /var/log/squid3/access.log:

logformat custom %>a [%tl] "%rm %ru HTTP/%rv" %Hs %<st %Ss:%Sh

Ten jest bardziej czytelny od domyślnego, ale domyślny może być czytany przez standardowe logparsery, o ile chcemy takich używać, zatem wedle uznania

Konieczne jest ustawienie na firewallu przekierowania odwołań do serwerów internetowych na porty 80, na serwer Squid, port 3128, zatem dodajemy w regule *nat w /etc/before.rules, za -A POSTROUTING liniki

# Forward port 80 requests to transparent squid proxy

-A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.1.2:3128

Zostawiłem komentarz dla zachowania czytelności pliku konfiguracyjnego.

Tu 192.168.1.2 to adres serwera w sieci wewnętrznej, jednak nie ustawiliśmy go jeszcze.

Serwer DHCP

Najlepiej by komputery w wewnętrznej sieci nie wymagały żadnych ustawień sieciowych, zatem dobrze jest ustawić usługę DHCP, by wszystkie potrzebne parametry przekazał serwer.

W /etc/dhcp3/dhcpd.conf

option domain-name-servers 192.168.1.2;

Każdy komputer otrzyma informację, iż pod tym IP jest serwer nazw domenowych. Można wedle uznania dodać też awaryjnie serwery dostawcy internetowego

subnet 192.168.1.0 netmask 255.255.255.0 { 
  range 192.168.1.100 192.168.1.240; 
  option routers 192.168.1.2;
}

Tym samym serwer DHCP będzie przydzielał komputerom adresy z podanych zakresów ip, a jako bramkę internetową poda 192.168.1.2.

Przydatną opcją jest też możliwość przydzielania na stałe numerów IP konkretnym komputerom, a raczej ich kartom sieciowym.

Za to odpowiedzialna jest sekcja host

host dev { 
  hardware ethernet 00:1B:FC:70:CF:D3;
  fixed-address 192.168.1.69;
}

Przydzieliłem tym samym komputerowi z kartą sieciową o podanym MACu stały numer 192.168.1.69.

Choć dla przekierowania portów większość "nowoczesnych" aplikacji stosuje usługi uPNP i NAT-PMP, a tę pierwszą nasz serwer udostępnia, czasem przydaje się jednak przydzielenie stałego numeru wybranej maszynie lub kilku oraz ustawieniu dla nich przekierowania portów na stałe.

Uruchamiamy ponownie serwer dhcp:

/etc/init.d/dhcp3-server restart (tradycyjnie, powinien wystarczyć reload)

Konfiguracja interfejsów sieciowych

Ustawiamy ostateczne adresy ip serwera dla wewnętrznej i zewnętrznej sieci

W /etc/network/interfaces

  • dla eth0 zostają domyślne, gdyż serwer będzie otrzymywał numer IP publiczny od modemu kablowego
  • dla eth1:

auto eth1
iface eth1 inet static
address 192.168.1.2
netmask 255.255.255.0

Restartujemy sieć:

/etc/init.d/networking restart

Teraz najlepiej zrestartować serwer, by sprawdzić, czy wszystko dobrze funkcjonuje od momentu startu serwera.

reboot

Teraz można przepiąć kabel sieciowy do karty interfejsu wewnętrznego.

iTunes media server – Firefly

apt-get install libid3tag0 mt-daapd

Otwieramy port serwera mediów dla sieci wewnętrznej

ufw allow from 192.168.1.0/24 to any port 3689

I aktualizujemy ustawienia firewalla

ufw disable && ufw enable

Tworzymy użytkownika media, opcja -m każe utworzyć katalog domowy.

useradd media -m

Zakładamy katalog /home/media/music

mkdir /home/media/music
chmod 777 /home/media/music - uprawnienia do modyfikacji katalogu dla wszystkich

Dodajemy katalog /home/media/music do udziałów Samba, by był dostępny do zapisu dla maszyn Windows

[media]
path = /home/media/music
guest ok = yes
writable = yes
comment = iTunes Media Folder

Przeładowujemy konfigurację serwera Samba:

/etc/init.d/samba reload

Teraz można wejść z dowolnej maszyny Windowsowej do katalogu media na serwerze i wgrać biblioteczkę muzyki.

W panelu administracyjnym, dostępnym pod http://ip_serwera:3689 (user: admin, hasło mt-daap) ustawiamy stosowne opcje, /home/media/music jest ustawiony domyślnie.

W Server Status konsoli Firefly odpalamy Start Full Scan, by odnalazł nasze utworki. Gdy uruchomimy iTunes, serwer Firefly powinien się pojawić jako jedno ze źródeł muzyki.

Można ustawić użytkowników i hasła dla serwera mediów, ale ... ufamy współlokatorom jako tako. ;)

Robimy z serwera wieżę: Music Player Daemon ;)

Ta usługa działająca na serwerze pozwala odtwarzać bezpośrednio z niego muzykę, natomiast sterować nim można za pomocą szeregu aplikacji klienckich, także dla Windows, Windows Mobile czy iPhone/iPod Touch.

Już wkrótce!

Na koniec

Być może stawianie pełnych serwerów DHCP i DNS dla niewielkiej domowej sieci to nieco za dużo, powinien wystarczyć znacznie mniej rozbudowany dnsmasq, spełniający funkcję prostego cache DNS i serwera DHCP.

Jeżeli macie uwagi merytoryczne, szczególnie z punktu widzenia bezpieczeństwa systemu, ale i zasad administracji systemami linuksowymi, proszę o komentarze. Nie jestem szczególnie zaawansowanym użytkownikiem linuksa, nie jest to moja działka, chcę po prostu działający domowy serwer o dość szerokim spektrum zastosowań, których raczej proste "sieciowe kieszenie na dyski" nie spełnią.

wtorek, 4 listopada 2008

Message crackers in windowsx.h

Looks like they are documented after all. In Knowledge Base though.

wtorek, 29 lipca 2008

Krok po kroczku - App Engine daje coraz więcej

appengine_lowres Tak naprawdę ku zabawie z Django skłoniła mnie premiera Google App Engine parę miesięcy temu. Dotąd nie byłem przekonany zbytnio do programowania aplikacji webowych w Pythonie, ponieważ PHP z Zend Frameworkiem jest całkiem niezłym kawałkiem biblioteki, a przełączenie się na coś zupełnie innego wymaga nieco wysiłku z początku. Ale załączenie Django w GAE SDK było wystarczającą rekomendacją tego projektu, jako rozwiązania dojrzałego i przyjaznego programiście. Google ma zwyczaj akurat o tę grupę dbać całkiem nieźle.

Będąc na co dzień programistą J2ME/J2EE, a tylko w prywatnych projektach robionych w domowym zaciszu wykorzystując bardziej nowoczesne lub po prostu inne zabawki, możliwość poprowadzenia z praktykantem małego projekciku w technologiach tak diametralnie różnych, to swoisty ratunek zdrowia psychicznego. ;)

Nie dość że zupełnie inne biblioteki, to jeszcze jazda całkowicie bez trzymanki! Jako platforma serwerowa posłuży Google App Engine z Django 1.0 alpha, natomiast po stronie klienckiej jest nic innego jak Android, w roli nowoczesnej platformy mobilnej. MIDP to przeżytek przecież. ;)

Cieszą mnie kolejne aktualizacje App Engine, jak ostatnio wypuszczona wersja 1.1.1, która teraz pozwala na utworzenie 10 aplikacji, zamiast dotychczasowych 3. Dodatkowo poprawiono sporo błędów, więc może być tylko lepiej. Żeby tak w androidowym SDK poprawili wreszcie najbardziej irytujące niedociągnięcia...

Źródło: Google App Engine Blog

wtorek, 8 lipca 2008

Jestem człowiekiem ery Web 1.0...

Już jakiś czas chodziło za mną przestawienie się całkowite z programowania webowego w PHP i Zend Framework na coś przynoszącego powiew świeżości i nowoczesności, a także większego porządku składniowego i dyscypliny.

Moje zauroczenie Pythonem trwa od przynajmniej dwóch lat, ale przekonać się do jego zastosowania w webie ciągle nie mogłem. Udało się wreszcie znaleźć do tego sposobność - projekt i w pracy i jeszcze zaległy zaliczeniowy, by móc złożyć pracę mgr z zaliczonym ostatnim semestrem. ;)

Django wygląda dojrzale i atrakcyjnie, sprawia wrażenie dobrze przemyślanego, a także porządnie wygrzanego w prawdziwych projektach, nie skupionego tylko na szybkim napisaniu aplikacji z tutoriala, by później się okazało że coś bardziej skomplikowanego, to wchodzenie pod stromy pagórek.

Co jednak mi pozostało w sposobie myślenia z twórczości phpowej, to poprzedni engine webowy do niedawna napędzający PDAclub.pl. Nieco się on zestarzał, a nie miałem czasu zająć się czymś nowszym, więc nowy główny programista przerobił mocno na użytek portalu Joomlę 1.5. Mniejsza o to.

Jednym z ciekawszych elementów, które tam opracowałem, to engine layoutów. Działało to w następujący sposób:

  • każda strona prezentująca jakieś treści była przedstawiona w postaci pliku html ze wstawionymi tagami komponentów (w tamtej nomenklaturze - "modułów"), jakie tam miały się pojawić; komponentem takim był np. fragment HTML (np. dla nagłówka, stopki), pobierający tytuł portalu i inne parametry z konfiguracji; inny to komponent wyświetlający parametryzowalną listę newsów, jeszcze inny postów na forum, inny wyświetlający pełną treść wybranego artykułu, kolejny listę nowych hotspotów, menu główne, reklamy, województwa, pliki w dziale download, kategorie itd. Strona główna przykładowo składała się z: nagłówka html, menu głównego, menu nawigacyjnego bocznego, listy najpopularniejszych artykułów, listy poprzednich 15 newsów, głównej części z listą aktualności, listy trzech komunikatów/ogłoszeń (spotkania klubów użytkowników), listy najnowszych wątków z forum, 5 ostatnich komentarzy w newsach, reklamy helionu, shoutboksa dla redakcji (tylko dla niej widocznego), stopki (copyright). Każdy element mogłem dowolnie ustawić, by wyświetlał dokładnie co chcę i jak to ma wyglądać, nigdy nie był uruchamiany niepotrzebny kod. Jeśli chciałem dodać listę trzech najnowszych recenzji sprzętu, wystarczyło wstawić odpowiedni tag do pliku layoutu i ewentualnie zdefiniować template dla takiego elementu - ani linijki kodu PHP do napisania!
  • parametry tych komponentów były podane w linijce z ich wywołaniem, przykładowo {mcm style="module: stories; template: stories_main; limit: 3d10; page: @p"}, oznaczało wstawienie listy newsów z trzech ostatnich dni, a minimalnie 10 najnowszych (jeśli przez ostatnie dni niewiele się działo - pomysł Alberta z czasów, gdy współpracowaliśmy nad pocketpage/palmpage ;) ), których kod html tworzony jest na podstawie templejtu templates/stories_main.tpl , @p-ta strona wyników, a wyrenderowana lista trafiała do pliku na dysku, by setki odsłon na minutę nie wywoływały ciągle tego samego kodu.
  • wartość @p brana była akurat z parametrów żądania HTTP, oczywiście w module stories zamieniana na int
  • Takie komponenty mogły być użyte wielokrotnie, nawet na tej samej stronie - często umieszczanych było kilka wariantów, np. inny z limit: 10; order: views; template: stories_popular, pokazywał najczęściej czytane artykuły za pomocą templejtu stories_popular.tpl
  • Był zatem główny skrypt, który pobierał plik layoutu. Kod html zostawiał nietkniętym, a tagi zamieniał na stosowną treść, uruchamiając dla każdego odpowiednie moduły z "module", przekazując im parametry z tagu, z urla (jeśli potrzebne), ewentualnie ze współdzielonej przez komponenty tablicy zmiennych.
  • Każde takie uruchomienie to był include_once skryptu "modules/{module}.inc.php" (odpowiednio zabezpieczone, by nie wywoływać nieistniejącego lub nie dopuścić do kombinacji ze ścieżkami), wywołanie funkcji a'la render i zwrócenie zamiennika dla taga

Dawało mi to sporą elastyczność, gdyż na różnych stronach mogły być te komponenty przedstawione w odmiennych wariantach, do dowolnych zastosowań. Założeniem było że są od siebie niezależne, ale nie przechowują żadnego stanu w sesji czy gdziekolwiek indziej - mają swoją pracę wykonać tylko na podstawie podanych parametrów i ewentualnie danych w bazie, jeśli z takiej korzystały (większość tak).

Było to bardzo mocno zoptymalizowane wydajnościowo rozwiązanie - jedyny narzut dawało samo parsowanie pliku layoutu, choć był na tyle pomijalny, że próby automatycznej "kompilacji" go do postaci kodu PHP (jak w enginie samych templejtów) skończyły się na eksperymentach.

Parę lat później stworzyłem nieco ulepszoną wersję także tego elementu. Można było robić include innego pliku layoutu, by najczęściej powtarzające się elementy dziedziczyć z innych stron, "moduły" były zrobione obiektowo, ale ogólna zasada działania pozostała.

Potem pojawił się Zend Framework. Zachwyciłem się nim, choć ze stratą tak dla mnie wygodnego rozwiązania jak owe "komponenty" się nie pogodziłem. Napisałem odpowiednie rozszerzenia frameworka, które realizowały ten sam pomysł na nowo. Tym razem opis layoutu to plik xml (kompilowany przez cache do kodu php), nie zawierający żadnego html, ani php, moduły robione w duchu ZF (wykorzystujące standardowe templejty ZF, tj. pliczki ze wstawkami kodu PHP). Ich obsługą w kontrolerach zajmował się helper uruchamiany w init() i postDispatch(). Bardzo proste i efektywne rozwiązanie - gdy wszelkie oprzyrządowanie było ustawione (przez mechanizmy ZF), tworzenie konkretnych stron z komponentami to była kwestia tworzenia pliku layoutu, napisania ewentualnie komponentu oraz templejta jakim prezentuje wynik swojej pracy. Skrypty kontrolerów poza tymi przyjmującymi dane z formularzy, to tylko proste klasy dziedziczące po bazowej, zawierające puste metody odpowiadające poszczególnym akcjom. To powstało przy okazji realizacji zamówienia kolegi na kilka mniejszych stronek i świetnie się sprawdziło. Ninjutsu, interaktywna część strony konkursowej ucha van gogha i kilka eksperymentów działa na nim w pełni sprawnie.

Teraz siedzę, rozpływam się w zachwytach wobec Django, ale brakuje mi tego rozwiązania. Nie chcę zawartości poszczególnych podstron definiować w kodzie pythonowym. Chciałbym móc layouty generować też dynamicznie z jakiegoś prostego designera, a to moja idea komponentów umożliwiłaby jak najbardziej. No cóż. zuber z blipa mi dał znać, iż tego typu mechanizmy nie sprawdziły się we frameworkach ery "Web 2.0", ale ja jestem chyba starej daty. W końcu jeśli to jest dla mnie ekstremalnie wydajne w tworzeniu, bardziej elastyczne i atrakcyjne od dziedziczenia szablonów Django, nie będę trzymał się sztywno MVC, MTV czy innych trzyliterowców nowego stulecia. ;)

A może jednak czegoś do końca nie zrozumiałem? Może w podobnie elastyczny sposób można to zrobić w domyślnej implementacji Django? Jak Ty to robisz, drogi Czytelniku? :)

wtorek, 29 kwietnia 2008

Scarlet - "serial"

Przykład tego że wirusowy marketing wymknął się spod kontroli. Już po trailerze widać, że jest to reklama ... czegoś. Na pierwszy rzut oka perfumy, a może telewizory? Się okaże już bardzo niebawem.

Marketingowców proszę o wymyślenie już czegoś innego, bo od czasów Heyah zrobiło się tego zdecydowanie za dużo. Niedługo sytuacja będzie przypominała jeden z odcinków "Simpsonów" - "Lisa the Skeptic"...

Natomiast tym postem pokazałem, że kampania działa. :/ Brawo, kolejna wygrana marketingowców.

środa, 2 kwietnia 2008

Urodzonego Windowsiarza zachwyty nad Mac OS X ;)

W ciągu ostatnich paru miesięcy rodziła się u mnie potrzeba zmiany wysłużonego Thinkpada R50e na coś nowszego. Ponieważ od dawna kusiło mnie skosztowanie także nadgryzionego jabłka, wziąłem pod uwagę produkty urodzone w Cupertino. Coś małego, zgrabnego, nie z telebimem 15,4", nie z pocztówką 12", ale coś pośrodku, koniecznie panoramicznego, to to, co znalazłem pod postacią MacBooka.
Dodatkowo czysto technologiczny aspekt systemu operacyjnego, napędzającego te maszynki, pożądanie nieco odpoczynku od naleciałości z czasów Windows 95, braku porządku i jednolitości w systemach Microsoftu (co prawda w pełni użytecznych i sprawdzających się w zadaniach jakie się im powierzy, bez dwóch zdań!) skusiły mnie by posmakować "białej" strony mocy.
Na kilka dni wszedłem sobie więc w światek Mac OSa, choć nie rzuciłem się na głęboką wodę i nie kupiłem maczka licząc że będzie wszystko dobrze i się szybko pozbieram. Szkoda że nie ma żadnej legalnej możliwości zapoznania się przez kilka dni z tym systemem, coś na zasadzie wypożyczenia na próbę. Postanie chwilę nad makówką w iSpocie nie daje niestety za wiele, gdy chcemy sobie taki system pod siebie skonfigurować, doinstalować niezbędne aplikacje, dołączyć ulubiony sprzęt i spróbować po prostu pożyć z nowością. Przecież nie pójdę do najbliższego salonu ze swoją myszką, klawiaturą, tabletem, pilotem, płytą z narzędziami, sterownikami, wymagać jeszcze by dali się przez parę godzinek pobawić, poinstalować co się żywnie podoba, pogadać ze znajomymi na google talk i jabberze, posłuchać muzyczki, obejrzeć jakiś film, popróbować wygaszacze, tapety i pośmigać w terminalu po systemie plików zapoznając się przy okazji z dokumentacją techniczną Mac OS i Darwina. A co jeśli mi się nie spodoba system na w ciemno zakupionym, jedynym legalnie działającym z Leopardem sprzęcie? Zainstaluję sobie jeszcze na parę miesięcy Windows, by oszczędzić sobie całkowitego biegania po omacku? A może ów sprzęt jest wolny i nie spełni oczekiwań? Co wtedy?
Jedynym sposobem było pobrać pierwszy lepszy build Leosia dla "hackintoshy" i zainstalować na moim sprzęcie, który przypomina nieco hybrydę kilku generacji iMaków i Maków Pro - procesor Core 2 Duo E8200 (2,66 GHz), płyta główna Gigabyte z chipsetem P35 (model P35C-DS3R), ALC 889 generujący dźwięk, gigabitowa sieć na pokładzie i poczciwa GeForce 6600GT w slocie PCI Express, pamięci Corsair 2x1GB (CL4), a kontroler SATA (ICH9R) obsadzony dyskiem Seagate 7200.10 250GB i napędem Asus DVD+/-RW.
To była dobra decyzja. Przestawienie się całkowite może być nieco trudniejsze niż myślałem. Owszem, system jest świeższy, ładniejszy, schludniejsza i bardziej elegancka architektura, pracy towarzyszy nieporównywalna innowacyjność i nowoczesność nawet w porównaniu z Vistą na każdym kroku, do tego w 20 sekund system w pełni gotowy do pracy przy pełnym bootowaniu, a pełny shut down w 3-5 sekund (tryby uśpienia na wersji "hack os x" ;) którą testuję jeszcze nie działają, ale to już poprawiono w nowszych). Dawno czegoś takiego nie widziałem!
Potęguje to moje wrażenie, że Microsoft brodzi po pas w zaszłościach historycznych Windows, by zachować kompatybilność kosztem tej swobody i szansy na zupełnie świeży start, którą dał sobie Apple tworząc Mac OS X.
Jednak lata nawyków (choćby intensywne wykorzystywanie kombinacji ctrl-lewo/prawo, ctrl-shift-lewo do przeskakiwania co słowo, ctrl-backspace do kasowania tegoż, czy podobnych szczegółów, bardzo przydatnych w pracy programistycznej) trudno jest przezwyciężyć, a mając przed sobą skończenie magisterki, wolę dwa miesiące przed obroną nie wchodzić w zupełnie nowe środowisko i sobie to przejście zorganizować po uzyskaniu tytułu.
Co ciekawe widać że nawet napisanie sterowników dla Maca to dla producentów sprzętu pestka w porównaniu z Windows. Już od miesięcy widać na forach Wacoma, że coś niedobrego się dzieje z pracą Windows z tabletami (m.in. Bamboo One), sam Wacom nie do końca wie co, sugeruje różne śmieszne rozwiązania, jak wyłączenie bootowania z usb w biosie. Pod makówką zainstalowałem najnowszy sterownik i wszystko chodzi bezproblemowo - "boom" po Steve-owemu. ;)
Podobnie z Bluetooth - nie ma chyba w makowym światku zmartwień o to, z którym oprogramowaniem dla sterowników dongla USB (tj. z którym stosem bluetooth) zadziała to czy tamto. Pod Windows trzeba się nagimnastykować, by system dogadał sie z Wiimote. Pod "makówką" ściągnąłem Darwiinremote, sparowałem pilota z komputerem, uruchomiłem aplikację i już miałem w pełni funkcjonalny Apple Remote, a widoki czujników ruchu zaczęły żywo odzwierciedlać oddziaływanie grawitacji na położenie zabawki.
Z innych "pierdół" - zachwycił mnie Mail. Tak prosta, a jakże przydatna rzecz, jak podświetlanie powiązanych wiadomości pocztowych - nie zawsze wygodny jest widok drzewka wiadomości, to jest ogromnym ułatwieniem, gdy chcemy znaleźć poprzednie wiadomości z dyskusji. Widać, że Thunderbird i Firefox są w dużej mierze wzorowane na makowych aplikacjach. Teraz gdy się z tymi nieco zapoznałem, widzę uderzające podobieństwa.
Natomiast jest inna, chyba ważniejsza od tego cecha Mac OS X - niesamowita spójność na każdym kroku. Zarówno skróty klawiszowe, te dobrze znane i wspólne dla wszystkich aplikacji, jak i przede wszystkim wygląd oraz funkcjonowanie oprogramowania. W Windows nawet wygląd menu różnić się może od aplikacji do aplikacji, ponieważ poza standardowymi, czysto tekstowymi wersjami menu, które oferuje Microsoft w "czystym" Win32, są jeszcze menu oferowane przez MFC (w tym imitacja Ribbon w najnowszej wersji biblioteki), kilka innych w WTL, a i Windows Forms oferuje przynajmniej dwa swoje style, oczywiście programista może i swoje malować - nie ma problemu (za jedno trzeba Windows pochwalić - ogromna elastyczność systemu, dosłownie wszędzie się można wpiąć i w pełni kontrolować, jednak te możliwości obecnie wykorzystują głównie twórcy spyware, wirusów i trojanów ;) ). Do tego w Windows Vista dochodzi jeszcze nowe (choć ciekawe) rozróżnienie menu na aplikacje "standardowe" i multimedialne. W tych drugich odchodzi się od standardowego menu i dąży bardziej ku przedstawieniu czegoś na kształt Ribbona z Office 2007. Pod Mac OS X wszędzie jest dokładnie tak samo i w dokładnie tym samym miejscu - w górnej belce systemowej. Pomiając też menu, każda aplikacja wygląda niemalże identycznie, tj. ten sam zestaw widgetów, te same rodzaje okien narzędziowych, dialogowych, pomocniczych. Aż przyjemnie popatrzeć i nie gubić się poznając nową aplikację. Mógłbym oczywiście rozpisywać się na temat innych elementów, które mi się tak podobają, ale to nie czas i pora. Póki jestem bardzo świeży, póki mnie nic w OS X nie ukąsiło, lepiej poczekać i na chłodno opisać wrażenia z pracy z systemem za parę miesięcy. Raczej na pewno kontynuację spłodzę na makówce. Na pewno jednak nie wydam 600 zł za rozszerzenie pamięci do 2GB. ;)

sobota, 15 marca 2008

HTTPS, Firefox 3 i użyteczność

Od paru tygodni używam na co dzień najświeższych buildów Firefoksa 3 i o ile nie mam większych problemów, podobają mi się usprawnienia, ulepszenia, coraz większa liczba działających dodatków (najważniejszy Hide Menubar ;) ), to mam pewną obawę.

Spora liczba sklepów internetowych (iSpot jako pierwszy z brzegu), stron nawet rządowych czy samorządowych, w przypadku lokalizacji szyfrowanych, używa niekwalifikowanych certyfikatów SSL. Widząc ile problemów mają niezbyt zaawansowani użytkownicy w przypadku odwiedzania ich w Internet Explorerze 7 (i wkrótce 8), gdzie dostają na twarz stronę wyglądającą dla nich jak błąd, przeszkodę której nie da się obejść bez "informatyka", wyobrażam sobie chaos w "erze" Firefoksa 3.

Ten nie pozwala po prostu kliknąć "Kontynuuj przeglądanie strony" (czy jakkolwiek to brzmi w polskiej wersji językowej).

Użytkownik musi przebrnąć przez masę ostrzeżeń, magicznych terminów jak certyfikat bezpieczeństwa, certyfikat samopodpisany, jeszcze mniej zrozumiały kod błędu, coś o konfiguracji serwera ("jakiego serwera, chcę po prostu wejść na stronę"), by dojrzeć na końcu link do czegoś, co brzmi jak rozwiązanie ostateczne, bardzo niebezpieczne (w zasadzie takie jest w pewnych przypadkach). Po kliknięciu w tę opcję pojawia się jeszcze jedno ostrzeżenie, że nie powinienem dodawać wyjątku, pod warunkiem że całkowicie ufam swojemu połączeniu internetowemu ("ale tepsie nie można ufać!").

Powiedzmy że jakiś wytrwały internauta, szukający sklepów w ulubionym ceneo, przebrnął przez te ostrzeżenia, jest odważny i zdeterminowany. Co dalej? Nowe okno z jeszcze większą ilością ostrzeżeń, żółtych wykrzykników, "pobierania certyfikatów", "nieznanych tożsamości" i przycisk "Potwierdź wyjątek bezpieczeństwa". O Boże, oby o 6 rano nie wdarli się z nakazem! Dobra, żyje się raz - tak okazyjnie blendera nie przepuszczę! Klik - i jesteśmy na stronie. Gratulacje! ("te komputery są takie skomplikowane")

Team Firefoksa naprawdę potrzebuje ludzi z Humanized.

środa, 12 marca 2008

IE 8 - panning hand

W IE8 trafiłem na ciekawą funkcję, mianowicie Panning Hand - nie wiem czy ona występuje tylko gdy system ma włączoną funkcjonalność Tablet PC, ale jeśli ją Microsoft dopracuje do czasu finalnego wydania IE 8, że można będzie w wygodny sposób przełączać między panning hand i zaznaczaniem tekstu, będzie to genialna opcja dla posiadaczy wszelkich urządzeń z dotykowym ekranem lub użytkowników tabletów (sam mam Bamboo One). Korzystałem jakiś czas z wtyczki Grab and drag dla firefoksa, ale stała się bardzo irytująca - za dużo klikania by przełączać między tymi trybami.

A polega ona na tym, że jeśli na dowolnej otwartej stronie WWW przytrzymamy przycisk myszy na elemencie nie będącym linkiem, możemy przesuwać i przewijać stronę we wszystkich kierunkach w bardzo naturalny sposób, bez użycia pasków przewijania czy rolki myszy. Vistowe flicks owszem da się wykorzystać do przewijania strony, tylko każde takie machnięcie musi być dokładne i dość gwałtowne, a nie wiem jak długo końcówka piórka tabletu to wytrzyma przy dłuższym przewijaniu. :)

O, właśnie "odkryłem", że ta opcja jest dostępna w Viście także w IE 7, tylko, jak zasugerowałem, wyłącznie w sytuacji, gdy działa podsystem Tablet PC, tj. w systemie jest zainstalowane urządzenie "piórkowe", jak tablet czy ekran dotykowy zgodny z Tablet PC. Popsuli mi satysfakcję z odkrycia! ;)

niedziela, 9 marca 2008

Głupoty w necie

Niezwykle namolny problem (z xkcd). :) Ilekroć się chcę odciąć od czytania komentarzy pod newsami, gdyż wiem że 80% z nich to pyskówki, wypowiedzi ludzi którzy mają znikome pojęcie o kwestii komentowanej (vide pclab.pl), to prawie zawsze wchodzę sprawdzać właśnie to, czy ktoś owe głupoty napisał. I niestety za każdym razem czuję się w obowiązku prostować, korygować, by ktoś kolejny raz nie wyrażał opinii "zapożyczonych" z innych miejsc w internecie, tylko bazował na swoich doświadczeniach i własnej wiedzy, o ile to możliwe. Jeśli jednak możliwe to nie jest, może po prostu lepiej nie odzywać się? Ach, to by było za proste, w końcu to jest właśnie internet.
Trzeba bardzo uważać, by uniknąć problemu "wypalenia", opisywanego kiedyś choćby przez autora VirtualDub. Musi być na niego gotowa każda osoba, która chce się w internecie ujawnić z jakąkolwiek twórczością, inicjatywą - wszystko, co może się spotkać z opinią.
Zatem: Ostrożnie, Internet!