Proszę o małą poradę - sugestię

0

Dzień Dobry

Jest to mój pierwszy post na forum, ale to chyba widać po lewej :)

Aktualnie piszę serwer HTTP, aczkolwiek pytanie moje dotyczy części związanej z konfiguracją samego serwera. Serwer sam w sobie jest daemonem działającym po cichu w tle i jak przy tego typu oprogramowaniu, ciekawym zagadnieniem jest zapewnienie sposobu bycia na bieŻąco (Boże, widzisz takie błędy i nie grzmisz) z konfiguracją.

I szukam właśnie pomysłu na zaimplementowanie takiego modułu, który pozwalałby serwerowi automatycznie rekonfigurować się w locie.

Obecnie, popularnym rozwiązaniem stosowanym np. w Apache'u jest manualnie wysyłanie sygnału USR1 do głównego procesu serwera, na co program odpowiada właśnie ponownym wczytaniem konfiguracji.

Ja jednak chcę to zrealizować inaczej, ponieważ zależy mi na zrezygnowaniu z plików tekstowych na rzecz narzędzi konfiguracyjnych i jednocześnie chcę zaimplementować możliwość wprowadzania zmian w locie z pominięciem plików konfiguracyjnych.

Ta ostatnia funkcjonalność jest niezbędna, gdyż serwer może działać w trybie developerskim (dla piszących strony), który jest niezależny od trybu usługi - czyli jest kolejną instancją serwera.

Zastanawiam się więc nad stworzeniem usługi konfiguracji serwerów, która to działając w tle umożliwiałaby konfigurację wszystkich aktywnych oraz nieaktywnych serwerów.

Czy uważacie to za dobre rozwiązanie? I przede wszystkim bezpieczne?

Ewentualnie czy macie jakieś inne propozycje - lub moglibyście coś dodać od siebie?

W jaki sposób proponowalibyście realizowanie takich konfiguracji? :)

0
mf napisał(a)

Ja jednak chcę to zrealizować inaczej, ponieważ zależy mi na zrezygnowaniu z plików tekstowych na rzecz narzędzi konfiguracyjnych i jednocześnie chcę zaimplementować możliwość wprowadzania zmian w locie z pominięciem plików konfiguracyjnych.

Ta ostatnia funkcjonalność jest niezbędna, gdyż serwer może działać w trybie developerskim (dla piszących strony), który jest niezależny od trybu usługi - czyli jest kolejną instancją serwera.

A po co developerom stron możliwość grzebania w konfiguracji serwera? To jakis specjalizowany system, czy dałeś się zbałamucić developerom? ;)

mf napisał(a)

Zastanawiam się więc nad stworzeniem usługi konfiguracji serwerów, która to działając w tle umożliwiałaby konfigurację wszystkich aktywnych oraz nieaktywnych serwerów.

Konfiguacja ma się opierać dalej na plikach, czy będzie wstrzukiwana do serwerów jakimś protokołem? Jeśli to pierwsze i Ty piszesz serwer, to zwróć uwagę na rozwiązania typu inotify. Jeśli to drugie, to nie rozumiem problemu.

mf napisał(a)

Czy uważacie to za dobre rozwiązanie? I przede wszystkim bezpieczne?

Dobre? Nie. Developer nie powinien mieć praw do rekonfigurowania serwera (o ile nie jest to jakiś specjalizowany system).
Bezpieczne? To zależy już od Ciebie.

mf napisał(a)

Ewentualnie czy macie jakieś inne propozycje - lub moglibyście coś dodać od siebie?
W jaki sposób proponowalibyście realizowanie takich konfiguracji? :)

Zazwyczaj dynamiczną konfigurację robi się z wykorzystaniem baz danych (SQL, LDAP). Z ustawieniami typu parametry wirtualki, jakieś rewrite'y itp. nie ma problemu, gdyż te dane są odczytywane na bieżąco. Schody się zaczynają np. przy zmianach adresów IP i portów, na których serwer nasłuchuje (trochę roboty przy przebindowywaniu) czy lokalizacji plików serwera (.pid, pamięć podręczna itp). Nie widziałem żeby ktoś się w to bawił i zwykle takie zmiany wchodzą w życie po restarcie serwera.

0

Instancja developerska jest procesem działającym na prawach użytkownika, który go uruchomił i nie jest forkowalna.
To z jednej strony ekwiwalent wbudowanego serwera w Ruby On Rails (do późniejszych identycznych zastosowań), a także do testowana wydajności pisanej strony i symulowania obciążeń.

Instancja developerska jest więc stricte "desktopowa" - ale nie produkcyjna.

Inna kwestia to to, że serwer HTTP nie jest wynikiem nudów :)
Jest to program hybrydowy, który może działać jako super-tiny http server, ale też rozbudowana instalacja dzieląca obciążenie na wiele instancji na innych fizycznych serwerach.

Właśnie dlatego niezbędna jest rekonfiguracja onfly.

INotify jest koruptogenny, gdyż mechanizm oparty o ten moduł jądra zakłada, że każda aktualizacja pliku wywołuje rekonfigurację całego środowiska objętego zmienionym plikiem. Zmiana jednak musi być dokonana wyłącznie na żądanie. Dlatego bardziej skłaniałbym się ku sygnałowi USR1 :)

Ale ciągle zastanawiam się nad daemonem a'la dbus :)

0
mf napisał(a)

Instancja developerska jest procesem działającym na prawach użytkownika, który go uruchomił i nie jest forkowalna.
To z jednej strony ekwiwalent wbudowanego serwera w Ruby On Rails (do późniejszych identycznych zastosowań), a także do testowana wydajności pisanej strony i symulowania obciążeń.

Skoro ten serwer działa na uprawnieniach usera, to user może sobie dowolnie zmieniać pliki konfiguracyjne. Może też go restartować i przeładowywać.
Nie wiem jak to jest zrobione w RoR, ale np. Paster (Python) przeładowuje tylko moduły (kontrolery są modułami pythonowymi) i to wszystko. Nie da się go zbytnio skonfigurować, a to co da się zmienić i tak wymaga restartu.

mf napisał(a)

Inna kwestia to to, że serwer HTTP nie jest wynikiem nudów :)
Jest to program hybrydowy, który może działać jako super-tiny http server, ale też rozbudowana instalacja dzieląca obciążenie na wiele instancji na innych fizycznych serwerach.

IMHO źle do tego podchodzisz. Serwer WWW ma tylko odpowiadać na żądania HTTP. Dzielenie obciążenia robi się nie w serwerze, lecz na revproxy takim jak haproxy, czy varnish. Czoło systemu nie powinno nigdy robić nic dodatkowego, co mogłoby spowodować jego awarię lub opóźnić obsługę połączeń, gdyż wtedy posiadanie wieloserwerowego zaplecza traci sens.

mf napisał(a)

Właśnie dlatego niezbędna jest rekonfiguracja onfly.

Może czegoś nie rozumiem, ale nie widzę tutaj żadnej potrzeby rekonfiguracji "onfly". Jeśli serwer WWW ma tylko serwować pliki statyczne, wyjście innych procesów (CGI), czy odpalać moduły (WSGI, PHP, ...), to developerzy nie mają potrzeby dłubać w jego konfiguracji. Specyficzne ustawienia "pozaserwerowe" można obsłużyć tak, jak robi to Apache (pliki .ht*), zaś dynamiczną konfigurację wirtualek tak jak np. Lighttpd (wirtualki oparte na katalogach). Do ustawień stricte serwerowych developer dostępu nie potrzebuje.
Jeśli zaś content jest zespawany w serwerze HTTP, to i tak jakakolwiek zmiana wymaga rekompilacji i restartu (piszesz w dziale C/C++ więc zakładam, że chcesz go tworzyć w tym języku).

mf napisał(a)

INotify jest koruptogenny, gdyż mechanizm oparty o ten moduł jądra zakłada, że każda aktualizacja pliku wywołuje rekonfigurację całego środowiska objętego zmienionym plikiem. Zmiana jednak musi być dokonana wyłącznie na żądanie. Dlatego bardziej skłaniałbym się ku sygnałowi USR1 :)

Czym się różni z punktu widzenia użytkownika żądanie przeładowania konfiguracji jakimś Twoim mechanizmem od żądania przeładowania/restartu serwera sygnałem lub skryptem?

mf napisał(a)

Ale ciągle zastanawiam się nad daemonem a'la dbus :)

D-Bus fajna rzecz, ale IMHO overkill do tego zastosowania (chyba, że wykorzystasz go w pełni jako szynę IPC).
Potrzebujesz wykonać reload serwera, ale nie automagicznie tylko na żądanie usera. Takim żądaniem jest wysłanie sygnału SIGUSR1, albo wykonanie skryptu restartującego. Naprawdę nie wiem co chcesz osiągnąć tworząc jakieś nowe, skomplikowane rozwiązania.

Odnoszę wrażenie, że chcesz po prostu zrobić klikalny narząd do konfigurowania serwera WWW i chcesz mieć w nim przycisk "przeładuj konfigurację". To nie jest "onfly" i z pewnością nie wymaga rezygnacji z plików konfiguracyjnych. Narząd może je generować, a przycisk wysyłać sygnał SIGUSR1. To jest rozwiązanie proste i odpowiednie. Jakiś plik konfiguracyjny przecież i tak musisz tworzyć, bo nie sądzę żebyś chciał zmuszać usera do wklepywania wszystkich ustawień na nowo po każdym starcie serwera.
Zobacz jak to jest robione np. w windowsowym porcie Apache, który ma taki klikalny narząd.

0

Czym się różni z punktu widzenia użytkownika żądanie przeładowania konfiguracji jakimś Twoim mechanizmem od żądania przeładowania/restartu serwera sygnałem lub skryptem?

No niby się różni.
Chcę, aby np. wirtualne hosty były dodawane onfly, co nie wymga rekonfiguracji aktywnych instancji. Sygnał nie może powiedzieć, co przeładować. Skrypt natomiast domniemam, że używałby finalnie właśnie sygnału.
Poprzez mechanizm będący ekwiwalentem dbusa, można byłoby szarpnąć się o bardziej złożone rządania, które byłyby już precyzyjne :)

Co prawda (teraz w sumie pomyślałem o tym), można by zastosować właśnie sygnał. Wystarczy przygotować skrypt, który generowalby dodatkowy plik informacyjny (serv-update vhost nowy1) i on w pierwszej kolejności byłby wczytywany przez serwer po otrzymaniu wspomnianego sygnału.

Wracając jeszcze do INode. Dobrze zaprojektowane pliki konfiguracyjne, pozwalają na wydzielanie dowolnych aspektów konfiguracji pomiędzy różne pliki. Ot, chociażby dla przejrzystości. Jeżeli założymy obecność takiej cechy, zmiana w każdym pliku wywoła rekonfigurację, pomimo iż cały proces zmian ustawień nie dobiegł końca, gdyż wymaga edycji jeszcze kilku.

Piszę w C. Oba wspomniane tryby serwera są dwoma innymi programami, wykorzystującymi wspólną bibliotekę, która w rzeczywistości dostarcza funkcje serwerowe. Przy okazji kompilacja produkcyjna pozbawiona jest kilku jej zbędnych, dodatkowych bibliotek jeszcze na poziomie dynamicznego linkowania (np. obsługi argumentów przesyłanych z linii poleceń).

Trzeba również zaznaczyć, że omawiany problem jest bardziej związany z moim pedantycznym podejściem do programowania. I nie rozchodzi się o wewnętrzną potrzebę stworzenia wyczesanego oprogramowania, a o znalezeinie najbardziej optymalnego rozwiązania, który oprócz pełniania swojej roli dawałby jeszcze wiele możliwości na potem.

0
mf napisał(a)

Chcę, aby np. wirtualne hosty były dodawane onfly, co nie wymga rekonfiguracji aktywnych instancji. Sygnał nie może powiedzieć, co przeładować. Skrypt natomiast domniemam, że używałby finalnie właśnie sygnału.

IMHO nadmierna kombinacja. Zobacz jak robi to Lighttpd. Tam możesz sobie skonfigurować, że root wirtualki znajduje się w katalogu /gdzieś/kiedyś/tld/1lvl/2lvl, np. foo.example.org jest w /gdzieś/kiedyś/org/example/foo. Dodanie nowej wirtualki sprowadza się do utworzenia odpowiedniego katalogu. Nic nie musisz przeładowywać. Jeśli rozłożenie wartości nagłówka Host nie rozwinie się na istniejący katalog, serwujesz domyślną/pierwszą wirtualkę, lub zwracasz 40*.

mf napisał(a)

Poprzez mechanizm będący ekwiwalentem dbusa, można byłoby szarpnąć się o bardziej złożone rządania, które byłyby już precyzyjne :)

OK, to może uściślijmy jakie parametry konfiguracyjne chcesz zmieniać.

mf napisał(a)

Co prawda (teraz w sumie pomyślałem o tym), można by zastosować właśnie sygnał. Wystarczy przygotować skrypt, który generowalby dodatkowy plik informacyjny (serv-update vhost nowy1) i on w pierwszej kolejności byłby wczytywany przez serwer po otrzymaniu wspomnianego sygnału.

Idziesz w dobrym kierunku, ale nadal nie rozumiem potrzeby wczytywania jakiegoś specjalnego pliku. Czy nie to samo uzyskasz zmieniając plik konfiguracyjny wirtualek?
Konfiguracja serwera powinna być spójna. Co z tym plikiem po przeładowaniu konfiguracji? Co ze zmianami w nim zapisanymi, w jaki sposób zostaną one naniesione na właściwe pliki konfiguracyjne?

mf napisał(a)

Wracając jeszcze do INode. Dobrze zaprojektowane pliki konfiguracyjne, pozwalają na wydzielanie dowolnych aspektów konfiguracji pomiędzy różne pliki. Ot, chociażby dla przejrzystości. Jeżeli założymy obecność takiej cechy, zmiana w każdym pliku wywoła rekonfigurację, pomimo iż cały proces zmian ustawień nie dobiegł końca, gdyż wymaga edycji jeszcze kilku.

Inotify to nie jest automat restartujący. Jak sobie jego obsługę napiszesz, tak będziesz miał. On Cię tylko poinformuje, że coś się zmieniło.

mf napisał(a)

Piszę w C. Oba wspomniane tryby serwera są dwoma innymi programami, wykorzystującymi wspólną bibliotekę, która w rzeczywistości dostarcza funkcje serwerowe. Przy okazji kompilacja produkcyjna pozbawiona jest kilku jej zbędnych, dodatkowych bibliotek jeszcze na poziomie dynamicznego linkowania (np. obsługi argumentów przesyłanych z linii poleceń).

Tylko nie przesadź z tym wycinaniem niepotrzebnych (Twoim zdaniem) funkcji... np. parsowania argumentów wywołania, które akurat jest dość potrzebne na produkcji :)

mf napisał(a)

Trzeba również zaznaczyć, że omawiany problem jest bardziej związany z moim pedantycznym podejściem do programowania. I nie rozchodzi się o wewnętrzną potrzebę stworzenia wyczesanego oprogramowania, a o znalezeinie najbardziej optymalnego rozwiązania, który oprócz pełniania swojej roli dawałby jeszcze wiele możliwości na potem.

No to tym bardziej powinieneś się trzymać plików konfiguracyjnych. Sygnały to jest eleganckie rozwiązanie, nie toporny mechanizm, który trzeba zastąpić czymś "nowocześniejszym". Pamiętaj też o biednym administratorze, który później będzie musiał się z Twoim serwerem użerać. On potrzebuje konfiguracji, którą da się hurtowo zmienić sed'em, awk'iem i grepem oraz przeładowywania konfiguracji sygnałami, bo na serwerach wszystko jest zautomatyzowane i bezobsługowe. U mnie np. mógłbyś zapomnieć o instalacji demona D-Bus na produkcji, czy uruchamianiu serwera WWW, któremu nie można w argumencie wywołania wskazać lokalizacji plików konfiguracyjnych i którego trzeba przeładowywać jakimiś wynalazkami nieprzystającymi do reszty systemu :)

Ok, rób jak chcesz. Według mnie ten pomysł jest zły, a proponowane przez Ciebie zmiany są niepotrzebne i nadmiernie całość komplikują. Nie przekonałeś mnie niczym co do zasadności Twojego rozwiązania, więc nic więcej do dyskusji nie jestem w stanie wnieść :)
Moja rada jest taka: zanim zaczniesz wymyślać mechanizmy porozmawiaj z jakimś developerem oraz administratorem, bo to dla nich ma być ten serwer, a nie dla Twojej samorealizacji :)

0

Idziesz w dobrym kierunku, ale nadal nie rozumiem potrzeby wczytywania jakiegoś specjalnego pliku. Czy nie to samo uzyskasz zmieniając plik konfiguracyjny wirtualek?

Właśnie chodzi o to, że zmieniałoby się pliki konfiguracyjne, ale informowało, którą tylko część przeładować. Taki plik w pierwszym zamyśle tworzony byłby przez skrypt, np. w /var, i usunięty przez serwer po odczytaniu.

Obmyśliłem jednak inny sposób i jego się będę trzymać.
Konfigurowanie serwera odbywać się będzie z plików konfiguracyjnych, jednak przechowywana będzie w plikach binarnych. Po edycji plików, wywołać będzie trzeba program serv-update.
Eliminuje to w oprogramowaniu produkcyjnym zbędny kod parsowania plików konfiguracyjnych, co zmiejszy podatność na luki.
Serv-update kończyłby przebudowę pliku binarnego (nie chodzi o wykonywalny) sygnałem USR1.
W pliku konfiguracji byłoby miejsce na informowanie o zmianach w stosunku do poprzedniej konfiguracji.

Tym samym serv-update może być dostarczany przez paranoidalnych adminów z przenośnego nośnika danych, np. USB Stick :D, kompletnie eliminując jego fizyczną obecność w serwerowym systemie plików :)

Pomysł z katalogami org/ia/www mi się spodobał :)
Dobry pomysł na wtyczkę. Dzięki :)

0
mf napisał(a)

Konfigurowanie serwera odbywać się będzie z plików konfiguracyjnych, jednak przechowywana będzie w plikach binarnych.

Rejestr systemu Windows jest znakomitym przykładem na to, jak chybionym pomysłem jest konfiguracja w plikach binarnych (pomimo, że sama koncepcja centralnego rejestru jest udana). Dodatkowo, pliki binarne skutecznie utrudniają wersjonowanie konfiguracji. Poprzez komplikowanie wszystkiego czynisz administrowanie tym niewiarygodnie uciążliwym :)

mf napisał(a)

Eliminuje to w oprogramowaniu produkcyjnym zbędny kod parsowania plików konfiguracyjnych, co zmiejszy podatność na luki.

Czyli Ci się nie chce pisać parsera ;)
BTW, jest coś takiego jak yacc i bison.

mf napisał(a)

Tym samym serv-update może być dostarczany przez paranoidalnych adminów z przenośnego nośnika danych, np. USB Stick :D, kompletnie eliminując jego fizyczną obecność w serwerowym systemie plików :)

Jestem pod wrażeniem Twojej determinacji utrudnienia pracy administratorom, ale boję się że nigdy nie miałeś do czynienia z serwerami. Funkcja wczytywania konfiguracji z pendrive jest bezużyteczna. Po pierwsze, serwery często są daleko od miejsca przebywania administratora (ja swoje serwery mam w Paryżu, a siedzę w Warszawie). Po drugie, serwery rekonfiguruje się zdalnie, nie siedząc przy maszynie fizycznie (w serwerowniach jest naprawdę zimno i głośno). Po trzecie, w niektórych firmach administrator systemu nie ma fizycznego dostępu do maszyn, ani przepustki do serwerowni. Po czwarte, nikt nie będzie co chwila biegał z pendrivem do serwerowni przy tuningowaniu konfiguracji. Po piąte, konfiguracja MUSI BYĆ DOSTĘPNA PRZEZ CAŁY CZAS DLA PROCESU SERWERA, gdyż maszyna może się np. zrestartować, albo może się okazać konieczne wymuszenie restartu (maszyny lub procesu serwera). Nie skorzystałeś z mojej rady, żeby najpierw porozmawiać z jakimś administratorem, a wychodzi na to, że nie masz zielonego pojęcia o zarządzaniu takimi rzeczami. Stąd prawdopodobnie wynikają te bardzo złe pomysły, które próbujesz zaimplementować.

mf napisał(a)

Pomysł z katalogami org/ia/www mi się spodobał :)
Dobry pomysł na wtyczkę. Dzięki :)

To nie mi dziękuj, tylko twórcom Lighttpd :)
Powinieneś brać z nich przykład i rozwiązywać problemy w sposób prosty, elastyczny i umożliwiający łatwą kontrolę i zarządzanie. Binarne pliki konfiguracyjne, D-Bus itp. idą w przeciwnym kierunku. Jeśli piszesz serwer dla siebie to spox, życzę Ci jak najlepiej. W przeciwnym wypadku odradzam i zapewniam, że Twoje rozwiązania nie spotkają się z entuzjazmem ludzi, którzy będą musieli tym zarządzać :)
Poczytaj o KISS.

0

Nie doczytałeś chyba dokładnie tego co napisałem.

Parser zostaje wyeliminowany z programu serwera, ale staje się częścią programu serv-update.
Administrator konfiguruje pliki tekstowe (jak w apache), które właśnie przez parser w serv-update są zapisywane w postaci binarnej.
Serwer od razu dzięki temu dostaje gotową konfigurację i nie jest narażony na zbędny kod.

Czytaj uważniej :)

No i jeszcze kwestia zdalnego dostępu.
Wyraźnie napisałem, że pendrive jest opcją dla paranoidalnego admina, a paranoidalny admin ma dostęp fizyczny, bo paranoidalnie unika zdalnej administracji.
Ba, opcja z tworzeniem USB Stick nie jest wymysłem, tylko efektem ubocznym dobrego pomysłu, który daje po prostu sporo możliwości, a nie tylko realizuje ciasne założenia.

Czepiasz się jakbym Twoje frydki z talerza wyjadał :)

Edit3 - proces edycji:

# nano /etc/server/config.conf
# serv-update
server: rebuilding configuration on fly...
server: done
0
mf napisał(a)

Parser zostaje wyeliminowany z programu serwera, ale staje się częścią programu serv-update.
Administrator konfiguruje pliki tekstowe (jak w apache), które właśnie przez parser w serv-update są zapisywane w postaci binarnej.
Serwer od razu dzięki temu dostaje gotową konfigurację i nie jest narażony na zbędny kod.

Jaki jest cel tego?
W jaki sposób takiego binarnego BLOBa wstrzykniesz do serwera?
Jaki to ma związek z lukami bezpieczeństwa?
W jaki sposób chroni to przed lukami bezpieczeństwa?
Żeby wykorzystać błędy w parserze konfiguracji atakujący musiałby mieć dostęp do samej konfiguracji i możliwości jej przeładowania. Oznacza to, że już musiałby być w systemie na prawach roota, zatem ma pełny dostęp do wszystkiego i nie potrzebuje wykorzystywać luk w serwerze.

0
mf napisał(a)

Czepiasz się jakbym Twoje frydki z talerza wyjadał :)

Prosiłeś o radę.

mf napisał(a)

Edit3 - proces edycji:

nano /etc/server/config.conf

serv-update

server: rebuilding configuration on fly...
server: done


Nie widzę różnic między tym a:

vim /etc/serwer/konfiguracja.conf

service serwer reload

0
Kumashiro napisał(a)
mf napisał(a)

Czepiasz się jakbym Twoje frydki z talerza wyjadał :)

Prosiłeś o radę.

mf napisał(a)

Edit3 - proces edycji:

# nano /etc/server/config.conf
# serv-update
server: rebuilding configuration on fly...
server: done

Nie widzę różnic między tym a:

# vim /etc/serwer/konfiguracja.conf
# service serwer reload

Ja widzę. Twój sposób jest ograniczony do systemów linux.
Ja chcę zdominować caaaały świat hehe :D

Wyznaję starą zasadę, że im ważniejszy program tym ma mieć jak najmniej kodu. Ma być go tyle, aby realizować założenia, ale nic więcej. Parser to na prawdę spory zastrzyk, który po prostu wypada przenieść do innego programu.
Poza tym, błąd parsera jest bardziej prawdopodobny niż błąd obsługi binarek. Przy przeładowywaniu mogłaby się pewnego czasu ujawnić tendencja do złego adresowania i nadpisywania newralgicznych danych, które przypadkiem mu "stana na drodze".

Dostęp do konfiguracji jest non-stop.

0

Nie mam siły wyperswadowywać Ci tego dalej. Ja się poddaję. Powodzenia :)

0

Ej! Nie! Jeszcze nie zacząłem Cię obrażać :( Co to za zwycięstwo bez skakania sobie do gardeł? :(

A tak na serio, to się zobaczy w praktyce. Najwyżej zrzucę na Ciebie całą winę, za nieudolne próby wypersfadowania mi tego pomysłu :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1