Samodzielny czytnik RSS na VPS: porównanie rozwiązań
Porównanie Miniflux, FreshRSS, CommaFeed, yarr oraz Tiny Tiny RSS pod kątem zużycia RAM, wymagań PostgreSQL lub SQLite oraz wsparcia dla API Fever i Google Reader na serwerze VPS.
Który samodzielnie hostowany czytnik RSS pasuje na mały VPS
Miniflux to czytnik RSS do samodzielnego hostowania, który warto umieścić na małym VPS. Składa się z jednego pliku binarnego Go oraz bazy danych PostgreSQL. Obsługuje API Fever oraz Google Reader, dzięki czemu łączą się z nim zewnętrzne aplikacje mobilne, a aktualizacja sprowadza się do jednego docker compose pull. Wybierz FreshRSS, jeśli potrzebujesz rozszerzeń oraz jednego kontenera z wbudowaną bazą SQLite.
Pięć czytników jest wartych miejsca na dysku VPS: Miniflux, FreshRSS, CommaFeed, yarr oraz Tiny Tiny RSS. Ta strona porównuje rzeczywiste różnice między nimi: zapotrzebowanie na pamięć RAM, wymaganą bazę danych, obsługiwane API synchronizacji dla aplikacji mobilnych oraz przebieg procesu aktualizacji. Każda liczba w tym zestawieniu pochodzi z dokumentacji projektu lub jest wynikiem prostych obliczeń, co zostało zaznaczone w tekście. Żaden z tych wyników nie jest benchmarkiem Twojego sprzętu, dlatego przeprowadź pomiary na własnej maszynie za pomocą docker stats.
Pięć czytników, po jednym akapicie
Miniflux jest napisany w języku Go i jest dostarczany jako pojedynczy, statycznie skompilowany plik binarny. Dokumentacja wprost wskazuje na jedną twardą zależność: aplikacja „działa wyłącznie z PostgreSQL”. Nie istnieje tryb SQLite. Program oferuje API typu REST, API kompatybilne z Fever oraz API kompatybilne z Google Reader, a także funkcje importu i eksportu OPML. Wyszukiwanie pełnotekstowe jest obsługiwane przez PostgreSQL, co stanowi jeden z powodów, dla których baza danych nie jest opcjonalna.
FreshRSS jest oparty na PHP i działa jako jeden kontener zawierający zarówno serwer WWW, jak i aplikację. SQLite jest domyślną bazą danych i nie wymaga osobnej usługi, natomiast PostgreSQL i MySQL są wspierane w przypadku większych instalacji. Aplikacja obsługuje API Google Reader oraz API Fever. Instalacja została już opisana w naszym przewodniku po FreshRSS na VPS, więc ta strona skupia się na porównaniu, zamiast powtarzać proces instalacji.
CommaFeed to aplikacja Java na frameworku Quarkus, której układ interfejsu kopiuje Google Reader. Baza danych jest wybierana na etapie budowania, a nie uruchamiania, dlatego projekt publikuje jeden obraz na bazę danych: athou/commafeed:latest-h2 dla wbudowanej bazy H2, athou/commafeed:latest-postgresql dla PostgreSQL oraz kolejne warianty dla MySQL i MariaDB. Aplikacja udostępnia API typu REST oraz API kompatybilne z Fever.
yarr (yet another rss reader) to pojedynczy plik binarny w języku Go z wbudowaną bazą SQLite, który nie wymaga kontenera. Zwykłe polecenie ./yarr uruchamia nasłuchiwanie na 127.0.0.1:7070. Flagi są krótkie: -addr 0.0.0.0:7070 -auth alice:secret udostępnia aplikację w sieci za hasłem, a -db /data/yarr.db pozwala wskazać lokalizację bazy danych. Czytnik posiada API kompatybilne z Fever. Najnowsze wydanie z tagiem to v2.8 z lipca 2024 roku, sprawdzone w sierpniu 2026 roku, więc należy traktować to oprogramowanie jako ukończone, a nie aktywnie rozwijane.
Tiny Tiny RSS jest najstarszym z pięciu czytników i najbardziej zasobożernym. Oficjalna konfiguracja Docker obejmuje cztery usługi: kontener PostgreSQL, kontener aplikacji PHP-FPM, osobny kontener aktualizatora pobierający kanały oraz kontener nginx działający jako warstwa przednia. Dokumentacja jasno stwierdza, że „ta konfiguracja wykorzystuje PostgreSQL”. Aplikacja posiada własne API JSON, z którego korzysta jej klient na system Android oraz kilka aplikacji zewnętrznych. Obsługa Fever nie jest częścią tego rozwiązania.
Zapotrzebowanie poszczególnych stosów na pamięć
Poniższe wartości to budżety, a nie pomiary: górne limity pamięci, w których każdy stos powinien się mieścić na małym VPS. Wartość dla CommaFeed pochodzi z oficjalnej dokumentacji projektu, która ogranicza kontener do 256 MB. Pozostałe wartości to limity uwzględniające zapas dla modułu pobierania kanałów, który wykazuje skoki zużycia zasobów w momencie rozpoczęcia cyklu odświeżania.
The data behind this chart
[
{
"label": "yarr (SQLite)",
"containers": 1,
"mem_limit_mb": 128
},
{
"label": "FreshRSS (SQLite)",
"containers": 1,
"mem_limit_mb": 256
},
{
"label": "CommaFeed (H2)",
"containers": 1,
"mem_limit_mb": 256
},
{
"label": "Miniflux + Postgres",
"containers": 2,
"mem_limit_mb": 320
},
{
"label": "Tiny Tiny RSS",
"containers": 4,
"mem_limit_mb": 640
}
]yarr zajmuje najmniej miejsca, bo 128 MB, ponieważ składa się z jednego pliku binarnego i jednego pliku SQLite, bez zewnętrznego serwera bazy danych czy środowiska uruchomieniowego języka. Miniflux wymaga 320 MB w ramach 2 kontenerów, przy czym większość tego zasobu przypada na PostgreSQL, a nie na sam Miniflux. Tiny Tiny RSS jest wyjątkiem z wartością 640 MB w ramach 4 kontenerów, ponieważ aplikacja, moduł aktualizacji, baza danych i serwer WWW to cztery oddzielne procesy z czterema oddzielnymi stertami pamięci.
Należy ustawić te wartości jako rzeczywiste limity, a nie tylko założenia. Limity pamięci w Docker Compose opisują składnię oraz zachowanie kontenera po osiągnięciu limitu. Kontener bez limitu nie kończy pracy w sposób kontrolowany po wyczerpaniu pamięci na serwerze: jądro systemu wybiera proces-ofiarę i kończy go, a ofiarą często nie jest kontener, który spowodował przeciążenie.
Wymuszane bazy danych w poszczególnych czytnikach
Baza danych stanowi największą różnicę operacyjną między tymi pięcioma rozwiązaniami. Jest to decyzja o większym znaczeniu niż jakakolwiek różnica w interfejsie użytkownika, ponieważ determinuje ona procedurę tworzenia kopii zapasowych oraz ryzyko związane z aktualizacjami.
PostgreSQL jest wymagany przez Miniflux oraz oficjalną konfigurację Tiny Tiny RSS. Zapewnia on pełnotekstowe wyszukiwanie oraz bezpieczne zapisy współbieżne. Wiąże się to z koniecznością utrzymywania drugiego kontenera, wolumenu oraz jednym powracającym problemem: oficjalne obrazy PostgreSQL nie potrafią migrować danych między głównymi wersjami w miejscu. Dokumentacja Tiny Tiny RSS mówi o tym wprost i ostrzega, że „oficjalne kontenery PostgreSQL nie wspierają migracji danych między głównymi wersjami”. Realne opcje to przypięcie starej głównej wersji lub wykonanie zrzutu i przywrócenia danych za pomocą pg_dump oraz pg_restore. Należy zaplanować taką operację raz na rok lub dwa lata.
SQLite jest domyślnym rozwiązaniem dla FreshRSS oraz yarr. Jeden plik, brak serwera, brak portu, brak hasła. Sprawdza się dobrze w przypadku jednej osoby z kilkuset kanałami, natomiast zwalnia, gdy wielu użytkowników zapisuje dane jednocześnie – wtedy opcja PostgreSQL we FreshRSS zaczyna uzasadniać swoje zastosowanie. Program yarr dodał opcjonalne wsparcie dla PostgreSQL w wersji v2.7, jednak użycie wbudowanego pliku jest standardowym sposobem uruchomienia.
H2 jest domyślną wbudowaną bazą dla CommaFeed i wymaga chwili zastanowienia przed rozpoczęciem, ponieważ CommaFeed wybiera bazę danych w momencie budowania obrazu. Przejście z H2 na PostgreSQL w późniejszym czasie nie jest zwykłą zmianą konfiguracji. Wymaga użycia innego obrazu oraz samodzielnego przeprowadzenia migracji danych, dlatego decyzję należy podjąć, zanim w systemie zgromadzi się rok historii przeczytanych artykułów.
Czy aplikacja mobilna będzie działać
To pytanie ma większe znaczenie, niż się powszechnie uważa, ponieważ interfejs webowy stanowi tylko połowę sposobu korzystania z czytnika kanałów.
Miniflux obsługuje API kompatybilne z Fever oraz API kompatybilne z Google Reader, dzięki czemu większość klientów na iOS i Androida łączy się z nim bez problemu. FreshRSS obsługuje te same dwa standardy, a jego dokumentacja ocenia je następująco: API Google Reader jest „najlepsze” i zapewnia pełną obsługę funkcji, podczas gdy API Fever oferuje „ograniczone funkcje i mniej wydajne” działanie. FreshRSS wymaga również wykonania dwóch kroków, zanim jakakolwiek aplikacja będzie mogła się zalogować. Należy włączyć opcję „Allow API access (required for mobile apps)” w sekcji Authentication, a następnie utworzyć hasło API w profilu użytkownika. Pominiecie kroku z hasłem API skutkuje błędem uwierzytelniania w aplikacji, podczas gdy logowanie przez przeglądarkę nadal działa, co bywa mylące, dopóki nie wiadomo, gdzie szukać przyczyny.
CommaFeed oraz yarr udostępniają wyłącznie API kompatybilne z Fever, więc współpracują z klientami obsługującymi ten standard, ale nie z aplikacjami komunikującymi się tylko przez Google Reader. Tiny Tiny RSS posiada własne, dedykowane API, co oznacza, że wymagany jest klient napisany specjalnie dla tego oprogramowania. Przed zaimportowaniem 300 kanałów należy sprawdzić, czy preferowana aplikacja obsługuje dany czytnik.
Działający plik compose dla serwera 1 GB
Oto stos Miniflux, dostosowany do przykładu Docker dostarczonego przez projekt w sierpniu 2026. Opublikowany port jest powiązany z interfejsem loopback, adres nasłuchiwania jest ustawiony jawnie, a oba kontenery posiadają limit pamięci.
services:
miniflux:
image: miniflux/miniflux:latest
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
depends_on:
db:
condition: service_healthy
environment:
- DATABASE_URL=postgres://miniflux:CHANGE_ME@db/miniflux?sslmode=disable
- LISTEN_ADDR=0.0.0.0:8080
- BASE_URL=https://rss.example.com/
- RUN_MIGRATIONS=1
- CREATE_ADMIN=1
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=CHANGE_ME_TOO
- POLLING_FREQUENCY=60
healthcheck:
test: ["CMD", "/usr/bin/miniflux", "-healthcheck", "auto"]
mem_limit: 128m
db:
image: postgres:18
restart: unless-stopped
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=CHANGE_ME
- POSTGRES_DB=miniflux
volumes:
- miniflux-db:/var/lib/postgresql
healthcheck:
test: ["CMD", "pg_isready", "-U", "miniflux"]
interval: 10s
start_period: 30s
mem_limit: 192m
volumes:
miniflux-db:Trzy linie w tym pliku są najczęściej błędnie konfigurowane. LISTEN_ADDR=0.0.0.0:8080 jest ustawione, ponieważ udokumentowana wartość domyślna binarki to 127.0.0.1:8080, a proces powiązany z loopback wewnątrz kontenera nie jest dostępny przez opublikowany port, co skutkuje błędem connection reset przy kontenerze wyglądającym na poprawnie działający. Ścieżka wolumenu /var/lib/postgresql odpowiada PostgreSQL 18; wersja 17 i starsze przechowują dane w /var/lib/postgresql/data, a zamontowanie błędnej ścieżki powoduje, że katalog danych nie znajduje się na wolumenie, co skutkuje utratą danych przy ponownym tworzeniu kontenera. 127.0.0.1:8080:8080 izoluje port od publicznego Internetu, ponieważ publikacja portu bez adresu dodaje regułę do łańcucha, którym ufw nie zarządza. Porty Docker omijające ufw wyjaśnia ten mechanizm, a reverse proxy Traefik wskazuje sposób zabezpieczenia go za pomocą TLS.
docker compose up -d
docker compose ps
docker compose logs -f miniflux
docker stats --no-streamdocker compose ps powinno wykazać działanie obu usług, z bazą danych oznaczoną jako healthy. Pierwsze uruchomienie Miniflux loguje migracje schematu, co jest wyzwalane przez RUN_MIGRATIONS=1. docker stats --no-stream wyświetla kolumnę bieżącego zużycia pamięci, którą należy porównać z limitami w powyższej tabeli. Jeśli kontener Miniflux restartuje się w pętli, należy sprawdzić jego logi: connect: connection refused oznacza, że wystartował on przed gotowością PostgreSQL do przyjmowania połączeń, czemu zapobiega warunek service_healthy, więc należy zweryfikować, czy warunek ten pozostał w pliku po edycji. Jeśli Compose jest nowym narzędziem, Podstawy Docker Compose na VPS opisuje strukturę plików.
Co nie zmieści się na serwerze 1 GB
Tiny Tiny RSS to usługa, z której należy zrezygnować. Jej oficjalny stos czterech usług działa na VPS 1 GB tylko wtedy, gdy serwer nie wykonuje żadnych innych zadań i nie współdzieli zasobów z inną aplikacją bazodanową oraz reverse proxy. Cztery usługi oznaczają cztery zestawy narzutów, a jedną z nich jest PostgreSQL.
CommaFeed mieści się w limitach, ale tylko przy użyciu obrazu H2 oraz limitu 256 MB, który wyznacza przykładowa konfiguracja projektu. Połączeniem, które przeciąża mały serwer, jest JVM działający obok osobnego serwera bazy danych, ponieważ JVM zajmuje każdą dostępną ilość pamięci. Dokumentacja CommaFeed wskazuje na -Xmx256m jako twardy limit oraz na OpenJ9 jako „bardziej wydajną pamięciowo alternatywę dla HotSpot JVM”, co wskazuje, gdzie zużywana jest pamięć.
Gdy serwerowi kończą się zasoby, mechanizm kernel out of memory killer wybiera proces i kończy jego działanie. dmesg -T wyświetla linię taką jak Out of memory: Killed process 1234 (java), a kontener po prostu znika z docker compose ps bez żadnego komunikatu w dzienniku aplikacji, ponieważ aplikacja nie zdążyła go zapisać.
Zachowanie aktualizacji dla poszczególnych rozwiązań
- Miniflux:
docker compose pull && docker compose up -d, z migracjami schematu wykonywanymi przy starcie, gdy ustawionoRUN_MIGRATIONS=1. Ryzyko związane z aktualizacją nie dotyczy samego Miniflux, lecz używanej wersji głównej PostgreSQL. - FreshRSS: należy pobrać nowy obraz. W przypadku SQLite nie ma silnika bazy danych do aktualizacji, więc typowe problemy wynikają z niekompatybilności rozszerzeń firm trzecich.
- CommaFeed: należy pobrać wariant obrazu zgodny z używaną bazą danych. Przejście z
latest-h2nalatest-postgresqlnie przenosi danych automatycznie. - yarr: należy zastąpić plik binarny i zachować plik bazy danych. Ponieważ od wydania v2.8 w lipcu 2024 r. (stan na sierpień 2026 r.) nie pojawiły się nowe wersje, zazwyczaj nie ma czego aktualizować.
- Tiny Tiny RSS:
docker compose pull && docker compose up -d. Migracje schematu uruchamiane są automatycznie, a interfejs przekierowuje użytkownika do ekranu migracji, gdy wymagane jest potwierdzenie.
Kopię zapasową bazy danych należy wykonać przed przystąpieniem do jakichkolwiek działań, a nie po nich.
docker compose exec -T db pg_dump -U miniflux miniflux | gzip > miniflux-$(date +%F).sql.gzKoszt interwału odświeżania w kontekście przepustowości
Poniższe liczby wynikają z obliczeń arytmetycznych, a nie z pomiarów. Przyjęto założenie 100 kanałów, jedno żądanie na kanał w każdym interwale oraz 40 KB na odpowiedź. Rzeczywisty ruch jest mniejszy, gdy serwer honoruje żądania warunkowe, a większy, gdy kanały zawierają pełną treść artykułów.
The data behind this chart
[
{
"label": "Every 5 minutes",
"fetches_per_month": "864,000",
"gb_per_month": 34.6
},
{
"label": "Every 15 minutes",
"fetches_per_month": "288,000",
"gb_per_month": 11.5
},
{
"label": "Every 30 minutes",
"fetches_per_month": "144,000",
"gb_per_month": 5.8
},
{
"label": "Every 60 minutes",
"fetches_per_month": "72,000",
"gb_per_month": 2.9
}
]Pięciominutowy interwał dla 100 kanałów to 864,000 żądań i około 34.6 GB miesięcznie. Odpytywanie co godzinę to 72,000 żądań i około 2.9 GB. Miniflux jest dostarczany z parametrem POLLING_FREQUENCY ustawionym na 60 minut, co odpowiada ostatniemu wierszowi tabeli; to ustawienie domyślne jest właściwe dla większości użytkowników. Artykuł nie pojawi się szybciej tylko dlatego, że częściej o niego pytasz.
Żądania warunkowe pozwalają utrzymać rzeczywistą liczbę transferów poniżej wartości wynikających z obliczeń arytmetycznych. Czytnik, który przechowuje nagłówki ETag oraz Last-Modified zwrócone przez kanał, odsyła je w kolejnym żądaniu jako If-None-Match oraz If-Modified-Since. Serwer, który nie posiada nowych danych, odpowiada kodem 304 Not Modified bez treści. Połączenie nadal wymaga wykonania uzgadniania (handshake), ale nie przesyła ładunku danych. Kanały ignorujące żądania warunkowe przesyłają cały dokument za każdym razem, więc kilka dużych kanałów może samodzielnie zdominować rachunek za transfer.
Zbyt częste odpytywanie prowadzi również do zablokowania. Serwer, który uzna, że jest przeciążany, odpowiada kodem 429 Too Many Requests, a niektóre witryny zwracają 403. Miniflux zapisuje ostatni błąd przy konkretnym kanale, dlatego lista kanałów jest pierwszym miejscem, które należy sprawdzić, gdy jeden kanał przestaje się aktualizować, podczas gdy pozostałe działają poprawnie.
Kanały RSS wygasają, a plik OPML nie jest kopią zapasową
Kanały RSS dezaktualizują się szybciej, niż można przypuszczać. Domeny wygasają, witryny przenoszą się na platformy bez obsługi kanałów, a adres URL, który wcześniej serwował XML, zaczyna zwracać stronę błędu HTML ze statusem 200 OK. Ten ostatni przypadek jest najbardziej problematyczny: pobranie kończy się sukcesem, parsowanie nie, a czytnik rejestruje błąd parsowania zamiast błędu sieciowego. Raz w roku posortuj listę kanałów według daty ostatniej aktualizacji i usuń te, które przestały działać.
Eksport OPML to jedynie lista subskrypcji. Zawiera adresy URL kanałów i nazwy folderów. Nie przechowuje stanu przeczytania, oznaczonych artykułów, ustawień dla poszczególnych kanałów, reguł filtrowania ani zapisanej treści artykułów. Zaimportowanie tego pliku OPML do nowej instalacji przywróci kanały, ale wszystkie przeczytane wcześniej artykuły zostaną ponownie oznaczone jako nieprzeczytane.
Kluczową kopią zapasową jest baza danych. W przypadku PostgreSQL całe zadanie sprowadza się do polecenia pg_dump wspomnianego powyżej. Dla czytników opartych na SQLite, takich jak FreshRSS czy yarr, należy zatrzymać proces zapisu i skopiować plik lub wykonać spójną kopię w trakcie działania za pomocą sqlite3 yarr.db ".backup '/tmp/yarr-backup.db'". Zwykłe polecenie cp wykonane na bazie danych, do której trwa zapis, może wygenerować plik, którego nie da się później otworzyć, ponieważ kopia przechwyci niedokończoną operację zapisu. Następnie należy regularnie przesyłać te pliki poza serwer, do czego służą kopie zapasowe restic na VPS, oraz przynajmniej raz przywrócić bazę w kontenerze testowym, aby upewnić się, że procedura działa poprawnie.
Czytnik kanałów RSS to jedna z najtańszych usług do samodzielnego utrzymania, dlatego znajduje się na każdej liście rzeczy wartych hostowania we własnym zakresie w 2026. Uruchom obok własną instancję SearXNG, a zarówno czytanie, jak i wyszukiwanie pozostaną na sprzęcie, który kontrolujesz.
FAQ
Który samodzielnie hostowany czytnik RSS zużywa najmniej pamięci?
yarr. Jest to pojedynczy plik binarny Go z wbudowaną bazą SQLite, więc nie wymaga serwera bazy danych ani dodatkowego środowiska uruchomieniowego, a limit 128 MB jest w zupełności wystarczający. Ceną za to jest utrzymanie i funkcjonalność: najnowsze wydanie to v2.8 z lipca 2024 roku, a aplikacja obsługuje wyłącznie API Fever. Jeśli poszukiwany jest aktywnie rozwijany projekt o podobnym zapotrzebowaniu na zasoby, lepszym wyborem będzie Miniflux wraz z PostgreSQL przy limicie 320 MB.
Czy mogę uruchomić samodzielnie hostowany czytnik RSS na VPS z 1 GB pamięci RAM?
Tak. Miniflux z PostgreSQL mieści się w około 320 MB po ustawieniu mem_limit dla obu kontenerów, a FreshRSS z SQLite mieści się w jednym kontenerze. Na 1 GB pamięci należy unikać oficjalnego stosu Tiny Tiny RSS, który składa się z 4 usług, w tym własnej instancji PostgreSQL. Zawsze należy ustawiać limity pamięci, ponieważ kontener bez limitów na zapełnionym serwerze powoduje zabicie procesu przez jądro systemu, a procesem wybranym do zamknięcia jest często baza danych, a nie sama aplikacja.
Które z tych rozwiązań współpracują z aplikacjami RSS na iOS i Androida?
Miniflux i FreshRSS obsługują zarówno API kompatybilne z Fever, jak i z Google Reader, dzięki czemu łączy się z nimi niemal każdy klient mobilny. CommaFeed i yarr oferują wyłącznie API Fever. Tiny Tiny RSS korzysta z własnego API, więc wymaga klienta przygotowanego specjalnie dla niego. W przypadku FreshRSS należy dodatkowo włączyć dostęp do API w sekcji Authentication i ustawić osobne hasło API w profilu, w przeciwnym razie aplikacja nie zaloguje się, mimo że dostęp przez przeglądarkę będzie działał.
Czy eksport OPML jest kopią zapasową mojego czytnika RSS?
Nie. Plik OPML zawiera jedynie adresy URL kanałów i foldery, więc pozwala jedynie na odtworzenie listy subskrypcji. Stan przeczytania, oznaczone gwiazdką elementy, reguły filtrowania oraz treść artykułów znajdują się w bazie danych. Należy tworzyć kopie zapasowe samej bazy danych za pomocą pg_dump dla PostgreSQL lub polecenia .backup dla SQLite, a następnie kopiować wynik poza serwer.
Czy Miniflux obsługuje SQLite?
Nie. Dokumentacja projektu wskazuje, że działa on „wyłącznie z PostgreSQL”, a wyszukiwanie pełnotekstowe jest zaimplementowane przy użyciu funkcji PostgreSQL, więc nie ma możliwości przełączenia na lżejszy tryb. Jeśli wymagany jest czytnik kanałów bez zewnętrznego kontenera bazy danych, należy uruchomić FreshRSS z domyślnym backendem SQLite lub yarr z wbudowanym plikiem bazy.