Miniflux with docker-compose

Published on 17 Jan 2018

The Old Reader had been giving me an inconsistent reading experience lately, so I decided to look for a better solution. Preferably a self-hosted RSS reader. The initial scouting process gave me three options: TTRSS, Stringer, and Miniflux. It does not need to be feature-rich with all bells and whistles. As long as it gives me a consistent reading experience (desktop & mobile), with the baked-in capability to fetch full article (if feeds only display excerpt), that is a major win already.

At first, I was tempted to try Stringer. It has a pretty modern-ish minimalistic interface. However, that thought was jettisoned after I read a review by David Young written in August 2017: Miniflux, lightweight self-hosted rss reader. Btw, he is awesome. He maintains a website full of cool Docker swarm recipes, the Geek’s Cookbook. He inspired me to, one fine day, tinker around with MkDocs.

Miniflux requires PostgreSQL as the db backend. This was a deal-breaker at first because I wished for something simpler like the SQLite. However, Postgres is much more robust so I was like “well, let’s give a try”. Since I need to deploy a database system, I went with Docker (and docker-compose) to set up an isolated environment because I figured it would be better that way.

Let’s install Docker and docker-compose (v1.18.0 latest as of January 16, 2018) first.

>> Install Docker
$ wget -qO- https://get.docker.com/ | sh
$ sudo usermod -aG docker ${USER}

>> Install docker-compose v1.18.0
$ sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

Here is the docker-compose.yml for my Miniflux (v2.0.0 latest as of January 16, 2018).

version: '2'
services:
  miniflux:
    image: miniflux/miniflux:2.0.0
    ports:
      - "8585:8080"
    environment:
      - DATABASE_URL=postgres://mflux:changemelol@db/miniflux?sslmode=disable
  db:
    image: postgres:10.1-alpine
    environment:
      - POSTGRES_USER=mflux
      - POSTGRES_PASSWORD=changemelol

Launch the docker-compose in the background.

$ docker-compose up -d

Initialize the Miniflux.

>> Run database migrations
$ docker exec -ti <container-name> /usr/local/bin/miniflux -migrate

>> Create the first user
$ docker exec -ti <container-name> /usr/local/bin/miniflux -create-admin

This Miniflux should be available at http://ip-address:8585. I use Caddy as the reverse-proxy with SSL/HTTPS provided by the Let’s Encrypt.

my-miniflux-example.net {
  tls [email protected]
  proxy / localhost:8585
}

Now it is up and running!

Update, 18 January 2018

When I was comparing the GitHub stars, Miniflux (v2: 70, v1: 919) is behind Stringer (2,766) so I was like “hmm, Miniflux seems to be less popular but GitHub stars is not a good proxy for popularity, nevertheless let’s run a brief comparison”. I used Stringer’s default docker-compose.yml to spin up Docker instances. Test machine was Xubuntu 17.10 running inside a virtual machine (Oracle Virtualbox) with 2 virtual CPUs and 1.2 GB memory.

Just so you know, Miniflux is written in Go while Stringer is written in Ruby. Both have their own Postgres instance. From here, it is kind of clear who would win.

Miniflux vs. Stringer

Stringer’s web instance was using 221.8 MiB (18.28%) memory while Miniflux’s web instance was using 5.445 MiB (0.45%) memory. Note that both did not have any feed subscription yet. In summary, Miniflux is a good choice for low-memory VPS.

Update, 19 January 2018

Running a postgres container without a Docker shared volume is a not a well-thought strategy. Data does not persist in containers, and that is a real concern with running a database container. This is a revised docker-compose.yml with shared volume.

version: '2'
services:
  miniflux:
    image: miniflux/miniflux:2.0.0
    container_name: miniflux_web
    restart: always
    ports:
      - "8585:8080"
    environment:
      - DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disable
  db:
    image: postgres:10.1-alpine
    container_name: miniflux_db
    restart: always
    volumes:
        - ./storage:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=miniflux
      - POSTGRES_PASSWORD=secret

The command docker-compose up -d runs the container set up process. Do not forget to initialize the Miniflux (see above) to bootstrap the Miniflux. Now, the postgres data (within container at /var/lib/postgresql/data) is mapped to the local folder ~/compose/miniflux/storage. The local folder can be defined as you like, but the postgres data folder within container must remain constant.

However, accessing the ./storage folder on host local folder is a little bit tricky. Since I am confused with the permission and stuff, regular $USER cannot access the folder, but superuser (with sudo su) can get into that folder. I tried changing the permission with chown but that crashed the whole setup.

A little bit tips on backing up the ./storage folder. Assuming I need to move from my current server and re-launch my Miniflux installation, I would go with archiving the ./storage folder first, transfer it to the new server, unzip it first, and then re-launch the docker-compose assuming no radical nor significant changes have been made to the image file and the docker-compose.yml file. The data should be preserved.