Установка FreshRSS на VPS с Ubuntu 24.04
Пошаговое руководство по развертыванию FreshRSS на стеке Apache, PHP и MariaDB. Вы узнаете, как настроить виртуальный хост, права доступа и cron для обновления лент новостей.
Что вы создаете
RSS-агрегатор с самостоятельным хостингом — это программа для чтения лент, которая работает на вашем собственном сервере. Никто не сможет отключить ее или изменить содержимое, которое вы видите. В этом руководстве описывается установка FreshRSS на VPS с Ubuntu 24.04: Apache в качестве фронтенда, PHP в качестве бэкенда, MariaDB для хранения данных и одна задача cron для получения новых статей. RSS (Really Simple Syndication) — это формат файлов, который публикует сайт, чтобы стороннее ПО могло считывать его статьи. FreshRSS — это PHP-приложение, которое собирает эти файлы, сохраняет статьи и предоставляет веб-интерфейс, а также API (интерфейс программирования приложений), с которым работают мобильные приложения.
Сама установка невелика: распаковка релиза, создание базы данных, настройка виртуального хоста и запуск установщика из командной строки. Большая часть работы, описанной ниже, касается этапов, на которых пользователи часто совершают ошибки: настройка обновления лент, кодирование слэшей для мобильного API и права доступа к файлам.
FreshRSS 1.29.1 является актуальным релизом на июль 2026 года, для его работы требуется PHP 8.1 или новее. В Ubuntu 24.04 поставляется PHP 8.3, поэтому стандартных пакетов дистрибутива достаточно, и вам не нужно подключать сторонние репозитории PHP.
Начните с работающего стека LAMP
FreshRSS — это обычное приложение на PHP, поэтому для него требуется та же база, что и для любого другого. Если вы еще не подготовили эту базу, сначала выполните настройку стека LAMP для Ubuntu 24.04 и вернитесь сюда. Краткая версия:
sudo apt update
sudo apt install -y apache2 mariadb-server php libapache2-mod-php
sudo systemctl enable --now apache2 mariadbsystemctl status apache2 должен выводить active (running). Если Apache не запускается, обычно это происходит из-за того, что другой процесс уже занял порт 80, и sudo ss -ltnp | grep :80 укажет его имя.
PHP-расширения, необходимые для FreshRSS
FreshRSS требует наличия libxml, cURL, JSON, PDO_MySQL, PCRE и ctype. Также необходимы mbstring, iconv, Zlib, ZipArchive, а для 32-битных систем — GMP. В Ubuntu эти компоненты устанавливаются как системные пакеты:
sudo apt install -y php-curl php-mbstring php-xml php-zip php-mysql php-intl php-gmp
sudo systemctl restart apache2Проверьте, какие расширения PHP загружены в данный момент, с помощью php -m. Отсутствие расширения не препятствует запуску установщика. Однако на этапе проверки системных требований появится сообщение об ошибке с указанием отсутствующего компонента. Чтобы избежать проблем на этом этапе, проверьте всё заранее. Перезапуск Apache обязателен, так как libapache2-mod-php загружает PHP непосредственно в процесс Apache, поэтому новые расширения будут недоступны веб-серверу до перезагрузки.
Загрузка релиза
Установите FreshRSS вне стандартного корневого каталога веб-сервера и укажите на него в настройках Apache. Размещение каталога приложения отдельно от корневого каталога документов гарантирует, что через HTTP доступна только папка public.
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/freshrssТеперь настройте права доступа, требования к которым во FreshRSS строги: пользователь веб-сервера должен владеть деревом каталогов, группа должна иметь права на чтение всех файлов, а также права на запись в ./data/.
sudo chown -R www-data:www-data /srv/freshrss
sudo chmod -R g+r /srv/freshrss
sudo chmod -R g+w /srv/freshrss/dataЕсли пропустить этот шаг, установщик завершится с ошибкой при записи конфигурации, так как PHP выполняется от имени www-data, а www-data не может записывать данные в каталог, принадлежащий пользователю root.
Создание базы данных
FreshRSS поддерживает SQLite, MariaDB, MySQL и PostgreSQL. SQLite не требует настройки и подходит для одного пользователя с несколькими сотнями лент. MariaDB является лучшим выбором при использовании экземпляра несколькими пользователями, так как одновременная запись из задачи обновления и веб-интерфейса больше не приводит к конфликтам из-за блокировки одного файла.
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;"Используйте utf8mb4, а не utf8. Ленты содержат эмодзи и нелатинские символы, а старая трехбайтовая кодировка utf8 обрезает заголовок статьи на первом четырехбайтовом символе.
Виртуальный хост Apache
Публичный каталог — это p/, а не корень дерева каталогов. Все остальные файлы, включая конфигурационный файл с паролем от базы данных, находятся выше корневого каталога документов, откуда Apache их не выдаст.
<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>Сохраните это как /etc/apache2/sites-available/freshrss.conf и активируйте конфигурацию:
sudo a2enmod rewrite
sudo a2ensite freshrss
sudo a2dissite 000-default
sudo apache2ctl configtest
sudo systemctl reload apache2configtest должен вывести Syntax OK. Директива AllowEncodedSlashes On кажется необязательной, но это не так: API Google Reader отправляет идентификаторы лент, содержащие %2F, и без этой директивы Apache отклоняет их. В результате мобильные приложения перестают синхронизироваться, хотя веб-интерфейс продолжает работать корректно.
Добавьте HTTPS перед входом в систему
Вы собираетесь ввести пароль на этом сайте, поэтому сначала получите сертификат. Укажите A-запись для сервера, затем выполните настройку Certbot для Apache в Ubuntu и запустите sudo certbot --apache -d rss.example.com. Certbot перепишет конфигурацию виртуального хоста для порта 443 и добавит перенаправление. Проверьте результат с помощью curl -I https://rss.example.com/, команда должна вернуть 200 или перенаправление на страницу входа.
Запуск установщика из командной строки
FreshRSS поддерживает установку через браузер, однако версия для командной строки позволяет повторять процесс и сохранять точную историю выбранных параметров.
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'Выполняйте обе команды от имени www-data. Запуск от имени root приводит к тому, что владельцем файлов конфигурации становится root, из-за чего веб-интерфейс впоследствии не может сохранять настройки. Параметр --environment production также важен, так как режим разработки выводит уведомления PHP непосредственно на страницу.
Загрузите https://rss.example.com/ и войдите в систему как admin.
Почему ленты не обновляются автоматически
Никакой процесс не опрашивает ваши ленты, пока вы не настроите его. FreshRSS выполняет обновление только тогда, когда открыт в браузере. Это означает, что если вы заходите в систему дважды в день, вы видите статьи, которые устарели на двенадцать часов. Решение заключается в использовании скрипта app/actualize_script.php, который поставляется вместе с проектом и должен запускаться через cron.
sudo crontab -u www-data -eДобавьте одну строку:
*/20 * * * * php /srv/freshrss/app/actualize_script.php > /tmp/FreshRSS.log 2>&1Двадцать минут — это разумный минимальный интервал. Скрипт отказывается обновлять любую ленту чаще, чем раз в двадцать минут, поэтому более частый запуск только создает лишнюю нагрузку на процессор. Сначала запустите его вручную:
sudo -u www-data php /srv/freshrss/app/actualize_script.phpПри корректной работе вывод содержит названия всех полученных лент и завершается без ошибок PHP. Если вывод пуст, значит, выбран неверный пользователь для cron, а ошибка прав доступа к data/ означает, что шаг chmod -R g+w был пропущен.
Добавление первых лент
Используйте кнопку с плюсом в левом верхнем углу интерфейса, вставьте адрес сайта, и FreshRSS автоматически обнаружит ссылку на ленту. Большинство сайтов публикуют её, даже если не рекламируют, обычно по адресам /feed, /rss или /atom.xml. Категории представляют собой папки, перемещение ленты между ними осуществляется перетаскиванием.
Если вы переходите с другого агрегатора, экспортируйте там файл OPML и импортируйте его на странице управления подписками. OPML (outline processor markup language) является стандартным форматом списка лент, который поддерживает любой достойный внимания агрегатор. Массовый импорт работает медленно при первом обновлении, так как каждая лента запрашивается один раз, поэтому дайте первому запуску cron время, прежде чем оценивать скорость работы.
Чтение на мобильном устройстве
FreshRSS поддерживает API Google Reader, с которым совместимо большинство RSS-приложений. Необходимо соблюдение двух условий. В настройках аутентификации должен быть включен параметр "Allow API access", который уже был активирован с помощью флага --api-enabled выше. В профиле пользователя должно быть задано значение в поле API password; оно намеренно отделено от основного пароля для входа, так как мобильное устройство легче потерять.
Перейдите по адресу https://rss.example.com/api/ и выберите "Check full server configuration". Корректно настроенная система возвращает PASS. Ошибка на этом этапе почти всегда вызвана отсутствием строки AllowEncodedSlashes On. В приложении укажите адрес сервера как https://rss.example.com/api/greader.php, в качестве имени пользователя введите вашего пользователя FreshRSS, а в качестве пароля — ваш API password.
Альтернатива Docker
Если вы не хотите обслуживать PHP и Apache вручную, проект предоставляет официальный образ freshrss/freshrss, а один файл compose позволяет развернуть приложение вместе с базой данных. Компромисс стандартный: меньше компонентов на хосте, но появляется дополнительный уровень для отладки при возникновении сбоев, а для TLS (transport layer security) по-прежнему требуется обратный прокси-сервер. Если этот вариант вам подходит больше, в основах Docker Compose для VPS описан формат файла, а строка cron принимает вид docker exec --user www-data freshrss php ./app/actualize_script.php.
Резервное копирование и обновление
Ваше состояние сохраняется в двух местах: в базе данных и в /srv/freshrss/data/. Создайте дамп первой с помощью sudo mysqldump freshrss > freshrss.sql, скопируйте вторую и храните обе копии отдельно от этого сервера. Также рекомендуется периодически экспортировать список подписок в формате OPML, так как этот файл позволяет восстановить настройки чтения в любом RSS-клиенте.
Обновление выполняется путем распаковки новой версии поверх существующего каталога и повторного выполнения команд по смене владельца файлов. FreshRSS автоматически применяет миграции базы данных при следующей загрузке страницы. Сначала создайте резервную копию, так как сбой миграции при отсутствии возможности восстановления базы данных приведет к потере работоспособности системы. Читалка RSS — это сервис с низким уровнем риска, который хорошо подходит в качестве первого проекта, если вы изучаете список сервисов, которые стоит размещать на собственном сервере.
FAQ
Почему мои ленты обновляются только при открытии FreshRSS?
Потому что планировщик задач не существует, пока вы его не создадите. FreshRSS обновляет ленты, пока открыта сессия браузера, и не выполняет никаких действий после закрытия вкладки. Добавьте строку cron, вызывающую app/actualize_script.php, от имени пользователя www-data, затем запустите скрипт вручную один раз и изучите вывод. Отсутствие вывода обычно означает, что cron запускает скрипт от имени неверного пользователя, поэтому PHP не может выполнить запись в data/.
Мое мобильное приложение не может подключиться, хотя веб-сайт работает. Почему?
API Google Reader помещает закодированные косые черты (%2F) в пути запросов, а Apache отклоняет их по умолчанию. Добавьте AllowEncodedSlashes On в конфигурацию виртуального хоста и перезагрузите Apache. Подтвердите исправление, открыв https://rss.example.com/api/ и запустив "Check full server configuration", что должно вернуть PASS. Также убедитесь, что в профиле задан пароль для API, так как он отличается от пароля для входа в систему.
Что использовать: SQLite или MariaDB?
SQLite подходит для одного пользователя, так как не требует установки и управления паролями. MariaDB следует использовать, если ленты читает более одного человека или если у вас более нескольких сотен лент, так как задача обновления и веб-интерфейс выполняют запись одновременно, и блокировка одного файла становится ограничением. Переход между ними возможен позже с помощью команд экспорта и импорта, поэтому это решение не является окончательным.
Установщик выдает ошибку при записи конфигурации. В чем проблема?
PHP работает от имени www-data в среде Apache, и этот пользователь не имеет прав на запись в директорию, принадлежащую root. Повторно выполните sudo chown -R www-data:www-data /srv/freshrss и sudo chmod -R g+w /srv/freshrss/data, затем снова запустите установщик. Если вы уже запускали установщик из командной строки от имени root, удалите файлы, созданные им в data/, перед повторной попыткой, так как проблема заключается именно в правах владения этими файлами.
Какие требования к серверу для собственного RSS-ридера?
Минимальные. Несколько сотен лент комфортно работают на небольшом тарифном плане, так как нагрузка представляет собой короткие всплески HTTP-запросов каждые двадцать минут, а база данных остается небольшой при условии удаления старых статей. Объем дискового пространства растет в зависимости от настроек хранения, поэтому установите политику очистки статей в настройках архивации, вместо того чтобы хранить всё бесконечно.