Saturday, September 8, 2018

How to setup tiny tiny rss on a raspberry pi

I normally use Feedly (the app on iOS and the website) to collect all my RSS feeds. After upgrading my PiHole DNS server's Raspberry Pi from the 3B to 3B+ I had a spare pi on hand. I decided to try using it as an Tiny Tiny RSS server. What follows are the steps needed to do this. It takes about 2 hours if all goes well :)

Note: I decided to use Postgres as the database for the Tiny Tiny RSS (TT-RSS) server since the TT-RSS documentation recommends it.

Warning: This guide does not have steps to secure your apache and postgres servers running on the pi. Do not expose this server on the internet. I used a VPN to connect to my local home network from the outside while travelling to read my feeds.

With that warning out of the way, here goes:
  • Enable SSH on the pi (instructions here - follow the section - Enable SSH on a headless Raspberry Pi)
  • After the Pi is setup, it has to be updated first
sudo apt update && sudo apt upgrade -y && sudo apt dist-upgrade
sudo apt-get autoremove
sudo apt-get clean
sudo apt-get check
  • I love vim for editing configuration files. So let's install that next
sudo apt-get install vim
  • Next install Apache
sudo apt-get install apache2
  • Then PHP and PHP libraries
sudo apt-get install php libapache2-mod-php
sudo apt-get install php7.0-mbstring
sudo apt-get install php7.0-xml
sudo apt-get install php-curl php-pgsql php-intl
  • Then install postgres. At the time of writing, the version available on the Raspbian repo is 9.6. You can find the version using
sudo apt-cache search postgresql | less
  • Install Postgres
sudo apt-get install postgresql-9.6
  • Install Git
sudo apt install git
  • go to the apache document root. This is where the TT-RSS server PHP code will reside
cd /var/www/
sudo chmod -R 777 html
cd html
  • now lets get the TT-RSS software
git clone tt-rss
  • time to prep Postgres. Login to Postgres and create the user and database which TT-RSS will use
sudo -u postgres psql postgres
  • at the prompt do the following
CREATE ROLE ttrssuser LOGIN PASSWORD 'put in a password here';
CREATE DATABASE ttrssdb WITH OWNER = ttrssuser;
  • type \q to exit the pgsql prompt
  • check if it worked
psql -h localhost -d ttrssdb -U ttrssuser -p 5432
  • enter the password you setup for the user. type \q to exit the pgsql prompt
  • The TT-RSS documentation recommends enabling PHP's opcode cache. Lets do that next
  • Where is the opcode library located? We need that so that we can enter it in the php.ini file
sudo find / -name
  • where is the php.ini to enable opcode cache in?
sudo find / -name php.ini
  • first backup the file
sudo cp -pv /etc/php/7.0/apache2/php.ini /etc/php/7.0/apache2/php.ini_BAK
  • edit the file
sudo vi /etc/php/7.0/apache2/php.ini
  • Add the following lines and save the file
in the ; Dynamic Extensions ; sectionadd the following lines
in the [opcache] section
  • check if the opcode cache is enabled and the PHP data objects driver for Postgres is loaded
  • to do this, create a info.php file in /var/www/html
sudo vi /var/www/html/info.php
  • put this line in the file and save it
<?php phpinfo(); ?>
  • Change owner to pi for this file
sudo chown pi:pi info.php
chmod 755 info.php
  • Restart apache
sudo service apache2 restart
  • From a browser hit the apache server
  • check for the following lines in the output
Opcode Caching     Up and Running
PDO drivers     pgsql
PostgreSQL(libpq) Version     9.6.7
  • now it's time to configure tt-rss. Back to the command line
  • Give write permissions to the pi user first
cd /var/www/html
chmod 777 tt-rss
cd tt-rss
chmod -R 777 cache/images
chmod -R 777 cache/upload
chmod -R 777 cache/export
chmod -R 777 cache/js
chmod -R 777 feed-icons
chmod -R 777 lock
  • From a browser hit the tiny tiny rss install link
  • enter your database connection details (for the hostname I used localhost), test the configuration and initialize the database
  • login to tt-rss (http://yourraspberrypi/tt-rss) and change the default password. Import your opml file. For this do the steps from this excellent Lifehacker article Step Four: Log In and Import Your Feeds
  • Enable api access so that you can use iOS apps to connect to the TT-RSS server. Click the Actions menu at the top-right corner of the screen and select Preferences. Next click the checkmark next to Enable API access. Save configuration by clicking the button at the bottom of the screen
  • setup crontab to refresh your feeds. To reduce wear on the Raspberry Pi SD card, I setup cron to run every 2 hours to refresh the feed. Back on the command line
crontab -e
  • add this line and save
1 */2 * * * /usr/bin/php /var/www/html/tt-rss/update.php --feeds --quiet

that's it. Enjoy your new RSS feed aggregator server!

For iOS I used the app Fiery Feeds to connect to my TT-RSS server over VPN to read my feeds.

Wednesday, July 4, 2018

Late night questions: Will duplicate rules be enforced even if the data load happens via the data loader?

While playing with Matching and Duplicate rules in Salesforce, I got a question on what the behavior would be if a record matching existing data was uploaded through the dataloader. The duplicate matching rules should kick-in but I had to try it out to see if for myself.

As with most doubts in Salesforce, this one could be easily tested using a developer sandbox.

Test Setup:

  1. Create and activate a contact matching rule to match contacts exactly on email and fuzzily (is that a valid word?) on the first name
  2. Create and activate a Duplicate matching rule to block creation of the duplicates. 
  3. Create a sample contact record using the default SFDC UI
  4. Download the record through SFDC Dataloader to serve as a CSV upload template
  5. Edit the downloaded file and remove the Id column. Change the first name to be close the initial value (say Rose to Rosey)
  6. Try to upload this file through the data loader

Data loader outputs an error to the error log:


"Test","Rosey","123 Main St","","Use one of these records?"

Use one of these records?
This is the default message configured on the Duplicate Matching rule. This clearly shows Duplicate rules are being enforced even when the dataloader is used to insert data

Interestingly, this behavior was the same even if the duplicate rule was set to Action On Create = Allow - you still get an error and the Contact is not created. This is different from what the SFDC UI would do - it would allow contact creation.

Tested on Summer '18 Patch 11.4