Packaging a 3rd Party App
-
This tutorial will show you how to package an existing app in the NASOS SDK
-
We will focus on the Transmission torrent app
-
Since this app is already packaged in most Linux distributions, we’ll use the Ubuntu container and its transmission package
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" }
-
As mentioned above, we’ll use the
com.ubuntu.trusty-lamp-1.0
since we want to use its transmission package. -
We also declare the main
WEB_UI
port and a dedicatedTORRENT
port for transmission. -
Finally, we use the
custom
redirect_mode because transmission doesn’t behave well behind a reverse proxy.
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: