Packaging a 3rd Party App


Note

You can download the full source code for this tutorial

Project File

Create the project using:

mkdir -p ~/Projects/transmission
echo -e "com.transmissionbt.transmission\n1.0\ncom.ubuntu.trusty-lamp-1.0" | sudo rainbow --init ~/Projects/transmission/
sudo chown -R rainbow:rainbow ~/Projects/transmission

Edit ~/Projects/transmission/package.json so it contains:

{
    "type": "application", 
    "id": "com.transmissionbt.transmission", 
    "version": "1.0", 
    "depends": [
        "com.ubuntu.trusty-lamp-1.0"
    ], 
    "network_ports": {
        "WEB_UI": 9091, 
        "TORRENT": 51413
    },
    "redirect_mode": "custom"
}

Transmission Configuration

The Ubuntu transmission package comes preconfigured, but we need to make a few changes.

The first one we want to change is the /etc/default/transmisison-daemon file. Create the following directory:

mkdir -p ~/Projects/transmission/source/etc/default

Then create the ~/Projects/transmission/source/etc/default/transmission-daemon file with the following content:

# defaults for transmission-daemon
# sourced by /etc/init.d/transmission-daemon

# Change to 0 to disable daemon
ENABLE_DAEMON=1

# This directory stores some runtime information, like torrent files 
# and links to the config file, which itself can be found in 
# /etc/transmission-daemon/settings.json
CONFIG_DIR="/var/lib/transmission-daemon/info"

# Default options foe daemon, see transmission-daemon(1) for more options
PIDFILE="/var/run/transmission-daemon/transmission-daemon.pid"
OPTIONS="--config-dir $CONFIG_DIR --pid-file $PIDFILE"

# (optional) extra options to start-stop-daemon
#START_STOP_OPTIONS="--iosched idle --nicelevel 10"

This file adds the --pid-file option to transmission’s startup, as shown by this diff with the file originally packaged by Ubuntu :

--- build/x86_64/chroot/.rw/etc/default/transmission-daemon 2013-07-27 21:34:44.000000000 +0200
+++ source/etc/default/transmission-daemon  2015-09-16 14:54:57.844898107 +0200
@@ -9,8 +9,9 @@
 # /etc/transmission-daemon/settings.json
 CONFIG_DIR="/var/lib/transmission-daemon/info"

-# Default options for daemon, see transmission-daemon(1) for more options
-OPTIONS="--config-dir $CONFIG_DIR"
+# Default options foe daemon, see transmission-daemon(1) for more options
+PIDFILE="/var/run/transmission-daemon/transmission-daemon.pid"
+OPTIONS="--config-dir $CONFIG_DIR --pid-file $PIDFILE"

 # (optional) extra options to start-stop-daemon
 #START_STOP_OPTIONS="--iosched idle --nicelevel 10"

The second file we need to modify is /etc/init.d/transmission-daemon. Create the following directory:

mkdir -p ~/Projects/transmission/source/etc/init.d

Then create the ~/Projects/transmission/source/etc/init.d/transmission-daemon file with the following content:

#!/bin/sh -e
### BEGIN INIT INFO
# Provides:          transmission-daemon
# Required-Start:    $local_fs $remote_fs $network
# Required-Stop:     $local_fs $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start or stop the transmission-daemon.
### END INIT INFO

NAME=transmission-daemon
DAEMON=/usr/bin/$NAME
USER=rainbow
STOP_TIMEOUT=30

export PATH="${PATH:+$PATH:}/sbin"

[ -x $DAEMON ] || exit 0

[ -e /etc/default/$NAME ] && . /etc/default/$NAME

. /lib/lsb/init-functions

start_daemon () {
    if [ $ENABLE_DAEMON != 1 ]; then
        log_progress_msg "(disabled)"
        log_end_msg 255 || true
    else    
        start-stop-daemon --start \
        --chuid $USER \
        $START_STOP_OPTIONS \
        --startas $DAEMON --pidfile $PIDFILE -- $OPTIONS || log_end_msg $?
        log_end_msg 0
    fi
}

case "$1" in
    start)
        log_daemon_msg "Starting bittorrent daemon" "$NAME"
        start_daemon
        ;;
    stop)
        log_daemon_msg "Stopping bittorrent daemon" "$NAME"
        start-stop-daemon --stop --quiet \
            --pidfile $PIDFILE --retry $STOP_TIMEOUT \
            --oknodo || log_end_msg $?
        log_end_msg 0
        ;;
    reload)
        log_daemon_msg "Reloading bittorrent daemon" "$NAME"
        start-stop-daemon --stop --quiet \
            --exec $DAEMON \
            --oknodo --signal 1 || log_end_msg $?
        log_end_msg 0
        ;;
    restart|force-reload)
        log_daemon_msg "Restarting bittorrent daemon" "$NAME"
        start-stop-daemon --stop --quiet \
            --exec $DAEMON --retry $STOP_TIMEOUT \
            --oknodo || log_end_msg $?
        start_daemon
        ;;
    status)
        status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
        ;;
    *)
        log_action_msg "Usage: /etc/init.d/$NAME {start|stop|reload|force-reload|restart|status}" || true
        exit 2
        ;;
esac

exit 0

It changes the runtime user to rainbow and adds the --pidfile handling to start-stop-daemon, as the following diff shows:

--- build/x86_64/chroot/.rw/etc/init.d/transmission-daemon  2012-05-28 18:11:33.000000000 +0200
+++ source/etc/init.d/transmission-daemon   2015-09-16 15:13:45.912904953 +0200
@@ -10,7 +10,7 @@

 NAME=transmission-daemon
 DAEMON=/usr/bin/$NAME
-USER=debian-transmission
+USER=rainbow
 STOP_TIMEOUT=30

 export PATH="${PATH:+$PATH:}/sbin"
@@ -29,7 +29,7 @@
         start-stop-daemon --start \
         --chuid $USER \
        $START_STOP_OPTIONS \
-        --exec $DAEMON -- $OPTIONS || log_end_msg $?
+        --startas $DAEMON --pidfile $PIDFILE -- $OPTIONS || log_end_msg $?
        log_end_msg 0
     fi
 }
@@ -42,7 +42,7 @@
     stop)
         log_daemon_msg "Stopping bittorrent daemon" "$NAME"
         start-stop-daemon --stop --quiet \
-            --exec $DAEMON --retry $STOP_TIMEOUT \
+            --pidfile $PIDFILE --retry $STOP_TIMEOUT \
             --oknodo || log_end_msg $?
         log_end_msg 0
         ;;

Transmission Configuration Script

The configuration for the transmission app itself is stored in the /etc/transmission-daemon/settings.json file. We will need to perform some runtime modification to this file, for which we will need a tool allowing making some changes to it.

Create the ~/Projects/transmission/scripts/config.py file with the following content:

#!/usr/bin/python

import json
import sys

TRANSMISSION_SETTINGS = '/etc/transmission-daemon/settings.json'

if len(sys.argv) < 3:
    sys.exit(1)

with open(TRANSMISSION_SETTINGS, 'r') as settings_file:
    settings = json.load(settings_file)

if sys.argv[1] not in settings:
    sys.exit(1)

value_type = type(settings[sys.argv[1]])
settings[sys.argv[1]] = value_type(sys.argv[2])

with open(TRANSMISSION_SETTINGS, 'w') as settings_file:
    json.dump(settings, settings_file, indent=4)

This script can be used as follows to change some settings:

config.py <key> <value>

We’ll use in the the startup script to set some runtime settings.

For this to work, we need to modify the default settings.json. Create the ~/Projects/transmission/source/settings.json file with the following content:

{
    "blocklist-enabled": 0, 
    "download-dir": "/shares/Public/", 
    "download-limit": 100, 
    "download-limit-enabled": 0, 
    "encryption": 1, 
    "max-peers-global": 200, 
    "peer-port": 51413, 
    "pex-enabled": 1, 
    "port-forwarding-enabled": 0, 
    "rpc-authentication-required": false, 
    "rpc-password": "transmission", 
    "rpc-port": 9091, 
    "rpc-username": "transmission", 
    "rpc-whitelist": "127.0.0.1", 
    "rpc-whitelist-enabled": 0, 
    "rpc-url": "/transmission/", 
    "umask": 0,
    "upload-limit": 100, 
    "upload-limit-enabled": 0
}

Build Script

Create the ~/Projects/transmission/build.sh file with the following content:

#!/bin/bash

# This is a trick to prevent transmission-daemon from starting after
# installation
/bin/echo -e '#!/bin/sh\nexit 101' > /usr/sbin/policy-rc.d
chmod +x /usr/sbin/policy-rc.d

# We need to update the ap-get database, since the container has a cleared one
apt-get update
# Here we need to make sure we disable interactive prompts and recommended packages
apt-get install -y -q --no-install-recommends transmission-daemon

# We can now remove this file
rm /usr/sbin/policy-rc.d

mkdir -p /var/run/transmission-daemon
chown debian-transmission:debian-transmission /var/run/transmission-daemon

install -m 755 /home/source/rc.local /etc
install -m 755 /home/source/settings.json /etc/transmission-daemon
install -m 755 /home/source/etc/default/transmission-daemon /etc/default
install -m 755 /home/source/etc/init.d/transmission-daemon /etc/init.d/

chown -R rainbow:root /etc/transmission-daemon
chown -R rainbow:root /var/lib/transmission-daemon
chown -R rainbow:root /run/transmission-daemon

exit 0

Note

We give ownership of the transmission directories to the rainbow user, since we modified the package to run as rainbow instead of the debian-transmission user.

Startup Script

Create the ~/Projects/transmission/source/rc.local file with the following content:

#!/bin/sh -e

python /scripts/config.py rpc-port $RAINBOW_PORT_WEB_UI
python /scripts/config.py peer-port $RAINBOW_PORT_TORRENT

/etc/init.d/transmission-daemon $1

exit 0

Note

Here, we use the config.py to take the port and path values into account.

Build the App

You can then build the app using:

sudo rainbow --build ~/Projects/transmission
sudo rainbow --pack ~/Projects/transmission

Then install it for testing:

sudo rainbow --install ~/Projects/transmission/build/x86_64/com.transmissionbt.transmission-1.0-x86_64.rbw

And check its URL:

sudo rainbow --list com.transmissionbt.transmission

Which should return something like:

-- com.transmissionbt.transmission: Transmission
    version                         : 1.0
    architecture                    : x86_64
    install_path                    : /opt/rainbow/transmission-01a49cc
    state                           : running
    blocking_state                  : not_blocked
    startup_mode                    : auto
    install_id                      : transmission-01a49cc
    public_key_hash                 : None
    nasos_min_version               : None
    nasos_max_version               : None
    url                             : http://10.0.2.15:9091/
    PIDS:
      \- 10989 : /usr/bin/transmission-daemon --config-dir /var/lib/transmission-daemon/info --pid-file /var/run/transmission-daemon/transmission-daemon.pid
    NETWORK PORTS:
      WEB_UI                        : 9091
      TORRENT                       : 51413

Open the http://10.0.2.15:9091/ in the browser, you should get:

Testing the App