SELFHOST.COMPUTER

Miniflux: a fast RSS reader on your own server

#miniflux#docker#self-hosting

Miniflux is a minimalist RSS reader. It's one small Go binary with a PostgreSQL database, no tracking, and a clean web UI. Pair it with a phone app that speaks its API and you have a news reader that doesn't need an account at a big company.

This builds on the Docker and Caddy setup. Start there if you haven't got Caddy running yet.

Add it to your compose file

  miniflux:
    image: miniflux/miniflux:2.2
    restart: unless-stopped
    mem_limit: 256m
    depends_on:
      miniflux-db:
        condition: service_healthy
    environment:
      DATABASE_URL: "postgres://miniflux:CHANGE_ME@miniflux-db/miniflux?sslmode=disable"
      RUN_MIGRATIONS: "1"
      CREATE_ADMIN: "1"
      ADMIN_USERNAME: "admin"
      ADMIN_PASSWORD: "CHANGE_ME"
      BASE_URL: "https://rss.example.com"
      POLLING_FREQUENCY: "60"
      BATCH_SIZE: "20"
      POLLING_PARSING_ERROR_LIMIT: "10"

  miniflux-db:
    image: postgres:17
    restart: unless-stopped
    mem_limit: 256m
    environment:
      POSTGRES_USER: miniflux
      POSTGRES_PASSWORD: CHANGE_ME
      POSTGRES_DB: miniflux
    volumes:
      - miniflux-db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "miniflux", "-d", "miniflux"]
      interval: 10s
      start_period: 30s

Add miniflux-db: under volumes: at the bottom of the file. Neither service has a ports: section. Only Caddy publishes ports, and the database is reachable only from the other containers.

The two CHANGE_ME passwords for the database must match. Generate something long and random with openssl rand -base64 24 or the secret generator. Avoid characters like @, / and : in the database password, because it sits inside a URL. The base64 output can contain / and +, so use openssl rand -hex 24 instead if that bites you.

Pin the tags to the versions you've actually tested. Postgres in particular does not upgrade across major versions by just changing the tag, so pick one major and stay on it until you plan a migration.

Add it to Caddy

rss.example.com {
    reverse_proxy miniflux:8080
}
docker compose up -d
docker compose exec -w /etc/caddy caddy caddy reload

Point a DNS record for rss.example.com at your server first, or Caddy can't get a certificate.

Log in and finish the admin account

Open https://rss.example.com and log in with the admin credentials from the compose file. Change the password under Settings, then remove CREATE_ADMIN, ADMIN_USERNAME and ADMIN_PASSWORD from the compose file and run docker compose up -d again. They're only needed on the first start, and a plain password sitting in a file is something to get rid of.

Miniflux has no open signup page, so only users an admin creates can log in. To add family members, use Users in the menu.

Import your feeds

Coming from another reader? Export an OPML file from it, then in Miniflux open Feeds, Import and upload the file. All your feeds and categories come across. To leave later, Export gives you OPML back, so you're never locked in.

Prefer to add feeds one at a time? Paste a site's address under Feeds, Add Feed, and Miniflux finds the feed itself in most cases.

Apps and API access

Miniflux has its own API and also supports the Fever and Google Reader-style APIs, so many mobile and desktop apps work with it. Under Settings, API Keys you can generate a token for apps that ask for one, and some apps use the Integrations page for a dedicated Fever or Google Reader password. Check your chosen app's documentation for which it wants. Because everything goes through your HTTPS address, there's nothing else to open on the firewall.

Keeping RAM low

Miniflux itself is tiny, usually well under 100 MB at idle, and Postgres is the bigger of the two. A few knobs help:

  • Polling: POLLING_FREQUENCY is how often (in minutes) each feed is checked. 60 is plenty for most feeds. Lower values mean more requests, more CPU and no real gain.
  • Batch size: BATCH_SIZE limits how many feeds are refreshed per run, which smooths out CPU and memory spikes if you follow hundreds of feeds.
  • Clean up old entries: keep read items for a limited time. The CLEANUP_ARCHIVE_READ_DAYS and CLEANUP_ARCHIVE_UNREAD_DAYS settings control how long entries stay, and a smaller database means less to back up.
  • Share Postgres: if you already run one Postgres for other apps, give Miniflux its own database and user in it and drop the miniflux-db service. Don't pay for two.

Watch docker stats for a few days and adjust the mem_limit values to what you actually see. The RAM budget post covers the method.

Back it up

Your feeds, read state and starred items live in Postgres. Don't copy the live data directory. Dump it first:

docker compose exec -T miniflux-db pg_dump -U miniflux miniflux > /srv/dumps/miniflux.sql

Add that line to the script in the restic backups post. If all you care about is the list of feeds, export an OPML file now and then too, which is small enough to keep anywhere.

When to use it

Miniflux suits you if you read a lot of blogs and want something quick, with keyboard shortcuts and no feed algorithm. If you want a heavily customisable reader with plugins and themes, look elsewhere. For a first server, it's one of the cheapest things to run; see the what to self-host first list for the rest.

< all posts · netcup voucher codes

Keep reading