Installing FreshRSS on a Raspberry Pi via Docker

I really like RSS and use it every day to keep up with the news and stop myself from endless scrolling websites for hours on end. I have been using Reeder as my RSS feed reader since moving to iOS a few years ago. I liked that the application allowed for local RSS accounts on the phone and also has a built in read-it-later functionality. These two functions allowed me to cut reliance on Feedly for RSS aggregation and Pocket for read-it-later. While I like that I'm not relying on a third party for my news aggregation, I would like to be able to read through my RSS feeds at a desktop.

This page is my attempt to document me setting up FreshRSS to take on the role of my RSS aggregator. I will be running the server using Docker on a Raspberry Pi 2 Model B.

I will specifically be writing about getting FreshRSS running on the local area network (LAN), this tutorial will not cover connecting the server to the internet. This will be added at a later date. See the to do later section

[NOTES] Items that will be custom to your set up will be written in bold and more detailed notes will accompany. I will also assume you are running all of this as the 'pi' users; I'll make notes of changes you'll need if running as a different user.

!! This guide is presented "as-is" and I cannot guarantee that it'll work. Always back up your work and do your due diligence to not break your stuff. !!

Table of Contents


I won't go into detail on how to install Raspberry Pi OS (formerly Raspbian) onto a Raspberry Pi. There are plenty of tutorials online on how to do it, including on I chose to install Raspberry Pi OS Lite as I knew that I was never going to use the GUI desktop and wanted a small download.

Post Operating System (OS) Installation Tasks

Once the OS has been installed, update the packages on the OS and reboot.

$ sudo apt -y update && \
  sudo apt -y upgrade && \
  sudo apt -y autoremove && \
  sudo apt -y clean && \

Also, make sure that your user (the user account 'pi' already is in the sudo group) is in the sudo group so that you can run sudo.

$ groups pi
pi : pi adm dialout cdrom sudo audio video plugdev games users input netdev spi i2c gpio

Installing Docker

These instructions are cribbed from Docker's own documentation. I found that FreshRSS's documentation is a little different and Docker's worked better for me.

According to Docker (link):

In testing and development environments, some users choose to use automated convenience scripts to install Docker. This is currently the only approach for Raspbian.

Also, the convenience script only works on systems that don't have docker already installed. I'll be using the convenience script to install Docker.

$ curl -fsSL -o
$ sudo sh 

If you want to run docker commands without being root, add that user to the docker group

$ sudo usermod -aG docker pi

For your new group association to take effect, log out and back in.

$ exit

After installing Docker via the convenience script, to upgrade Docker we can just use apt to update

$ sudo apt -y update && \
  sudo apt -y upgrade && \
  sudo apt -y autoremove && \
  sudo apt -y clean

Now we can verify that Docker is working

$ docker run hello-world

Installing FreshRSS

This section, I will be cribbing from FreshRSS's Docker

Create an isolated network

$ docker network create freshrss-network

Create persistent volume containers for FreshRSS

$ docker volume create freshrss-data
$ docker volume create freshrss-extensions

Now we run docker to build our containers. A couple of these you can edit (I've bolded them) to meet your needs.

$ docker run -d --restart unless-stopped --log-opt max-size=10m \
  -v freshrss-data:/var/www/FreshRSS/data \
  -v freshrss-extensions:/var/www/FreshRSS/extensions \
  -e 'CRON_MIN=4,34' \
  -e TZ=Europe/Paris \
  -p 8080:80 \
  --net freshrss-network \
  --name freshrss freshrss/freshrss:arm

You can edit the CRON_MIN variable to specify how often FreshRSS grabs new articles and the TZ variable for your local timezone. For a list of vaild timezones.

By default FreshRSS uses SQLite, which works well for a Raspberry Pi, due to it's small CPU and RAM overhead.

Configuring FreshRSS

Once FreshRSS is installed you can finish configuring it via a web browser. Navigate to your Raspberry Pi's IP address to start the process.

http://IP address here:8080
  1. Languages - Choose your preferred language
  2. Checks - Automatic checks that all the requirements are installed
  3. Database Configuration - Allows you to choose your preferred database. By default FreshRSS uses SQLite, which works well for a Raspberry Pi, due to it's small CPU and RAM overhead.
  4. General Configuration - Create your first user account. (I default to setting Authentication Method to Web Form, because I am not too worried about security threats when this server doesn't exit the LAN)
  5. This is the end - All done

Using FreshRSS

Once you're done you'll log in with your new account and land on the main page.

FreshRSS Housekeeping

Here are some CLI tools for administrative tasks, they've been taken from the FreshRSS cli page and modified for use with Docker. For more notes on options on some of these, check out the FreshRSS cli page.

$ docker exec --user www-data -it freshrss ./cli/create-user.php --user username [ --password 'password' --api_password 'api_password' --language en --email --token 'longRandomString' --no_default_feeds --purge_after_months 3 --feed_min_articles_default 50 --feed_ttl_default 3600 --since_hours_posts_per_rss 168 --max_posts_per_rss 400 ]

$ docker exec --user www-data -it freshrss ./cli/delete-user.php --user username

$ docker exec --user www-data -it freshrss ./cli/list-users.php

$ docker exec --user www-data -it freshrss ./cli/export-sqlite-for-user.php --user username --filename /tmp/db.sqlite

$ docker cp freshrss:/tmp/db.sqlite /tmp/db.sqlite

$ docker exec --user www-data -it freshrss ./cli/import-sqlite-for-user.php --user username [ --force-overwrite ] --filename /tmp/db.sqlite

To Do Later

This guide is thin and I'd like to fill it out more. I'll be coming back to this in a little bit and revise this so that the server is accessible to the reader from the internet.

Full Output

pi@raspberrypi:~ $ sudo apt -y update && \
>   sudo apt -y upgrade && \
>   sudo apt -y autoremove && \
>   sudo apt -y clean && \
>   reboot
Get:1 buster InRelease [15.0 kB]
Get:2 buster InRelease [32.8 kB]
Get:3 buster/main armhf Packages [13.0 MB]
Get:4 buster/main armhf Packages [364 kB]
Get:5 buster/non-free armhf Packages [104 kB]
pi@raspberrypi:~ $ curl -fsSL -o
pi@raspberrypi:~ $ sudo sh
# Executing docker install script, commit: 3d8fe77c2c46c5b7571f94b42793905e5b3e42e4
+ sh -c apt-get update -qq >/dev/null
+ sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sh -c curl -fsSL "" | apt-key add -qq - >/dev/null
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sh -c echo "deb [arch=armhf] buster stable" > /etc/apt/sources.list.d/docker.list
+ sh -c apt-get update -qq >/dev/null
+ [ -n  ]
+ sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
pi@raspberrypi:~ $ sudo usermod -aG docker pi
pi@raspberrypi:~ $ sudo apt -y update && \
>   sudo apt -y upgrade && \
>   sudo apt -y autoremove && \
>   sudo apt -y clean
Hit:1 buster InRelease
Hit:2 stable InRelease
Hit:3 buster InRelease
Hit:4 buster InRelease
pi@raspberrypi:~ $ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
4ee5c797bcd7: Pull complete
Digest: sha256:7e02330c713f93b1d3e4c5003350d0dbe215ca269dd1d84a4abc577908344b30
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:

For more examples and ideas, visit:

pi@raspberrypi:~ $ docker network create freshrss-network
pi@raspberrypi:~ $ docker volume create freshrss-data
pi@raspberrypi:~ $ docker volume create freshrss-extensions
pi@raspberrypi:~ $ docker run -d --restart unless-stopped --log-opt max-size=10m \
>   -v freshrss-data:/var/www/FreshRSS/data \
>   -v freshrss-extensions:/var/www/FreshRSS/extensions \
>   -e 'CRON_MIN=4,34' \
>   -e TZ=America/Phoenix \
>   -p 8080:80 \
>   --net freshrss-network \
>   --name freshrss freshrss/freshrss:arm
Unable to find image 'freshrss/freshrss:arm' locally
arm: Pulling from freshrss/freshrss
db574d82360c: Pull complete
5138682648dd: Pull complete
68b44b1a81c9: Pull complete
b7d98187ba94: Pull complete
cd3646c658c4: Pull complete
483530910a63: Pull complete
0f87fd089e2c: Pull complete
4c44806c69c5: Pull complete
29bfb205fe4c: Pull complete
e9be3c2200ec: Pull complete
c52f219d78fc: Pull complete
Digest: sha256:94e100ce7f4cab4ac823430f20dc8ea3efae3d5705940c5ae4c0abee0ceb1b13
Status: Downloaded newer image for freshrss/freshrss:arm
Shedtepherd - Homepage