FreshRSS na VPS: instalacja na Ubuntu 24.04
Zainstaluj FreshRSS 1.29.1 na Ubuntu 24.04 z Apache, PHP 8.3 i MariaDB. Skonfiguruj virtual host, cron odświeżający kanały oraz API aplikacji mobilnej.
Co jest instalowane
Samodzielnie hostowany czytnik RSS to czytnik kanałów działający na własnym serwerze. Dzięki temu nikt nie może go wyłączyć ani zmienić wyświetlanych treści. W tym przewodniku FreshRSS zostanie uruchomiony na VPS z Ubuntu 24.04: Apache będzie serwerem frontowym, PHP będzie obsługiwać aplikację, MariaDB będzie przechowywać dane, a jedno zadanie cron będzie pobierać nowe artykuły. RSS (really simple syndication) to format pliku publikowany przez witrynę, aby oprogramowanie mogło odczytywać jej artykuły. FreshRSS to aplikacja PHP, która gromadzi te pliki, przechowuje artykuły oraz udostępnia interfejs WWW i API (application programming interface), z którym komunikują się aplikacje mobilne.
Sama instalacja jest niewielka: należy rozpakować wydanie, utworzyć bazę danych, zapisać jedną konfigurację virtual hosta i uruchomić jeden instalator wiersza poleceń. Większość opisanych poniżej czynności dotyczy problemów występujących później: zadania odświeżania, kodowania ukośników w ścieżkach mobilnego API oraz własności plików.
FreshRSS 1.29.1 jest aktualnym wydaniem na lipiec 2026 i wymaga PHP 8.1 lub nowszego. Ubuntu 24.04 zawiera PHP 8.3, dlatego wystarczą pakiety dystrybucyjne i nie ma potrzeby dodawania repozytorium PHP innej firmy.
Rozpoczęcie od działającego stosu LAMP
FreshRSS to zwykła aplikacja PHP, dlatego wymaga takiej samej podstawy jak inne aplikacje tego typu. Jeśli ta podstawa nie została jeszcze skonfigurowana, należy najpierw wykonać konfigurację stosu LAMP w Ubuntu 24.04, a następnie wrócić tutaj. W skrócie:
sudo apt update
sudo apt install -y apache2 mariadb-server php libapache2-mod-php
sudo systemctl enable --now apache2 mariadbsystemctl status apache2 powinno zwrócić active (running). Jeśli Apache nie uruchamia się, zwykle oznacza to, że inny proces już zajmuje port 80. Polecenie sudo ss -ltnp | grep :80 wyświetla jego nazwę.
Rozszerzenia PHP wymagane przez FreshRSS
FreshRSS traktuje libxml, cURL, JSON, PDO_MySQL, PCRE i ctype jako wymagane. Wymaga również mbstring, iconv, Zlib i ZipArchive, a w systemie 32-bitowym także GMP. W systemie Ubuntu są one dostarczane w postaci pakietów dystrybucyjnych:
sudo apt install -y php-curl php-mbstring php-xml php-zip php-mysql php-intl php-gmp
sudo systemctl restart apache2Sprawdź, które rozszerzenia zostały faktycznie załadowane przez PHP, używając php -m. Brak rozszerzenia nie uniemożliwia uruchomienia instalatora. Instalator zatrzyma się na ekranie wymagań i wyświetli czerwony wiersz z nazwą rozszerzenia. Wykrycie problemu dopiero w tym miejscu może być mylące, dlatego należy sprawdzić to teraz. Ponowne uruchomienie Apache ma znaczenie, ponieważ libapache2-mod-php utrzymuje PHP wewnątrz procesu Apache. Dlatego nowo zainstalowane rozszerzenie pozostaje niewidoczne dla serwera WWW do czasu jego ponownego uruchomienia.
Pobieranie wydania
Zainstaluj FreshRSS poza domyślnym katalogiem głównym serwera WWW i wskaż go w konfiguracji Apache. Oddzielenie katalogu aplikacji od katalogu dokumentów sprawia, że przez HTTP dostępny jest wyłącznie katalog publiczny.
cd /tmp
curl -fsSLO https://github.com/FreshRSS/FreshRSS/archive/refs/tags/1.29.1.tar.gz
tar xzf 1.29.1.tar.gz
sudo mv FreshRSS-1.29.1 /srv/freshrssUstaw teraz uprawnienia, zgodnie z wymaganiami dokumentacji FreshRSS: użytkownik serwera WWW jest właścicielem całego drzewa, grupa może odczytywać każdy plik, a grupa może zapisywać w ./data/.
sudo chown -R www-data:www-data /srv/freshrss
sudo chmod -R g+r /srv/freshrss
sudo chmod -R g+w /srv/freshrss/dataPominięcie tego kroku powoduje niepowodzenie instalatora podczas zapisywania konfiguracji, ponieważ PHP działa jako www-data, a www-data nie może zapisywać w katalogu należącym do root.
Utworzenie bazy danych
FreshRSS obsługuje SQLite, MariaDB, MySQL i PostgreSQL. SQLite nie wymaga konfiguracji i jest odpowiedni dla jednej osoby korzystającej z kilkuset kanałów. Po udostępnieniu instancji kilku osobom lepszym wyborem jest MariaDB, ponieważ równoczesne zapisy z zadania odświeżania i interfejsu internetowego nie konkurują już o blokadę pojedynczego pliku.
sudo mariadb -e "CREATE DATABASE freshrss CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
sudo mariadb -e "CREATE USER 'freshrss'@'localhost' IDENTIFIED BY 'ReplaceThisPassword';"
sudo mariadb -e "GRANT ALL PRIVILEGES ON freshrss.* TO 'freshrss'@'localhost';"
sudo mariadb -e "FLUSH PRIVILEGES;"Należy użyć utf8mb4, a nie utf8. Kanały zawierają emoji i znaki z alfabetów innych niż łaciński, a użycie starszego, trzybajtowego kodowania utf8 powoduje obcięcie tytułu artykułu przy pierwszym znaku zajmującym 4 bajty.
Wirtualny host Apache
Katalog publiczny to p/, a nie najwyższy poziom drzewa katalogów. Wszystkie pozostałe elementy, w tym plik konfiguracyjny zawierający hasło do bazy danych, znajdują się powyżej katalogu głównego dokumentów, dlatego Apache nigdy ich nie udostępni.
<VirtualHost *:80>
ServerName rss.example.com
DocumentRoot /srv/freshrss/p/
<Directory /srv/freshrss/p>
AllowOverride AuthConfig FileInfo Indexes Limit
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/freshrss_error.log
CustomLog ${APACHE_LOG_DIR}/freshrss_access.log combined
AllowEncodedSlashes On
</VirtualHost>Zapisz konfigurację jako /etc/apache2/sites-available/freshrss.conf i włącz ją:
sudo a2enmod rewrite
sudo a2ensite freshrss
sudo a2dissite 000-default
sudo apache2ctl configtest
sudo systemctl reload apache2Polecenie configtest powinno wyświetlić Syntax OK. Dyrektywa AllowEncodedSlashes On może wyglądać na opcjonalną, ale nie jest opcjonalna: interfejs API Google Reader wysyła identyfikatory kanałów zawierające %2F. Bez tej dyrektywy Apache je odrzuca, dlatego aplikacje mobilne nie mogą synchronizować danych, mimo że interfejs WWW działa prawidłowo.
Dodaj HTTPS przed zalogowaniem
Za chwilę zostanie wpisane hasło do tej witryny, dlatego najpierw należy uzyskać certyfikat. Należy skierować rekord A na serwer, a następnie postępować zgodnie z instrukcją konfiguracji Certbot dla Apache na Ubuntu i uruchomić sudo certbot --apache -d rss.example.com. Certbot modyfikuje konfigurację virtual hosta dla portu 443 i dodaje przekierowanie. Należy potwierdzić działanie za pomocą curl -I https://rss.example.com/. Polecenie powinno zwrócić 200 lub przekierowanie do strony logowania.
Uruchamianie instalatora z wiersza poleceń
FreshRSS ma instalator uruchamiany w przeglądarce, ale wersja z wiersza poleceń jest powtarzalna i pozostawia zapis dokładnie wybranych opcji.
sudo -u www-data php /srv/freshrss/cli/do-install.php \
--default-user admin --auth-type form --environment production \
--base-url https://rss.example.com --language en --api-enabled \
--db-type mysql --db-host localhost --db-user freshrss \
--db-password 'ReplaceThisPassword' --db-base freshrss
sudo -u www-data php /srv/freshrss/cli/create-user.php \
--user admin --password 'a-long-passphrase' --api-password 'a-different-passphrase'Uruchom oba polecenia jako www-data. Uruchomienie ich jako root powoduje utworzenie plików konfiguracyjnych należących do root. Interfejs WWW nie może wtedy później zapisywać żadnych ustawień. Znaczenie ma również --environment production, ponieważ ustawienie deweloperskie wyświetla komunikaty PHP w treści strony.
Załaduj https://rss.example.com/ i zaloguj się jako admin.
Dlaczego kanały nie odświeżają się automatycznie
Kanały nie są odpytywane, dopóki nie zostanie to skonfigurowane. FreshRSS odświeża kanały, gdy w przeglądarce jest otwarta jego strona. Oznacza to, że instancja odwiedzana dwa razy dziennie wyświetla artykuły sprzed dwunastu godzin. Rozwiązaniem jest dostarczony przez projekt skrypt app/actualize_script.php uruchamiany przez cron.
sudo crontab -u www-data -eDodaj jeden wiersz:
*/20 * * * * php /srv/freshrss/app/actualize_script.php > /tmp/FreshRSS.log 2>&1Dwadzieścia minut to rozsądne minimum, ponieważ skrypt nie odświeża żadnego pojedynczego kanału częściej niż raz na dwadzieścia minut. Krótszy interwał powoduje więc tylko niepotrzebne zużycie CPU. Najpierw uruchom skrypt ręcznie:
sudo -u www-data php /srv/freshrss/app/actualize_script.phpPrawidłowe działanie powoduje wyświetlenie nazwy każdego pobranego kanału i kończy się bez błędu PHP. Jeśli skrypt nie wyświetli niczego, użyto niewłaściwego użytkownika cron. Błąd uprawnień dotyczący data/ oznacza, że pominięto krok chmod -R g+w.
Dodawanie pierwszych kanałów
Użyj przycisku plusa w lewym górnym rogu interfejsu, wklej adres witryny, a FreshRSS automatycznie znajdzie odnośnik do kanału. Większość witryn nadal publikuje kanał, nawet jeśli go nie reklamuje, zwykle pod adresem /feed, /rss lub /atom.xml. Kategorie są folderami, a przenoszenie kanału między nimi odbywa się metodą przeciągania.
Jeśli używany był wcześniej inny czytnik, wyeksportuj w nim plik OPML i zaimportuj go na stronie zarządzania subskrypcjami. OPML (outline processor markup language) to standardowy format listy kanałów, obsługiwany przez każdy czytnik, z którego warto zrezygnować. Duży import jest wolny podczas pierwszego odświeżania, ponieważ każdy kanał jest pobierany jeden raz. Przed oceną szybkości należy odczekać na pierwsze uruchomienie zadania cron.
Czytaj na telefonie
FreshRSS obsługuje Google Reader API, które jest obsługiwane przez prawie każdą aplikację RSS. Muszą być spełnione dwa warunki. W ustawieniach uwierzytelniania opcja „Allow API access” musi być włączona. Ustawiono ją już za pomocą flagi --api-enabled powyżej. W profilu pole hasła API musi zawierać wartość. Jest ono celowo oddzielone od hasła logowania, ponieważ telefon łatwiej zgubić.
Przejdź do https://rss.example.com/api/ i wybierz „Check full server configuration”. Prawidłowo działająca konfiguracja zwraca PASS. Przyczyną niepowodzenia jest prawie zawsze brak wiersza AllowEncodedSlashes On. W aplikacji jako adres serwera podaj https://rss.example.com/api/greader.php, jako nazwę użytkownika podaj użytkownika FreshRSS, a jako hasło podaj hasło API.
Alternatywa dla Docker
Jeśli nie chcesz ręcznie utrzymywać PHP i Apache, projekt publikuje oficjalny obraz freshrss/freshrss, a jeden plik Compose zapewnia aplikację i jej bazę danych. Kompromis jest standardowy: mniej elementów do utrzymania na hoście, ale dodatkowa warstwa do diagnozowania w razie awarii. Do obsługi TLS (bezpieczeństwo warstwy transportowej) nadal potrzebny jest reverse proxy. Jeśli takie rozwiązanie jest bardziej odpowiednie, podstawy Docker Compose dla VPS opisują format pliku, a wpis cron przyjmuje postać docker exec --user www-data freshrss php ./app/actualize_script.php.
Kopie zapasowe i aktualizacje
Stan systemu jest przechowywany w dwóch miejscach: w bazie danych oraz w /srv/freshrss/data/. Utwórz zrzut pierwszego elementu za pomocą sudo mysqldump freshrss > freshrss.sql, skopiuj drugi i przechowuj obie kopie poza tym serwerem. Lista subskrypcji również powinna być okresowo eksportowana do formatu OPML, ponieważ ten plik pozwala odtworzyć konfigurację czytnika w dowolnym oprogramowaniu RSS.
Aktualizacja polega na rozpakowaniu nowszego wydania w tym samym katalogu i ponownym wykonaniu poleceń zmieniających właściciela. FreshRSS zastosuje własne migracje bazy danych podczas ładowania następnej strony. Najpierw utwórz kopię zapasową, ponieważ nieudana migracja bazy danych, której nie można odtworzyć, prowadzi do sytuacji bez możliwości odzyskania danych. Uruchomienie czytnika wiąże się z niskim ryzykiem, dlatego jest to dobry pierwszy kandydat, jeśli przeglądana jest lista usług, które warto hostować samodzielnie.
FAQ
Dlaczego moje kanały aktualizują się tylko po otwarciu FreshRSS?
Dzieje się tak, ponieważ harmonogram nie istnieje, dopóki nie zostanie utworzony. FreshRSS odświeża kanały, gdy sesja przeglądarki jest otwarta, i nie wykonuje żadnych działań po zamknięciu karty. Należy dodać wpis cron wywołujący app/actualize_script.php jako użytkownik www-data, a następnie ręcznie uruchomić skrypt i odczytać jego dane wyjściowe. Brak danych zwykle oznacza, że cron uruchamia skrypt jako niewłaściwy użytkownik, dlatego PHP nie może zapisywać do data/.
Aplikacja mobilna nie może się połączyć, ale strona internetowa działa. Dlaczego?
Google Reader API umieszcza zakodowane ukośniki (%2F) w ścieżkach żądań, a Apache domyślnie je odrzuca. Należy dodać AllowEncodedSlashes On w obrębie virtual hosta i ponownie wczytać konfigurację Apache. Poprawność zmiany należy potwierdzić, otwierając https://rss.example.com/api/ i uruchamiając „Check full server configuration”; wynik powinien zawierać PASS. Należy także sprawdzić, czy hasło API zostało ustawione w profilu, ponieważ różni się ono od hasła logowania.
Czy należy używać SQLite czy MariaDB?
SQLite jest odpowiedni dla jednego użytkownika, ponieważ nie wymaga instalacji ani zarządzania hasłem. MariaDB należy wybrać, gdy z instancji korzysta więcej niż jedna osoba lub gdy liczba kanałów przekracza kilkaset, ponieważ zadanie odświeżania i interfejs internetowy zapisują dane jednocześnie, a pojedyncza blokada pliku staje się ograniczeniem. Późniejsza migracja między tymi rozwiązaniami jest możliwa za pomocą poleceń eksportu i importu, więc nie jest to decyzja nieodwracalna.
Instalator kończy działanie błędem podczas zapisywania konfiguracji. Jaki jest problem?
PHP działa w Apache jako www-data, a ten użytkownik nie może zapisywać do katalogu należącego do root. Należy ponownie uruchomić sudo chown -R www-data:www-data /srv/freshrss i sudo chmod -R g+w /srv/freshrss/data, a następnie ponownie uruchomić instalator. Jeśli instalator wiersza poleceń został już uruchomiony jako root, przed ponowną próbą należy usunąć pliki utworzone przez niego w data/, ponieważ problemem są ich uprawnienia i właściciel.
Jakich zasobów serwera potrzebuje samodzielnie hostowany czytnik RSS?
Niewielkich. Kilkaset kanałów na małym planie nie powinno powodować problemów, ponieważ obciążenie ma postać krótkich serii żądań HTTP wykonywanych co dwadzieścia minut, a baza danych pozostaje niewielka po usunięciu starych artykułów. Zajętość dysku rośnie wraz z okresem przechowywania, dlatego w ustawieniach archiwizacji należy skonfigurować zasady usuwania artykułów zamiast przechowywać je bezterminowo.