Just one more self-hosted application, then I’ll stop, I promise
Self-Hosting FreshRSS is kind of pointless as a single user but I’m going to do it anyway.
Why though?
Whilst not quite as straightforward as self-hosting a music streaming server , running your own RSS server is eminently do-able.
However you will end up with a very pretty and usable interface.
This, and the ability to synchronise the feeds across multiple devices using an API are the main reasons I chose to do this.
It’s a learning exercise as a single user though (unless you care deeply about having thousands of articles archived on your server for posterity).
FreshRSS Main Stream Screenshot
Create a sub-domain
Not strictly a requirement as I could access it locally but I want to be able to sync the feeds with multiple devices (phone, tablet etc.) so a dedicated URL is preferred (by me).
Create a MySQL database and user
I already have MariaDB installed and running as it is the DB behind this WordPress site.
PostgreSQL is recommended, although as the installation is just for me and I already had MariaDB installed I went with that.
If needed, install by running the following in a Terminal:
sudo apt install mariadb-server -y
However if this is the first time MariaDB has been installed it is a good idea to run through an initial setup in a Terminal:
sudo mysql_secure_installation
To check that it’s running and to start on a reboot, run the following in a Terminal:
sudo systemctl start mariadb
sudo systemctl enable mariadb
sudo systemctl status mariadb
To add the Gitea database run the following in a Terminal:
sudo mysql -u root -p
Then run:
CREATE DATABASE `freshrss`;
CREATE USER 'freshrss'@'localhost' IDENTIFIED BY 'super_long_password';
GRANT ALL PRIVILEGES ON `freshrss`.* TO 'freshrss'@localhost;
FLUSH PRIVILEGES;
QUIT;
Self-Hosting FreshRSS – Installing
https://github.com/FreshRSS/FreshRSS?tab=readme-ov-file#installation
https://freshrss.github.io/FreshRSS/en/admins/03_Installation.html
https://freshrss.github.io/FreshRSS/en/admins/06_LinuxInstall.html
To download and install, first, navigate to:
cd /usr/share/
Then, clone the git repository:
sudo git clone https://github.com/FreshRSS/FreshRSS.git
Set the installation permissions
Move to the ‘FreshRSS
‘ directory:
cd FreshRSS
Then run the permissions script:
sudo cli/access-permissions.sh
Self-Hosting FreshRSS – nginx
https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html
nginx part I – pre Certbot
Create an nginx conf file:
sudo nano /etc/nginx/sites-available/rss
Then paste in something similar to the below:
server {
listen 80;
#listen 443 ssl;
# HTTPS configuration
#ssl on;
#ssl_certificate /etc/nginx/server.crt;
#ssl_certificate_key /etc/nginx/server.key;
# your server’s URL(s)
server_name rss.example.net;
# the folder p of your FreshRSS installation
root /srv/FreshRSS/p/;
index index.php index.html index.htm;
# nginx log files
access_log /var/log/nginx/rss.example.net_access.log;
error_log /var/log/nginx/rss.example.net_error.log;
# php files handling
# this regex is mandatory because of the API
location ~ ^.+?\.php(/.*)?$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
# By default, the variable PATH_INFO is not set under PHP-FPM
# But FreshRSS API greader.php need it. If you have a “Bad Request” error, double check this var!
# NOTE: the separate $path_info variable is required. For more details, see:
# https://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location / {
try_files $uri $uri/ index.php;
}
}
Ensure it has the right PHP version:
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
Check, symlink and restart
First, check that nginx is configured correctly and return no errors:
sudo nginx -t
Then, symlink the newly created file:
sudo ln -s /etc/nginx/sites-available/rss /etc/nginx/sites-enabled/
Finally, re-check and re-load nginx:
sudo nginx -t && sudo systemctl reload nginx
Certbot
sudo certbot
The result (i.e. successful) should look something like this:
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/rss.example.net/fullchain.pem
Key is saved at: /etc/letsencrypt/live/rss.example.net/privkey.pem
nginx part II – post Certbot
Certbot should have taken care of adding the HTTPS settings.
However for completeness here is mine.
server {
# HTTPS configuration
listen 443 ssl; # managed by Certbot
listen [::]:443 ssl;
http2 on;
# Server
server_name rss.example.net;
root /usr/share/FreshRSS/p/;
# index pages
index index.php index.html index.htm;
# SSL
ssl_certificate /etc/letsencrypt/live/rss.example.net/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/rss.example.net/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
# logging
access_log /var/log/nginx/rss.example.net_access.log;
error_log /var/log/nginx/rss.example.net_error.log;
# php files handling
# this regex is mandatory because of the API
location ~ ^.+?\.php(/.*)?$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
# By default, the variable PATH_INFO is not set under PHP-FPM
# But FreshRSS API greader.php need it. If you have a “Bad Request” error, double check this var!
# NOTE: the separate $path_info variable is required. For more details, see:
# https://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location / {
try_files $uri $uri/ index.php;
}
}
# HTTP redirect
server {
if ($host = rss.example.net) {
} # managed by Certbot
listen 80;
server_name rss.example.net;
return 404; # managed by Certbot
}
Check and reload nginx
sudo nginx -t && sudo systemctl reload nginx
FreshRSS – initial setup
Go to:
rss.example.net
Go through the setup
Host = localhost
Remember that the first user created will have ‘admin’ rights.
Then, log in and create new users as needed.
FreshRSS Subscription Management Screenshot
Self-Hosting FreshRSS – API access
At this point it might be useful to set up API access, especially if your plan is to use an external client.
Go to (and tick):
Administration | Authentication | Allow API access
Refresh feeds with cron
https://freshrss.github.io/FreshRSS/en/admins/08_FeedUpdates.html
FreshRSS is updated by the actualize_script.php
script.
This can be triggered to run at set times using cron
.
Not normal cron, the www-data
user cron.
Swap to www-data
user and open a sh prompt:
sudo -u www-data sh
First, see if the command works:
/usr/bin/php /usr/share/FreshRSS/app/actualize_script.php > /tmp/FreshRSS.log 2>&1;
nano /tmp/FreshRSS.log
Then, setup www-data
cron:
Run the following in a Terminal:
crontab -e
Then add something like the below (choose your preferred run frequency):
# Refresh all of the FreshRSS feeds, every 10 minutes
*/10 * * * * /usr/bin/php /usr/share/FreshRSS/app/actualize_script.php > /tmp/FreshRSS.log 2>&1;
#
To exit the sh
Terminal press:
shift - ctrl - d
Self-Hosting FreshRSS – Extensions
FreshRSS extensions are added to the following directory:
cd /usr/share/FreshRSS/extensions
Auto-Refresh-Extension
https://github.com/Eisa01/FreshRSS—Auto-Refresh-Extension
Whilst having a browser tab log-out after a period of time is good security I would prefer my session to stay alive as long as my browser window is open.
That is what the ‘Auto-Refresh-Extension’ achieves.
First, download the zip to a local machine and extract.
Then, rsync to the /TEMP/ folder on the server (assuming there is a /TEMP/ obviously):
rsync -av -e ssh /home/foo/Downloads/FreshRSS---Auto-Refresh-Extension-master/xExtension-AutoRefresh/* foo@server:/home/foo/TEMP/AutoRefresh/
Now, on the remote machine, create the ‘extension’ directory and then copy the files and folders.
Run the following in a Terminal to make a directory for the extension to live in:
sudo mkdir /usr/share/FreshRSS/extensions/AutoRefresh
Then, copy the extracted files to the newly created directory:
sudo cp -R /home/foo/TEMP/AutoRefresh/* /usr/share/FreshRSS/extensions/AutoRefresh/
Finally, refresh the web page and ‘enable’ the new extension.
Other extensions are available.
Self-Hosting FreshRSS – Clients
I’m using the FreshRSS Android Client from F-Droid (link seems broken):
f-droid.org/packages/fr.chenry.android.freshrss
(Hence why API access was activated earlier.)
Other clients on other platforms are available:
https://github.com/FreshRSS/FreshRSS#apis–native-apps
Finally
Whilst it might have been a bit of a drawn out process; self-hosting FreshRSS does mean that I am no longer exporting and importing OPML files across devices.
Also, the server side works perfectly, although I’m not sure I’m ever going to read those thousands of archives links that are building up.
The Client works perfectly too with a whole bunch of settings to tinker with.
Overall 10/10 would do again.