My reading list used to be somebody else’s product.
Every article arrived pre-scored, ordered by an inference engine I never agreed to and could not inspect, with one control: the scroll. That is a strange thing to hand over. What you read shapes what you think, and I had outsourced the selection to a system tuned for the minutes I spend, not the value I take away.
Last night I stopped. I stood up my own reader: 35 sources, 92 megabytes of RAM, and a sort order that is simply chronological. Which is to say there is no algorithm at all.
What it actually is
Miniflux. A single static Go binary under Apache-2.0, backed by PostgreSQL. No plugin directory, no theme marketplace, and no vendor mobile app in the store. You hand it feed addresses; it fetches them on a schedule and shows you a list, newest first.
The design choices are the opposite of the genre. There is no “for you” tab. There is no engagement metric. There is no recommendation of any kind, because recommending is not the job. The project describes itself as a minimalist and opinionated feed reader, which is the sort of confidence you only get from software that knows what it is for.
35 feeds makes me a small operator, and that is the point. A reader is not a network; it is a list you curate and can read to the end.
The build, with the actual commands
The host is a Proxmox box. The reader runs in an unprivileged LXC with 2 cores, 2 GB of RAM and 8 GB of disk — the smallest container I have, deliberately.
Debian 13 base, then:
apt-get update
apt-get install -y --no-install-recommends postgresql curl ca-certificates
Miniflux publishes a .deb, and I do not install packages without checking what I downloaded:
curl -fsSL -O https://github.com/miniflux/v2/releases/download/2.3.3/miniflux_2.3.3_amd64.deb
sha256sum miniflux_2.3.3_amd64.deb
The digest on the release itself is in the GitHub API for that asset, so the comparison is not folklore — you read the expected value from the publisher’s own record and compare. Mine matched, and only then did dpkg -i run.
Configuration is one file, /etc/miniflux.conf, mode 0640, owned by the service user:
DATABASE_URL=postgres://miniflux:REDACTED@127.0.0.1:5432/miniflux?sslmode=disable
LISTEN_ADDR=192.168.1.42:8080
BASE_URL=http://192.168.1.42:8080
RUN_MIGRATIONS=1
LOG_LEVEL=info
Note LISTEN_ADDR. It binds one address, not everything. I would rather the service be unreachable from places it has no business being than rely on a firewall I might misconfigure later.
The first command that caught me out is creating the admin user. The Miniflux CLI does not read systemd’s EnvironmentFile, so running it by hand fails with a database authentication error that looks like a password problem and is not:
set -a; . /etc/miniflux.conf; set +a
script -qec "/usr/bin/miniflux -create-admin" /dev/null
Source the config first and it behaves. Worth knowing before you spend 20 minutes suspecting your database password.
Then the feeds. I keep the list as an OPML file, which means the whole reader is rebuildable from a text file I own — if the container dies, I import and walk away. 35 feeds in, and the first refresh pulled 1,527 entries.
What it costs
92 megabytes of RAM in use when I looked — roughly 37 of that the Miniflux process itself, the rest PostgreSQL and the base system. 1.1 GB of disk, of which the database accounts for 19 MB and the binary 23 MB on its own. That is a reading from one evening, not a spec sheet: the number drifts with the size of your feed list and how much your database has accumulated. Mine is carrying 1,527 articles. The scheduler runs every 60 minutes and picks up whichever feeds are due, based on when each was last fetched — which is more current than any news app I have used on a phone that spent the day guessing when to bother me.
The money cost is the electricity of a container that idles. The real cost is not measured in either: it is a service, so it is a service you patch. 2 processes, a single configuration file, and an update duty that is now mine. I would rather say that plainly than pretend self-hosting is free of maintenance — the maintenance is the price of the ownership.
3 things that will annoy you, honestly
A site without a feed cannot be added. Miniflux subscribes; it cannot conjure a feed out of a plain web page. 2 sources I wanted are benched for exactly that reason. If scraping feedless pages matters more to you than a small codebase, FreshRSS does XPath scraping and is the better tool for that job — it is also a PHP stack with a larger surface to keep patched. I chose the smaller thing.
Reddit rate-limits you. 4 feeds failed on the first burst with “too many requests”. An individual retry cleared most of them; setting a descriptive per-feed user-agent cleared the rest. Miniflux lets you do that per feed, which is the correct amount of knob.
Pruning is now your job. 1,527 articles arrived on the first refresh, and nobody ranked them. A self-hosted reader does not filter for you — it removes the filter and hands you the decision. That is the trade: you stop being curated and start being responsible.
One more thing, since this is a page about owning your reading list. The reader holds no credentials beyond its own database. It can reach the internet to fetch feeds and nothing else on my network — not the file server, not the backups. When I run something that spends its day parsing hostile content from strangers, I want the blast radius to be a container with a database in it and no keys.
The point
I am not going to tell you a self-hosted reader makes you safe. It makes you smaller, which is different and more useful. There is no profile being built for an advertising system, no ranking function between me and the writing, and no dependency on a company’s continued interest in running a product it does not profit from.
A reading list you own is smaller than the one you were given. That is the feature, not the compromise.
That said, I have been running it for one evening. Ask me again in a month, when half those feeds have gone stale and I find out whether I have the discipline to prune them — or whether I just built myself a slower version of the same problem.
