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 domowy
Laptop 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 ECC
- Dyski:
- 2× Samsung 970 Pro NVMe w RAID-1 — dane i kontenery
- 500 GB SSD — system operacyjny
- Wbudowany 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 NVMe
Dwa 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 sieci
Internet
│
▼
[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 domem
WireGuard łą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 przerwie
- Niskie opóźnienia dzięki UDP
- Prosta konfiguracja na kluczach publicznych
VPS robi za koncentrator — nie trzyma żadnych danych, tylko przekazuje ruch.
GeoIP filtering — ograniczenie geograficzne dostępu
Na 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 routingu
HAProxy 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ów
Zamiast 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.
| Kontener | IP | Serwis |
|---|---|---|
www | 10.10.0.10 | Strona rodzinal.pl |
cloud | 10.10.0.20 | Nextcloud |
mail | 10.10.0.30 | Stalwart Mail |
collabora | 10.10.0.40 | Collabora (LibreOffice) |
roundcube | 10.10.0.50 | Roundcube (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 pocztowy
Stalwart 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, DMARC
- Web UI do zarządzania kontami
- Natywne JMAP (nowoczesny protokół synchronizacji poczty)
Konfiguracja DNS obejmuje:
- Rekord MX wskazujący na VPS
- SPF i DKIM dla domeny rodzinal.pl
- DMARC z raportowaniem
Port 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 grupy
Każ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ści
Stalwart 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 Stalwarcie
- Zmiana hasła w jednym miejscu — obowiązuje od razu wszędzie
- Brak lokalnych kont w Nextcloudzie i Roundcube — mniejsza powierzchnia ataku
- Możliwość centralnego wyłączenia dostępu — dezaktywacja konta w Stalwarcie odcina użytkownika od wszystkich serwisów jednocześnie
Nextcloud + Collabora — chmura z edycją dokumentów
Nextcloud 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ę SIM
To 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 kalendarza
Nextcloud 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.
Backup
Backup ma cztery warstwy:
- RAID-1 — ochrona przed awarią nośnika, nie przed błędem logicznym ani utratą danych
- Lokalny 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ęciem
- Backup offsite na Contabo VPS — zaszyfrowane kopie przesyłane na serwer Contabo (6.5 EUR/miesiąc); chroni przed fizyczną utratą sprzętu
- Wewnętrzny backup Contabo — Contabo wykonuje własne snapshoty środowiska VPS niezależnie; dodatkowa warstwa bez żadnego dodatkowego kosztu
Kopie lokalna i offsite są szyfrowane przed transferem. Cel: możliwość odtworzenia środowiska na nowej maszynie bez utraty danych.
Podsumowanie kosztów
| Pozycja | Koszt |
|---|---|
| Sprzęt (ThinkPad P51, używany) | ~2000 PLN jednorazowo |
| Contabo 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ąc |
Ten 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ów
Aktualny stan przy pełnym obciążeniu produkcyjnym (wszystkie kontenery aktywne):
- RAM: ~2 GB
- Load average: 0.13 / 0.06 / 0.02
To 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 wady
Self-hosting na własnym sprzęcie ma konkretne zalety i wady.
Zalety:
- Pełna kontrola nad danymi — bez dostawcy chmurowego w środku
- Niski koszt przy amortyzacji sprzętu
- Nauka — każdy element wymaga zrozumienia
- Możliwość customizacji, której SaaS nie daje
Wady:
- Czas i wiedza do utrzymania — to nie jest zero-ops
- Dostępność zależy od łącza domowego
- Awaria sprzętu wymaga ręcznej interwencji
- Bezpieczeństwo spoczywa wyłącznie na właścicielu
Dla 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 — selfsource
rodzinal.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.