SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-07

Установка FreshRSS на VPS с Ubuntu 24.04

Пошаговое руководство по развертыванию FreshRSS на стеке Apache, PHP 8.3 и MariaDB. Узнайте, как настроить права доступа, cron для обновления лент и API для мобильных приложений.

Что вы создаете

Self-hosted 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 mariadb

systemctl 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. Размещение каталога приложения отдельно от document root гарантирует, что через 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/, а не корень дерева каталогов. Все остальные файлы, включая конфигурационный файл с паролем от базы данных, находятся выше document root, откуда 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 apache2

configtest должен вывести 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) по-прежнему требуется reverse proxy. Если этот вариант вам подходит больше, в основах 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-запросов каждые двадцать минут, а база данных остается небольшой при условии удаления старых статей. Объем диска растет в зависимости от настроек хранения, поэтому установите политику очистки статей в настройках архивирования, вместо того чтобы хранить всё бесконечно.