← Blog
Self-hosting14 min czytania

Seafile — własna chmura plików z szyfrowaniem po stronie klienta

Czternaście lat rozwoju, model danych zbudowany jak w Gicie i chunkowanie zależne od treści, dzięki któremu synchronizuje się tylko zmienione bloki. Rozebraliśmy szyfrowanie bibliotek na podstawie kodu źródłowego — cztery wersje formatu, liczby iteracji funkcji wyprowadzającej klucz i moment, w którym wprowadzono sól per repozytorium. Wyjaśniamy też, czego to szyfrowanie nie chroni i dlaczego wyklucza edytory online.

Prośba klienta brzmi zwykle w trzech krokach: chcemy własną chmurę plików, pliki mają zostać u nas, a najlepiej żeby nawet administrator serwera nie mógł ich przeczytać. Pierwsze dwa punkty realizuje dziś kilkanaście projektów. Trzeci jest tym, przy którym większość odpowiedzi robi się nieprecyzyjna — bo „szyfrowanie" znaczy w tych projektach bardzo różne rzeczy.

Seafile (github.com/haiwen/seafile) jest jedną z dwóch poważnych odpowiedzi na to pytanie i różni się od popularniejszej alternatywy w sposób, który przy takim wymaganiu ma znaczenie. Dlatego w tym wpisie nie poprzestanę na opisie funkcji — rozebrałem mechanizm szyfrowania na podstawie kodu źródłowego i podaję, co dokładnie robi, w której wersji formatu i czego nie obejmuje.

Stan projektu i mapa repozytoriów

Zacznę od rzeczy, która przy tym projekcie myli najczęściej: repozytorium, do którego prowadzi nazwa „seafile", zawiera klienta synchronizacji, a nie serwer. README wyjaśnia to wprost — przed wersją 6.0 kod klienta i serwera był wspólny, a po rozdzieleniu repozytorium klienta pozostało „stroną główną" projektu.

Dane z API GitHuba na 16 października 2026:

  • klient synchronizacji (to repozytorium): 15 228 gwiazdek, założone 12 lipca 2012 — czternaście lat, kod w C, ostatni push z końca sierpnia 2026, 95 otwartych zgłoszeń,
  • rdzeń serwera (haiwen/seafile-server): 546 gwiazdek, ostatni push z 3 września 2026, a najnowsza etykieta wersji to 13.0.25,
  • interfejs webowy (haiwen/seahub): push w dniu poprzedzającym napisanie tego tekstu,
  • osobne repozytoria mają też klient graficzny, aplikacje na iOS i Androida oraz WebDAV.

Warto przy tym wiedzieć, że wydania oznaczane na GitHubie nie są tu źródłem prawdy. Ostatnie oznaczone wydanie klienta to 9.0.5 z lutego 2024, podczas gdy commit z sierpnia 2026 podnosi wersję do 9.0.21. Numer wersji, którą się wdraża, trzeba więc brać z dziennika zmian w dokumentacji, nie z listy wydań w repozytorium.

Licencja: pięć komponentów, cztery licencje

GitHub pokazuje przy tym projekcie „licencja nierozpoznana" i ma dobry powód — każdy komponent ma inną. README wylicza je precyzyjnie:

  • klient synchronizacji na komputery — GPLv2, z jawnie dodanym pozwoleniem na łączenie z biblioteką OpenSSL,
  • rdzeń serwera — AGPLv3,
  • interfejs webowy Seahub — Apache-2.0,
  • klient iOS — Apache-2.0, klient Androida — GPLv3.

Praktyczne skutki tego układu omawiam w ostatnim akapicie, ale jedną rzecz warto powiedzieć od razu: rdzeń serwera na AGPLv3 to najmocniejszy element tej konstrukcji, a interfejs webowy na Apache-2.0 — najbardziej swobodny. Kto zamierza modyfikować wygląd i funkcje panelu, trafia więc na licencję permisywną, a kto chce zmieniać silnik — na copyleft z klauzulą sieciową.

Istnieje przy tym wersja komercyjna: README kieruje klientów tej edycji do kontaktu mailowego, zamiast do publicznego trackera. To układ typu otwarty rdzeń, prowadzony przez firmę Seafile Ltd.

Model danych zbudowany jak w Gicie

Przeglądając drzewo źródeł, natrafiłem na coś, co tłumaczy większość zachowań tego systemu. W katalogu wspólnym siedzą moduły o nazwach: menedżer commitów, menedżer gałęzi, menedżer systemu plików, menedżer bloków oraz katalog z indeksem zawierającym drzewo pamięci podręcznej i tablicę haszy nazw.

To nie jest przypadkowa zbieżność nazw. Biblioteka w Seafile jest repozytorium w sensie bardzo bliskim gitowemu: ma historię commitów, gałąź, obiekty systemu plików i bloki danych. Z tej jednej decyzji projektowej wynikają trzy rzeczy, które w innych systemach są dorobione osobno:

  • Wersjonowanie jest darmowe — historia jest właściwością modelu, nie funkcją kopiującą pliki na boku,
  • Deduplikacja jest darmowa — identyczne bloki mają ten sam identyfikator, więc przechowuje się je raz,
  • Rozwiązywanie konfliktów opiera się na historii, a nie na znaczniku czasu — i to jest zdanie z README, które warto docenić. System, który przy konflikcie porównuje daty modyfikacji plików, myli się przy każdym rozjeżdżonym zegarze i przy każdej kopii przywróconej z backupu. System, który ma wspólnego przodka, wie, która zmiana jest której potomkiem.

Chunkowanie zależne od treści

Drugi katalog wart uwagi zawiera implementację chunkowania zależnego od treści wraz z sumą kontrolną Rabina. Jest to mechanizm stojący za obietnicą z README: „przesyłamy do serwera tylko różnicę treści".

Warto rozumieć, dlaczego to działa lepiej niż dzielenie pliku na kawałki o stałym rozmiarze. Przy stałym podziale wstawienie jednego bajta na początku pliku przesuwa całą zawartość — każdy kolejny kawałek ma inną treść, więc trzeba przesłać wszystko od nowa. Chunkowanie zależne od treści wyznacza granice bloków na podstawie zawartości okna przesuwnego, więc wstawka zmienia jeden blok, a granice pozostałych zostają na miejscu.

Praktyczna konsekwencja dla klienta: dopisanie akapitu do dużego dokumentu wysyła kilobajty, nie megabajty, a przerwany transfer da się wznowić, bo jednostką transferu jest blok, nie plik. Przy zespole pracującym na plikach projektowych ważących setki megabajtów jest to różnica decydująca o użyteczności całego rozwiązania.

Szyfrowanie bibliotek, wersja po wersji

Tu jest sedno tego wpisu. Zamiast powtarzać marketingowe „szyfrowanie po stronie klienta", przeczytałem nagłówek i implementację modułu kryptograficznego. Oto co robi.

Konstrukcja podstawowa jest poprawna i warta pochwały. Dane nie są szyfrowane kluczem wyprowadzonym z hasła. System generuje losowy klucz danych o długości 32 bajtów, a następnie szyfruje ten klucz hasłem użytkownika. Wynika z tego rzecz bardzo praktyczna: zmiana hasła nie wymaga ponownego zaszyfrowania wszystkich plików — wystarczy przepakować klucz, co realizuje osobna funkcja aktualizująca. To jest właściwy sposób budowania takiego mechanizmu.

Szyfrowanie danych to AES w trybie wiązania bloków, z blokiem szesnastobajtowym, kluczem szesnastobajtowym w wersji pierwszej formatu i trzydziestodwubajtowym w nowszych.

Ciekawiej jest w funkcji wyprowadzającej klucz z hasła, bo obsługiwane są cztery wersje formatu biblioteki szyfrowanej i każda liczy inaczej:

  • Wersja 1 — stara funkcja OpenSSL wyprowadzająca klucz, z AES-128 i liczbą iteracji 2 do potęgi 19, czyli 524 288,
  • Wersja 2 — PBKDF2 z HMAC-SHA256 i liczbą iteracji 1000,
  • Wersja 3 i wyższe — ta sama funkcja i ta sama liczba iteracji, ale z solą osobną dla każdego repozytorium,
  • Wersja 4 — dodatkowo obsługuje sól repozytorium o długości 32 bajtów w wariancie kompilacji z biblioteką na licencji GPL.

Dwie obserwacje z tego kodu są warte wyłożenia bez ozdób.

Pierwsza: sól per repozytorium pojawiła się dopiero w wersji trzeciej. W kodzie nadal stoi ośmiobajtowa sól wpisana na stałe, używana przez starsze wersje formatu, z komentarzem autorów mówiącym, że sól powinna być losowa dla każdego repozytorium. Innymi słowy: autorzy sami oznaczyli to jako dług, a wersja trzecia go spłaciła. Wniosek praktyczny: przy zakładaniu nowych bibliotek szyfrowanych upewnij się, że serwer tworzy je w najnowszej wersji formatu, a stare biblioteki rozważ utworzyć od nowa.

Druga: tysiąc iteracji PBKDF2 jest dziś liczbą niską. Współczesne zalecenia dla tej funkcji z SHA-256 mówią o setkach tysięcy iteracji, a wersja pierwsza formatu — paradoksalnie — używała ich pół miliona. Trzeba to jednak ocenić w kontekście całej konstrukcji: hasło nie chroni danych bezpośrednio, a jedynie opakowanie losowego klucza, i to opakowanie jest tym, co atakujący musiałby łamać. Konsekwencja dla użytkownika jest mimo to jednoznaczna: siła zabezpieczenia opiera się na długości hasła. Hasło zapamiętywalne przy tysiącu iteracji jest słabym punktem; długie hasło losowe z menedżera haseł czyni tę liczbę bez znaczenia.

Warto też odnotować, że kod ma nowszy, wymienny mechanizm haszowania hasła przyjmujący nazwę algorytmu i jego parametry jako argumenty — czyli droga do mocniejszej funkcji jest w architekturze otwarta, a serwer może ją wybrać konfiguracją.

Do weryfikacji hasła służy osobna wartość kontrolna, generowana z identyfikatora repozytorium, soli i hasła. Dzięki temu serwer potrafi sprawdzić poprawność hasła bez przechowywania go — ale, jak zaraz zobaczymy, samo to nie wystarcza, żeby uznać dane za niedostępne dla operatora.

Czego to szyfrowanie nie chroni

Ta sekcja jest równie ważna jak poprzednia i wymaga precyzji, bo tu popełnia się najkosztowniejsze pomyłki w rozmowie z klientem.

README wymienia dwie osobne pozycje w sekcji o ochronie prywatności: „szyfrowanie biblioteki hasłem wybranym przez użytkownika" oraz „szyfrowanie po stronie klienta przy synchronizacji na komputery". To rozdzielenie jest celowe i mówi wszystko: właściwość „serwer nie widzi treści" jest przypisana konkretnie do synchronizacji przez klienta desktopowego, a nie do biblioteki szyfrowanej w ogóle.

Wynika z tego reguła, którą warto wypowiedzieć klientowi wprost: jeśli wymaganie brzmi „operator serwera nie może przeczytać plików", to jedyną drogą, którą da się to obronić, jest praca przez klienta desktopowego. Dostęp przez przeglądarkę albo aplikację mobilną do biblioteki szyfrowanej wymaga podania hasła po stronie serwera, żeby ten mógł treść odszyfrować i pokazać.

Jest też druga konsekwencja, czysto logiczna, a przez to niepodważalna: szyfrowanie biblioteki wyklucza wszystkie funkcje wymagające, by serwer czytał zawartość plików. A takich funkcji Seafile ma niemało i są w README wymienione jako zaleta:

  • integracja z pakietami biurowymi online — OnlyOffice i Collabora,
  • SeaDoc, czyli wbudowany edytor dokumentów do pracy zespołowej,
  • Wiki jako baza wiedzy,
  • integracja z Excalidrawem do wspólnej tablicy,
  • a także wyszukiwanie pełnotekstowe i podglądy plików.

Żadna z nich nie może działać na treści, której serwer nie potrafi odczytać. Decyzja o szyfrowaniu biblioteki jest więc decyzją o rezygnacji z połowy funkcji współpracy — i to jest rozmowa, którą trzeba przeprowadzić z klientem przed wdrożeniem, a nie po pierwszym pytaniu „dlaczego nie mogę otworzyć tego dokumentu w przeglądarce".

Praktyczny wzorzec, który bym proponował: dwie biblioteki o różnym przeznaczeniu. Jedna nieszyfrowana, z pełną współpracą, na dokumenty robocze zespołu. Druga szyfrowana, dostępna wyłącznie przez klienta desktopowego, na to, co faktycznie musi pozostać nieczytelne dla serwera — umowy, dane kadrowe, materiały przed publikacją.

Funkcje, które wyróżniają ten projekt

Poza modelem danych i szyfrowaniem warto znać cztery rzeczy, bo w tej kategorii nie są standardem:

  • Klient dyskowy — dostęp do wszystkich plików przez dysk wirtualny, z synchronizacją na żądanie. Czyli katalog widoczny w systemie bez zajmowania miejsca, aż do pierwszego otwarcia pliku,
  • Synchronizacja z dwoma lub więcej serwerami jednocześnie oraz z istniejącymi katalogami — nietypowa elastyczność przy pracy dla kilku klientów naraz,
  • Zarządzanie metadanymi: rozszerzalne właściwości plików, takie jak właściciel, termin czy status, widoki tabelaryczny, kanbanowy, galeria, mapa i statystyki, a do tego znaczniki z hierarchią nadrzędny-podrzędny. To jest kierunek zamieniający katalog plików w coś bliższego bazie dokumentów,
  • Linki do pobrania z hasłem i linki do wysyłania — czyli przyjęcie plików od kogoś, kto nie ma konta. Prozaiczna funkcja, o którą klienci pytają najczęściej.

Pułapki

  • Repozytorium o nazwie projektu to klient, nie serwer — serwer jest osobno i ma własną numerację wersji,
  • Wydania na GitHubie są przestarzałe; wersję bierz z dziennika zmian w dokumentacji,
  • Pięć komponentów, cztery licencje — przy audycie u klienta trzeba wymienić każdą osobno,
  • Tysiąc iteracji funkcji wyprowadzającej klucz w wersjach formatu od drugiej. Używaj długich haseł losowych,
  • Sól per repozytorium dopiero od wersji trzeciej formatu — starsze biblioteki szyfrowane warto założyć od nowa,
  • Szyfrowanie wyklucza edytory online, wyszukiwanie pełnotekstowe i podglądy,
  • Właściwość „serwer nie widzi treści" dotyczy synchronizacji desktopowej, a nie dostępu przez przeglądarkę,
  • Utrata hasła biblioteki szyfrowanej to utrata danych — nie ma tu mechanizmu odzyskiwania, bo gdyby był, szyfrowanie nie miałoby sensu. To jest zdanie do umowy, nie do rozmowy,
  • Wersja komercyjna istnieje i część funkcjonalności oraz wsparcia jest po tamtej stronie,
  • Kod w C i model gitowy znaczą, że diagnostyka problemów z synchronizacją wymaga zrozumienia commitów i bloków, nie tylko czytania logów.

Gdzie to ma sens

  • Zespół pracujący na dużych plikach. Chunkowanie zależne od treści i transfer bloków to konkretna przewaga przy plikach projektowych, graficznych i wideo,
  • Klient z wymogiem nieczytelności dla operatora — pod warunkiem uczciwego postawienia granicy: biblioteka szyfrowana, dostęp przez klienta desktopowego, bez edytorów online,
  • Wymiana plików z osobami bez konta — linki z hasłem w obie strony,
  • Praca dla kilku klientów jednocześnie, gdzie jeden klient synchronizacji obsługuje kilka serwerów,
  • Katalog dokumentów z metadanymi, gdy klient chce statusów, terminów i widoku kanbanowego nad plikami, a nie osobnego systemu obiegu dokumentów,
  • Zastąpienie dysku sieciowego klientem dyskowym z synchronizacją na żądanie — bez zajmowania miejsca na stacjach roboczych.

Czego bym nie robił: nie obiecywałbym szyfrowania i pełnej współpracy w jednym worku, bo to sprzeczne wymagania. I nie wybierałbym tego rozwiązania tam, gdzie klient potrzebuje przede wszystkim wtyczek, kalendarza, kontaktów i aplikacji dodatkowych — Seafile jest systemem plików z bardzo dobrym silnikiem synchronizacji, a nie platformą biurową.

Podsumowanie

  • Czternaście lat rozwoju i wciąż aktywne trzy repozytoria: klient, serwer i interfejs webowy,
  • Model danych jak w Gicie — commity, gałęzie, obiekty i bloki; z tego bierze się wersjonowanie, deduplikacja i rozstrzyganie konfliktów po historii,
  • Chunkowanie zależne od treści z sumą Rabina: dopisany akapit to kilobajty transferu,
  • Losowy klucz danych opakowany hasłem — zmiana hasła nie wymaga ponownego szyfrowania plików,
  • Cztery wersje formatu biblioteki szyfrowanej, z solą per repozytorium od wersji trzeciej,
  • Tysiąc iteracji PBKDF2 w nowszych wersjach — długość hasła ma tu znaczenie decydujące,
  • Szyfrowanie wyklucza edytory online, wyszukiwanie i podglądy,
  • Rozdziel biblioteki: jedna do współpracy, druga do rzeczy naprawdę poufnych,
  • Cztery licencje w pięciu komponentach, z AGPLv3 na rdzeniu serwera,
  • Klient dyskowy z synchronizacją na żądanie zastępuje dysk sieciowy,
  • Utrata hasła to utrata danych — zapisz to w umowie.

Licencja: Seafile nie ma jednej licencji i to jest pierwsza rzecz do zaraportowania przy audycie u klienta. Rdzeń serwera jest na AGPLv3 — najmocniejszym copylefcie w powszechnym użyciu, z klauzulą obejmującą udostępnianie usługi przez sieć. Znaczy to, że uruchomienie niezmodyfikowanego serwera dla klienta nie rodzi obowiązków publikacyjnych, ale modyfikacja rdzenia i udostępnienie go użytkownikom przez sieć wymaga udostępnienia im kodu tych zmian. Interfejs webowy Seahub jest natomiast na Apache-2.0, czyli licencji permisywnej — i to jest dobra wiadomość, bo większość realnych zmian we wdrożeniu dotyczy właśnie panelu: wyglądu, oznaczeń i drobnych funkcji. Klient desktopowy jest na GPLv2, z jawnie dodanym pozwoleniem na łączenie z OpenSSL — klauzulą, której brak historycznie tworzył realny problem prawny w projektach GPL korzystających z tej biblioteki; jej obecność świadczy o tym, że ktoś tu przemyślał sprawę. Klienci mobilne dokładają jeszcze Apache-2.0 na iOS i GPLv3 na Androida. Poza kodem trzeba wziąć pod uwagę dwie rzeczy. Po pierwsze, istnieje edycja komercyjna prowadzona przez Seafile Ltd., z osobnym kanałem wsparcia; przy wyborze wersji darmowej warto sprawdzić, które funkcje potrzebne klientowi są po której stronie. Po drugie i praktyczniej: integracje z pakietami biurowymi online mają własne licencje i własne modele rozliczeń, więc „darmowa chmura plików z edycją dokumentów" bywa darmowa tylko w części dotyczącej plików.