rodzinal.pl — jak zbudowałem prywatną infrastrukturę dla rodziny na laptopie

Architektura self-hosted serwisów rodzinnych: Incus, WireGuard, HAProxy, Stalwart Mail, Nextcloud i Collabora — na ThinkPadzie P51 stojącym w domu.

rodzinal.pl to mój prywatny serwis rodzinny — poczta, chmura z edycją dokumentów, strona. Nie chciałem płacić za Google Workspace ani polegać na zewnętrznych dostawcach przy danych rodziny. Efekt: działający stack na laptopie ThinkPad P51 stojącym w domu, VPS we Francji jako punkt wejścia i failover przez kartę SIM.W tym artykule opisuję architekturę od sprzętu po routing, z uzasadnieniem każdej decyzji projektowej.Sprzęt — ThinkPad P51 jako serwer domowyLaptop nie był przypadkowy. ThinkPad P51 to stacja robocza w formacie laptopa:CPU: Intel Xeon E3-1505M (4 rdzenie, 8 wątków, 2.8–3.7 GHz)RAM: 32 GB ECCDyski:2× Samsung 970 Pro NVMe w RAID-1 — dane i kontenery500 GB SSD — system operacyjnyWbudowany adapter SIM — kluczowy element failoverŁączny koszt sprzętu (używany): ok. 2000 PLN jednorazowo. Zmierzone watomierzem zużycie w idle: 10W — jak mini-PC, dużo lepiej niż klasyczna wieża. Bonus: wbudowana bateria robi za UPS przy chwilowych przerwach prądu, a przy niskim obciążeniu wentylator się nie włącza.RAID-1 na NVMeDwa dyski NVMe w RAID-1 zapewniają ochronę przed awarią nośnika bez wpływu na wydajność odczytu. Dane /var/lib/incus (kontenery i wolumeny) są na tej macierzy.Obecnie: pełne szyfrowanie LUKS całych dysków. Docelowo planuję szyfrować tylko partycję z danymi Incusa (/var/lib/incus), a resztę systemu zostawić bez szyfrowania — żeby restart po awarii prądu nie wymagał ręcznego wpisywania hasła.Topologia sieciInternet │ ▼ [VPS — FR] ←────── WireGuard VPN ──────► [ThinkPad P51 — PL] HAProxy (zewnętrzny) HAProxy (ruch zewnętrzny) GeoIP filtering HAProxy (most między-kontenerami) Kontenery Incus ├── www (10.10.0.10) ├── cloud (10.10.0.20) ├── mail (10.10.0.30) ├── collabora (10.10.0.40) └── roundcube (10.10.0.50) VPS od Contabo we Francji (~28 PLN/miesiąc) to punkt wejścia. Ma stały publiczny IP i przekazuje ruch do laptopa przez tunel VPN. Laptop w domu ma dynamiczne IP od ISP — dlatego VPN jest kluczowy.WireGuard — prywatna sieć między VPS a domemWireGuard łączy VPS (FR) z laptopem (PL) w prywatną sieć 10.0.0.0/24. Każde żądanie do rodzinal.pl docierające na VPS jest przez tunel przekazywane do kontenera na laptopie.Dlaczego WireGuard:Mała powierzchnia ataku (krótki codebase w porównaniu do OpenVPN)Automatyczny reconnect po przerwieNiskie opóźnienia dzięki UDPProsta konfiguracja na kluczach publicznychVPS robi za koncentrator — nie trzyma żadnych danych, tylko przekazuje ruch.GeoIP filtering — ograniczenie geograficzne dostępuNa HAProxy (na VPS-ie) mam skonfigurowany filtr GeoIP. Ruch HTTPS wpuszczam tylko z czterech krajów:PL — Polska (dom)FR — Francja (lokalizacja VPS — potrzebne do wewnętrznych healthchecków)AT — Austria (część rodziny)IT — Włochy (część rodziny)Żądania z innych krajów są odrzucane na poziomie load balancera — HAProxy zamyka połączenie TCP, zanim ruch w ogóle dotrze do tunelu VPN czy kontenerów. To mocno ogranicza ekspozycję na skanery, boty i brute-force.HAProxy korzysta z bazy MaxMind GeoLite2 aktualizowanej automatycznie.HAProxy — trzy poziomy routinguHAProxy zewnętrzny (VPS)Sprawdza GeoIP i przekazuje cały ruch TCP do laptopa przez WireGuard. HAProxy na VPS-ie działa w trybie TCP — nie terminuje TLS, nie routuje po SNI. Używa PROXY protocol, żeby prawdziwy IP klienta dotarł dalej. Ruch zablokowany przez GeoIP jest odrzucany na poziomie TCP (zamknięcie połączenia).HAProxy wewnętrzny — routing ruchu zewnętrznego (laptop)Pierwszy serwis HAProxy na laptopie nasłuchuje na interfejsie WireGuard, odbiera ruch z VPS i routuje go po SNI do konkretnych kontenerów Incusa po ich wewnętrznych adresach IP (10.10.0.x). Działa w trybie TCP z PROXY protocol — kontener dostaje prawdziwy IP klienta, nie adres HAProxy. TLS obsługują same kontenery — każdy z publicznym endpointem (www, cloud, mail, roundcube) ma własny certyfikat Let's Encrypt i sam go odnawia. Collabora nie ma certyfikatu publicznego — działa tylko wewnętrznie i go nie potrzebuje.frontend https_in bind 10.0.5.2:443 accept-proxy mode tcp use_backend cloud_443 if { req.ssl_sni -i cloud.rodzinal.pl } use_backend mail_443 if { req.ssl_sni -i mail.rodzinal.pl } use_backend roundcube_443 if { req.ssl_sni -i m.rodzinal.pl } default_backend www_443 Dzięki temu kontenery nie mają bezpośredniego dostępu do internetu — cały ruch przychodzący przechodzi przez ten jeden punkt wejścia.HAProxy wewnętrzny — most między kontenerami (laptop)Drugi, osobny HAProxy robi coś zupełnie innego: jest mostem dla komunikacji między samymi kontenerami. Zamiast pozwolić kontenerom gadać ze sobą bezpośrednio po sieci Incusa, ruch między nimi przechodzi przez ten serwis.Przykład: Nextcloud musi wysłać powiadomienie e-mail — nie łączy się bezpośrednio ze Stalwartem na 10.10.0.30, tylko przez wewnętrzny most HAProxy. To samo dotyczy Roundcube komunikującego się ze Stalwartem przez IMAP/SMTP, czy Nextclouda łączącego się z Collaborą.Każde dozwolone połączenie między kontenerami jest jawnie zdefiniowane jako reguła. Jeśli kontener próbuje połączyć się z czymś, do czego nie ma reguły — ruch jest blokowany. Nawet kompromitacja jednego kontenera nie daje atakującemu swobodnego dostępu do pozostałych serwisów.Kontenery Incus — izolacja serwisówZamiast stawiać wszystko bezpośrednio na hoście, każdy serwis żyje we własnym kontenerze systemowym Incus. Incus to następca LXD — aktywnie utrzymywany projekt open source.KontenerIPSerwiswww10.10.0.10Strona rodzinal.plcloud10.10.0.20Nextcloudmail10.10.0.30Stalwart Mailcollabora10.10.0.40Collabora (LibreOffice)roundcube10.10.0.50Roundcube (webmail)Każdy kontener to oddzielny system plików i przestrzeń procesów. Awaria jednego serwisu (np. crash Nextclouda) nie wpływa na pozostałe. Aktualizacje można robić per kontener, bez zatrzymywania całości.Wolumeny z danymi są montowane do kontenerów z macierzy RAID-1.Stalwart Mail — serwer pocztowyStalwart to nowoczesny serwer pocztowy napisany w Ruście — SMTP, IMAP i JMAP w jednym procesie. W porównaniu do klasycznego Postfix+Dovecot, Stalwart ma:Wbudowaną obsługę SPF, DKIM, DMARCWeb UI do zarządzania kontamiNatywne JMAP (nowoczesny protokół synchronizacji poczty)Konfiguracja DNS obejmuje:Rekord MX wskazujący na VPSSPF i DKIM dla domeny rodzinal.plDMARC z raportowaniemPort 25 (SMTP) wychodzący jest odblokowany przez ISP — to często bywa problemem w sieciach domowych. Jednak nawet odblokowany port 25 nie wystarczy — wysyłanie poczty bezpośrednio z domowego IP skutkuje odrzucaniem wiadomości przez serwery odbiorców, bo adresy IP sieci domowych mają złą reputację u dostawców poczty.Rozwiązanie: reguła iptables dodana przez WireGuard kieruje cały ruch wychodzący na port 25 przez VPS we Francji. Stalwart wysyła wiadomość, ale połączenie do serwera odbiorcy wychodzi z IP VPS-a — czystego adresu z puli datacenter. Domowe IP w ogóle nie jest widoczne dla zewnętrznych serwerów pocztowych.Początkowo używałem portu 587 (SMTP z STARTTLS). Zmieniłem na 465 (SMTPS). Różnica jest istotna: STARTTLS na 587 zaczyna połączenie plaintextem i dopiero potem negocjuje szyfrowanie — teoretycznie możliwy jest atak downgrade wymuszający nieszyfrowane połączenie. Port 465 z implicit TLS szyfruje od pierwszego bajtu. Dla serwera rodzinnego, gdzie kontroluję konfigurację wszystkich klientów, 465 to prostszy i bezpieczniejszy wybór.Konta użytkowników i grupyKażda osoba w rodzinie ma własne konto w Stalwarcie — osobną skrzynkę pocztową i osobne dane logowania. Oprócz indywidualnych kont skonfigurowane są grupy dla wspólnych adresów e-mail (np. kontaktowy adres całej rodziny), na które wiadomości trafiają do wielu skrzynek jednocześnie.Stalwart jako dostawca tożsamościStalwart obsługuje OAuth2/OIDC — działa jako Identity Provider dla całego stosu. Nextcloud i Roundcube uwierzytelniają użytkowników przez Stalwarta.W praktyce: jedno konto = jeden login do poczty, chmury i webmaila. Użytkownik loguje się do Nextclouda tymi samymi danymi co do poczty — Nextcloud deleguje weryfikację do Stalwarta przez OAuth2 i dostaje potwierdzenie bez dotykania hasła.Zalety tego podejścia:Jedno źródło prawdy — konta zarządzane tylko w StalwarcieZmiana hasła w jednym miejscu — obowiązuje od razu wszędzieBrak lokalnych kont w Nextcloudzie i Roundcube — mniejsza powierzchnia atakuMożliwość centralnego wyłączenia dostępu — dezaktywacja konta w Stalwarcie odcina użytkownika od wszystkich serwisów jednocześnieNextcloud + Collabora — chmura z edycją dokumentówNextcloud daje synchronizację plików, kalendarze i kontakty (CalDAV/CardDAV). Collabora to serwer LibreOffice Online — edycja .docx, .xlsx, .odt prosto w przeglądarce, zintegrowana z Nextcloudem. Collabora nie ma publicznego endpointu — działa tylko wewnętrznie i jest dostępna wyłącznie dla Nextclouda.Kalendarze z Nextclouda synchronizuję z telefonami przez CalDAV — wystarczy dodać konto w ustawieniach telefonu. Poczta na telefonie idzie przez K-9 Mail, który łączy się ze Stalwartem po IMAP i SMTP. Roundcube to webmail — dostęp do poczty z przeglądarki bez instalowania czegokolwiek, przydatny gdy ktoś z rodziny jest na obcym komputerze. Roundcube ma podpiętą książkę adresową z Nextclouda przez plugin CardDAV — zmiana kontaktu w jednym miejscu widoczna jest wszędzie.Na Nextcloudzie jest wspólna przestrzeń dyskowa dla całej rodziny — dokumenty, zdjęcia, co tam trzeba.Do zastosowań domowych taki stack w zupełności wystarcza: poczta, chmura z edycją dokumentów, kalendarze i kontakty zsynchronizowane między telefonami i komputerami — bez polegania na zewnętrznych dostawcach.Collabora i Nextcloud działają w oddzielnych kontenerach i komunikują się przez sieć wewnętrzną Incusa. Nextcloud łączy się z Collaborą przez wewnętrzny adres 10.10.0.40 — ruch nie wychodzi poza maszynę.Dane Nextclouda (pliki, baza danych) są na wolumenie z RAID-1.Failover przez kartę SIMTo jeden z ciekawszych elementów. ThinkPad P51 ma wbudowany adapter SIM, który pojawia się jako dodatkowy interfejs sieciowy (wwan0).Problem z łącznością domową jest prosty: awaria ISP, reboot routera, przerwa prądu — VPN pada, serwisy niedostępne.Rozwiązanie: metryki routingu w Linuksie.# Kabel (ethernet) — niższa metryka = preferowana ip route add default via 192.168.1.1 metric 100 # SIM — wyższa metryka = fallback ip route add default via 10.128.0.1 metric 200 Kiedy interfejs ethernetowy traci link (router wyłączony, kabel odłączony), kernel automatycznie przełącza ruch na trasę z wyższą metryką (SIM). Kiedy link wraca — niższa metryka znów wygrywa i ruch wraca na kabel. Uwaga: jeśli ISP padnie, ale router domowy nadal działa i przydziela DHCP — ethernet ma link UP i failover nie nastąpi. Pełna automatyzacja tego scenariusza wymagałaby watchdoga sprawdzającego łączność z internetem.WireGuard po przerwie wznawia tunel sam. Okno niedostępności przy przełączaniu: kilkanaście sekund.Karta SIM na failover to koszt 25 PLN miesięcznie. Warto.Powiadomienia SMS z kalendarzaNextcloud trzyma kalendarze rodziny. Napisałem skrypt, który cyklicznie odpytuje CalDAV, pobiera nadchodzące eventy i wysyła SMS-y z przypomnieniem — kto, co i o której.Ciekawostka: SMS nie idzie przez żadne zewnętrzne API ani bramkę. Wychodzi prosto przez modem ThinkPada P51 — tę samą kartę SIM T-Mobile, która robi za failover łączności. Modem jest widoczny jako urządzenie szeregowe, skrypt wysyła SMS-y komendami AT prosto do modemu.Jedna karta SIM, dwie role: failover internetu i kanał powiadomień SMS. Zero dodatkowych kosztów, zero zewnętrznych zależności.BackupBackup ma cztery warstwy:RAID-1 — ochrona przed awarią nośnika, nie przed błędem logicznym ani utratą danychLokalny backup na dysku systemowym — zaszyfrowana kopia danych kontenerów na partycji dysku 500 GB (tego samego co system operacyjny); chroni przed błędem logicznym i przypadkowym usunięciemBackup offsite na Contabo VPS — zaszyfrowane kopie przesyłane na serwer Contabo (6.5 EUR/miesiąc); chroni przed fizyczną utratą sprzętuWewnętrzny backup Contabo — Contabo wykonuje własne snapshoty środowiska VPS niezależnie; dodatkowa warstwa bez żadnego dodatkowego kosztuKopie lokalna i offsite są szyfrowane przed transferem. Cel: możliwość odtworzenia środowiska na nowej maszynie bez utraty danych.Podsumowanie kosztówPozycjaKosztSprzęt (ThinkPad P51, używany)~2000 PLN jednorazowoContabo VPS (punkt wejścia + backup offsite)~28 PLN/miesiąc (6.5 EUR)Karta SIM (failover + SMS)25 PLN/miesiącŁącznie miesięcznie~53 PLN/miesiącTen sam VPS Contabo robi dwie rzeczy: punkt wejścia dla ruchu (HAProxy, WireGuard) i miejsce na backup offsite — bez dodatkowych kosztów.Prąd przy 10W to ok. 7 kWh miesięcznie — niecałe 5 PLN. Pomijalne.Dla porównania: Google Workspace dla rodziny (6 kont) to ok. 360 PLN miesięcznie. Ta architektura kosztuje ponad 6× mniej, z pełną kontrolą nad danymi.Zużycie zasobówAktualny stan przy pełnym obciążeniu produkcyjnym (wszystkie kontenery aktywne):RAM: ~2 GBLoad average: 0.13 / 0.06 / 0.02To spora zmiana w porównaniu do tego co było wcześniej. Używałem osobnych VM-ek z Mailcow zamiast Stalwarta — tamta konfiguracja zjadała ok. 18 GB RAM. Przejście na kontenery Incus + Stalwart zamiast pełnych VM + Mailcow zmniejszyło zużycie pamięci o ponad 80%.VM-ki mają własne kernele i pełne systemy gościa — stąd ogromne narzuty. Kontenery Incus dzielą kernel hosta, co eliminuje sporą część tego kosztu. Stalwart w jednym procesie zastępuje cały stos Mailcow (Postfix, Dovecot, Rspamd, Redis, MySQL...).Na ThinkPadzie z 32 GB RAM mam teraz 30 GB wolnych — sporo miejsca na przyszłe serwisy.Zalety i wadySelf-hosting na własnym sprzęcie ma konkretne zalety i wady.Zalety:Pełna kontrola nad danymi — bez dostawcy chmurowego w środkuNiski koszt przy amortyzacji sprzętuNauka — każdy element wymaga zrozumieniaMożliwość customizacji, której SaaS nie dajeWady:Czas i wiedza do utrzymania — to nie jest zero-opsDostępność zależy od łącza domowegoAwaria sprzętu wymaga ręcznej interwencjiBezpieczeństwo spoczywa wyłącznie na właścicieluDla rodziny, która rozumie kontekst i akceptuje te wymagania — sprawdza się. System chodzi od kilku miesięcy bez większych problemów.Drugi węzeł — czy da się dodać laptop w innej lokalizacji?WireGuard obsługuje wielu peerów — technicznie da się dodać drugi laptop (np. u rodziny w Austrii) jako kolejny węzeł w tej samej sieci VPN. VPS we Francji robiłby wtedy za koncentrator obu węzłów. HAProxy na VPS-ie mógłby sprawdzać stan obu backendów i kierować ruch do tego, który działa.Dla serwisów bezstanowych (strona www) to działa bez problemów — HAProxy robi health-check i failover jest automatyczny.Problem pojawia się przy serwisach ze stanem:Nextcloud — pliki muszą być zsynchronizowane między węzłami. Można to rozwiązać przez replikację RAID-1 przez sieć (np. DRBD), ale to złożone i wrażliwe na opóźnienia między lokalizacjami. Prostsze podejście: jeden węzeł jest aktywny, drugi to hot standby — dane są replikowane jednostronnie, failover jest ręczny lub półautomatyczny.Stalwart Mail — Stalwart wspiera tryb klastrowy, więc wielowęzłowe wdrożenie jest możliwe. Wymaga jednak współdzielonego backendu bazodanowego i storage dla wiadomości. W prostym scenariuszu failover wystarczy jedna aktywna instancja z replikowanymi danymi.Wniosek: architektura nadaje się do rozbudowy o drugi węzeł jako pasywny failover — VPS kieruje ruch do aktywnego węzła, w razie awarii przełącza na drugi. Active-active z dwoma węzłami piszącymi jednocześnie wymagałoby istotnie innego podejścia do synchronizacji danych i wykracza poza zakres tej architektury.Co dalej — selfsourcerodzinal.pl zaczęło się jako własny projekt, ale przy okazji udowodniło że taka architektura działa. Każdy element — Incus, WireGuard, HAProxy, Stalwart, Nextcloud — da się powtórzyć. Problem w tym, że wymaga to wiedzy z kilku dziedzin naraz: sieci, Linuksa, konfiguracji poczty, konteneryzacji.Właśnie to jest punktem wyjścia dla selfsource — platformy, która pozwoli każdemu postawić taką infrastrukturę przez panel administracyjny, bez grzebania w konfiguracjach. Wybierasz serwisy, podajesz domenę — reszta dzieje się sama.rodzinal.pl to prototyp. selfsource to produkt.