FreshRSS в Docker Compose: готовый файл
Google Reader закрыли ещё в 2013-м, но проблема осталась той же: облачные RSS-читалки либо режут число лент на бесплатном тарифе, либо просят подписку, либо просто закрываются вместе с сервисом, на котором вы годами собирали источники. FreshRSS решает это одним компактным контейнером — свой сервер, свои ленты, никаких лимитов и рекламы. Ниже — рабочий docker-compose.yml, который поднимается за пять минут, плюс всё, что нужно для домена с SSL, мобильных клиентов и бэкапа.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Зачем self-hosted RSS-агрегатор и почему именно FreshRSS
RSS не умер — просто перестал быть на виду. Блоги, документация проектов, форумы, изменения в репозиториях на GitHub, подкасты — у всего этого до сих пор есть фид, и агрегатор экономит часы, которые иначе уходят на ручной обход десятков сайтов или скроллинг соцсетей с алгоритмической лентой вместо хронологической.
Из готовых облачных вариантов остаются Feedly (бесплатно — 100 лент, дальше платно), Inoreader (похожая модель) и NewsBlur. Все они работают, но это чужая инфраструктура: ваш список источников и история чтения лежат на серверах третьей компании, а бесплатный тариф рано или поздно упирается в потолок.
FreshRSS — open-source альтернатива, которая закрывает эти вопросы:
- Лёгкий. PHP-приложение, может работать на SQLite без отдельной базы — под него хватит самого младшего VPS.
- API-совместимость. Поддерживает Google Reader API и Fever API, поэтому подключается почти любой мобильный или десктопный RSS-клиент — не нужен отдельный клиент именно под FreshRSS.
- Без лимитов на ленты и пользователей — можно завести несколько аккаунтов (например, себе и партнёру) на одном инстансе.
- Расширения — правила фильтрации, автоматические теги, интеграции с read-later сервисами.
Минус тоже стоит проговорить честно: обновлять и бэкапить сервер придётся самому — это не SaaS с автоматическим сопровождением. Но для агрегатора, который открывают раз в день, это разумная цена за независимость от чужого бесплатного тарифа.
Готовый docker-compose.yml
Самый простой вариант — с встроенной SQLite, без отдельного контейнера базы данных. Для личного использования и небольшого числа лент этого достаточно с запасом:
services:
freshrss:
image: freshrss/freshrss:latest
container_name: freshrss
restart: unless-stopped
ports:
- "8080:80"
environment:
TZ: Europe/Moscow
CRON_MIN: "3,33"
volumes:
- freshrss_data:/var/www/FreshRSS/data
- freshrss_extensions:/var/www/FreshRSS/extensions
volumes:
freshrss_data:
freshrss_extensions:
CRON_MIN включает внутри контейнера cron, который дважды в час (на 3-й и 33-й минуте) дёргает обновление лент — без него ленты будут обновляться только при заходе в веб-интерфейс.
Если планируете десятки лент и несколько пользователей, лучше сразу вынести данные в PostgreSQL — так надёжнее и проще делать бэкап отдельно от файлов:
services:
db:
image: postgres:16-alpine
container_name: freshrss-db
restart: unless-stopped
environment:
POSTGRES_USER: freshrss
POSTGRES_PASSWORD: сгенерируйте_свой_пароль
POSTGRES_DB: freshrss
volumes:
- freshrss_db:/var/lib/postgresql/data
freshrss:
image: freshrss/freshrss:latest
container_name: freshrss
restart: unless-stopped
depends_on:
- db
ports:
- "8080:80"
environment:
TZ: Europe/Moscow
CRON_MIN: "3,33"
volumes:
- freshrss_data:/var/www/FreshRSS/data
- freshrss_extensions:/var/www/FreshRSS/extensions
volumes:
freshrss_db:
freshrss_data:
freshrss_extensions:
Контейнер базы данных не публикует порт наружу — FreshRSS обращается к нему по внутреннему имени сервиса db, это имя пригодится на шаге настройки в веб-интерфейсе. Пароль в POSTGRES_PASSWORD замените на свой перед первым запуском — после инициализации базы сменить его без пересоздания volume уже сложнее.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверПервый запуск: мастер настройки в браузере
Сохраните нужный вариант файла как docker-compose.yml в отдельной папке на сервере и запустите:
docker compose up -d
docker compose logs -f freshrss
Через несколько секунд контейнер должен перейти в статус healthy. Открываете http://IP-сервера:8080 — попадаете в мастер установки FreshRSS. Он спрашивает:
- Язык — выбирайте русский или английский, интерфейс потом можно переключить в настройках.
- Тип хранилища. Для варианта с SQLite просто соглашайтесь с предложенным по умолчанию. Для варианта с Postgres выбирайте PostgreSQL и указывайте хост
db, имя базы, пользователя и пароль — те же значения, что задали вPOSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB. - Администратор — логин и пароль первого пользователя.
- Часовой пояс и заголовок сайта.
После завершения мастера сразу заходите в Настройки → Профиль → Подключиться через API и включаете API — без этого мобильные клиенты работать не будут (об этом — ниже).
Если тестируете локально без домена, на этом этапе всё уже работает. Для боевого использования — с телефона, из другого клиента, из дома и с работы — нужен нормальный домен и HTTPS, дальше про это.
Домен и SSL: reverse-proxy перед контейнером
Открывать FreshRSS по IP и порту 8080 без шифрования — плохая идея: логин и пароль будут уходить в открытом виде. Проще всего поставить перед контейнером Caddy — он сам получает и продлевает сертификат Let's Encrypt.
Минимальный Caddyfile:
rss.ваш-домен.ru {
reverse_proxy freshrss:80
}
Если Caddy запущен в том же docker-compose-проекте, что и FreshRSS, достаточно завести их в одной сети и обращаться по имени сервиса, как в примере выше; если Caddy живёт отдельно — используйте reverse_proxy IP-сервера:8080 и настройте DNS A-записью на этот же сервер. Подробный разбор установки и частых проблем с сертификатами — в статье про установку Caddy с авто-SSL на VPS; там же — что делать, если сертификат не выдаётся из-за занятого 80-го порта или неправильной DNS-записи.
После того как домен поднялся по HTTPS, зайдите в Настройки FreshRSS → Профиль и укажите итоговый https://rss.ваш-домен.ru как базовый URL — это важно для корректной работы API у мобильных клиентов, иначе они будут пытаться достучаться до внутреннего адреса контейнера.
Подключение мобильных и десктопных клиентов через API
Главное преимущество FreshRSS над самописными читалками — совместимость с чужими API. В настройках профиля включаете:
- Google Reader API — под него заточено больше всего клиентов: Fluent Reader (Windows/macOS/Linux), ReadYou и FocusReader (Android), NetNewsWire на части версий.
- Fever API — исторически поддерживается Reeder (iOS/macOS) и некоторыми Android-клиентами.
При подключении клиента указываете:
- адрес сервера — тот самый
https://rss.ваш-домен.ru/api/greader.php(для Google Reader API) илиhttps://rss.ваш-домен.ru/api/fever.php(для Fever); - логин FreshRSS;
- API-пароль, отдельный от обычного пароля входа — генерируется в том же разделе настроек профиля, где включали API.
Если клиент пишет «не удаётся подключиться» — почти всегда причина в том, что базовый URL в настройках FreshRSS не совпадает с реальным адресом (например, остался http://localhost), либо API просто не включён для конкретного протокола.
Автообновление лент, бэкап и обновление образа
CRON_MIN в примерах выше уже настроил регулярное обновление лент — раз в полчаса этого достаточно для большинства источников, для новостных сайтов можно поставить более частые минуты через запятую, например "0,15,30,45".
Бэкап для варианта с SQLite — это volume freshrss_data, для варианта с Postgres — volume freshrss_db плюс freshrss_data (в нём тоже лежат кэш иконок и часть настроек). Дамп базы вручную:
docker compose exec db pg_dump -U freshrss freshrss > freshrss-backup-$(date +%F).sql
Общий подход к резервному копированию именно docker-томов — с ротацией и переносом на другой сервер — разобран в статье про бэкап docker volume; там же — типичные ошибки вроде бэкапа «на горячую» без остановки записи.
Обновление образа — обычные для Compose два шага:
docker compose pull
docker compose up -d
FreshRSS сам применяет миграции базы при старте новой версии, поэтому дополнительных действий обычно не требуется — но перед обновлением на новую мажорную версию лишний раз сделать дамп базы не помешает. Если не хотите следить за обновлениями руками, автоматизировать это можно через Watchtower — как его настроить и на что обратить внимание (например, чтобы не обновить контейнер базы данных на несовместимую мажорную версию), написано в статье про автообновление контейнеров Watchtower.
Если Docker для вас не обязателен и хочется классическую установку пакетами прямо в систему — с nginx, php-fpm и системным cron — такой вариант тоже есть, он разобран в статье про установку FreshRSS на Ubuntu 24.04 без контейнеров; плюс в предсказуемости обновлений системы целиком, минус — больше ручной настройки зависимостей.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько ресурсов сервера нужно FreshRSS?
Для личного использования с несколькими десятками лент хватает 1 vCPU и 512 МБ–1 ГБ RAM даже с вариантом на SQLite. PostgreSQL добавляет постоянное потребление памяти под сам процесс базы — закладывайте на связку в целом от 1 ГБ RAM.
Можно ли перенести ленты из Feedly или Inoreader?
Да, через OPML: экспортируете список подписок из старого сервиса файлом .opml, в FreshRSS — раздел «Управление подписками» → «Импорт/экспорт» → загружаете файл. Прочитанные статьи и история при этом не переносятся, только сам список источников.
FreshRSS сам ходит на сайты источников или мне нужен отдельный краулер?
Сам — по расписанию из CRON_MIN внутри контейнера или при ручном обновлении в интерфейсе. Отдельный сервис не нужен.
Что делать, если сайт-источник отдаёт RSS с ошибками или блокирует запросы сервера?
Такое встречается редко, но случается — некоторые сайты блокируют по User-Agent или IP-диапазону дата-центров. В большинстве случаев проблема решается сменой региона сервера или обращением к владельцу сайта; специфику конкретного фида FreshRSS не обходит автоматически.
Нужен ли отдельный домен именно под RSS-читалку?
Не обязательно — можно использовать поддомен (rss.ваш-домен.ru) на том же сервере, где крутятся другие сервисы за тем же reverse-proxy, как показано выше с Caddy.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →