I have been using miniflux for a while now, and I really like it. It’s a great RSS reader.
Here I want to share my experience with self-hosting it with docker and nginx.
The provisioning is done with Ansible.
Pretty simple, and I think it’s a good starting point for anyone who wants to self-host miniflux.
TLDR;
- Provisioning with Ansible
- Running miniflux with docker
- Reverse proxy with nginx
Provisioning with Ansible
The basic idea is to spin up the docker container with miniflux, providing all the necessary env variables to configure it correctly.
Then you can configure nginx to reverse proxy the miniflux container.
E.g. you could host it on https://rss.example.com
and then let nginx route the traffic to the container running miniflux.
Running miniflux with docker
You’ll need to install the community.docker
ansible galaxy plugin:
ansible-galaxy collection install community.docker
The docker compose file (translated in an Ansible task) looks like this, and is located in roles/miniflux/tasks/main.yml
:
- community.docker.docker_compose:
project_name: miniflux
definition:
version: '2'
services:
db:
image: postgres
restart: unless-stopped
environment:
POSTGRES_PASSWORD: "{{ miniflux_password }}"
POSTGRES_USER: "{{ miniflux_username }}"
volumes:
- miniflux-db:/var/lib/postgresql/data
miniflux:
image: miniflux/miniflux
restart: unless-stopped
environment:
DATABASE_URL: "postgres://{{ miniflux_username }}:{{ miniflux_password }}@db/miniflux?sslmode=disable"
RUN_MIGRATIONS: 1
CREATE_ADMIN: 1
ADMIN_USERNAME: "{{ miniflux_admin_username }}"
ADMIN_PASSWORD: "{{ miniflux_admin_password }}"
POLLING_FREQUENCY: 10
BASE_URL: "https://{{ miniflux_domain }}"
HTTPS: on"
ports:
- "127.0.0.1:3000:8080"
depends_on:
- db
volumes:
miniflux-db:
driver: local
register: output
- ansible.builtin.assert:
that:
- "output.services.miniflux.miniflux_miniflux_1.state.running"
- "output.services.db.miniflux_db_1.state.running"
As you can see, we’re running a postres container alongside miniflux, exposing the miniflux container port 8080
to the host port 3000
. This will later be used by nginx to reverse proxy the traffic.
We’re also setting various environment variables to configure miniflux, and then asserting the services are running.
This means you’ll also need to configure a file containing the variables / secrets.
You could do this in a group_vars
file, or in a secrets
file.
I’ll use ansible-vault
to decrypt when editing and then encrypt the secrets file, like this
#create a new secrets file
touch secrets
#encrypt and decrypt it providing a vault password
ansible-vault encrypt secrets
ansible-vault decrypt secrets
The secrets file looks like this:
miniflux_username: miniflux
miniflux_password: <your password>
miniflux_admin_username: <your username>
miniflux_admin_password: <your password>
miniflux_domain: <your domain>
Reverse proxy with nginx
The nginx configuration looks like this, put it in roles/miniflux/templates/miniflux.conf.j2
:
upstream miniflux {
server 127.0.0.1:3000 max_fails=5 fail_timeout=60s;
}
server {
server_name {{ miniflux_domain }};
listen 80;
listen [::]:80;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml;
client_max_body_size 16m;
ignore_invalid_headers off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass http://miniflux;
}
}
In the playbook, we copy the template to the nginx sites-available directory, and then symlink it to the sites-enabled directory.
- name: install nginx
become: true
apt:
name: nginx
state: present
- name: rm /etc/nginx/sites-enabled/default
file:
path: /etc/nginx/sites-enabled/default
state: absent
- name: setup nginx vhost
template:
src=miniflux.conf.j2
dest=/etc/nginx/sites-available/miniflux.conf
- name: symlink nginx vhost
file:
src=/etc/nginx/sites-available/miniflux.conf
dest=/etc/nginx/sites-enabled/miniflux.conf
state=link
- name: reload nginx
service:
name=nginx
state=reloaded
PS: you could use handlers here, instead of reloading the service directly, I took it out for simplicity.
The Ansible project
Before running the playbook you need to configure the hosts file.
Create a new file called hosts
and add the following:
<your server name> ansible_host=<your ip> ansible_user=<user> ansible_connection=ssh ansible_ssh_private_key_file=<ssh key> ansible_ssh_port=22
Also, add a requirements.yml
file to install some dependencies with ansible-galaxy install -r requirements.yml
:
---
roles:
- name: geerlingguy.pip
- name: geerlingguy.docker
Your project structure should look like this:
.
├── hosts
├── playbook.yml
├── requirements.yml
├── roles
│ ├── app-miniflux
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ └── miniflux.conf.j2
└── secrets
Running the playbook
Now you can run the playbook:
ansible-playbook -i hosts miniflux.yml --ask-vault-pass
You’ll be prompted for the vault password you set when encrypting the secrets file.