FreshRSS Setup Guide: Docker Install, Mobile Apps, Extensions, and Theming
The internet has a content discovery problem. Social media algorithms show you what drives engagement, not what's useful. Newsletter inboxes become unmanageable. News aggregators inject sponsored content between actual articles. And the websites you genuinely want to follow? You forget to check them for weeks.
Photo by Dennis Irorere on Unsplash
RSS fixes all of this. You subscribe to sources. They publish. You read when you want. No algorithm, no tracking, no ads injected between articles. The protocol is 25 years old and still works perfectly.
FreshRSS is one of the best self-hosted RSS readers available. It's lightweight (50-100MB of RAM), supports hundreds of feeds without breaking a sweat, exposes APIs for mobile app sync, and has an extension system that fills in any gaps. This guide walks through everything you need to go from zero to a fully configured, daily-driver RSS setup.
Why FreshRSS Over Other Self-Hosted Readers
Before diving into setup, here's why FreshRSS is the recommendation over Miniflux and Tiny Tiny RSS:
Miniflux is excellent if you want minimalism. It's a Go binary with a clean interface, Fever/Google Reader API support, and very low resource usage. But it has no extension system, no themes beyond light/dark, and no plugin ecosystem. What you see is what you get.
Tiny Tiny RSS is powerful but has a reputation for a hostile lead developer and a more complex setup. Its plugin system is good, but the community ecosystem around FreshRSS has grown larger and more active.
FreshRSS hits the sweet spot: low resource usage, rich extension ecosystem, multiple API options for mobile apps, theming support, and an active community. It runs on PHP, which means it works on virtually any hosting environment.
Docker Compose Setup
The fastest way to run FreshRSS is with Docker. Here's a production-ready Compose file:
# docker-compose.yml
services:
freshrss:
image: freshrss/freshrss:latest
container_name: freshrss
restart: unless-stopped
ports:
- "8080:80"
environment:
TZ: America/New_York
CRON_MIN: "1,31" # Fetch feeds at :01 and :31 every hour
volumes:
- freshrss_data:/var/www/FreshRSS/data
- freshrss_extensions:/var/www/FreshRSS/extensions
logging:
options:
max-size: "10m"
volumes:
freshrss_data:
freshrss_extensions:
Start it up:
docker compose up -d
Navigate to http://your-server:8080 and you'll see the installation wizard. Walk through these steps:
- Language — Pick your language
- Checks — FreshRSS verifies PHP extensions and write permissions. Everything should be green with the Docker image.
- Database — Choose SQLite for simplicity (handles thousands of feeds fine) or PostgreSQL for multi-user deployments
- Configuration — Set your default user credentials and base URL
- Done — Log in and start adding feeds
Using PostgreSQL Instead of SQLite
If you expect multiple users or 500+ feeds, PostgreSQL is the better database choice:
services:
freshrss:
image: freshrss/freshrss:latest
container_name: freshrss
restart: unless-stopped
depends_on:
- db
ports:
- "8080:80"
environment:
TZ: America/New_York
CRON_MIN: "1,31"
volumes:
- freshrss_data:/var/www/FreshRSS/data
- freshrss_extensions:/var/www/FreshRSS/extensions
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: freshrss
POSTGRES_USER: freshrss
POSTGRES_PASSWORD: your-secure-password-here
volumes:
- freshrss_db:/var/lib/postgresql/data
volumes:
freshrss_data:
freshrss_extensions:
freshrss_db:
During the installation wizard, select PostgreSQL and enter:
- Host:
db - Database:
freshrss - User:
freshrss - Password: the password from your compose file
Feed Management
Adding Feeds
FreshRSS accepts feeds in several ways:
- Direct URL — Paste a website URL or RSS feed URL into Subscription Management > Add. FreshRSS auto-discovers the feed.
- OPML import — If you're migrating from another reader, export your feeds as OPML and import them via Subscription Management > Import/Export.
- Bookmarklet — FreshRSS provides a browser bookmarklet. Click it on any page and it attempts to find and subscribe to that site's RSS feed.
Organizing with Categories
Categories in FreshRSS are folders for your feeds. Create them before bulk-importing feeds so you can organize as you go:
- Tech News — Ars Technica, Hacker News, The Verge
- Blogs — Individual bloggers you follow
- YouTube — Channel RSS feeds (yes, every YouTube channel has an RSS feed)
- Reddit — Subreddit feeds (append
.rssto any subreddit URL) - Releases — GitHub release feeds for projects you track
YouTube RSS Feeds
Every YouTube channel has an RSS feed. The URL format is:
https://www.youtube.com/feeds/videos.xml?channel_id=CHANNEL_ID
To find a channel's ID: go to the channel page, view source, and search for channelId. Or use a browser extension like "Get RSS Feed URL" that extracts it automatically.
Reddit Feeds
Any subreddit has an RSS feed at:
https://www.reddit.com/r/selfhosted/.rss
https://www.reddit.com/r/homelab/top/.rss?t=week
You can filter by hot, new, top (with time range), etc.
GitHub Release Feeds
Track new releases for any GitHub project:
https://github.com/FreshRSS/FreshRSS/releases.atom
https://github.com/immich-app/immich/releases.atom
Like what you're reading? Subscribe to Self-Hosted Weekly — free weekly guides in your inbox.
Enabling the API for Mobile Apps
This is where FreshRSS becomes a daily-driver tool rather than a web-only curiosity. FreshRSS supports two APIs that mobile RSS apps understand: the Google Reader API and the Fever API.
Google Reader API (Recommended)
The Google Reader API is the more capable of the two. It supports categories, tagging, read state sync, and starring. Most modern mobile RSS apps support it.
To enable it:
- Go to Settings > Profile
- Under API password, set an API-specific password (can be different from your login password)
- Your API endpoint is:
https://your-freshrss-domain/api/greader.php
Fever API
Some older apps only support the Fever API. Enable it:
- Go to Settings > Profile
- Under Fever API, check "Allow Fever API access"
- Set a Fever-specific password
- Your API endpoint is:
https://your-freshrss-domain/api/fever.php
Recommended Mobile Apps
Android:
- FeedMe — Best Google Reader API support, clean interface, offline reading
- Read You — Material Design, open-source, supports FreshRSS via Google Reader API
- Reeder — Premium but beautiful, supports Google Reader and Fever APIs
iOS:
- NetNewsWire — Free, open-source, excellent Google Reader API support
- Reeder Classic — The gold standard for iOS RSS readers, supports Google Reader API
- lire — Full-text extraction built in, supports Fever API
Desktop:
- Fluent Reader — Electron-based, supports Fever/Google Reader APIs
- NewsFlash — Native Linux app (GTK4), supports FreshRSS directly
Configure any of these apps by entering your FreshRSS URL, username, and API password. Articles you read on mobile sync back to the web interface and vice versa.
Extensions
FreshRSS has a healthy extension ecosystem. Extensions are PHP files dropped into the extensions directory. With the Docker setup above, they persist in the freshrss_extensions volume.
Installing Extensions
The easiest method is through FreshRSS itself:
- Go to Settings > Extensions
- Browse the available extensions list
- Click "Install" on the ones you want
- Enable them after installation
Essential Extensions
Auto Read on Scroll — Marks articles as read as you scroll past them. Saves you from manually marking things read.
Custom CSS — Inject your own CSS to customize the interface. Useful for adjusting font sizes, hiding elements, or tweaking the layout to your preference.
Reddit Image — Automatically displays Reddit image posts inline instead of requiring you to click through. Essential if you follow image-heavy subreddits.
YouTube Embed — Embeds YouTube videos directly in your feed instead of just showing a link. Watch videos without leaving FreshRSS.
Full-Text RSS — Fetches the full content of articles when sites only provide summaries in their RSS feeds. This is one of the most useful extensions — many sites only put the first paragraph in their RSS feed to drive clicks. This extension grabs the full article.
Title Wrap — Wraps long titles instead of truncating them. Small quality-of-life improvement that makes scanning headlines easier.
Installing Extensions Manually
If an extension isn't in the built-in list, you can install it manually:
# Find the extensions volume location
docker volume inspect freshrss_extensions
# Clone an extension into it
cd /var/lib/docker/volumes/freshrss_extensions/_data/
git clone https://github.com/some-user/xExtension-SomeExtension.git
Extension directories must follow the naming convention xExtension-Name with a metadata.json and extension.php inside.
Theming
FreshRSS comes with several built-in themes and supports custom themes.
Built-in Themes
Access themes at Settings > Display > Theme. The defaults include:
- Origine — The default light theme, clean and functional
- Origine-compact — Denser layout, shows more articles per screen
- Dark — Dark mode with good contrast
- Mapco — Alternative light theme with a different aesthetic
- Pafat — Minimalist theme
Installing Custom Themes
Custom themes are CSS files placed in the themes directory. With Docker:
# Copy a custom theme into the container
docker cp my-custom-theme/ freshrss:/var/www/FreshRSS/p/themes/my-custom-theme/
Community themes are available on GitHub. Search for "FreshRSS theme" to find options. The most popular community themes include Nord-themed dark modes and Material Design-inspired layouts.
Custom CSS via Extension
For quick tweaks without creating a full theme, use the Custom CSS extension:
/* Increase article title font size */
.flux .item-title {
font-size: 1.1em;
}
/* Wider reading pane */
#stream.reader .flux_content .content {
max-width: 900px;
}
/* Hide the FreshRSS logo */
.header .item.title a.logo {
display: none;
}
Feed Fetching and Performance
Adjusting Fetch Frequency
The CRON_MIN environment variable controls how often FreshRSS checks for new articles. The default Docker setup uses the container's built-in cron:
environment:
CRON_MIN: "1,31" # Every 30 minutes
For more frequent updates:
environment:
CRON_MIN: "*/15" # Every 15 minutes
For less frequent (saves bandwidth, kinder to feed sources):
environment:
CRON_MIN: "3" # Once per hour at :03
Feed-Specific Settings
Individual feeds can have their own fetch settings:
- Go to Subscription Management
- Click the gear icon next to a feed
- Set "Minimum update interval" to slow down or speed up individual feeds
- Enable "Retrieve full content" for feeds that only provide summaries
Handling Slow or Broken Feeds
FreshRSS tracks feed health and will warn you about feeds that consistently timeout or return errors. Check your feed health at Subscription Management > sort by "Last update" or "Errors." Remove dead feeds periodically to keep your fetcher fast.
User Management
FreshRSS supports multiple users, each with their own feed subscriptions, read state, and settings:
# Create a new user via CLI
docker exec -it freshrss php ./cli/create-user.php \
--user partner \
--password 'secure-password' \
--language en
# List users
docker exec -it freshrss php ./cli/list-users.php
# Delete a user
docker exec -it freshrss php ./cli/delete-user.php --user olduser
Each user gets an independent feed list and read state. There's no shared feed or shared read state — each user operates independently.
Backup and Restore
OPML Export
The most portable backup is an OPML export of your feed list:
Settings > Profile > Import/Export > Export as OPML
This gives you a file you can import into any RSS reader. It captures feeds and categories but not read state or starred articles.
Full Backup
For a complete backup including read state, starred articles, and settings, back up the Docker volume:
# Stop the container for a consistent backup
docker compose stop freshrss
# Backup the data volume
docker run --rm -v freshrss_data:/data -v $(pwd):/backup \
alpine tar czf /backup/freshrss-backup-$(date +%Y%m%d).tar.gz /data
# Restart
docker compose start freshrss
Database Maintenance
If you're using SQLite and have been running FreshRSS for months with hundreds of feeds, the database can grow large. FreshRSS has a built-in archiving system:
Settings > Archiving — Set how long to keep articles. The default (3 months) is reasonable for most users. Reducing this to 1 month can significantly shrink the database for high-volume feed collections.
You can also run manual optimization:
docker exec -it freshrss php ./cli/db-optimize.php
Reverse Proxy with HTTPS
For production use, put FreshRSS behind a reverse proxy with HTTPS. Here's a Caddy example:
freshrss.yourdomain.com {
reverse_proxy freshrss:80
}
Or with Nginx:
server {
listen 443 ssl http2;
server_name freshrss.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/freshrss.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/freshrss.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
After setting up HTTPS, update your FreshRSS base URL in Settings > System Configuration so API URLs resolve correctly for mobile apps.
Daily Workflow Tips
After a week with FreshRSS, you'll develop a rhythm. Here are tips that make the daily experience smoother:
Use keyboard shortcuts — Press
?in FreshRSS to see all shortcuts.j/kto navigate articles,sto star,nto next article. These make reading dramatically faster.Star, don't bookmark — Use FreshRSS's starring feature instead of browser bookmarks for articles you want to return to. Stars are searchable and accessible from mobile.
Use "Mark above as read" — When you've scrolled through a category, right-click the last article you care about and "Mark above as read." Faster than marking each article individually.
Prune aggressively — If a feed consistently produces articles you skip, unsubscribe. A focused feed list with 30 high-quality sources beats 200 noisy ones.
Check feed health monthly — Remove dead feeds, fix broken URLs, and review your category organization.
RSS is one of those rare self-hosted services that has essentially zero maintenance overhead once configured. FreshRSS will run quietly in the background indefinitely, fetching your feeds and presenting them cleanly. The only ongoing effort is curating your feed list — which is the fun part.
