Transmission in pkgsrc zone on OmniOS

Omni

We will use zadm for zone administration, installation is simple:

# pkg install zadm

We need a vnic for our zone, so let’s create an instance:

# dladm create-vnic -l e1000g0 zone_transmission_0

Then set up the zone with zadm:

# zadm create -b pkgsrc transmission

The zone config will open in your $EDITOR, modify it like shown below:

{
   "autoboot" : "true",
   "bootargs" : "",
   "brand" : "pkgsrc",
   "dns-domain" : "lan",
   "fs" : [
      {
         "dir" : "/torrent",
         "options" : [
            "rw"
         ],
         "special" : "/mnt/torrent",
         "type" : "lofs"
      }
   ],
   "fs-allowed" : "",
   "hostid" : "",
   "ip-type" : "exclusive",
   "limitpriv" : "default",
   "net" : [
      {
         "physical" : "zone_transmission_0"
      }
   ],
   "pool" : "",
   "resolvers" : [
      "10.0.0.1"
   ],
   "scheduling-class" : "",
   "zonename" : "transmission",
   "zonepath" : "/zones/transmission"
}

Save and close the editor, zadm will create the zone as requested:

# zadm list                                                           
NAME              STATUS     BRAND       RAM    CPUS  SHARES
global            running    ipkg        16G       4       1
transmission      installed  pkgsrc        -       -       1

Let’s boot our new zone:

# zadm boot transmission

also console into it:

# zlogin transmission
[Connected to zone 'transmission' pts/8]
Last login: Sat Jan 11 09:01:49 2025 on pts/3
OmniOS r151052  omnios-r151052-dbe4644ba92      November 2024
root@transmission:~#

Set up our networking:

ipadm create-addr -T static -a 10.0.0.30/24 zone_transmission_0/v4
route -p add default 10.0.0.1

Install transmission-daemon using pkgin:

# pkgin update
# pkgin search transmission
# pkgin in transmission

Pkgin automatically created a transmission user for me with 978 UID and 100 GID. This will be important later on.

Transmission gets installed in the /opt/local/bin folder.

I had to modify the /etc/passwd file defining a valid home direcotry for the transmission user:

transmission:x:978:100:transmission user:/home/transmission:/false

Create the following files:

transmission-daemon.xml :

<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='export'>
        <service name='application/transmission-daemon' type='service' version='1'>
                <!-- Wait for network interfaces to be initialized.  -->
                <dependency name='network' grouping='require_all' restart_on='none' type='service'>
                        <service_fmri value='svc:/milestone/network:default' />
                </dependency> 

                <!-- Wait for all local filesystems to be mounted.  -->
                <dependency name='filesystem' grouping='require_all' restart_on='none' type='service'>
                        <service_fmri value='svc:/system/filesystem/local' />
                </dependency> 

                <exec_method type='method' name='start' exec='/lib/svc/method/transmission-daemon.sh start' timeout_seconds='60' />

                <exec_method type='method' name='stop' exec=':kill -9' timeout_seconds='60' />

                <!--
                        Both action_authorization and value_authorization are needed
                        to allow the framework general/enabled property to be changed
                        when performing action (enable, disable, etc) on the service.
                -->
                <property_group name='general' type='framework'>
                        <propval name='value_authorization' type='astring'
                                value='solaris.smf.value.transmission' />
                        <propval name='action_authorization' type='astring'
                                value='solaris.smf.manage.transmission' />
                </property_group>

                <property_group name='startd' type='framework'>
                        <!-- sub-process core dumps shouldn't restart session -->
                        <propval name='ignore_error' type='astring'
                                value='core,signal' />
                </property_group>

                <instance name='default' enabled='false'>

                        <method_context>
                                <method_credential user='transmission' group='transmission' />
                        </method_context>

                </instance>

                <stability value='Evolving' />

                <template>
                        <common_name>
                                <loctext xml:lang='C'>
                                        Transmission BitTorrent Client (Daemon)
                                </loctext>
                        </common_name>
                </template>

        </service>

</service_bundle>

transmission-daemon.sh :

#!/bin/sh

. /lib/svc/share/smf_include.sh

# ----- *ADVANCED* CONFIGURATION -----
# Only change these options if you know what you are doing!
#
# The folder where Transmission stores the config & web files.
# ONLY change this you have it at a non-default location
TRANSMISSION_HOME="/home/transmission"
TRANSMISSION_WEB_HOME="/opt/local/share/transmission/public_html"
#
# The arguments passed on to transmission-daemon.
# ONLY change this you need to, otherwise use the
# settings file as per above.
TRANSMISSION_ARGS=" -c /torrent/torrent_file "


# ----- END OF CONFIGURATION -----

PATH=/opt/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NAME=transmission-daemon
DAEMON=`which ${NAME}`

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

#
# Function that starts the daemon/service
#

do_start()
{
        # Export the configuration/web directory, if set
        if [ -n "$TRANSMISSION_HOME" ]; then
                export TRANSMISSION_HOME
        fi
        if [ -n "$TRANSMISSION_WEB_HOME" ]; then
                export TRANSMISSION_WEB_HOME
        fi

        ${DAEMON} ${TRANSMISSION_ARGS}
}

#
# Function that stops the daemon/service
#
do_stop()
{
        pkill -9 transmission
}

case "$1" in
        start)
                do_start
                ;;
        stop)
                do_stop
                ;;
        refresh)
                do_stop
                do_start
                ;;
        *)
                echo "Usage: ${0} {start|stop|refresh}" >&2
                exit $SMF_EXIT_ERR_FATAL
                ;;
esac

exit $SMF_EXIT_OK

Make it executable and move the start-script to the correct location:

# chmod +x transmission-daemon.sh
# mv transmission-daemon.sh /lib/svc/method/

Import the service:

# svccfg import transmission-daemon.xml
# svcs transmission-daemon
# svcadm enable transmission-daemon

Transmission should automatically create its config files in the /home/transmission folder. Edit it, then force the daemon to reload:

Make sure the transmission user have write right on the defined folders (UID 978, GID 100)!

kill -HUP <Transmission process ID>