Skip to content
Yves Martin edited this page Dec 3, 2017 · 13 revisions

Generic service support in spksrc

Context

A third party application packaged for Synology often provide a web user interface and users expect to get simple access to it thanks to a service shortcut.

A packager may consider running such a user interface as root is a non-affordable security risk and will push effort to get it run as non-privileged user.

As maintainer facing a large upgrade, work on packages created with copy-paste pattern of many similar files are both time consumming and error prone; so generated files from generic support appear as a requirement.

Concept

Thanks to a small set of spk Makefile variables, a package designer can benefit from generic installer and start-stop-status scripts, with possibility to adapt default behavior thanks to hooks as shell functions.

Provided support

  • User creation (SERVICE_USER) and removal to run backgroup service process
  • Share folder creation based on wizard variable (SERVICE_WIZARD_SHARE)
  • Group creation for managing access to share folder (SERVICE_WIZARD_GROUP)
  • Service port (SERVICE_PORT) configuration for firewall and DSM shortcut
  • Logging support in both installer and start-stop-status script
  • Hooks in package specific script (SERVICE_SETUP)
  • A specific start-stop-status script is provided for package with STARTABLE=no

Support is enabled as far as a SERVICE_ variable is set in spk Makefile.

Example

Package spk/demoservice is provided as non-arch example of how to design your package and wizard screens.

Replacement of defaults

If INSTALLER_SCRIPT is set with a installer script, it replaces generic one.

If SSS_SCRIPT is set with a specific start-stop script, it replaces generic one.

In any case, scripts/service-setup is generated from package variables and SERVICE_SETUP if provided.

Reference documentation

Configuration

DSM UI integration

Generated ${DSM_UI_DIR}/config and icons generated from SPK_ICON are included in package.tgz when both SPK_ICON and SERVICE_PORT are set in Makefile.

A single URL link is built from:

  • DISPLAY_NAME
  • DESCRIPTION
  • SERVICE_PORT
  • SERVICE_PORT_PROTOCOL, defaults to http
  • SERVICE_URL, defaults to /)
  • SERVICE_PORT_ALL_USERS, defaults to true

If not set in Makefile, DSM_UI_DIR default value is app.

For information, ADMIN_PORT, ADMIN_PROTOCOL and ADMIN_URL are also available to generate administration link visible from Package Center entry.

DSM 6 privilege

conf/privilege is generated with username=SPK_NAME if SERVICE_USER variable is set to auto.

In rare case package requires an alternate service account name, SERVICE_USER value other than auto is used to run

For DSM 5 compatibility, installer script will create a system account and start-stop-status invokes su to start SERVICE_COMMAND as non-priviliged user.

Worker: service configuration for port

conf/resource/SPK_NAME.sc is generated except if FWPORTS_FILE is provide in Makefile. By defaults, it configure ADMIN_PORT as tcp with port forwarding enabled.

[SPK_NAME]
title="(ADMIN_PORT_TITLE:SPK_NAME)"
desc="(DISPLAY_NAME:SPK_NAME)"
port_forward="yes"
dst.ports="ADMIN_PORT/tcp"

If defaults do not suit your need, provide a package specific file relative path as FWPORTS_FILE variable. File is then copied as conf/resource/SPK_NAME.sc and handled by installer script as standard one.

Scripts

Both generic installer and start-stop-status scripts source service-setup script which is generated aggregating following variables and SERVICE_SETUP script if set in spk Makefile

GROUP and SHARE_PATH are set from wizard variable names declared in Makefile variables SERVICE_WIZARD_GROUP and SERVICE_WIZARD_SHARE

# Service USER to run background process
USER="demoservice"
# Group name from UI if provided
if [ -n "${wizard_group}" ]; then GROUP="${wizard_group}"; fi
# Share download location from UI if provided
if [ -n "${wizard_download_dir}" ]; then SHARE_PATH="${wizard_download_dir}"; fi
# Service port
ADMIN_PORT=
# start-stop-status script redirect stdout/stderr to LOG_FILE
LOG_FILE="${SYNOPKG_PKGDEST}/var/${SYNOPKG_PKGNAME}.log"
# Service command has to deliver its pid into PID_FILE
PID_FILE="${SYNOPKG_PKGDEST}/var/${SYNOPKG_PKGNAME}.pid"
# Service shell to run command
SERVICE_SHELL="/bin/sh"
# Service command to execute (either with shell or as is)
SERVICE_COMMAND=

Installer

SERVICE_SETUP script can provide shell function invoked as hook when installer steps are run by DSM: service_preinst, service_postinst, service_preuninst, service_postuninst, service_preupgrade, service_save, service_restore, service_postupgrade.

For DSM 5 compatibility, scripts have to be designed to run with busybox.

installer script logs to /tmp/${SPK_NAME}_install.log and if successfully installed file is copied as /var/packages/${SPK_NAME}/target/var/${SPK_NAME}_install.log and also available at /usr/local/${SPK_NAME}/var/${SPK_NAME}_install.log

By defaults on DSM 5, only var folder is writable by service account. If required, add required commands in service_postinst shell function in package specific SERVICE_SETUP script.

Wizard variables are stored in /var/packages/${SPK_NAME}/etc/installer-variables so that they can be retreived and used in uninstall or upgrade.

Service startup

start-stop-status generic script starts SERVICE_COMMAND as non-privileged user, account name defaults to package name SPK_NAME except if SERVICE_USER is different from auto.

Package status feedback relies on pid file /var/packages/${SPK_NAME}/target/var/${SPK_NAME}.pid available as PID_FILE shell variable.

Service is expected to provides this file containing its main process PID, two means are available to do so:

  • if application supports such PID file generation, service_postinst shell function should configure it from PID_FILE variable

  • PID_FILE variable has to be provided as command argument in SERVICE_COMMAND so that process PID write down there, at least from shell special variable $!

Process standard output and error streams are aggregated into log file /var/packages/${SPK_NAME}/target/var/${SPK_NAME}.log which is readable thanks to Package Center "View Log" package action.

Script is verbose by default. This behavior can be switched off setting variables in SERVICE_SETUP script:

  • SVC_NO_REDIRECT=y prevents process streams to be collected in package log
  • SVC_QUIET=y prevents logging start/stop date and action
  • SVC_KEEP_LOG=y prevent log content to be cleared before each startup
Clone this wiki locally