Quick Start: FreshRSS Running in 5 Minutes
Running your own RSS reader is one of those homelab wins that quietly improves every single day. I’ve been self-hosting FreshRSS for over two years, and it’s the service I’d miss most if it vanished. No algorithm, no ads, no feed throttling — just the content you subscribed to, delivered when it’s published.
Here’s the fastest path to a working FreshRSS instance:
mkdir -p ~/freshrss/{data,extensions}
docker run -d \
--name freshrss \
-p 8080:80 \
-e TZ=Asia/Tokyo \
-e CRON_MIN='*/15' \
-v ~/freshrss/data:/var/www/FreshRSS/data \
-v ~/freshrss/extensions:/var/www/FreshRSS/extensions \
--restart unless-stopped \
freshrss/freshrss:latest
Open http://<your-server-ip>:8080 and you’ll land on the setup wizard. Pick a database (SQLite is fine for personal use), create your admin account, and you’re live.
That single command is all you need to get started. But if you want it production-grade — persistent, proxied, and syncing across all your devices — keep reading.
Deep Dive: Docker Compose Setup with PostgreSQL
SQLite works fine solo, but once you hit hundreds of feeds or need multi-user support, PostgreSQL is the smarter call. Here’s a compose file I’ve refined through actual use:
version: '3.8'
services:
freshrss:
image: freshrss/freshrss:latest
container_name: freshrss
restart: unless-stopped
ports:
- '8080:80'
environment:
TZ: Asia/Tokyo
CRON_MIN: '*/15'
FRESHRSS_ENV: production
volumes:
- ./data:/var/www/FreshRSS/data
- ./extensions:/var/www/FreshRSS/extensions
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
container_name: freshrss-db
restart: unless-stopped
environment:
POSTGRES_DB: freshrss
POSTGRES_USER: freshrss
POSTGRES_PASSWORD: your_strong_password_here
volumes:
- ./db:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U freshrss']
interval: 10s
timeout: 5s
retries: 5
docker compose up -d
During the setup wizard, choose PostgreSQL as the database type and fill in the credentials matching your compose file. FreshRSS creates the schema automatically on first run — nothing extra needed.
Putting It Behind a Reverse Proxy
Port 8080 is fine for testing. The moment you access FreshRSS from outside your LAN, you want HTTPS. If Nginx Proxy Manager or Traefik is already running in your homelab, point a subdomain like rss.yourdomain.com at port 8080 on your Docker host.
Nginx Proxy Manager is a few clicks: add a proxy host, set the forward hostname to your Docker host IP, port 8080, enable SSL via Let’s Encrypt, force HTTPS. Done in under two minutes.
Traefik users can add these labels to the freshrss service instead:
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.freshrss.rule=Host(`rss.yourdomain.com`)'
- 'traefik.http.routers.freshrss.entrypoints=websecure'
- 'traefik.http.routers.freshrss.tls.certresolver=letsencrypt'
- 'traefik.http.services.freshrss.loadbalancer.server.port=80'
Configuring Feed Refresh Intervals
The CRON_MIN variable controls how often FreshRSS polls your feeds. */15 means every 15 minutes — a reasonable balance between freshness and server load. On a resource-constrained VPS, bump it to */30 and you’ll barely notice the difference in practice.
You can also trigger a one-off refresh from Administration → Archiving, or hit the CLI directly:
docker exec -it freshrss php /var/www/FreshRSS/app/actualize_script.php
API Access and Mobile Sync
Most self-hosted RSS tools stop at web access. FreshRSS goes further — it implements the Google Reader API (plus Fever API via extension), making it compatible with nearly every RSS client that supports Google Reader backends. That’s a surprisingly large ecosystem.
Enabling the API
Head to User settings → Profile and set an API password. It can match your login password, but a separate one is cleaner. Then go to Administration → Authentication and check Allow API access.
Your API endpoint will be:
https://rss.yourdomain.com/api/greader.php
Mobile Client Setup
My daily setup: NetNewsWire on iOS and Reeder 5 on macOS — both support Google Reader API natively. Point them at your FreshRSS URL with your username and API password. Sync is near-instant over both WiFi and LTE.
On Android, FeedMe and Read You (fully open source) both work well with the same endpoint.
Importing Your Existing Feeds
Migrating from Feedly, Inoreader, or anything else? Export your subscriptions as OPML, then import at Subscription management → Import/Export. I imported 340 feeds from Feedly in about 8 seconds — FreshRSS didn’t even flinch.
Automating Backups
Everything lives in ./data: feeds, read states, settings, user data. A simple nightly script covers you:
#!/bin/bash
BACKUP_DIR="/mnt/nas/backups/freshrss"
DATE=$(date +%Y%m%d)
tar -czf "${BACKUP_DIR}/freshrss-${DATE}.tar.gz" ~/freshrss/data ~/freshrss/db
find "${BACKUP_DIR}" -name '*.tar.gz' -mtime +30 -delete
Add it to cron (crontab -e) to run at 3am:
0 3 * * * /home/user/scripts/backup-freshrss.sh
Practical Tips from Daily Use
Stuff I learned by actually running this for two years — skip these and you’ll hit the same walls I did.
1. Watch Your Feed Volume
FreshRSS handles hundreds of feeds on modest hardware. A 1-core, 1GB RAM VPS runs it without complaint. The real bottleneck is high-frequency sources — some news sites push 50+ items a day. Cap retention per feed under Subscription management. I keep 200 articles for most feeds, unlimited for a handful of key ones. That keeps the database lean.
2. The Labels System Is Underrated
Most people ignore FreshRSS’s label system. Don’t. Create labels like Read Later, DevOps, or Newsletters, then set filtering rules to auto-assign them based on feed source or title keywords. It turns FreshRSS from a passive reader into a lightweight content curation layer — no third-party tool required.
3. Use the Sharing Integrations
Under User settings → Sharing, you can wire up one-click saving to Pocket, Wallabag, or any custom URL. Mine points to a self-hosted Wallabag instance. Long reads get saved with a single click, no tab-juggling.
4. Debugging Feed Fetch Issues
When a feed stops updating, check its status in Subscription management — feeds with errors get flagged there. Nine times out of ten it’s a changed RSS URL, a downed site, or a feed that now requires auth. Test any URL directly from inside the container:
docker exec -it freshrss curl -I 'https://example.com/feed.xml'
5. Memory Usage Tuning
On low-memory VPS hosts, add resource limits to prevent runaway usage:
services:
freshrss:
# ... other config
deploy:
resources:
limits:
memory: 256M
FreshRSS with SQLite sits comfortably under 100MB in normal use. PostgreSQL adds a bit more overhead, but you’re still well under 256MB for personal workloads.
6. Extensions Worth Installing
The ./extensions volume exists for a reason. Three I actually use day-to-day:
- xExtension-CustomCSS — tweak the UI without touching core files
- cn-metrics — useful if you follow Chinese-language tech feeds
- Fever API extension — enables Reeder’s Fever protocol compatibility
Drop extensions into ~/freshrss/extensions/ and activate them under Administration → Extensions.
7. Keeping the Image Updated
FreshRSS ships updates regularly. The upgrade path with Docker Compose is two commands:
docker compose pull
docker compose up -d
Database migrations run automatically on startup. Still, take a backup before any major version jump. It takes 30 seconds and you’ll be glad you did if something goes sideways.
After two-plus years running FreshRSS daily, it’s become infrastructure I don’t think about — which is the highest compliment you can give a self-hosted service. Lightweight, solid API support, compatible with every mobile client I’ve tried. If you’re building a homelab, an RSS reader you actually control is worth having. FreshRSS is the one I’d recommend without hesitation.

