Since the retirement of Google Reader, I had been itching for a RSS aggregator & feed reader for a while. While Vienna for OSX used to be a favorite when I had a desktop on close to 24-7, it could/would miss occasional posts once I started sleeping/powering down machines in their off-hours. I had been using Feedly for a year or two at this point, but was growing increasingly disenfranchised with their cloud-style model & push for pay-for services (accompanied with reduced free functionality).
Having surveyed some of the available open-source/self-hosting solutions, I finally settled on giving FreshRSS a try. Months ago, I attempted to set this up in a test jail on my FreeBSD sever to no avail, and abandoned the work until a couple weeks ago. About a month ago, I started experimenting with Linux (particularly Manjaro, an Arch derivative) as a potential desktop replacement.
With Arch running on a Raspberry Pi Zero W (to get more familiarized with the Arch/Manjaro ecosystem), I finally renewed my attempts to get this installed on a Linux platform (which had more documentation available). With substantially less problems, I was able to get it stably running & configured. Trialling it as a replacement for Feedly for a couple weeks, I was satisfied with its performance, even on the Pi Zero! Since I migrated my web hosting from Bluehost for this site and others to a VPS running FreeBSD, I now wanted to translate this self-hosted service from my private network to a production environment accessible from the Internet at large.
With WordPress on this host published atop nginx and php71, I wanted to get FreshRSS published atop these same web modules, ideally. Most of the installation instructions were aimed at providing FreshRSS atop Apache and php5, but I wanted to avoid stretching myself into other platforms when I could hopefully enrich my understanding of existing ones. Through some reasonable troubleshooting (mostly in identifying missing php modules), I finally got a production installation going. I will outline the steps below.
In either a FreeBSD installation (I am running in 11 presently) or a containerized jail
(my personal preference for sandboxing and snapshots), you need to install some packages first. As I performed all this within the jail, assume all operations are executed as root
.
- Necessary packages:
- Pick a location to acquire & unpack the FreshRSS code from GitHub, and give the
www
user permission to work with it fromnginx
: - Link just the publishable directory to
/usr/local/www
to avoid exposing some of the sensitive guts: - OPTIONAL: If you want to generate a self-signed SSL certificate for encrypting communications with your installation, I used/condensed the instructions I found here. If you’re not concerned about HTTPS access, you can skip ahead to step 10.
- Create a location for the SSL cert, key, and associated
nginx
configuration snippets: - Generate the certificate with a duration (
${CERT_LENGTH}
) of your choosing with a key size rsa-2048 or greater (I use 4096 by default, personally), and save the private key & certificate in separate locations: - Generate a strong Diffie-Hellman group. Don’t arbitrarily bump this up to 4096; that may take a long while to generate:
- Create a certificate snippet (e.g.
/usr/local/etc/nginx/snippets/self-signed.conf
) with the following contents: - Create a configuration snippet (e.g.
/usr/local/nginx/snippets/ssl-params.conf
) for the SSL parameters: - Create a relatively lean
nginx
configuration file (/usr/local/etc/nginx/nginx.conf
by default on FreeBSD) for publishing: - If you are already hosting other pages, or for the sake of simplicity/cleanness just want to import the configuration, you can just write the
server{}
block to the file ashttp{}
should already be declared in the mainnginx.conf
file. - Now for some trickier work: we need to configure php!
- First, we will copy the production
php.ini
file into place. Edits should be unnecessary, as installing the php modules should automatically link them into theini
files: - Second, we will lockdown php to just serve itself on a local socket, and bump up the maximum number of children threads (revert the last edit if it gives you trouble later on):
- Everything should be configured, so let us commit them to startup:
- Testing the configuration files for the services should be successful without consequence. If not, you will need to go back to steps 3–11 to resolve.
- If the configurations pass muster, then you are ready to fire the services up & test the site:
pkg install git-lite \
nginx \
php71 \
php71-{ctype,curl,dom,fileinfo,filter,gmp,json,\
pdo_sqlite,session,simplexml,xml,zip}
cd /usr/local/share
git clone https://github.com/FreshRSS/FreshRSS.git FreshRSS
chown -R www:www FreshRSS
chown -R g+rw FreshRSS
ln -s /usr/local/share/FreshRSS/p /usr/local/www/freshrss
mkdir -p /etc/ssl/{certs,private} /usr/local/nginx/snippets
openssl req -x509 \
-nodes \
-days ${CERT_LENGTH} \
-newkey rsa:4096 \
-keyout /etc/ssl/private/nginx-selfsigned.key \
-out /etc/ssl/certs/nginx-selfsigned.crt
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.crt;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
user www;
worker_processes: 2;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80; # http on port 80
# Delete/comment out if not using self-signed cert configured earlier
listen 443 ssl; # https on port 443
include /usr/local/nginx/snippets/self-signed.conf
include /usr/local/nginx/snippets/ssl-params.conf
# your server's url(s)
your.website.com;
# the folder p of your FreshRSS installation
root /usr/local/www/freshrss;
index index.php index.html index.htm;
# nginx log files
access_log /var/log/nginx/rss.acc.log;
error_log /var/log/nginx/rss.err.log;
# php files handling
# this regex is mandatory because of the API
location ~ ^.+?\.php(/.*)?$ {
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location / {
try_files $uri $uri/ index.php;
}
}
}
cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini
sed -i .backup \
's/listen\ \=\ 127.0.0.1\:9000/listen\ \=\ \/var\/run\/php-fpm.sock/' \
/usr/local/etc/php-fpm.d/www.conf
sed -i ''\
's/;listen.owner\ \=\ www/listen.owner\ \=\ www/'\
/usr/local/etc/php-fpm.d/www.conf
sed -i ''\
's/;listen.group\ \=\ www/listen.group\ \=\ www/'\
/usr/local/etc/php-fpm.d/www.conf
sed -i ''\
's/;listen.mode\ \=\ 0660/listen.mode\ \=\ 0660/'\
/usr/local/etc/php-fpm.d/www.conf
sed -i ''\
's/pm.max_children\ \=\ 5/pm.max_children\ \=\ 10/'\
/usr/local/etc/php-fpm.d/www.conf
sysrc -f /etc/rc.conf.local php_fpm_enable="YES" nginx_enable="YES"
php-fpm -t
nginx -t
service php-fpm start
service nginx start
At this point, you should be able to browse to your box’s/instance’s address and be good to go for configuring FreshRSS from its web interface!