Nie szukaj, po prostu znajdź: moja recepta na skuteczne archiwum e‑mail z silnikiem Tantivy

by | Jun 11, 2026 | Homelab

Kiedy „szukaj” przestaje wystarczać

Wyobraź sobie taki scenariusz: prowadzisz dla klienta projekt, który ciągnie się od kilkunastu miesięcy. Komunikacja odbywa się głównie przez e‑mail — ustalenia, korekty, zatwierdzenia, faktury. Pewnego dnia klient dzwoni i pyta o szczegóły decyzji podjętej rok temu. Ty sięgasz po wyszukiwarkę w Gmailu, wpisujesz kilka słów kluczowych i… nic. Albo gorzej — wyniki są, ale nie te. Zaczynasz przekopywać foldery, przełączasz się między kontami, bo część korespondencji szła z adresu prywatnego, część z firmowego. Minęło pół godziny, a Ty wciąż nie masz odpowiedzi.

To nie jest wymyślony przykład. To codzienność każdego, kto przez lata prowadzi projekty i komunikuje się e‑mailem z wieloma stronami jednocześnie. Problem nie leży w tym, że wiadomości gdzieś zniknęły — one są. Problem leży w tym, że są rozproszone, a narzędzia, które mamy pod ręką, nie są zoptymalizowane do przeszukiwania historii sprzed lat, szczególnie gdy ta historia rozciąga się na kilka kont pocztowych.

Przez długi czas żyłem z tym problemem, traktując go jako nieunikniony koszt pracy z e‑mailem. Dopóki nie trafiłem na Bichon — lekki, napisany w Rust archiwizator poczty z silnikiem pełnotekstowym Tantivy. I dopóki nie zainstalowałem go na swoim QNAPie.

Zanim przejdę do szczegółów wdrożenia, chcę wyraźnie zaznaczyć jedną rzecz: Bichon to nie jest klient poczty. Nie służy do wysyłania wiadomości, nie zastępuje Gmaila ani Outlooka. To narzędzie do długoterminowej archiwizacji i błyskawicznego przeszukiwania zgromadzonej korespondencji. Różnica jest fundamentalna i warto ją mieć w głowie od samego początku.

Jest jeszcze jeden aspekt, o którym rzadko się mówi wprost: poleganie wyłącznie na chmurze dostawcy e‑mail to ryzyko. Konta są zamykane, polityki retencji się zmieniają, dostęp może zostać zablokowany z powodów, na które nie masz wpływu. Historia Twojej pracy — ustalenia z klientami, umowy, decyzje projektowe — siedzi na cudzych serwerach. Bichon pozwala to zmienić.

Warto też powiedzieć wprost, czym Bichon nie jest: nie jest to rozwiązanie klasy enterprise, nie ma wbudowanego systemu ticketów ani integracji z CRM. To celowo prosty, skupiony na jednym zadaniu archiwizator — i właśnie ta prostota jest jego siłą. Jeden kontener Docker, jeden katalog z danymi, jeden interfejs webowy. Nic zbędnego.

Bichon - dashboard

Sprzęt i strategia przechowywania danych

QNAP TS-664 jako platforma dla Bichona

Bichon działa u mnie jako kontener Docker na QNAP TS-664 z procesorem Intel Celeron N509524 GB RAM. To maszyna, która w moim homelabowym ekosystemie pełni rolę głównego serwera aplikacji — hostuje kilkanaście kontenerów, od Immich przez Paperless-ngx po n8n. Bichon jest jednym z nich i działa stabilnie od tygodni bez żadnej interwencji z mojej strony.

Procesor N5095 z obsługą AES-NI radzi sobie bez problemu z szyfrowaniem bazy danych Bichona — operacje kryptograficzne są sprzętowo akcelerowane, więc nie odczuwam żadnego narzutu wydajnościowego. 24 GB RAM to z kolei komfortowy bufor dla indeksów Tantivy, które Bichon trzyma w pamięci podczas wyszukiwania. Przy archiwum liczącym dziesiątki tysięcy wiadomości indeks mieści się w pamięci operacyjnej w całości, co przekłada się na czas odpowiedzi mierzony w milisekundach.

System operacyjny QTS zarządza całą infrastrukturą storage i kontenerami. Container Station — graficzny interfejs QNAP do zarządzania Dockerem — pozwala wdrożyć Bichona bez dotykania terminala, choć ja i tak wolę pracować z plikiem docker-compose.yml bezpośrednio.

Tiering storage: dlaczego Bichon siedzi na NVMe

Mój QNAP ma trzy pule pamięci masowej, każda z innym przeznaczeniem i inną charakterystyką wydajnościową:

  • Pula 1 — główny magazyn danych (RAID 5, 5 × 8 TB HDD, ~29 TB użytecznej przestrzeni): media, biblioteki, kopie zapasowe, dane archiwalne. Wysoka pojemność, umiarkowana prędkość sekwencyjna, słabe losowe I/O.
  • Pula 2 — szybki magazyn aplikacji (RAID 1, 2 × 512 GB NVMe, ~444 GB): kontenery Docker i dane wymagające intensywnego I/O. Wysoka prędkość, niska latencja, redundancja przez lustrzane odbicie.
  • Pula 3 — scratch disk (Single, 1 × 2 TB Samsung 870 EVO SSD): tu lądują dane aplikacji takich jak Immich, które mają własne mechanizmy backupu i nie wymagają redundancji na poziomie storage.

Bichon trafia na Pulę 2, czyli na NVMe. To nie jest przypadek. Silnik pełnotekstowy Tantivy, który Bichon wykorzystuje do indeksowania i przeszukiwania wiadomości, jest wyjątkowo wrażliwy na opóźnienia I/O. Indeksy Tantivy to struktury danych, które podczas wyszukiwania są intensywnie odczytywane z losowych lokalizacji na dysku — to jest dokładnie ten wzorzec dostępu, przy którym HDD kapituluje, a NVMe błyszczy.

Dane Bichona montowane są pod ścieżką /share/vol2-data/docker-data/app-bichon/data, co w logice mojego storage tieringu oznacza: dane krytyczne dla wydajności, wymagające szybkiego dostępu, z redundancją RAID 1. Gdybym umieścił Bichona na Puli 1 (HDD), wyszukiwanie w dużym archiwum e‑mail byłoby odczuwalnie wolniejsze. Na NVMe jest natychmiastowe.

Warto też wspomnieć o architekturze storage Bichona od strony aplikacyjnej. Aplikacja zarządza trzema oddzielnymi obszarami danych:

  • Root directory (BICHON_ROOT_DIR) — konfiguracja kont, ustawienia systemowe, zaszyfrowane dane uwierzytelniające. To „mózg” instalacji.
  • Index directory (domyślnie podfolder envelope) — indeks Tantivy z metadanymi wiadomości i informacjami o synchronizacji z serwerami IMAP.
  • Data directory (domyślnie podfolder eml) — surowe dane e‑mail skompresowane algorytmem Zstd. To największy obszar, rosnący proporcjonalnie do liczby zarchiwizowanych wiadomości.

W mojej konfiguracji wszystkie trzy obszary siedzą w jednym katalogu na NVMe, co upraszcza zarządzanie i backup. Bichon od wersji 0.3.2 pozwala je rozdzielić — np. trzymać indeks na szybkim NVMe, a surowe dane na pojemnym HDD — ale przy moich wolumenach danych nie ma takiej potrzeby.

Wdrożenie przez Container Station

Docker Compose w praktyce

Bichon wdrażam przez Container Station — graficzny interfejs QNAP do zarządzania kontenerami Docker. Konfiguracja jest prosta i sprowadza się do jednego pliku docker-compose.yml:

services:
     bichon:
     image: rustmailer/bichon:latest
     container_name: bichon
     ports:
          - "10001:15630"
     volumes:
          - /share/vol2-data/docker-data/app-bichon/data:/data
     environment:
          BICHON_ROOT_DIR: /data
          BICHON_LOG_LEVEL: info
          BICHON_ENCRYPT_PASSWORD: hasło

Kilka słów o tym, co tu widać. Port 10001 to mój wewnętrzny port dostępowy — Bichon nasłuchuje natywnie na 15630, ale mapuję go na 10001 zgodnie z moją konwencją numerowania portów dla aplikacji. Wolumin /share/vol2-data/docker-data/app-bichon/data to właśnie ta ścieżka na Puli 2 NVMe, o której pisałem wcześniej. Zmienna BICHON_ROOT_DIR wskazuje Bichonowi, gdzie wewnątrz kontenera szukać katalogu z danymi.

Obraz rustmailer/bichon:latest jest wieloarchitekturowy — obsługuje zarówno amd64 jak i arm64. Na QNAP TS-664 z procesorem x86_64 pobierany jest wariant amd64. Kontener zawiera wbudowany health check monitorujący endpoint /api/status.

Fundament bezpieczeństwa: BICHON_ENCRYPT_PASSWORD

Jedną z pierwszych rzeczy, które należy zrobić przed uruchomieniem Bichona, jest ustawienie zmiennej BICHON_ENCRYPT_PASSWORD. To hasło, którym Bichon szyfruje wszystkie wrażliwe dane przechowywane w swojej bazie: hasła do kont IMAP, tokeny OAuth 2.0, hasła dostępowe do interfejsu webowego. Szyfrowanie odbywa się algorytmem AES-256-GCM — standardem przemysłowym, który w połączeniu ze sprzętową akceleracją AES-NI procesora N5095 nie generuje żadnego mierzalnego narzutu.

Uwaga: hasło musi być ustawione przed pierwszym uruchomieniem i przed zapisaniem jakichkolwiek danych. Po jego ustawieniu nie można go zmienić — modyfikacja hasła po fakcie sprawi, że wszystkie wcześniej zaszyfrowane dane staną się nieczytelne i konieczne będzie zbudowanie archiwum od zera.

W praktyce oznacza to, że BICHON_ENCRYPT_PASSWORD powinno trafić do pliku .env lub bezpośrednio do konfiguracji kontenera jako zmienna środowiskowa — i powinno być silne.

Dodawanie kont: IMAP i OAuth 2.0

Po uruchomieniu kontenera konfiguracja kont pocztowych odbywa się przez interfejs webowy dostępny na porcie — w przypadku mojego mapowania — 10001. Bichon obsługuje dwa tryby uwierzytelniania:

  • IMAP z hasłem — klasyczne podejście, sprawdza się dla kont firmowych i serwerów pocztowych, które nie wymagają OAuth. Podajesz serwer IMAP, port, login i hasło — Bichon resztą zajmuje się sam.
  • OAuth 2.0 — dla kont Google i Microsoft. Bichon obsługuje automatyczne odświeżanie tokenów, więc po jednorazowej autoryzacji nie trzeba się tym zajmować. Tokeny są przechowywane zaszyfrowane w bazie danych.

W moim przypadku archiwizuję zarówno konta prywatne (Gmail), jak i konto firmowe. Każde konto konfiguruje się osobno wskazując serwer IMAP, login i metodę uwierzytelniania. Po zapisaniu konfiguracji Bichon natychmiast rozpoczyna synchronizację — pobiera wiadomości, parsuje je i indeksuje w Tantivy. Pierwsza synchronizacja dużego konta może trwać kilka godzin, ale odbywa się w tle i nie blokuje interfejsu.

Bichon pozwala też wybrać, które foldery IMAP mają być synchronizowane. Jeśli nie chcesz archiwizować folderu Spam czy Kosz, możesz je wykluczyć z konfiguracji konta. To przydatne, gdy zależy Ci na czystości archiwum i nie chcesz zaśmiecać indeksu niechcianą korespondencją.

Silnik Tantivy i mechanizmy oszczędzania miejsca

Pełnotekstowe wyszukiwanie, które naprawdę działa

Tantivy to napisany w Rust silnik wyszukiwania pełnotekstowego — odpowiednik Apache Lucene, ale szybszy i lżejszy. Bichon używa go do indeksowania tematów, treści wiadomości i zawartości załączników. Dane surowe (pliki EML) przechowywane są w osobnym magazynie z kompresją Zstd, co znacząco redukuje zajmowane miejsce bez wpływu na szybkość wyszukiwania.

Efekt praktyczny? Wpisuję w interfejsie Bichona kilka słów z treści wiadomości sprzed lat i wynik pojawia się natychmiast. Nie ma tu żadnego „ładowania” ani „indeksowania w tle”. Tantivy na NVMe to kombinacja, która sprawia, że wyszukiwanie w lokalnym archiwum potrafi być szybsze niż w Gmailu.

Wyszukiwanie działa na kilku poziomach jednocześnie: temat wiadomości, treść (zarówno plain text jak i HTML po konwersji), nadawca, odbiorca oraz zawartość załączników tekstowych. Możesz szukać po frazie, po nadawcy, po zakresie dat — interfejs webowy oferuje zarówno proste pole wyszukiwania, jak i zaawansowane filtry.

Indeksacja danych to doskonała sprawa, według dokumentacji Bichona 145 GB wiadomości generuje zaledwie 1,3 GB indeksu Tantivy. To oznacza, że nawet bardzo duże archiwum nie obciąży znacząco mojej Puli 2. Stosunek rozmiaru indeksu do danych zależy od zawartości: im więcej dużych załączników binarnych, tym mniejszy procentowo indeks.

Poniżej możecie zobaczyć, jak to wygląda u mnie: dane wszystkich kont liczą około 40 GB, które po kompresji i deduplikacji zajmują na dysku około 22,2 GB miejsca. Pliki indeksu natomiast to raptem nieco ponad 200 MB.

Bichon - dashboard

Deduplikacja BLAKE3: jeden załącznik, jedno miejsce

Bichon implementuje deduplikację treści opartą na algorytmie haszowania BLAKE3. Mechanizm działa na poziomie identyfikatorów wiadomości (Message-ID) i treści załączników. Praktyczne znaczenie tego jest następujące: jeśli wysłałem ten sam plik PDF do dziesięciu osób, Bichon przechowa go tylko raz, niezależnie od tego, ile razy pojawi się w archiwum.

BLAKE3 to kryptograficzna funkcja skrótu nowej generacji — szybsza od SHA-256 i MD5, a przy tym bezpieczna. Bichon używa jej do identyfikacji identycznych treści, nie do szyfrowania (to zadanie AES-256-GCM). Dzięki temu deduplikacja jest błyskawiczna i nie obciąża procesora.

W środowisku firmowym, gdzie te same dokumenty krążą między wieloma odbiorcami, deduplikacja potrafi zaoszczędzić znaczną część przestrzeni dyskowej. Wyobraź sobie firmowy regulamin wysyłany do całego działu — 50 osób, jeden plik, ale w archiwum bez deduplikacji zajmuje 50 razy więcej miejsca. Bichon przechowuje go raz.

Thread Grouping i automatyczna książka adresowa

Dwie funkcje, które doceniam w codziennym użytkowaniu:

  • Thread Grouping — Bichon rekonstruuje wątki konwersacji na podstawie nagłówków wiadomości (In-Reply-To, References). Zamiast widzieć setki luźnych e‑maili, widzę logicznie pogrupowane rozmowy. Szukam konkretnego projektu — widzę całą historię wymiany, od pierwszego maila do ostatniego, w chronologicznym porządku.
  • Contacts View — jest to automatyczna książka adresowa budowana na podstawie zarchiwizowanej korespondencji. Bichon wyciąga adresy e‑mail i nazwy nadawców/odbiorców i prezentuje je jako przeszukiwalny katalog kontaktów. Przydatne, gdy chcę szybko znaleźć wszystkie wiadomości od konkretnej osoby lub firmy.

Warto też wspomnieć o architekturze dual-storage, którą Bichon stosuje wewnętrznie. Każda wiadomość jest identyfikowana przez swój Message-ID — to unikalny klucz, który zapobiega duplikatom nawet jeśli ta sama wiadomość pojawi się w kilku folderach IMAP (np. w Wysłanych i w kopii do siebie). Przeniesienie wiadomości między folderami aktualizuje istniejący rekord zamiast tworzyć nowy — archiwum pozostaje czyste.

Praktyczne wnioski: co zyskałem

Niezależność od chmury dostawcy

Bichon wpisuje się w szerszą strategię, którą realizuję w swoim homelabowym środowisku: stopniowe uniezależnianie się od zewnętrznych usług chmurowych. Nie chodzi o to, żeby całkowicie zrezygnować z Gmaila czy Outlooka — to byłoby niepraktyczne. Chodzi o to, żeby mieć lokalną kopię własnej historii komunikacji, nad którą mam pełną kontrolę.

Historia e‑mail to de facto historia mojej pracy zawodowej. Ustalenia z klientami, decyzje projektowe, potwierdzenia zamówień, korespondencja z kontrahentami — to wszystko ma wartość dokumentacyjną i prawną. Trzymanie tego wyłącznie na serwerach Google czy Microsoft to ryzyko, które przestało mi odpowiadać. Szczególnie w kontekście rosnących cen subskrypcji i zmieniających się warunków usług.

Bichon jest projektem open source (licencja AGPL‑3.0), aktywnie rozwijanym — w momencie pisania tego artykułu repozytorium na GitHubie ma ponad 1700 gwiazdek i ponad 50 forków. To dobry sygnał dla projektu self-hosted: aktywna społeczność oznacza regularne aktualizacje i szybkie łatanie błędów.

Szybkość pracy: konkretna różnica

Wróćmy do scenariusza z początku artykułu. Szukam faktury wystawionej trzy lata temu, która przyszła na konto, którego już aktywnie nie używam. W Gmailu: logowanie na stare konto, czekanie na załadowanie, kilka prób z różnymi frazami, przewijanie wyników. Czas: kilka minut, jeśli mam szczęście.

W Bichonie: wpisuję fragment tematu lub treści, wynik pojawia się w ułamku sekundy. Czas: poniżej 5 sekund. Różnica jest na tyle duża, że zmieniła mój workflow — zamiast unikać sięgania do starych wiadomości, robię to bez zastanowienia. Bichon stał się dla mnie tym, czym dobra wyszukiwarka jest dla internetu: narzędziem, które sprawia, że informacja jest zawsze w zasięgu ręki.

Szczególnie doceniam to przy pracy z klientami długoterminowymi. Gdy ktoś pyta „czy ustalaliśmy coś w tej sprawie rok temu?”, nie muszę już mówić „sprawdzę i oddzwonię”. Sprawdzam na bieżąco, podczas rozmowy. To zmienia dynamikę komunikacji.

Bezpieczeństwo: dostęp bez otwierania portów

Bichon jest dostępny wyłącznie w sieci lokalnej i przez Twingate — zero-trust VPN, który pozwala mi bezpiecznie łączyć się z homelabem z zewnątrz bez otwierania żadnych portów na routerze. Interfejs webowy Bichona nie jest wystawiony na świat. Nawet jeśli ktoś przeskanuje mój publiczny adres IP, nie znajdzie żadnego otwartego portu prowadzącego do archiwum e‑mail.

Dane archiwum są objęte moją standardową strategią backupu realizowaną przez HBS3 na QNAP. Codziennie o godzinie 9:00 uruchamia się zadanie, które kopiuje dane kontenerów Docker — w tym katalog Bichona — na Synology DS213+ przez WebDAV z deduplikacją QuDedup. Następnie, po zakończeniu kopii lokalnej, uruchamia się kolejne zadanie, które replikuje te dane do Hetzner Storage Box. Archiwum e‑mail jest więc zabezpieczone w modelu 3–2‑1: oryginał na QNAP, kopia lokalna na Synology, kopia off-site w chmurze Hetznera.

Warto podkreślić, że backup Bichona wymaga skopiowania trzech obszarów danych: katalogu root (konfiguracja i zaszyfrowane dane uwierzytelniające), katalogu indeksu Tantivy oraz katalogu z surowymi danymi EML. W mojej konfiguracji wszystkie trzy siedzą w jednym katalogu /share/vol2-data/docker-data/app-bichon/data, więc backup jest prosty — jeden katalog, jedna reguła.

Podsumowanie

Bichon rozwiązał problem, z którym żyłem latami. Nie jest to narzędzie dla każdego — wymaga własnego serwera lub NAS z obsługą Dockera, chwili poświęconej na konfigurację i świadomości, że to archiwizator, a nie klient poczty. Ale jeśli te warunki są spełnione, efekt jest natychmiastowy i trwały.

Silnik Tantivy na dyskach NVMe to połączenie, które sprawia, że przeszukiwanie lat korespondencji staje się tak samo szybkie i naturalne jak wyszukiwanie w wyszukiwarce Google. Tyle że dane są moje, leżą u mnie i nigdzie nie znikną. Deduplikacja BLAKE3 dba o to, żeby archiwum nie rosło w nieskończoność, a backup 3–2‑1 zapewnia, że nawet awaria sprzętu nie oznacza utraty historii mojej korespondencji.

Jeśli prowadzisz projekty, komunikujesz się przez e‑mail z wieloma stronami i zdarzyło Ci się kiedyś spędzić pół godziny na szukaniu wiadomości sprzed roku — Bichon jest dla Ciebie. Wdrożenie zajmuje mniej niż godzinę, a efekty są natychmiastowe.

Nie szukaj. Po prostu znajdź.