Skip to content

Run selfoss at a Heroku like PaaS

Jan Tojnar edited this page Sep 6, 2022 · 10 revisions

Note: Deis has been acquired by Microsoft and decommissioned, and Heroku will no longer offer free accounts.

This guide shows you how to deploy selfoss on a Heroku-like PaaS. I explicitly say "Heroku-like" because I only tested it with deis. But the steps for Heroku or Cloudfoundry will be similar.

Requirements

You need access to a PaaS and have the required client tools installed. In my case it is the deis client. For Heroku it would be the Heroku toolbelt. For Cloudfoundry it'll be the cloudfoundry cli.

You usually want to have git installed as well. And some nice text editor like vim or Sublime Text or whatever you prefer.

You need access to a mysql or postgresql database from within your PaaS.

Preparation

Before we start, we have to check out the current selfoss to a directory. I usually have my projects at ~/projects/. So I opened up my terminal and typed

$ cd ~/projects
$ git clone https://github.com/SSilence/selfoss.git
$ cd selfoss

If you want a specific version, you should check that version out:

$ git checkout 2.14

Now we need to add a few files:

$ touch .env
$ touch .buildpacks
$ touch Procfile
$ touch clock.sh

In the .env file we'll add all out environment variables. The Procfile will tell your PaaS what kind of processes there are and how to start them. The clock.sh is a custom script for updating our RSS-feeds every once in a while.

Our configuration in .env

Usually we configure selfoss by creating a "config.ini" file. But in 'the cloud' we like to configure our applications through environment variables (short: "ENV"), so we can tell our PaaS to change the variable and restart the application whenever our needs change. This way we don't have to push the changed files back to the server.

The .env file is a file that contains all the ENV variables that'll later be made available to our application by the PaaS. A basic sample is shown below

BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-multi
SELFOSS_DB_TYPE=mysql
SELFOSS_DB_HOST=10.0.0.100
SELFOSS_DB_PORT=3306
SELFOSS_DB_USERNAME=selfoss
SELFOSS_DB_PASSWORD=randompassword
SELFOSS_DB_DATABASE=selfoss
SELFOSS_SALT=8XddRN5nPHXLTMsM
SELFOSS_PASSWORD=https://yourselfoss.com/password
SELFOSS_USERNAME=your_desired_username
SELFOSS_BASE_URL=https://yourselfoss.com

Important: Do not blindly copy this into your .env file. You must change the following variables (I omitted the SELFOSS_ prefix):

  • DB_TYPE: use mysql or pgsql. Don't use sqlite, or you lose your feeds every time you upgrade your app. See 12factor.net, especially the chapters about backing services and disposability.
  • DB_HOST, DB_USERNAME, DB_PASSWORD, DB_DATABASE: obvious, right?
  • DB_PORT: 3306 for mysql, 5432 for PostgreSQL
  • SALT: Create your own salt!
  • PASSWORD: After the first deployment, open your selfoss instance in the browser and point it to the "/password" page. Use this page to generate the hashed & salted password, which you put here afterwards. (And don't forget to re-submit the config once you've changed it in here!)
  • USERNAME: again, obvious.
  • BASE_URL: Some PaaS don't somehow hide the real URL through which the user accesses because they do a lot of proxying and therefore the auto-detection of the client facing URL breaks. Put your full URL here. I think you can omit the protocol and write "://yourselfoss.com", but I don't use that and didn't test it.

Since version 2.18, selfoss no longer bundles the JavaScript libraries – it needs Node.js buildpack in addition to PHP one to obtain them. The .buildpacks file contains a list of buildpacks to use.

https://github.com/heroku/heroku-buildpack-nodejs
https://github.com/heroku/heroku-buildpack-php

On Heroku, you can also run heroku buildpacks:add --index 1 heroku/nodejs instead of creating the file, see https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app

Our processes in the Procfile

We're going to have two processes. One is the web server (Apache2). The second one is the update process which will fetch the RSS feeds for us.

The Procfile looks like this:

web: vendor/bin/heroku-php-apache2
clock: sh ~/clock.sh

Note: Never start more than one instance of the clock process on your PaaS. Also, some PaaS don't run the clock process by default, so you have to set it manually to one instance. (E.g. with deis: deis ps:scale clock=1).

Our henchman, the clock.sh script

This script will call the cliupdate.php file from the command-line (i.e. php cliupdate.php) and then wait a certain amount of time, just to call the cliupdate.php file once more. And again, and again, and again.

The file looks like this:

#!/bin/sh
#
# Runs the update task every now and then sleeps for a while.
# Use SELFOSS_UPDATE_INTERVAL to adjust the sleep time. Defaults to 5 mintes.
# 
# Author: Christian Mäder <mail*cimnine.ch>
# License: WTFPL
# 
# Inspired by 
# http://stackoverflow.com/questions/10614454/php-heroku-background-workers
#

echo "Clock V1.0.0"
echo Started at `date`
echo Started in `pwd`
echo ENV:

LD_LIBRARY_PATH=$HOME/.heroku/php/usr/lib/x86_64-linux-gnu:$HOME/.heroku/php/usr/lib
PATH="$HOME/.heroku/php/bin:$HOME/.heroku/php/sbin:$PATH"

printenv

while :
do
	echo "Update now."
	php cliupdate.php
	echo "Sleep now for ${SELFOSS_UPDATE_INTERVAL-600}"
	sleep ${SELFOSS_UPDATE_INTERVAL-600}
done

You can adjust the update interval through the ENV variable SELFOSS_UPDATE_INTERVAL. It defaults to 600 seconds.

Deployment

This is now very specific to your PaaS. I'll show the commands for the deis PaaS, those for Heroku will look very similar, probably those of Cloudfoundry as well.

Modern PaaS leverage git to publish to them. This has the advantage that you only send the delta of the version that is already deployed on the PaaS to the version you would like to deploy.

$ cd ~/projects/selfoss
$ deis create selfoss
$ deis config:push
$ git commit -a -m "ready for deployment"
$ git push deis

First I created a new application on my PaaS. Then I pushed the configuration we prepared in .env. An finally I uploaded the code to the PaaS.

You should now be able to access your selfoss instance through the web. But you can not login because you have not yet created the password hash. Do this now: https://yourselfoss.com/password. Copy the value and adjust the SELFOSS_PASSWORD variable in the .env file and finally re-upload the configuration (e.g. deis config:push).

Known Issues

No Favicons

As selfoss stores some files, especially favicons, on the filesystem, you must call '/update' at least once manually. Usually the clock task runs in a separate container so it will put the favicons in a folder in his own container rather the container selfoss is delivered from. You still get the feeds updated because they are stored in the DB.

This will get tricky if you deliver selfoss from multiple instances behind a loadbalancer.

Troubleshooting

Somehow you must get access to the application logs to do proper troubleshooting. On deis you get access to the logs by running deis logs. The following things happened to me during the deployment before everything worked out:

It does not start at all

  1. Check if your symptoms are the same as in #22 described. See #652 for a way to fix it. (Please make a note in the pull request #652 if you ran into problem #22.)
  2. Make sure your web process is scheduled. (E.g. deis ps:list and eventually deis ps:scale web=1)
  3. Is the DB connection information correct? (You can also check if your PaaS applied the ENV correctly. In my case: deis run -- sh -c printenv)

It does not render pretty and images & scripts don't load. It redirects me to weird URLs.

Check and adjust SELFOSS_BASE_URL.

It does not update my feeds automatically!

  1. Did you schedule the clock process? (E.g. deis ps:list and deis ps:scale clock=1)
  2. Does the manual import run?
  3. Login to https://yourselfoss.com/
  4. Open https://yourselfoss.com/update

I cannot login!

  1. Did you generate your password hash with https://yourselfoss.com/password ?
  2. Did you put it into your .env file?
  3. Did you push the changed config to the PaaS? (E.g. deis config:list and deis config:push, maybe also check the ENV on the PaaS with deis run -- sh -c printenv.

It's something else!

There's only one thing left to do for you: Read the logs! (E.g. deis logs)