Instructions for installing Tiny Tiny RSS on a Debian system.

Uses Apache and MySQL.

PRESS STOP

Tiny Tiny RSS is now a part of Debian's official repository (at least in the unstable branch at the time of writing (2013–03–14)), so just use sudo apitude install tt-rss instead, if applicable.

There were still some caveats during installation, so I'll quickly describe my installation process using the "official" method here.

  1. Install:

     sudo aptitude install tt-rss
    

    If you have root access to the database server, let dbconfig configure the database setup via the prompts that are launched during installation. When it asks you for a password for the ttrss MySQL user, just leave it blank to get a randomly generated one. This will only be used by the scripts (and it can be found in plaintext in the configuration anyway).

  2. Enter server URL at SELF_URL_PATH in /etc/tt-rss/config.php.

  3. If you use Apache 2.2 as compared to Apache 2.4, you need to explicitly link the installed Apache rules:

     sudo ln -s ../conf-available/50-tt-rss.conf /etc/apache2/conf.d
    

    Reported as bug #703272. Will not be needed in the future when this is fixed.

    Reload Apache rules after this fix:

     sudo service apache2 reload
    

    this should no longer be needed as of tt-rss 1.7.5+dfsg-1 according to earlier linked bug report.

  4. Set DISABLED=0 in /etc/default/tt-rss to be able to start the service.

  5. Start the service:

     sudo service tt-rss start
    
  6. Go to http://localhost/tt-rss and continue configuration.

Old instructions, for whom it may concern

Prerequisites

Install web and MySQL (or PostgreSQL) server, including PHP5 support. Use separate guides for this step, but it shouldn't be much more than

sudo aptitude install apache2 mysql-server libapache2-mod-php5 php5-mysql

The rest of the document assumes that

  • the web root is /var/www,
  • MySQL is listening on localhost:3306 and
  • the web server is listening on localhost:80.

Install library dependencies:

sudo aptitude install php5-cli php5-xmlrpc php5-curl

Installation

Download the latest version of Tiny Tiny RSS at http://tt-rss.org/ and link it in. With example version 1.5.0:

VERSION="1.5.0"
wget http://tt-rss.org/download/tt-rss-${VERSION}.tar.gz
sudo tar -C /usr/local/lib/ tt-rss-${VERSION}.tar.gz
echo "Alias /tt-rss /usr/local/lib/tt-rss-${VERSION}" | sudo tee /etc/apache2/conf.d/tt-rss.local
sudo service apache2 reload

Database setup

Create MySQL user and belonging database:

mysql -u root -p
<enter MySQL root password>
CREATE USER ttrss@localhost IDENTIFIED BY 'ttrsspassword';
CREATE DATABASE ttrss;
GRANT all ON ttrss.* TO ttrss;

Set up initial database structure:

mysql -u ttrss -p -D ttrss < /usr/local/lib/tt-rss-1.5.0/schema/ttrss_schema_mysql.sql
<enter ttrss password>

Configuration

Create Tiny Tiny RSS configuration file:

sudo cp /usr/local/lib/tt-rss-1.5.0/config.php{-dist,}

Configure it:

DB_TYPE=mysql
DB_USER=ttrss
DB_NAME=ttrss
DB_PASS=ttrsspassword
ENABLE_UPDATE_DAEMON=true
DAEMON_SLEEP_INTERVAL=600
DEFAULT_UPDATE_METHOD=1

Make cache directories writeable for the web server and regular user (needed for feeds, icons, lock files, etc.):

sudo chmod 777 -R /usr/local/lib/tt-rss-1.5.0/{cache,icons,lock,lib/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer}

Hindsight: this is not a very beautiful solution. If you are on single user system it is probably fine, but otherwise you should give ownership to the web server user and let it do all the updating. The feed updating procedure must then also be run as this user. I don't use this method any longer as I noted in the beginning of this document, and 1.5.0 is not a recent version, so I won't give specifics here. It is probably described better in official documentation now that the project is more mature.

Run it

Start the updating daemon, e.g. with an init script (also included at the end of this document):

sudo wget http://howto.landure.fr/gnu-linux/debian-4-0-etch/installer-tiny-tiny-rss-sur-debian-4-0-etch/tt-rss-default -O /etc/default/tt-rss
sudo wget http://howto.landure.fr/gnu-linux/debian-4-0-etch/installer-tiny-tiny-rss-sur-debian-4-0-etch/tt-rss-initd -O /etc/init.d/tt-rss
sudo chmod 755 /etc/init.d/tt-rss

Modify /etc/default/tt-rss and set FORKING=1 for a performance boost.

From now on the daemon can be started with

sudo service tt-rss start

and stopped with

sudo service tt-rss stop

To run the daemon at startup, issue;

sudo update-rc.d tt-rss defaults

An alternative to daemonizing via init script is using screen:

screen -S tt-rss-updater
cd /usr/local/lib/tt-rss-1.5.0
./update_daemon2.php

Use it

Go to http://localhost/tt-rss and have a look.

It was a bit bugged out with Opera 11 (could read but not add feeds, etc.), but worked with Google Chrome.

Migrating: Google Reader → Tiny Tiny RSS

  1. Go to
    1. Google Reader
    2. "Reader Settings"
    3. "Import/Export"
    4. "Export your subscriptions as an OPML file"
    5. Save file.
  2. Go to
    1. Tiny Tiny RSS
    2. "Preferences"
    3. "Feeds"
    4. "OPML"
    5. "Choose file" and choose the OPML file from Google Reader
    6. "Import" et voilà!

Init scripts

/etc/default/tt-rss show

## Defaults for Tiny Tiny RSS update daemon init.d script

# Set DISABLED to 1 to prevent the daemon from starting.
DISABLED=0

# Emplacement of your Tiny Tiny RSS installation.
TTRSS_PATH="/usr/local/lib/tt-rss-1.5.0"

# Set FORKING to 1 to use the forking daemon (update_daemon2.php) in stead of
# the standard one.
# This option is only available for Tiny Tiny RSS 1.2.20 and over.
FORKING=0

hide

/etc/init.d/tt-rss show

#! /bin/sh
### BEGIN INIT INFO
# Provides:          ttrss-DOMAIN
# Required-Start:    $local_fs $remote_fs networking
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Tiny Tiny RSS update daemon for DOMAIN
# Description:       Update the Tiny Tiny RSS subscribed syndication feeds.
### END INIT INFO

# Author: Pierre-Yves Landuré <pierre-yves@landure.org>

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Tiny Tiny RSS update daemon"
NAME=$(command basename "${0}")
DISABLED=0
FORKING=0

# Read configuration variable file if it is present
[ -r "/etc/default/${NAME}" ] && . "/etc/default/${NAME}"

DAEMON_SCRIPT="update.php -daemon"

if [ "$FORKING" != "0" ]; then
    DAEMON_SCRIPT="update_daemon2.php"
fi

DAEMON=/usr/bin/php
DAEMON_ARGS="${TTRSS_PATH}/${DAEMON_SCRIPT}"
DAEMON_DIR="${TTRSS_PATH}"
PIDFILE="/var/run/${NAME}.pid"
SCRIPTNAME="/etc/init.d/${NAME}"

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

if [ "$DISABLED" != "0" -a "$1" != "stop" ]; then
    log_warning_msg "Not starting $DESC - edit /etc/default/tt-rss-DOMAIN and change DISABLED to be 0.";
    exit 0;
fi

#
# Function that starts the daemon/service
#
do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    start-stop-daemon --start --make-pidfile --background --quiet --chdir "$DAEMON_DIR" --pidfile "$PIDFILE" --exec "$DAEMON" --test > /dev/null \
        || return 1

    start-stop-daemon --start --make-pidfile --background --quiet --chdir "$DAEMON_DIR" --pidfile "$PIDFILE" --exec "$DAEMON" -- \
        $DAEMON_ARGS \
        || return 2
    # Add code here, if necessary, that waits for the process to be ready
    # to handle requests from services started subsequently which depend
    # on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    start-stop-daemon --stop --make-pidfile --quiet --retry=TERM/1/KILL/5 --pidfile $PIDFILE --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    # Wait for children to finish too if this is a daemon that forks
    # and if the daemon is only ever run from this initscript.
    # If the above conditions are not satisfied then add some other code
    # that waits for the process to drop all resources that could be
    # needed by services started subsequently.  A last resort is to
    # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=0/1/KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2
    # Many daemons don't delete their pidfiles when they exit.
    rm -f $PIDFILE
    return "$RETVAL"
}


case "$1" in
    start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        do_start
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
            2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
    stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
            2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
    restart|force-reload)
        #
        # If the "reload" option is implemented then remove the
        # 'force-reload' alias
        #
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
            0|1)
                do_start
                case "$?" in
                    0) log_end_msg 0 ;;
                    1) log_end_msg 1 ;; # Old process is still running
                    *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
            *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
    *)
        echo "Usage: ${SCRIPTNAME} {start|stop|restart|force-reload}" >&2
        exit 3
        ;;
esac

:

hide