Blog / Tutorials

Self-Host FreshRSS on a VPS — Take Your Feeds Back

By the NoctHost TeamAugust 28, 20266 min read

The algorithmic feed decides what you see. RSS lets you decide. That's the whole pitch, and once you've lived with it for a week it's hard to go back. You follow the sites you actually want — a few blogs, a couple of news outlets, that one person who posts four times a year but always worth reading — and they show up in a plain reverse-chronological list. No "for you", no engagement bait, no post from six days ago resurfaced because a stranger liked it. Just the things you chose, in the order they happened.

RSS never died, it just stopped being fashionable, which honestly made it better. And FreshRSS is the reader I'd hand to anyone who wants to run their own: light, fast, boringly reliable, and it plays nice with every phone app worth using.

Why bother self-hosting instead of using a service

You could sign up for a hosted reader and be done in a minute, and that's a fine choice. But a reader is a long-term relationship — it accumulates years of subscriptions and read state — and hosted readers have a habit of shutting down or pivoting. Google Reader is the ghost that haunts this whole category. Self-hosting means the day FreshRSS is your reader is the last day you have to think about migrating, because it isn't going anywhere you don't take it.

It also sips resources. FreshRSS on a 1 GB box will use a fraction of it and never blink. This is not Nextcloud; it's a PHP app and a small database politely doing very little most of the time.

Getting it running

You'll want Docker and a domain pointed at your server. FreshRSS ships an official image, and the maintainers include a SQLite mode that's perfect for a single user — no separate database container, the whole thing lives in one volume.

Drop this in a docker-compose.yml. It pairs FreshRSS with Caddy so HTTPS is automatic:

services:
  freshrss:
    image: freshrss/freshrss:latest
    restart: unless-stopped
    volumes:
      - freshrss_data:/var/www/FreshRSS/data
    environment:
      - TZ=Europe/Berlin
      - CRON_MIN=13,43

  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
    depends_on:
      - freshrss

volumes:
  freshrss_data:
  caddy_data:

The Caddyfile is two lines:

rss.example.com {
  reverse_proxy freshrss:80
}

Bring it up with docker compose up -d, then open https://rss.example.com and walk through the installer. Pick SQLite for the database — for one person or a small household it's plenty and there's one less moving part. Create your admin account and you're in.

That CRON_MIN line matters more than it looks, so let's talk about it.

Refreshing feeds without babysitting it

FreshRSS only shows you new articles when it goes and fetches them. Left alone, it refreshes when you load the page, which is fine but means a cold open sometimes shows stale content. The CRON_MIN environment variable above tells the image's built-in cron to poll your feeds at those minutes past the hour — here, at :13 and :43, so roughly every half hour.

Don't set this too aggressively. Polling every couple of minutes hammers the sites you're subscribed to for no benefit; most blogs update daily at best, and some feeds will start rate-limiting or blocking you if you hit them constantly. Twice an hour is generous for a personal reader. If you follow a fast-moving news feed and want it snappier, that's what the manual refresh button is for.

The part that makes it stick: your phone

A reader you can only use at a desk won't survive contact with real life. The reason FreshRSS is the one I recommend is that it speaks two APIs that mobile apps already know, so you get a proper native app instead of squinting at the mobile web page.

  • It implements the Google Reader API. Reeder, NetNewsWire, and others can sync against it as if it were the old Google service. You point the app at your URL, log in, and your feeds and read state sync across every device.
  • It also speaks the Fever API, which a handful of older apps prefer.

Turn these on under Settings, then Authentication, and set an API password. On the app side you enter your FreshRSS URL, your username, and that API password — not your login password. Now read state is shared: an article you read on the train is marked read on your laptop, and vice versa. This is the feature that turns FreshRSS from a website into your reader.

Bringing your subscriptions with you

You are almost certainly leaving something — a hosted reader, a dying app, a browser's built-in feeds. Nearly all of them export OPML, which is just an XML list of your subscriptions. Find the export button in whatever you're abandoning, save the .opml file, then in FreshRSS go to Subscription management, Import / Export, and upload it. Your folders and feeds come across in one shot.

If you're coming from a social platform's "following" list rather than a reader, check whether the sites you follow publish a feed — most blogs, news sites, YouTube channels, and even some newsletters do, often at /feed or /rss or discoverable by pasting the page URL straight into FreshRSS, which will hunt for the feed itself.

A note on locking it down

FreshRSS has its own login, so it's not wide open, but there's no reason to leave the admin panel of your reader exposed to the whole internet if you don't have to. If you already run a VPN into your server, you can bind FreshRSS to the private interface and reach it over the tunnel — though that does complicate mobile sync, since your phone then needs the VPN up to fetch. For most people the built-in auth over HTTPS is a reasonable middle ground; just use a real password and, if you want, put it behind an extra layer with your reverse proxy.

Running your own reader on a small server you rent for pocket change — the kind of thing NoctHost exists for — is one of those self-hosting projects that pays off every single day, quietly, for years. No account to lose, no feed to be manipulated, no shutdown email. Just the web, the way you actually wanted to read it.

Spin one up in about a minute

Email signup, pay with crypto, hourly billing. Trying a box costs cents — destroy it when you are done.

Deploy a server

Frequently asked

Do I need MySQL or PostgreSQL, or is SQLite fine?
For a single user or a small household, SQLite is genuinely fine and simpler — no second container, one volume to back up. Switch to PostgreSQL only if you're running many users or tens of thousands of articles and notice it dragging, which most people never will.
Which mobile app should I use with FreshRSS?
Any that support the Google Reader API: Reeder and NetNewsWire are popular on Apple devices, and there are several solid Android readers too. Enable the API in FreshRSS settings, set an API password, and point the app at your URL. Read state syncs both ways.
How often should feeds refresh?
Twice an hour via the built-in cron is plenty for a personal reader and polite to the sites you follow. Refreshing every couple of minutes gains you almost nothing and risks getting rate-limited by the feeds themselves. Use the manual refresh for anything you want instantly.
Can I move my subscriptions in from another reader?
Yes — export OPML from whatever you're leaving and import it under Subscription management. Folders and feeds come across together. It's the standard format basically every reader supports.
How much server does FreshRSS need?
Very little. A 1 vCPU / 1 GB instance runs it comfortably with room to spare; it's a small PHP app polling feeds a couple of times an hour, not a resource hog.

Keep reading