Why self-host FreshRSS on a VPS
FreshRSS is an RSS/Atom feed aggregator written in PHP, designed to be light on resources while handling thousands of articles. Self-hosting on a VPS solves three problems that closed services do not address: durability (your monitoring does not vanish overnight), privacy (nobody profiles your subscriptions) and freshness (you set the refresh frequency via cron, with no imposed quota). A VPS, unlike shared hosting, gives you full SSH access, the right to run a Docker container and to schedule tasks — exactly what FreshRSS needs to refresh feeds in the background.
Concrete benefits of a self-hosted FreshRSS
- Native API compatible with Fever and Google Reader: synchronize with Reeder, FeedMe or Fluent Reader on mobile.
- GReader / scraping extension: retrieve the full content of truncated articles thanks to XPath filters.
- Multi-user with per-account quotas: ideal for sharing an instance within an agency.
- Minimal memory footprint (200 to 300 MB): runs on the smallest of VPSes without flinching.
- Cron-driven refresh: you decide whether the feeds update every 5 minutes or every hour.
- Trivial backup: a SQLite/MySQL database and a data folder are enough to restore everything.
Technical requirements
FreshRSS is one of the most frugal self-hosting applications. Plan for 1 vCPU and 1 GB of RAM for a personal instance with a few users; 10 GB of disk is amply sufficient, the bulk of it taken up by the article history. On the software side: Docker and the Docker Compose plugin installed on the VPS, a domain name (or a subdomain like rss.yourdomain.com) pointed with an A record to the server's IP, and port 80/443 open for the reverse proxy. PHP does not need to be installed on the host: the official freshrss/freshrss image bundles everything.
Deploy FreshRSS step by step
Prepare the VPS and Docker
Connect via SSH, update the system, then install Docker: curl -fsSL https://get.docker.com | sh. Check with docker compose version. Create a project folder mkdir -p /opt/freshrss && cd /opt/freshrss.
Write the docker-compose.yml
Define a service from the freshrss/freshrss:latest image, mount two volumes (./data:/var/www/FreshRSS/data and ./extensions:/var/www/FreshRSS/extensions) and set CRON_MIN=*/20 to refresh the feeds every 20 minutes. Expose internal port 80 only to the reverse proxy, not to the outside.
Launch the container
Start the stack with docker compose up -d, then follow the initialization via docker compose logs -f. The container applies the migrations and creates the data tree on first startup.
Set up the reverse proxy and SSL
Place a reverse proxy (Caddy or Nginx Proxy Manager) in front of FreshRSS. With Caddy, two lines are enough: rss.yourdomain.com { reverse_proxy freshrss:80 } and the Let's Encrypt certificate is obtained and renewed automatically.
Complete the web installation
Open https://rss.yourdomain.com, choose the database backend (SQLite for personal use, MySQL/PostgreSQL for multiple users), create the administrator account and enable the API in Profile for mobile synchronization.
Import your feeds and make the cron reliable
Import your existing OPML from the old reader. Check that the internal job runs with docker compose exec freshrss ./cli/actualize.php launched manually a first time to validate article retrieval.
For sites that publish only an excerpt in their feed, install the official "FreshRSS Content Selector" extension: configure a CSS selector (e.g. article.post-content) per subscription and FreshRSS will fetch the full text on each refresh. Combine it with the filters extension to automatically hide sponsored articles detected by keyword.