Skip to content

Instantly share code, notes, and snippets.

@Kindrat Kindrat/guide.md
Last active Mar 3, 2019

Embed
What would you like to do?
Liquid feedback Installation Guide

Tested requirements:

  • Ubuntu 14.04 LTS amd64
  • PostgreSQL 9.3.4
  • lf-core 3.0.1
  • webmcp 1.2.5
  • rocketwiki-lqfb 0.4
  • lf-frontend 2.2.5
  • lighttpd 1.4.33-1+nmu2ubuntu2

Add postgresql repository (check distro version). Create /etc/apt/sources.list.d/pgdg.list. Add there deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main

wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

Install debian security updates:

apt-get update
apt-get upgrade

Install the neccessary debian packages:

apt-get install lua5.1 postgresql postgresql-server-${version}-dev build-essential libpq-dev liblua5.1-0-dev lighttpd ghc libghc-parsec3-dev imagemagick exim4 nano

+500MB

Create a database role for www-data:

createuser www-data
passwd postgres
su - postgres
psql
postgres-# ALTER ROLE postgres WITH PASSWORD 'postgres';
postgres-# CREATE USER liquid WITH PASSWORD 'feedback';
postgres-# CREATE DATABASE lf;
postgres=# GRANT ALL PRIVILEGES ON DATABASE lf to liquid;
postgres=# \q
exit

Make www-data user possible to login with. Edit /etc/passwd. Find www-data entry and change shell from /usr/sbin/nologin to /bin/bash (or what you prefer)

Configure db connection. Edit /etc/postgres/${version}/main/pg_hba.conf, change peer to md5

local all postgres md5
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all  all md5

Reload postgres configuration:

service postgresql reload

Create a directory for unpacking source tarballs:

cd /root
mkdir install

Install and configure LiquidFeedback Core:

cd /root/install
wget http://www.public-software-group.org/pub/projects/liquid_feedback/backend/v3.0.1/liquid_feedback_core-v3.0.1.tar.gz
tar -xvzf  liquid_feedback_core-v3.0.1.tar.gz
cd liquid_feedback_core-v3.0.1
make
mkdir /opt/liquid_feedback_core
cp core.sql lf_update /opt/liquid_feedback_core/
chmod u+rwXs,g+rwXs -R /opt/liquid_feedback_core/
chown www-data:www-data -R /opt/liquid_feedback_core/
su - www-data
cd /opt/liquid_feedback_core
psql -U liquid -v ON_ERROR_STOP=1 -f core.sql lf
psql -U liquid -d lf

lf=> SELECT * FROM liquid_feedback_version;
 string | major | minor | revision 
--------+-------+-------+----------
 3.0.1  | 3 	| 0 	| 1
(1 row)

lf=> SELECT * FROM system_setting;
 member_ttl 
------------
(0 rows)

lf=> INSERT INTO system_setting (member_ttl) VALUES ('1 year');
INSERT 0 1

lf=> SELECT * FROM contingent;
 polling | time_frame | text_entry_limit | initiative_limit 
---------+------------+------------------+------------------
(0 rows)

lf=> INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (false, '1 hour', 20, 6);
INSERT 0 1

lf=> INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (false, '1 day', 80, 12);
INSERT 0 1

lf=> INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (true, '1 hour', 200, 60);
INSERT 0 1

lf=> INSERT INTO contingent (polling, time_frame, text_entry_limit, initiative_limit) VALUES (true, '1 day', 800, 120);
INSERT 0 1

lf=> SELECT * FROM policy;
 id | index | active | name | description | polling | admission_time | discussion_time | verification_time | voting_time | issue_quorum_num | issue_quorum_den | initiative_quorum_num | initiative_quorum_den | direct_majority_num | direct_majority_den | direct_majority_strict | direct_majority_positive | direct_majority_non_negative | indirect_majority_num | indirect_majority_den | indirect_majority_strict | indirect_majority_positive | indirect_majority_non_negative | no_reverse_beat_path | no_multistage_majority 
----+-------+--------+------+-------------+---------+----------------+-----------------+-------------------+-------------+------------------+------------------+-----------------------+-----------------------+---------------------+---------------------+------------------------+--------------------------+------------------------------+-----------------------+-----------------------+--------------------------+----------------------------+--------------------------------+----------------------+------------------------
(0 rows)

lf=> INSERT INTO policy (index, name, admission_time, discussion_time, verification_time, voting_time, issue_quorum_num, issue_quorum_den, initiative_quorum_num, initiative_quorum_den) VALUES (1, 'Default policy', '8 days', '15 days', '8 days', '15 days', 10, 100, 10, 100);
INSERT 0 1

lf=> SELECT * FROM policy;
 id | index | active |  name  | description | polling | admission_time | discussion_time | verification_time | voting_time | issue_quorum_num | issue_quorum_den | initiative_quorum_num | initiative_quorum_den | direct_majority_num | direct_majority_den | direct_majority_strict | direct_majority_positive | direct_majority_non_negative | indirect_majority_num | indirect_majority_den | indirect_majority_strict | indirect_majority_positive | indirect_majority_non_negative | no_reverse_beat_path | no_multistage_majority 
----+-------+--------+----------------+-------------+---------+----------------+-----------------+-------------------+-------------+------------------+------------------+-----------------------+-----------------------+---------------------+---------------------+------------------------+--------------------------+------------------------------+-----------------------+-----------------------+--------------------------+----------------------------+--------------------------------+----------------------+------------------------
  1 | 1 | t  | Default policy | | f   | 8 days | 15 days | 8 days| 15 days |   10 |  100 |10 |   100 |   1 |   2 | t  |0 |0 | 1 | 2 | t|  0 |  0 | t| f
(1 row)

lf=> SELECT * FROM unit;
 id | parent_id | active | name | description | member_count | text_search_data 
----+-----------+--------+------+-------------+--------------+------------------
(0 rows)

lf=> INSERT INTO unit (name) VALUES ('Our organization');
INSERT 0 1

lf=> SELECT * FROM unit;
 id | parent_id | active |   name   | description | member_count | text_search_data 
----+-----------+--------+------------------+-------------+--------------+--------------------------
  1 |   | t  | Our organization | |  | 'organization':2 'our':1
(1 row)

lf=> SELECT * FROM area;
 id | unit_id | active | name | description | direct_member_count | member_weight | text_search_data 
----+---------+--------+------+-------------+---------------------+---------------+------------------
(0 rows)

lf=> INSERT INTO area (unit_id, name) VALUES (1, 'Default area');
INSERT 0 1

lf=> SELECT * FROM area;
 id | unit_id | active | name | description | direct_member_count | member_weight |   text_search_data   
----+---------+--------+--------------+-------------+---------------------+---------------+----------------------
  1 |   1 | t  | Default area | | |   | 'area':2 'default':1
(1 row)

lf=> SELECT * FROM allowed_policy;
 area_id | policy_id | default_policy 
---------+-----------+----------------
(0 rows)

lf=> INSERT INTO allowed_policy (area_id, policy_id, default_policy) VALUES (1, 1, TRUE);
INSERT 0 1

liquid_feedback=> \q

exit

Install WebMCP:

cd /root/install
wget http://www.public-software-group.org/pub/projects/webmcp/v1.2.5/webmcp-v1.2.5.tar.gz
tar -xvzf webmcp-v1.2.5.tar.gz
cd webmcp-v1.2.5
nano Makefile.options
# append  -I /usr/include/lua5.1  at end of CFLAGS line
# change -I /usr/include/postgresql -I /usr/include/postgresql/server to
# -I /usr/include/postgresql/${version} -I /usr/include/postgresql/${version}/server
# append  -I /usr/include/postgresql  at end of CFLAGS_PGSQL
make
mkdir /opt/webmcp
cp -RL framework/* /opt/webmcp/
chown www-data:www-data -R /opt/webmcp/
chmod u+rwXs,g+rwXs -R /opt/webmcp/

Install RocketWiki LqFb-Edition:

cd /root/install
wget http://www.public-software-group.org/pub/projects/rocketwiki/liquid_feedback_edition/v0.4/rocketwiki-lqfb-v0.4.tar.gz
tar -xvzf rocketwiki-lqfb-v0.4.tar.gz
cd rocketwiki-lqfb-v0.4
make
mkdir /opt/rocketwiki-lqfb
cp rocketwiki-lqfb rocketwiki-lqfb-compat /opt/rocketwiki-lqfb/
chown www-data:www-data -R /opt/rocketwiki-lqfb/
chmod u+rwXs,g+rwXs -R /opt/rocketwiki-lqfb/

Install LiquidFeedback-Frontend:

cd /root/install
wget http://www.public-software-group.org/pub/projects/liquid_feedback/frontend/v2.2.5/liquid_feedback_frontend-v2.2.5.tar.gz
tar -xvzf liquid_feedback_frontend-v2.2.5.tar.gz
mv liquid_feedback_frontend-v2.2.5 /opt/liquid_feedback_frontend
chown www-data:www-data -R /opt/liquid_feedback_frontend
chmod u+rwXs,g+rwXs -R /opt/liquid_feedback_frontend

Create HTML code for help texts:

cd /opt/liquid_feedback_frontend/locale
PATH=/opt/rocketwiki-lqfb:$PATH make

Make tmp directory of LiquidFeedback-Frontend writable for webserver:

chown www-data /opt/liquid_feedback_frontend/tmp

Compile binary for fast delivery of member images:

cd /opt/liquid_feedback_frontend/fastpath
nano getpic.c
check#define GETPIC_CONNINFO "dbname=lf"
make

Configure mail system:

dpkg-reconfigure exim4-config

Create webserver configuration for LiquidFeedback:

cd /etc/lighttpd
nano conf-available/60-liquidfeedback.conf
server.modules += ("mod_cgi", "mod_rewrite", "mod_setenv")

Enable CGI-Execution of *.lua files through lua binary

cgi.assign += ( ".lua" => "/usr/bin/lua5.1" )

alias.url += ( "/lf/fastpath/" => "/opt/liquid_feedback_frontend/fastpath/",
"/lf/static"=> "/opt/liquid_feedback_frontend/static",
"/lf"   => "/opt/webmcp/cgi-bin" )

Configure environment for demo application

$HTTP["url"] =~ "^/lf" {
  setenv.add-environment += (
"LANG" => "en_US.UTF-8",
"WEBMCP_APP_BASEPATH" => "/opt/liquid_feedback_frontend/",
"WEBMCP_CONFIG_NAME"  => "myconfig")
}

URL beautification

url.rewrite-once += (
  # do not rewrite static URLs
  "^/lf/fastpath/(.*)$" => "/lf/fastpath/$1",
  "^/lf/static/(.*)$"   => "/lf/static/$1",

  # dynamic URLs
  "^/lf/([^\?]*)(\?(.*))?$" => "/lf/webmcp-wrapper.lua?_webmcp_path=$1&$3",    
)

$HTTP["url"] =~ "^/lf/fastpath/" {
  cgi.assign = ( "" => "" )
  setenv.add-response-header = ( "Cache-Control" => "private; max-age=86400" )
}
cd /etc/lighttpd/conf-enabled
ln -s ../conf-available/60-liquidfeedback.conf .

Configure LiquidFeedback-Frontend:

cd /opt/liquid_feedback_frontend/config
cp example.lua myconfig.lua
nano myconfig.lua

While configuring the LiquidFeedback-Frontend, use the following option to enable fast image loading:

config.fastpath_url_func = function(member_id, image_type)
  return request.get_absolute_baseurl() .. "fastpath/getpic?" .. tostring(member_id) .. "+" .. tostring(image_type)
end

Set database options

config.database = { engine='postgresql', dbname='lf', user='liquid', password='feedback' }

Edit vHost name:

config.absolute_base_url = "http://liquid-feedback.local/"

Execute lf_update once:

su - www-data
cd /opt/liquid_feedback_core
./lf_update dbname=lf user=liquid password=feedback && echo OK
exit

The commands lf_update dbname=lf user=liquid password=feedback and lf_update_suggestion_order dbname=lf user=liquid password=feedback have to be executed regulary. Create the following shell script to call this command in an endless loop:

nano /opt/liquid_feedback_core/lf_updated

#!/bin/sh

PIDFILE="/var/run/lf_updated.pid"
PID=$$

if [ -f "${PIDFILE}" ] && kill -CONT $( cat "${PIDFILE}" ); then
  echo "lf_updated is already running."
  exit 1
fi

echo "${PID}" "${PIDFILE}"

while true; do
  su - www-data -c 'nice /opt/liquid_feedback_core/lf_update dbname=lf user=liquid password=feedback 2>&1 | logger -t "lf_updated"'
  su - www-data -c 'nice /opt/liquid_feedback_core/lf_update_suggestion_order dbname=lf user=liquid password=feedback 2>&1 | logger -t "lf_updated"'
  sleep 5
done

chmod +x /opt/liquid_feedback_core/lf_updated

Create the following init-script for lf_updated...

nano /etc/init.d/lf_updated
#! /bin/sh
### BEGIN INIT INFO
# Provides:  lf_updated
# Required-Start:$syslog
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop:  0 1 6
# Short-Description: lf_updated
# Description:   Calls LiquidFeedback lf_update regulary
### END INIT INFO

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="lf_updated"
NAME=lf_updated
DAEMON=/opt/liquid_feedback_core/lf_updated
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

. /lib/lsb/init-functions

do_start()
{
	start-stop-daemon -b --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null || return 1
	start-stop-daemon -b --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_ARGS || return 2
}

do_stop()
{
	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
	RETVAL="$?"
	[ "$RETVAL" = 2 ] && return 2
	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
	[ "$?" = 2 ] && return 2
	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
	;;
  status)
   	status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
   	;;
  restart|force-reload)
	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|status|restart|force-reload}" >&2
	exit 3
	;;
esac

and make the init script executable and let it start automatically at boot time

chmod +x /etc/init.d/lf_updated
update-rc.d lf_updated defaults

Start sending of event notifications:

 su - www-data -c 'cd /opt/liquid_feedback_frontend/ && nohup echo "Event:send_notifications_loop()" | ../webmcp/bin/webmcp_shell myconfig &>/dev/null &'

Restart the webserver:

/etc/init.d/lighttpd restart

Create an administrator account:

su - www-data
cd /opt/liquid_feedback_core
psql -U liquid -d lf

lf=> INSERT INTO member (login, name, admin, invite_code) VALUES ('admin', 'Administrator', TRUE, _INSERT_ADMIN_INVITE_CODE_IN_SINGLE_QUOTES_HERE_);
INSERT 0 1

lf=> \q
exit
@Sprbb

This comment has been minimized.

Copy link

Sprbb commented Oct 27, 2015

no content. lighttpd works. plz help.

@elplatt

This comment has been minimized.

Copy link

elplatt commented Apr 28, 2016

Same as @basneve. I get the static content from my document root, but no liquid feedback. I do get content under /lf/static/ but /lf/ gives a 404.

'''Problem Solved:''' I had a typo in the url alias ("cig-bin"). I was able to find it by adding debug.log-request-handling = "enable" to the liquid feedback lighttpd config.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.