Reclaiming RSS: Self-Hosting FreshRSS with RSS‑Bridge on TrueNAS

How to bring back RSS feeds for sites that removed them, scrape full article content, and unify everything in a single self-hosted reader.

RSS isn’t dead — it’s just been abandoned by publishers chasing engagement metrics and walled gardens. Websites that once offered clean XML feeds now force you into newsletters, push notifications, or algorithmic timelines. But with a bit of self-hosting, you can take that control back.

This post walks through my setup: FreshRSS as the reader, RSS-Bridge as the scraper for sites that killed their feeds, all running on TrueNAS Scale with Docker and exposed through Tailscale for secure remote access.

The Architecture

The data flow is straightforward:

Website
(no RSS)
RSS-Bridge
scrapes & generates feed
FreshRSS
polls & displays
You
browser / app

For sites that still offer RSS, FreshRSS subscribes directly. For sites that removed their feeds, RSS-Bridge sits in between — it loads the page, parses the HTML with CSS selectors, and generates a standard Atom feed that FreshRSS can consume like any other subscription.

Why RSS-Bridge Over Alternatives

There are several tools that can generate feeds from websites. I chose RSS-Bridge for a few reasons:

Lightweight. RSS-Bridge is PHP-based and runs in about 50 MB of RAM. Compare that with RSSHub (Node.js, 300 MB+) or Huginn (Ruby, even heavier). On a NAS where every container counts, this matters.

FreshRSS integration. There’s a native FreshRSS extension (xExtension-RssBridge) if you want tight integration, though the simpler approach — just subscribing to the generated feed URL — works perfectly and survives app updates.

CssSelectorBridge. This built-in bridge is incredibly flexible. Give it a URL, tell it which CSS selectors match your articles, and it produces a feed. No coding required, no custom JavaScript routes to maintain.

Deploying RSS-Bridge on TrueNAS

I run RSS-Bridge as a Docker container through Portainer. First, create the config directory and enable all bridges:

bash# Create config directory on ZFS
sudo mkdir -p /mnt/zfs_tank/docker/rss-bridge

# Enable all bridges
sudo tee /mnt/zfs_tank/docker/rss-bridge/config.ini.php << 'EOF'
[system]
enabled_bridges[] = *
EOF

Then deploy the stack in Portainer:

docker-composeversion: "3"
services:
  rss-bridge:
    image: rssbridge/rss-bridge:latest
    container_name: rss-bridge
    restart: unless-stopped
    ports:
      - "3001:80"
    volumes:
      - /mnt/zfs_tank/docker/rss-bridge:/config

RSS-Bridge is now accessible at http://<truenas-ip>:3001.

Remote Access with Tailscale Serve

If you already run a Tailscale container on your TrueNAS box, you can expose RSS-Bridge through it:

bashdocker exec ix-tailscale-tailscale-1 tailscale serve --bg --https 3001 http://localhost:3001

This makes RSS-Bridge available at https://your-machine.tailnet-name.ts.net:3001/ from any device on your tailnet. Use a non-443 port to avoid overwriting your TrueNAS GUI’s Tailscale Serve config.

Tip When adding feed URLs to FreshRSS, use the local IP (e.g. http://192.168.0.13:3001/...) rather than the Tailscale hostname. Both services run on the same box, so going through the LAN is faster and more reliable — and the FreshRSS container may not have Tailscale DNS available.

Scraping a Site: A Real Example

The Greek tech blog techblog.gr removed its RSS feed during a 2025 site redesign. Here’s how I brought it back.

Step 1 — Identify the selectors

Open the site, right-click an article title, and choose Inspect. On techblog.gr, each article title is an <a> inside an <h3>. On article pages, the content lives inside div.article-content.

Step 2 — Configure CssSelectorBridge

In the RSS-Bridge web UI, find CSS Selector and fill in:

FieldValue
Site URLhttps://techblog.gr/
Selector for article linksh3 a
URL pattern(empty)
Expand article content.article-content
Content cleanup(empty)
Title cleanup| Techblog.gr
Limit20

Step 3 — Generate and subscribe

Click Generate feed, right-click the Atom button and copy the link. In FreshRSS, go to Subscription management → Add a feed and paste the URL. Done — full article content in your reader, from a site with no RSS feed.

Finding the Right CSS Selectors

For the article link selector: On the homepage, right-click an article title → Inspect. Look at the tag structure. Common patterns are h2 a, h3 a, or .post-title a. If the site uses generic <a> tags everywhere, combine with a URL pattern to filter (e.g. /blog/202 to match only blog post URLs).

For the content selector: Open any individual article, right-click the body text → Inspect. Look at the parent <div> wrapping all the paragraphs. WordPress sites typically use .entry-content or .article-content. Drupal sites often use .field-name-body or .node-content.

Gotcha: Iframes Some sites (especially job boards) load content inside iframes. RSS-Bridge can only parse the main page HTML — if the content is in an iframe, you’re limited to titles and links. Check your browser’s inspector for <iframe> elements if the content selector doesn’t seem to work.

Setting Sensible Limits

The Limit field controls how many items RSS-Bridge returns per request. Since FreshRSS remembers articles it has already seen, you only need enough to cover new posts between polling intervals:

Feed typeLimitReasoning
News sites20High frequency, many posts per day
Blogs10Weekly or monthly posts
Job boards10Few listings, slow turnover

What About Paywalled Sites?

RSS-Bridge has limits. If a site blocks automated requests (returning 403 errors) or loads content via JavaScript that requires authentication, RSS-Bridge can’t help. This applies to most academic journals and some major news outlets.

For journals like NEJM, the publisher’s RSS feed is your only option — and it often contains just titles and volume/page references, no abstracts. A useful workaround for medical journals: use PubMed’s RSS feeds instead. PubMed indexes the same articles and includes full abstracts. Search for a journal, save the search, and create an RSS feed from the results.

Unifying Multiple Feed Readers

If you’re migrating from a desktop reader like Akregator to a self-hosted FreshRSS instance, both support OPML import/export. Export from both, then compare the feed URLs to identify:

Feeds in both — already synced, nothing to do.

Feeds only in the old reader — evaluate whether to add them to FreshRSS or drop them.

Feeds only in FreshRSS — typically your newer RSS-Bridge feeds replacing broken native feeds.

Watch for feeds that exist in both but with different URLs — same source, different CDN, or an old Politepol/feed proxy URL that you’ve since replaced with RSS-Bridge.

Closing Thoughts

This setup takes about 30 minutes to deploy and configure. What you get in return is a single, self-hosted interface for consuming content from any website — with or without their cooperation. No algorithms deciding what you see, no newsletters cluttering your inbox, no tracking pixels following you around.

RSS never died. It just needs a little infrastructure.

  • FreshRSS
  • RSS-Bridge
  • TrueNAS
  • Docker
  • Self-Hosting
  • Tailscale
  • RSS

Leave a comment

Discover more from /root

Subscribe now to keep reading and get access to the full archive.

Continue reading