DSM Developer Guide 7 Enu
DSM Developer Guide 7 Enu
privilege 1.6.4.1
resource 1.6.4.2
PKG_DEPS 1.6.4.3
PKG_CONX 1.6.4.4
LICENSE 1.6.5
Resource 1.7.4
Resource Config 1.7.4.1
2
Resource List 1.7.4.4
Docker 1.7.4.4.4
M aria DB 1.7.4.4.7
Port 1.7.5
M onitor 1.7.6
Package Examples 1.8
Compile 1.11.2
Compile Open Source Projects 1.11.3
3
Package Developer Guide
THIS DOCUM ENT CONTAINS PROPRIETARY TECHNICAL INFORM ATION WHICH IS THE PROPERTY OF SYNOLOGY
INCORPORATED AND SHALL NOT BE REPRODUCED, COPIED, OR USED AS THE BASIS FOR DESIGN,
M ANUFACTURING, OR SALE OF APPARATUS WITHOUT WRITTEN PERM ISSION OF SYNOLOGY INCORPORATED
Copyright
Synology Inc. ® 2022 Synology Inc. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, mechanical,
electronic, photocopying, recording, or otherwise, without prior written permission of Synology Inc., with the following exceptions:
Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of
documentation for personal use provided that the documentation contains Synology’s copyright notice.
No licenses, express or implied, are granted with respect to any of the technology described in this document. Synology retains all
intellectual property rights associated with the technology described in this document. This document is intended to assist application
developers to develop applications only for Synology-labeled computers.
Every effort has been made to ensure that the information in this document is accurate. Synology is not responsible for typographical
errors.
Synology Inc. 9F., No.1, Yuandong Rd., New Taipei City 22063, Taiwan
Synology and the Synology logo are trademarks of Synology Inc., registered in the United States and other countries.
M arvell is registered trademarks of M arvell Semiconductor, Inc. or its subsidiaries in the United States and other countries.
Freescale is registered trademarks of Freescale. Intel and Atom is registered trademarks of Intel.
Semiconductor, Inc. or its subsidiaries in the United States and other countries.
Other products and company names mentioned herein are trademarks of their respective holders.
Even though Synology has reviewed this document, SYNOLOGY M AKES NO WARRANTY OR REPRESENTATION, EITHER
EXPRESS OR IM PLIED, WITH RESPECT TO THIS DOCUM ENT, ITS QUALITY, ACCURACY, M ERCHANTABILITY, OR
FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS DOCUM ENT IS PROVIDED “AS IS,” AND YOU, THE
READER, ARE ASSUM ING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL SYNOLOGY
BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAM AGES RESULTING FROM
ANY DEFECT OR INACCURACY IN THIS DOCUM ENT, even if advised of the possibility of such damages.
THE WARRANTY AND REM EDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR
WRITTEN, EXPRESS OR IM PLIED. No Synology dealer, agent, or employee is authorized to make any modification, extension, or
addition to this warranty.
4
Package Developer Guide
Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the
above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights
which vary from state to state.
5
Release Notes
Breaking Changes
Find more details please refer to breaking changes Breaking Changes In 7.0.
1. Package Framework
Force lower privilege for package
Force some INFO fields to be neccessary
Remove package signing
Remove run-as system from privilege
Change default home path from target to home
2. Package Center
Remove keyring
Remove trust level
3. Commands
synopkg start starts the package with its dependees
synopkg install checks if the package can be installed
New Features
1. SDK Plugin
Add package_install module
Add package_uninstall module
Add package_start module
Add package_stop module
2. Package Framework
Add var directory for FHS
Add tmp directory for FHS
Add home directory for FHS
Add prereplace script
Add postreplace script
Add install_on_cold_storage to INFO
6
Release Notes
3. Resource Worker
Add strong-dependence to data-share worker for package who needs auto start after encrypted share mounted
Add systemd-user-unit worker
Enhancements
1. Package Framework
Restart package after repaired according to its original state
Cannot continue to install package if spk checksum is incorrect
2. Package Center
Be able to start a package with its dependees
Be able to stop a package with its dependers
Be able to uninstall a package with its dependers
Be able to repair start-failed package via repair button
Community sources should have same name / source
7
Breaking Changes
Package operation log is still at /var/log/synopkg.log but control script log will be at /var/log/packages/[package_name].log . Besides,
when you are developing a package, you should always pay attention to the content of /var/log/messages to check if there are any
warning or error.
8
Breaking Changes
User are no longer be able to add / remove keyrings on package center since we have deprecated the codesign mechanism of spk.
Similarly, there will be no trust level settings for user to choose. Any non-synology package will get alert on installation.
Command Changes
1. synopkg start starts a package with its dependees
If A depends on B, run synopkg start A will also start B when B is not started.
9
Getting Started
Getting Started
Getting started to learn how to easily build packages just the way you like!
1. Prepare a NAS
You can choose one at our official site and buy it from local synology partner. It is recommended to take one from the Plus Series.
Since our NAS is not always in x86 or x86_64 architecture, we should prepare corresponding environment to our NAS (for cross
compiling if you are developing in C/C++). We provide tons of tools for creating different development environments of our NAS
in an easy way.
If you want to develop an application in Node.js , you can make your package depend on our official Node.js package. If you
want to develop in PHP , you can still make your package depend on PHP package. We have already provided Node.js , PHP ,
Perl , Python , Java packages for langugage run time on DSM .
10
Getting Started
You can make great packages by leveraging our Package Framework to have stable, controllable and power saving properties. We
provide complete toolkit for cross compiling and packing so you can also develop in an easy way.
System Requirement
Prepare Environment
Your First Package
11
System Requirements
System Requirements
Toolkit Requirements
64bit generic linux environment with root permission (e.g., Ubuntu 18.04 LTS)
bash (>= 4.1.5)
python (>= 2.7.3)
Please DO NOT install toolkit on S ynology NAS as your development environment. NAS is specialized for storage, and not for
generic developing purpose. Instead, you can install Docker package on NAS then setup a generic linux container to install the toolkit.
Runtime Requirements
If your package is for DSM 6 then you should have a DSM 6 NAS.
If your package is for DSM 7 then you should have a DSM 7 NAS.
1. Open your DSM web UI, go to Support Center > Support Services.
2. Press "Generate Logs" button and you will get a file named debug.dat .
3. Send the debug.dat to Synology.
4. The Synology will sign a token and send it to you.
5. Put the development token to /var/packages/syno_dev_token on the NAS where the debug.dat generated.
If everything works fine, your unsigned package will be accepted for installation. If not, you would receive the error message:
Failed to install. The package should run with a lower privilege level. Please contact the package developer to modify the privilege
settings.
If you believe you are doing it correct and the problem persists, please contact us for help.
The development token is only valid for the NAS generating the debug.dat . Installing the token to another NAS does not make the
bypass work.
12
Prepare Envrionment
Prepare Environment
Install Toolkit
Toolkit Installation:
You need to clone the front-end scripts from this link. We will use /toolkit as toolkit base in this document from now on.
Then you need to install a few tools to make the built tool work:
/toolkit
├── pkgscripts-ng/
│ ├── include/
│ ├── EnvDeploy (deployment tool for chroot environment)
│ └── PkgCreate.py (build tool for package)
└── build_env/ (directory to store chroot environments)
You can use EnvDeploy to deploy corresponding environment of your NAS. For example, if there is a NAS in avoton architecture, it is
possible to use following commands to deploy a environment for avoton :
cd /toolkit/pkgscripts-ng/
git checkout DSM7.0
./EnvDeploy -v 7.0 -p avoton # for DSM7.0
It is possible to download environment tarballs manually. You have to put base_env-7.0.txz , ds.{platform}-7.0.dev.txz and ds.
/toolkit
├── pkgscripts-ng/
└── toolkit_tarballs/
├── base_env-7.0.txz
├── ds.avoton-7.0.dev.txz
└── ds.avoton-7.0.env.txz
cd /toolkit/pkgscripts-ng/
13
Prepare Envrionment
As mentioned before, the deployed environment contains some pre-built libraries and headers which can be found under cross gcc
sysroot. Sysroot is the default search path of compiler. If gcc cannot find header or library from the given path, it will then search
sysroot/usr/{lib,include} .
/toolkit
├── pkgscripts-ng/
│ ├── include/
│ ├── EnvDeploy
│ └── PkgCreate.py
└── build_env/
├── ds.avoton-7.0/
└── ds.avoton-6.2/
└── usr/local/x86_64-pc-linux-gnu/x86_64-pc-linux-gnu/sys-root/
Available Platforms
You can use one of the following commands to show available platforms. If -v is not given, available platforms for all versions will be
listed.
You may use any toolkit that belong to the same platform family to create spk for all platforms within the same platform family. e.g.
you may use the toolkit for braswell to create package runs on all x86_64 compatible platforms. For platform family, please check
Platform and Arch Value M apping Table.
Update Environment
Use EnvDeploy again to update the environment. For example, you can update avoton for DSM 7.0 as follows.
Remove Environment
To remove a environment, you first need to unmount the /proc folder then remove the environment folder. The following commands
illustrate how to remove an environment with version 7.0 and platform avoton.
umount /toolkit/build_env/ds.avoton-7.0/proc
rm -rf /toolkit/build_env/ds.avoton-7.0
14
Your First Package
/toolkit/
├── build_env/
│ └── ds.${platform}-${version}/
├── pkgscripts-ng/
│ ├── EnvDeploy
│ └── PkgCreate.py
└── source/
└──ExamplePackage/
├── examplePkg.c
├── INFO.sh
├── Makefile
├── PACKAGE_ICON.PNG
├── PACKAGE_ICON_256.PNG
├── scripts/
│ ├── postinst
│ ├── postuninst
│ ├── postupgrade
│ ├── postreplace
│ ├── preinst
│ ├── preuninst
│ ├── preupgrade
│ ├── prereplace
│ └── start-stop-status
└── SynoBuildConf/
├── depends
├── build
└── install
This example will echo some messages by a program written in C language, so it is neccessary to compile program in build stage. We
apply Makefile in this example to help us doing cross compilation.
We do not concern what you do in build configuration so that it can even do nothing. The build system will just chroot into
environment then call the corresponding build , install script according to the commands.
Configure Properties
The package information and its behavior are controlled by INFO.sh which will be translated into INFO file in install .
#!/bin/bash
# INFO.sh
source /pkgscripts/include/pkg_util.sh
15
Your First Package
package="ExamplePackage"
version="1.0.0000"
os_min_ver="7.0-40000"
displayname="ExamplePackage Package"
description="this is an example package"
arch="$(pkg_get_unified_platform)"
maintainer="Synology Inc."
pkg_dump_info
#!/bin/sh
# scripts/start-stop-status
case $1 in
start)
examplePkg "Start"
echo "Hello World" > $SYNOPKG_TEMP_LOGFILE
exit 0
;;
stop)
examplePkg "Stop"
echo "Hello World" > $SYNOPKG_TEMP_LOGFILE
exit 0
;;
status)
exit 0
;;
esac
// examplePkg.c
#include <sys/sysinfo.h>
#include <syslog.h>
#include <stdio.h>
int main(int argc, char** argv) {
struct sysinfo info;
int ret;
ret = sysinfo(&info);
if (ret != 0) {
syslog(LOG_SYSLOG, "Failed to get info\n");
return -1;
}
syslog(LOG_SYSLOG, "[ExamplePkg] %s sample package ...", argv[1]);
syslog(LOG_SYSLOG, "[ExamplePkg] Total RAM: %u\n", (unsigned int) info.totalram);
syslog(LOG_SYSLOG, "[ExamplePkg] Free RAM: %u\n", (unsigned int) info.freeram);
return 0;
}
# Makefile
include /env.mak
EXEC= examplePkg
OBJS= examplePkg.o
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
install: $(EXEC)
16
Your First Package
mkdir -p $(DESTDIR)/usr/bin/
install $< $(DESTDIR)/usr/bin/
clean:
rm -rf *.o $(EXEC)
Any additional files (e.g., compiled program, media resources) should be packed into package.tgz file inside .spk . We provide several
script commands to do such operations. In this example, we will pack compiled examplePkg executable via install build script.
# SynoBuildConf/install (partial)
create_package_tgz() {
local firewere_version=
local package_tgz_dir=/tmp/_package_tgz
local binary_dir=$package_tgz_dir/usr/bin
rm -rf $package_tgz_dir && mkdir -p $package_tgz_dir
mkdir -p $binary_dir
cp -av examplePkg $binary_dir
make install DESTDIR="$package_tgz_dir"
pkg_make_package $package_tgz_dir "${PKG_DIR}"
}
cd /toolkit/pkgscripts-ng/
./PkgCreate.py -v 7.0 -p avoton -c ExamplePackage
/toolkit/
├── pkgscripts-ng/
├── build_env/
│ └── ds.${platform}-${version}
└── result_spk/
└── ${package}-${version}/
└── *.spk
Once you have installed and started the package, you can see its message on UI and log at /var/log/messages .
17
Your First Package
Read More
Synology Toolkit
Synology Package
Synology DSM Integration
Package Examples
18
Synology Toolkit
Synology Toolkit
In this section, we will explain the workflow of Package Toolkit. If you want to build a Synology Package without using Package
Toolkit, you must:
Creating a package manually can be very complex for most developers, so we recommended using the Package Toolkit to make the
package creation process easier.
/toolkit/
├── build_env/
│ └── ds.${platform}-${version}/
└── pkgscripts-ng/
├── EnvDeploy
└── PkgCreate.py
Build S tage: compile your project and all dependent projects in the correct order.
Pack S tage: pack your project into an .spk file
To create your .spk file with PkgCreate.py properly, you need to provide additional configuration files and build scripts to describe
how to build your project. These files are put in a folder named “S ynoBuildConf” under your project.
SynoBuildConf/depends : defines the dependency of your project. For further details, please refer to Build Stage
SynoBuildConf/build : specifies PkgCreate.py on how to compile your project. For further details, please refer to Build Stage
SynoBuildConf/install : specifies PkgCreate.py on how to pack your SPK file. For further details, please refer to Pack Stage
SynoBuildConf/install-dev : similar to SynoBuildConf/install, but this will pack your .spk file in chroot environment rather than
general DSM system. For further details, please refer to Compile Open Source Project: nmap.
19
Synology Toolkit
20
Build Stage
Build Stage:
In the Build Stage, PkgCreate.py will compile the project and its dependent projects. Please note that in this stage, PkgCreate.py
depends on two build scripts ( SynoBuildConf/build and SynoBuildConf/depends ) to get the necessary information.
/toolkit/
├── build_env/
│ └── ds.${platform}-${version}/
├── pkgscripts-ng/
│ ├── EnvDeploy
│ └── PkgCreate.py
└── source/
└──${project}/
└── SynoBuildConf/
├── depends
├── build
└── install
21
Build Stage
SynoBuildConf/depends
PkgCreate.py will resolve your dependency according to this configuration file. You need to specify your project dependency and the
build environment of your project in this file. For example:
[BuildDependent]
# each line here is a dependent project
[ReferenceOnly]
# each line here is a project for reference only but no need to be built
[default]
all="7.0" # toolkit environment version of specific platform. (all platform use 7.0 toolkit environment)
BuildDependent: Describes other projects which are dependent on this project. For further details about this field, please refer to
Compile Open Source Project: nmap.
ReferenceOnly: Describes other projects which are referred by this project, without the build process.
default: Describes the toolkit environment. This section is a necessary field. It indicates each platform to build against some DSM
version and the key "all" means all platform use this version by default.
You can use ProjDepends.py script to see whether the dependency order of your projects is correct. Option -x0 will traverse all
dependent projects of ${project}.
cd /toolkit/pkgscripts-ng
./ProjDepends.py -x0 ${project}
If your application contains more than one project, put them in /toolkit/source and edit SynoBuildConf accordingly for each of them.
For advanced usage, you may refer to Compile Open Source Project and References.
22
Build Stage
SynoBuildConf/build
SynoBuildConf/build is a shell script that tells PkgCreate.py how to compile your project. The current working directory of this shell
script is located in /source/${project} under chroot environment.
All pre-built binaries, headers, and libraries are under cross compiler sysroot in chroot environment. Since sysroot is the default search
path of cross compiler, you do not need to provide -I or -L to CFLAGS or LDFLAGS .
Variables:
You can also find most of them in /toolkit/build_env/ds.${platform}-${version}/{env.mak,env32/64.mak} . They can be used in
SynoBuildConf/build :
# SynoBuildConf/build
case ${MakeClean} in
[Yy][Ee][Ss])
make distclean
;;
esac
make ${MAKE_FLAGS}
The above example calls the make command and compiles your project according to your Makefile located in /source/${project} .
Synology toolkit environment has included selected prebuild projects. You can enter the chroot and use following commands to check if
needed header or project is provided by toolkit.
## inner chroot
dpkg -l # list all dpkg projects.
dpkg -L {project dev} # list project install files
dpkg -S {header/library pattern} # search header/library pattern.
For example, the project needs zlib.h and libz.so in the build stage. Use following command to check if zlib and its component are
installed in chroot.
23
Build Stage
chroot /tookit/build_env/ds.avoton-7.0/
## inner chroot
>> dpkg -l | grep zlib
ii zlib-1.x-avoton-dev 7.0-7274 all Synology build-time library
Some open source projects require to use other projects' cross compiled product while building their own . For example, python needs
libffi and zlib while configure, we need to provide those two project before build python . You can install the cross compiled
product into the destination you want in build script. Please refer to Compile Open Source Project: nmap for more information.
Makefile
The following example shows a Makefile . M ost of the content contains typical makefile rules. Note that when writing your project
Makefile , you can utilize pre-defined variables in /env.mak .
## You can use CC CFALGS LD LDFLAGS CXX CXXFLAGS AR RANLIB READELF STRIP after include env.mak
include /env.mak
EXEC= examplePkg
OBJS= examplePkg.o
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
install: $(EXEC)
mkdir -p $(DESTDIR)/usr/bin/
install $< $(DESTDIR)/usr/bin/
clean:
rm -rf *.o $(EXEC)
For more detailed descriptions about makefile, please refer to the article here.
24
Pack Stage
Pack Stage:
In the Pack Stage, PkgCreate.py packs all the necessary files according to your metadata and creates a .spk at /toolkit/result_spk .
If you want PkgCreate.py to enter the Pack Stage without the Build Stage, simply run PkgCreate.py with the -i option.
cd /toolkit
pkgscripts-ng/PkgCreate.py -i ${project}
/toolkit/
├── build_env/
│ └── ds.${platform}-${version}/
├── pkgscripts-ng/
│ ├── EnvDeploy
│ └── PkgCreate.py
└── source/
└──${project}/
└── SynoBuildConf/
├── depends
├── build
└── install
25
Pack Stage
SynoBuildConf/install
This file must be written in bash and indicates on how to pack your project. The current working directory is /source/${project}
under chroot environment. If this is the top project of your package, this file will define how to create the .spk file, including directory
structure and the INFO file.
#!/bin/bash
### Use PKG_DIR as working directory.
PKG_DIR=/tmp/_test_spk
rm -rf $PKG_DIR
mkdir -p $PKG_DIR
create_inner_tarball() {
local inner_tarball_dir=/tmp/_inner_tarball
create_spk(){
local scripts_dir=$PKG_DIR/scripts
26
Pack Stage
create_inner_tarball
create_spk
At the beginning, the script called the PrepareDirs function which will prepare the necessary folder for the project.
After created the folder, the script called S etupPackageFiles to move necessary resource files to $INST_DIR and $PKG_DIR . In this
step, we called the INFO.sh file to create the INFO file. Although you may put the codes that generate the INFO file in the
SynoBuildConf/install script, we highly recommend that you create the INFO seperately. Generally, we name it INFO.sh . You can see
how to write INFO.sh in the following subsections.
After moving the resource file to the proper location, we called the MakePackage function to create the package. We included/sourced a
script called pkg_util.sh which is located at /pkgscripts-ng/include . The pkg_make_package and pkg_make_spk defined in
pkg_util.sh can help to create package.tgz and .spk .
INFO.sh
As mentioned earlier, INFO.sh is just an optional script. You can create the INFO file by hand or move the code to
SynoBuildConf/install . However, we strongly recommend that you utilize INFO.sh so that you can create the INFO file separately
from SynoBuildConf/install .
#!/bin/bash
source /pkgscripts-ng/include/pkg_util.sh
package="ExamplePkg"
version="1.0.0000"
displayname="Example Package"
maintainer="Synology Inc."
arch="$(pkg_get_unified_platform)"
description="this is a Example package"
[ "$(caller)" != "0 NULL" ] && return 0
pkg_dump_info
The above code is just an example to show some important variables for pkg_dump_info . If you want to know more details about
the INFO file and each fields, please refer to INFO.
Similar to SynoBuildConf/install , we must first include pkg_util.sh . After that, we can set up proper variables and call the
pkg_dump_info to create the INFO file correctly. As you may have noticed, we used another helper function called pkg_get_platform
to set the architecture variable. This variable indicates the current platform we are building.
27
Pack Stage
ng/include/pkg_util.sh .
(No function) noarch Package only contain scripts. spk can be run on all synology M odels.
x86_64 i686 armv7 Unify platforms with same kernel into a platform family . The
pkg_get_platform_family
armv5 ppc... package can run on same family of synology models.
bromolow cedarview Directly output the platform where the toolkit environment is used.
pkg_get_spk_platform
qoriq armadaxp... The package can only run on the specific platform.
If your package doesn't have any native binary, you can use noarch as the platfrom and write the scripts for your package.
Package with arch=noarch can be installed onto any synology model.
If your package doesn’t have any kernel related functions, the package can run on the same architecture platforms. Use function
pkg_get_platform_family to get platform family. Package can be installed on the models included in the same platform family. For
example, package with arch=x86_64 can be install onto bromolow cedarview broadwell models.
If your package contains kernel related functions, every platforms will need a specific spk. Please use function
pkg_get_spk_platform to get the platform(s) which is compatiable with your environment.
Corresponding
Function name Example Description
platform function
examplePkg-
bromolow-
1.0.0000.spk / Spk name depends on which toolkit
pkg_get_spk_name pkg_get_spk_platform
examplePkg- environment is using.
cedarview-
1.0.0000.spk ...
You need to use path of INFO as argument. If no path specified, the function will get INFO file from $PKG_DIR/INFO
automatically.
28
Pack Stage
source_path is spk source directory. All spk files must copy into this direcotry before run pkg_make_spk.
dest_path is target spk path.
spk_name is spk name with/without platform info.
Example:
pkg_make_spk /tmp/_test_spk "/image/packages" $(pkg_get_spk_family_name)
29
Sign Package (only for DSM 6.X)
Between DSM 5.1 and DSM 6.X, we have a built-in code sign mechanism to ensure the package's publisher integrity. The toolkit has a
CodeSign.php script to sign the package with GnuPG keys. If you do not have a GPG key, you will need to generate one.
The package signing scripts now only support keys generated by GPG 2.1. If you don't have your own GPG key or you are using GPG
keys in GPG 2.2 format, you need to prepare GPG tool and generate one.
M ake sure you are using GPG 2.1. If your dist does not provides GPG 2.1, Follow the instructions in the next section to prepare your
GPG tool.
mkdir /tmp/gpgkey
docker run --rm -it -v /tmp/gpgkey:/root/.gnupg -e GPG_TTY=/dev/console vladgh/gpg:0.2.3 --gen-key
mv /tmp/gpgkey /path/to/build_env/ds.avoton-6.2/root/.gnupg
WARNING: Please make sure that you do not type any characters in the passphrase field, otherwise the build process will
FAIL.
After completing the steps above, the key will be generated under ~/.gnupg . You need to move them into the chroot environment.
cp ~/.gnupg/* /toolkit/build_env/ds.${platform}-6.2/root/.gnupg/
You can also use the following commands to verify whether the key has successfully imported or not.
cd /toolkit/build_env/ds.${platform}-6.2/
chroot .
30
Sign Package (only for DSM 6.X)
gpg -K
/root/.gnupg/secring.gpg
------------------------
sec 2048R/145E0AFD 2015-12-21
uid Synology Inc. <[email protected]>
ssb 2048R/E0C20F11 2015-12-21
PkgCreate.py -i ${project}
In addition, if you want to sign the package on your own, you can use the following command to sign your package manually.
chroot /toolkit/build_env/ds.${platform}-${version}
php /pkgscripts-ng/CodeSign.php [option] --sign=package-path
Options:
--keydir=keyrings directory (default is /root/.gnupg)
--keyfpr=key's fingerprint (default is "". Under this circumstances, we will using the first key in the key directory to sign
the package)
Examples:
php /pkgscripts-ng/CodeSign.php --sign=phpBB-3.0.12-0031.spk
php /pkgscripts-ng/CodeSign.php --keydir=/root/.gpg --keyfpr=C1BF63CD --sign=phpBB-3.0.12-0031.spk
31
References
References
This section illustrates advanced types of usage for the Package Toolkit.
Option
Option Purpose
Name
(default) Run build stage only which include link and compile source code. It's the same as -U option.
-x Build dependent project level. Each project is built according to their own SynoBuildConf/build (e.g., -x0, -x1)
Run both build stage and pack stage which include link source code, compile source code, pack package and
-c
sign the final spk.
-U Run build stage only which includes link and compile source code.
-l Run build stage only, but will only link your source code.
-L Run build stage only, but will compile your source code only.
-I Run pack stage only, which will pack and sign your spk.
--no-sign Tells PkgCreat.py not to sign your spk file. for example, PkgCreat.py -I --no-sign ${project}
The following table shows the relationship between command options in different stages. You can choose the proper options based on
your needs. Option -c is enough for most cases.
Platform-Specific Dependency
Platform-specific dependency means you can have several dependent projects for different platforms by appending ":${platform}" to
the following sections: BuildDependent and ReferenceOnly. The following example shows 816x and aramda370 projects that are on
libbar-1.0.
# SynoBuildConf/depends
[BuildDependent]
libfoo-1.0
[BuildDependent:816x,armada370]
libfoo-1.0
32
References
libbar-1.0
[default]
all="7.0"
The current working directory of S ynoBuildConf/collect is /source/${project} will be under chroot environment.
33
Synology Package
Package Introduction
In this section, you will learn the layout of synology package (.spk) and the meaning of each file.
spk
├ ─ ─ INFO
├ ─ ─ package.tgz
├ ─ ─ scripts
│ ├ ─ ─ postinst
│ ├ ─ ─ postuninst
│ ├ ─ ─ postupgrade
│ ├ ─ ─ preinst
│ ├ ─ ─ preuninst
│ ├ ─ ─ preupgrade
│ └ ─ ─ start-stop-status
├ ─ ─ conf
│ ├ ─ ─ privilege
│ └ ─ ─ resource
├ ─ ─ LICENSE
├ ─ ─ PACKAGE_ICON.PNG
└ ─ ─ PACKAGE_ICON_256.PNG
Package Structure
A Synology package contains the following files:
To create such package layout, please refer to the Pack Stage for detailed steps.
34
Synology Package
35
INFO
INFO
This file describes the properties of a package
key=value
Necessary Fields
Optional Fields
thirdparty="yes"
maintainer="mycompany"
description="mydescription"
distributor="mycompany"
package="mypackagename"
silent_install="yes"
silent_uninstall="yes"
silent_upgrade="yes"
os_min_ver="7.0-40000"
version="0.0.1-0001"
arch="noarch"
36
Necessary Fields
Value: String
Example:
package="DownloadStation"
DS M Requirement: 2.0-0731
Note:
Example:
version="3.6-3263"
version="1.2.3-0001"
DS M Requirement: 2.0-0731
os_min_ver="7.0-40000"
DS M Requirement: 6.1-14715
Value: String
37
Necessary Fields
Example:
description = "Download Station is a web-based download application which allows you to download files from the Internet
through BT, FTP, HTTP, NZB, Thunder, FlashGet, QQDL, and eMule, and subscribe to RSS feeds to keep you updated on the hot
test or latest BT. It offers the auto unzip service to help you extract compressed files to your Synology NAS whenever fi
les are downloaded. With Download Station, you can download files from multiple file hosting sites, and search for torren
t files via system default search engines as well as self-added engines with the BT search function."
DS M Requirement: 2.3-1118
DS M Requirement: 4.2-3160
Value: (arch values are separated with a space. Please refer Appendix A: Platform and Arch Value M apping Table to more
information)
Note:
1. "noarch" means the package can be installed and work in any platform. For example, the package is written in PHP or shell
script.
2. Please not pack all binary files with different platforms to one package spk file.
Example:
arch="noarch"
or
arch="x86_64 alpine"
DS M Requirement: 2.0-0731
Value: String
Example:
maintainer="Synology Inc."
DS M Requirement: 2.0-0731
38
Optional Fields
Value: String
Default Value: The value of package key
Example: None
DS M Requirement: 2.3-1118
displayname_enu="Hello World"
displayname_cht=""
DS M Requirement: 2.3-1118
enu (English)
cht (Traditional Chinese)
chs (Simplified Chinese)
krn (Korean)
39
Optional Fields
ger (German)
fre (French)
ita (Italian)
spn (Spanish)
jpn (Japanese)
dan (Danish)
nor (Norwegian)
sve (Swedish)
nld (Dutch)
rus (Russian)
plk (Polish)
ptb (Brazilian Portuguese)
ptg (European Portuguese)
hun (Hungarian)
trk (Turkish)
csy (Czech)
Value: String
description_enu="Hello World"
description_cht=""
DS M Requirement: 2.3-1118
maintainer_url="http://www.synology.com"
DS M Requirement: 4.2-3160
distributor="Synology Inc."
DS M Requirement: 4.2-3160
40
Optional Fields
Example:
distributor_url ="http://www.synology.com/enu/apps/3rd-party_application_integration.php"
DS M Requirement: 4.2-3160
Value: String
Example:
support_url="https://myds.synology.com/support/support_form.php".
Value: "yes"/"no"
Default Value: "no"
Example: None
DS M Requirement: 5.0-4458
model="synology_bromolow_3612xs synology_cedarview_rs812rp+".
DS M Requirement: 4.0-2219
Value: (arch values are separated with a space. Please refer Appendix A: Platform and Arch Value M apping Table to more
information)
Default Value: (Empty)
Example: None
DS M Requirement: 6.0
41
Optional Fields
Example:
exclude_arch="bromolow cedarview".
Value: 0~65536
Default Value: 80
Example:
adminport="9002"
DS M Requirement: 2.0-0731
Value: String
Default Value: (Empty)
Example:
adminurl="web"
DS M Requirement: 2.3-1118
adminprotocol="http"
DS M Requirement: 3.2-1922
42
Optional Fields
1. If only one path is provided, the path will be the relative path to dsmuidir in package target and the link name will be
package name.
2. If multiple key:value pairs are provided, the key will be the name of link and the value will be the relative path to
dsmuidir in package target.
3. Please refer Integrate Your package into DSM for more information.
Value: String
Default Value: (Empty)
Example:
dsmuidir="ui"
dsmuidir="MyLinkName1:ui/app1 MyLinkName2:ui/app2"
dsmappname="SYNO.SDS.PhotoStation SYNO.SDS.PersonalPhotoStation"
DS M Requirement: 3.2-1922
dsmappname="SYNO.SDS.AdminCenter.Application"
dsmapppage="SYNO.SDS.AdminCenter.FileService.Main"
DS M Requirement: 7.0-40332
43
Optional Fields
Example:
dsmapplaunchname="SYNO.SDS.AdminCenter.Application"
DS M Requirement: 7.0-40796
Value: "yes"/"no"
Default Value: "yes"
Example: None
DS M Requirement: 3.2-1922
Value: "yes"/"no"
Default Value: "yes"
Example: None
DS M Requirement: 6.1-14907
44
Optional Fields
helpurl="https://www.synology.com/en-global/knowledgebase"
DS M Requirement: 3.2-1922
45
Optional Fields
install_dep_packages="packageA"
or
install_dep_packages="packageA>2.2.2:packageB"
DS M Requirement: 3.2-1922
install_conflict_packages="packageA:packageB"
or
install_conflict_packages="packageA>2.2.2:packageB"
DS M Requirement: 4.1-2851
install_break_packages="packageA:packageB"
or
install_break_packages="packageA>2.2.2:packageB"
DS M Requirement: 6.1-15117
46
Optional Fields
Description: After your package is installed or upgraded, these to-be-replaced packages will be removed. The format consists of a
package name, e.g. install_replace_packages="packageA". If more than one to-be-replaced packages are required with the
format, the name of the package(s) will be separated with a colon, e.g. install_replace_packages="packageA:packageB". If a
specific version range is required, package name will be followed by one of the special characters =, <, >, >=, <= and package
version which is composed by number and periods, e.g. install_replace_packages="packageA>2.2.2:packageB".
Value: Package names
Note: Each package name is separated with a colon.
install_replace_packages="packageA:packageB"
or
install_replace_packages="packageA>2.2.2:packageB"
DS M Requirement: 6.1-15117
install_dep_services="apache-web ssh"
DS M Requirement: 3.2-1922
install_dep_services="apache-web ssh"
DS M Requirement: 3.2-1922
47
Optional Fields
extractsize="253796"
DS M Requirement: 4.0-2166
Value: "yes"/"no"
Default Value: "no"
Example:
support_conf_folder="yes"
1. Be careful when setting this, as it may result in the DiskStation crashing if your package runs out of the space in the
root file system.
Value: "system"
Default Value: (Empty)
Example:
install_type="system"
DS M Requirement: 5.0-4458
48
Optional Fields
silent_install="yes"
DS M Requirement: 5.0-4458
silent_upgrade="yes"
DS M Requirement: 5.0-4458
silent_uninstall="yes"
DS M Requirement: 5.0-4458
auto_upgrade_from="2.0"
DS M Requirement: 5.2-5565
offline_install="yes"
49
Optional Fields
Value: "yes"/"no"
Default Value: "no"
Example:
thirdparty="yes"
DS M Requirement: 4.0~4.3
os_max_ver="6.1-14715"
DS M Requirement: 6.1-14715
support_move="yes"
DS M Requirement: 6.2-22306
exclude_model="synology_cedarview_713+ synology_kvmx64_virtualdsm"
DS M Requirement: 7.0-40329
50
Optional Fields
install_replace_packages="packageA"
use_deprecated_replace_mechanism="yes"
DS M Requirement: 7.0-40340
install_on_cold_storage="yes"
DS M Requirement: 7.0-40726
51
package.tgz
package.tgz
The package.tgz is a compressed file (tgz / xz) containing all the files you would need when bringing up your applications such as:
executable files
library files
UI files
configuration files
You can use pkg_make_package function to create the package.tgz instead of packing it manually.
In addition to the target directory, system will also create other directories for package to store its data for different purposes.
Detailed information can be found HERE.
52
scripts
scripts
This folder contains shell scripts controlling the lifecycle of a package.
S cript
Required Description
Name
It can be used to check conditions before installation but not to make side effects onto the
preinst O
system. Package installation will be aborted for non-zero returned value.
It can be used to prepare environment for package after installed. Package status will become
postinst O
corrupted for non-zero returned value.
It can be used to check conditions before uninstallation but not to make side effects onto the
preuninst O
system. Package uninstallation will be aborted for non-zero returned value.
It can be used to check conditions before upgrade but not to make side effects onto the system.
preupgrade O
Package upgrade will be aborted for non-zero returned value.
It can be used to prepare environment for package after upgraded. Package status will become
postupgrade O
corrupted for non-zero returned value.
start-stop-
O It can be used to control package lifecycle.
status
#!/bin/sh
exit 0
start-stop-status
#!/bin/sh
case "$1" in
start)
;;
stop)
;;
status)
;;
esac
exit 0
This script is used to start, stop a package and detect running status. DSM would call this script with different parameters in different
scenario:
start: When a user runs the package or the system is turning on, the package should do its start operation.
stop: When a user stops the package or the system is turning off, the package should do its stop operation.
53
scripts
status: When the package status is being checked, the following exit codes should be returned according to its status:
0: package is running.
1: program of package is dead and /var/run pid file exists.
2: program of package is dead and /var/lock lock file exists
3: package is not running
4: package status is unknown
150: package is broken and should be reinstalled.
prestart: If precheckstartstop in INFO is set to yes , the package could check if it is allowed to be started.
Note: It will also run before starting a package at booting up after DSM 7.0.
prestop: If precheckstartstop in INFO is set to yes , the package could check if it is allowed to be stopped.
Execution Order
Installation
1. prereplace
2. preinst
3. postinst
4. postreplace
5. start-stop-status with prestart argument if end user chooses to start it immediately
6. start-stop-status with start argument if end user chooses to start it immediately
Upgrade
1. start-stop-status with prestop argument if it has been started (old)
2. start-stop-status with stop argument if it has been started (old)
3. preupgrade (new)
4. preuninst (old)
5. postuninst (old)
6. prereplace (new)
7. preinst (new)
8. postinst (new)
9. postreplace (new)
10. postupgrade (new)
11. start-stop-status with prestart argument if it was started before being upgraded (new)
12. start-stop-status with start argument if it was started before being upgraded (new)
Uninstallation
1. start-stop-status with prestop argument if it has been started
2. start-stop-status with stop argument if it has been started
3. preuninst
4. postuninst
Start
1. start-stop-status with prestart argument
2. start-stop-status with start argument
54
scripts
Stop
1. start-stop-status with prestop argument
2. start-stop-status with stop argument
55
Script Environment Variables
56
Script Environment Variables
57
Script M essages
If you want to prompt users according to their language, you can use $SYNOPKG_DSM_LANGUAGE variable for language abbreviation as
shown in the example below:
case $SYNOPKG_DSM_LANGUAGE in
chs)
echo "" > $SYNOPKG_TEMP_LOGFILE
;;
cht)
echo "" > $SYNOPKG_TEMP_LOGFILE
;;
csy)
echo "Český" > $SYNOPKG_TEMP_LOGFILE
;;
dan)
echo "Dansk" > $SYNOPKG_TEMP_LOGFILE
;;
enu)
echo "English" > $SYNOPKG_TEMP_LOGFILE
;;
fre)
echo "Français" > $SYNOPKG_TEMP_LOGFILE
;;
ger)
echo "Deutsch" > $SYNOPKG_TEMP_LOGFILE
;;
hun)
echo "Magyar" > $SYNOPKG_TEMP_LOGFILE
;;
ita)
echo "Italiano" > $SYNOPKG_TEMP_LOGFILE
;;
jpn)
echo "" > $SYNOPKG_TEMP_LOGFILE
;;
krn)
echo "" > $SYNOPKG_TEMP_LOGFILE
;;
nld)
echo "Nederlands" > $SYNOPKG_TEMP_LOGFILE
;;
nor)
echo "Norsk" > $SYNOPKG_TEMP_LOGFILE
;;
plk)
echo "Polski" > $SYNOPKG_TEMP_LOGFILE
;;
ptb)
echo "Português do Brasil" > $SYNOPKG_TEMP_LOGFILE
;;
ptg)
echo "Português Europeu" > $SYNOPKG_TEMP_LOGFILE
;;
rus)
echo "Русский" > $SYNOPKG_TEMP_LOGFILE
;;
58
Script M essages
spn)
echo "Español" > $SYNOPKG_TEMP_LOGFILE
;;
sve)
echo "Svenska" > $SYNOPKG_TEMP_LOGFILE
;;
trk)
echo "Türkçe" > $SYNOPKG_TEMP_LOGFILE
;;
*)
echo "English" > $SYNOPKG_TEMP_LOGFILE
;;
esac
Please refer to "scripts" and "Script Environment Variables" sections for more information.
Notification title and message here should be in the format of [package_id]:[i18n_section]:[i18n_key] where package_id is the
package value in package INFO file. I18N string example can be found in I18N page. Remember to specify desktop notification
strings to preloadTexts field in application config.
59
conf
conf
The conf folder contains the following files:
File/Folder File/Folder DS M
Required Description
Name Type Requirement
S ince DS M 7.0, all packages are forced to lower the privilege explicitly. The privilege must be provided for package to work.
60
privilege
Privilege
DS M 7.0, packages are forced to lower the privilege by applying privilege mechanism explicitly.
To reduce security risks, package should run as an user rather than root . Package can apply such mechanism by providing a
configuration file named pivilege :
To overcome the limitation that normal user cannot be used to do privileged operations, we provide a way for package to request system
resources. Please refer to Resource for more information.
{
"defaults": {
"run-as": "package"
}
}
61
resource
Resource
Packages can obtain system resources even in lower privilege identity if they apply this mechanism.
{
"data-share": {
"shares": [
{
"name": "MyShareFolderName",
"permission": {
"ro": ["MyUserName"]
}
}
]
}
}
62
PKG_DEPS
PKG_DEPS
The PKG_DEPS is similar to install_dep_packages key in INFO file, but it additionally defines the restriction according to specific
OS versions.
Each configuration file is defined in standard .ini file format with key/value pairs and sections. A section describes a unique name of
dependent/conflicting package. Each section contains information about the requirements of package versions and the restriction of OS
versions.
X.Y-Z
DSM 4.2 - M inimum required DSM version. Replaced by
dsm_min_ver DSM major number, DSM minor
DSM 7.1 os_min_ver since DSM 7.2
number, DSM build number
X.Y-Z
DSM 4.2 - M aximum required DSM version. Replaced by
dsm_max_ver DSM major number, DSM minor
DSM 7.1 os_max_ver since DSM 7.2
number, DSM build number
X.Y-Z
DSM 7.2-
os_min_ver M inimum required OS version. OS major number, OS minor number,
60112
OS build number
X.Y-Z
DSM 7.2-
os_max_ver M aximum required OS version. OS major number, OS minor number,
60112
OS build number
; Your package depends on Package D with version 2 or newer but it will be ignored when OS version is smaller than 7.2-60000
[Package D]
os_min_ver=7.2-60000
pkg_min_ver=2
; Your package depends on Package E with version 2 or newer but it will be ignored when OS version is bigger than 7.2-60000
[Package E]
os_max_ver=7.2-60000
pkg_min_ver=2
63
PKG_CONX
PKG_CONX
The PKG_CONX is similar to install_conflict_packages key in INFO file, but it additionally defines the restriction according to
specific OS versions.
Each configuration file is defined in standard .ini file format with key/value pairs and sections. A section describes a unique name of
dependent/conflicting package. Each section contains information about the requirements of package versions and the restriction of OS
versions.
X.Y-Z
DSM 4.2 - M inimum required DSM version. Replaced by
dsm_min_ver DSM major number, DSM minor
DSM 7.1 os_min_ver since DSM 7.2
number, DSM build number
X.Y-Z
DSM 4.2 - M aximum required DSM version. Replaced by
dsm_max_ver DSM major number, DSM minor
DSM 7.1 os_max_ver since DSM 7.2
number, DSM build number
X.Y-Z
DSM 7.2-
os_min_ver M inimum required OS version. OS major number, OS minor number,
60112
OS build number
X.Y-Z
DSM 7.2-
os_max_ver M aximum required OS version. OS major number, OS minor number,
60112
OS build number
; Your package conflicts with Package D version 2 or newer, but it will be ignored when OS version is smaller than 7.2-60000
[Package D]
os_min_ver=7.2-60000
pkg_min_ver=2
; Your package conflicts with Package E with version 2 or newer but it will be ignored when OS version is bigger than 7.2-6000
0
[Package E]
os_max_ver=7.2-60000
pkg_min_ver=2
64
LICENSE
License
The LICENSE file contains the licenses / user terms & conditions / end user aggrements to show on the package installation wizard. The
package center would open up a dialog to show the content of LICENSE file and provide a checkbox for user to agree these terms on the
dialog.
If the LICENSE file is properly put inside spk, the installation wizard would show your license file content like this:
65
Synology DSM Integration
66
FHS
/var/packages/[package_name]
├── etc -> /volume[volume_number]/@appconf/[package_name] (move to volume since 7.0-41330, and old path still works)
├── var -> /volume[volume_number]/@appdata/[package_name]
├── tmp -> /volume[volume_number]/@apptemp/[package_name]
├── home -> /volume[volume_number]/@apphome/[package_name]
└── target -> /volume[volume_number]/@appstore/[package_name]
/var/packages/[package_name]
├── etc -> /usr/syno/etc/packages/[package_name]
├── var -> /usr/local/packages/@appdata/[package_name]
├── tmp -> /usr/local/packages/@apptemp/[package_name]
├── home -> /usr/local/packages/@apphome/[package_name]
└── target -> /usr/local/packages/@appstore/[package_name]
Please refer to install_type in INFO for more information about installation on volume / system partition.
Creation
Directory Purpose Mode Remove Timing S cript Variable
Timing
installed /
etc permanant config storage 0755 none none
upgraded
var
installed /
(since 7.0- permanant data storage 0755 none SYNOPKG_PKGVAR
upgraded
40314)
tmp
installed / uninstalled /
(since 7.0- temporary data storage 0755 SYNOPKG_PKGTMP
upgraded upgrading
40356)
home
installed /
(since 7.0- private storage 0700 none SYNOPKG_PKGHOME
upgraded
40759)
Please refer to Privilege section for more information about defaults run-as.
67
Desktop Application
Desktop Application
You can provide a App Config for your package so that the configured application will show on the menu of desktop. It is possible to
customize icon, application privilege and target url.
To distinguish different role of users, one package can even provide more than one application such as admin application for
administrators and normal application for normal users.
In addition, any application can bring its own help documents into desktop by providing a Help Config.
68
Desktop Application
2. Add dsmuidir key to your INFO or INFO.sh whose value is the relative path to the directory you just created on previous step.
dsmuidir="ui"
dsmuidir="MyApp1:appui1 MyApp2:appui2"
If you have multiple applications, the second form should be applied. In the example above, MyApp1 represents an identifier
and appui1 represents a relative path.
Once the package is installed, DSM will create corresponding soft link at /usr/syno/synoman/webman/3rdpaty/[identifier]/
linking to the path where your relative path is. When the identifier is not presented in the first form, DSM will use package
name as identifier by default.
3. Create your own App Config and Help Config under the directory specified by dsmuidir if necessary.
4. Add dsmappname key to your INFO or INFO.sh whose value is the unique application name inside App Config. This application
will be the target application when open button of package is clicked in package center.
dsmappname="com.company.App1"
69
Desktop Application
70
Application Config
Application Config
To integrate desktop applications into DSM , you have to provide a config file in JSON format under the directory specified by
dsmuidir in INFO .
{
".url": {
"com.company.App1": {
"type": "url",
"icon": "images/app_{0}.png",
"title": "Test App1",
"desc": "Description",
"url": "http://www.yahoo.com",
"allUsers": true,
"preloadTexts": [
"app_tree:index_title",
"app_tree:node_1"
]
},
"com.company.App2": {
"type": "url",
"icon": "images/app2_{0}.png",
"title": "Test App2",
"desc": "Description 2",
"url": "http://www.synology.com",
"allUsers": true
}
}
}
com.company.App1
O In “.url”, each object should have a unique property name.
com.company.App2
When you click the menu item, the address you use to connect to the DSM management
UI will be shown in the right frame of the management UI. However, you can customize
the address as you wish.
type O
The “type” value can be "url". "url" means when you click the application icon, the
URL will be opened in a pop-up window.
You can follow the descriptions below to set up your customized URL.
“icon” indicates the icon for the application. It is a template string. The “{0}” can be
replaced by “16”, “24”, “32”, “48”, “64”, “72”, “256” depending on the resolution of
the icon.
The icon must be saved under /usr/syno/synoman/webman/3rdparty/xxx/ where xxx is
the directory name of your package.
For example, if you create a directory named "images" and put the icon image file
“icon.png” in it, the full path for the icon would be:
icon O /usr/syno/synoman/webman/3rdparty/xxx/images/icon_16.png
/usr/syno/synoman/webman/3rdparty/xxx/images/icon_24.png
/usr/syno/synoman/webman/3rdparty/xxx/images/icon_32.png
/usr/syno/synoman/webman/3rdparty/xxx/images/icon_48.png
/usr/syno/synoman/webman/3rdparty/xxx/images/icon_64.png
/usr/syno/synoman/webman/3rdparty/xxx/images/icon_72.png
/usr/syno/synoman/webman/3rdparty/xxx/images/icon_256.png
The icon value should also be set as "images/icon_{0}.png"
title O “title” represents the application name that will be displayed in the main menu.
desc X “desc” displays more details about this application upon mouse-over.
The following is an example of value setting for your URL of the application:
url O “url”: http://www.synology.com/
“url”: “3rdparty/xxx/index.html”
71
Application Config
in with an admin account. If you would like to have all users see the menu items, please
allUsers X set the key value as below:
"allUsers": true
The default setting is that only the admin can find the application.
The specified i18n section:key strings will be loaded even when application ui is not
preloadTexts X opened. This is necessary when corresponding strings are used to send desktop
notifications.
72
Application Help
Application Help
To integrate help documents into DSM Help, please follow these steps:
1> Provide a helptoc.conf describing your help document structure and put it under the directory specified by dsmuidir in INFO .
{
"app": "SYNO.App.TestAppInstance",
"title": "app_tree:index_title",
"content": "testapp_index.html",
"toc": [
{
"title": "app_tree:node_1",
"content": "testapp_node1.html",
"nodes": [
{
"title": "app_tree:node_1_child",
"content": "testapp_node1_child.html"
}
]
}, {
"title": "app_tree:node_2",
"content": "testapp_node2.html"
}
]
}
Property Description
3> Write each help document in the following HTML format so that the UI style can be consistent with others.
<!DOCTYPE html>
<html class="img-no-display">
<head>
73
Application Help
74
Application I18N
Application Internationalization
The desktop application can have i18n text referenced by config, help, etc.
You have to create directories according to supported languages then create a file named strings inside each language directory.
[dsmuidir]/texts/enu/strings
[app_tree]
index_title="This is a title"
node_1="This is node1"
[app_tab]
tab1="This is tab1"
tab2="This is tab2"
[dsmuidir]/texts/cht/strings
[app_tree]
index_title=""
node_1="1"
[app_tab]
tab1="1"
tab2="2"
When you want to use these texts, just reference them in section:key format (one value can only be one i18n string)
"title": "app_tree:node_1"
I18N strings are loaded only when application opened on desktop after DSM 7.0. If the strings are used as desktop notifications,
those strings should be specified in preloadTexts of application config.
75
Application Authentication
Application Authentication
After integrating your application into Synology DSM , you may want to perform an authentication check to ensure only logged-in users
can access the page.
You can run /usr/syno/synoman/webman/modules/authenticate.cgi to check the user login status. However the authenticate.cgi must be
run with some environment variables (HTTP_COOKIE, REM OTE_ADDR, SERVER_ADDR, etc.). So execute the authenticate.cgi
directly from the package custom CGI is recommended since the environment variables needed are set automatically.
Here is the sample code for 3rd party CGI (Note. compile this with -std=c99)
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
/**
* Check whether user is logged in.
*
* If user has logged in, put the username into "user".
*
* @param user The buffer for get username
* @param bufsize The buffer size of user
*
* @return 0: User not logged in or error
* 1: User logged in. The user name is written to given "user"
*/
bzero(user, bufsize);
fp = popen("/usr/syno/synoman/webman/modules/authenticate.cgi", "r");
if (!fp) {
return 0;
}
bzero(buf, sizeof(buf));
fread(buf, 1024, 1, fp);
if (strlen(buf) > 0) {
snprintf(user, bufsize, "%s", buf);
login = 1;
}
pclose(fp);
return login;
}
printf("Content-Type: text/html\r\n\r\n");
if (IsUserLogin(user, sizeof(user)) == 1) {
printf("User is authenticated. Name: %s\n", user);
76
Application Authentication
} else {
printf("User is not authenticated.\n");
}
return 0;
}
Login
Access the following cgi with your credential information, you will receive the session information in your cookie.
https://your-ip:5001/webapi/auth.cgi?api=SYNO.API.Auth&version=3&method=login&account=admin&passwd=your_admin_password&format=
cookie
Note. If you're using the insecure http protocol, please alter the protocol and change the port number to 5000.
https://your-ip:5001/path/to/test.cgi
If you are having trouble accessing your test.cgi, please try to access any other webapi with your cookie. This would help you to
clearify if your cookie information is valid or not.
https://your-ip:5001/webapi/entry.cgi?api=SYNO.Core.System&version=3&method=info
Logout
By accessing the following webapi, you will be logged out.
https://your-ip:5001/webapi/auth.cgi?api=SYNO.API.Auth&version=1&method=logout
77
Privilege Config
Privilege Config
To make your package work, there must exist conf/privilege inside your package. It controls security related behaviours in entire
package lifecycle.
{
"defaults":{
"run-as": "package"
},
"username": "myusername",
"groupname": "mygroupname",
"tool": [{
"relpath": "bin/mytool",
"user": "package",
"group": "package",
"permission": "0700"
}]
}
defaults (required)
Controls default settings for entire privilege file. It can only be set as value below.
ctrl-script (optional)
Control the identity to run scripts.
"ctrl-script": [{
"action": "start",
"run-as": "package"
}]
action
6.0- one of preinst , postinst , preuninst , postuninst , preupgrade , postupgrade , start , stop ,
5891 status , prestart , prestop
6.0-
run-as see the description above
5891
executable (optional)
Specify the identity to chown on installed for specific file.
"executable": [{
"relpath": "bin/mybin",
"run-as": "package"
78
Privilege Config
}]
tool (optional)
Specify the identity to chown and chmod on installed for specific file.
"tool": [{
"relpath": "bin/mytool",
"user": "package",
"group": "package",
"permission": "0700"
}]
permission 6.0-5891 4 digit number to set file permission, for example: 4750
"tool": [{
"relpath": "bin/mytool",
"user": "package",
"group": "package",
"capabilities": "cap_chown,cap_net_raw",
"permission": "0700"
}]
capabilities 7.0-40656 capabilities string without any +-=eip symbol. the value can be viewed HERE
79
Resource Config
Resource Config
It defines the system resource that is neccesary for this package to work.
{
"<resource-id>": {
<specification>
}
}
{
"usr-local-linker": {
"lib": ["lib/foo"],
"bin": ["bin/foo"],
"etc": ["etc/foo"],
}
}
From this example, the usr-local-linker represents the resource id and its value represents the file to be linked.
80
Resource Timing
Resource Timing
Every worker acquires resources at certain timings and holds it during an interval. For example, /usr/local linker holds the resource
during the interval FROM_ENABLE_TO_DISABLE , which means it acquires resource at WHEN_ENABLE and releases it at WHEN_DISABLE . The
timings are listed and explained below:
81
Resource Timing
NOTE To let the package itself decide whether uninstallation should continue or not, WHEN_PREUNINST is processed after the preuninst
script.
82
Resource Update
Resource Update
Some workers support update operation outside of worker timings. /usr/syno/sbin/synopkgheler should be used to accomplish this job.
Below are the steps to update the resource:
2. Execute the command /usr/syno/sbin/synopkghelper update [package_name] [resource_id] to trigger updating procedure.
For example, suppose a package allows the user to edit its listening port and needs to update correponding network settings:
3. The application executes the command /usr/syno/sbin/synopkghelper update ${package} port-config , then the port-config
NOTE Not all resource support update operation, please refer to the Updatable section of each resource.
83
Resource List
Available Workers
As mentioned in the section Resource, a worker is needed for resource management.
Given a Resource Config file, the resource worker will acquire / release the resource at certain time. This section describes the available
resource workers on the DSM .
84
Resource List
/usr/local linker
Description
Package's executables and library files should be installed to /usr/local. This worker link / unlink files to /usr/local/{bin,lib,etc} during
package start / stop.
Acquire() : Create symbolic links under /usr/local/{bin,lib,etc}/ that points to files in /var/packages/${package}/target/.
Files not found under /var/packages/${package}/target/ will be ignored.
If the target file already exists in /usr/local/{bin,lib,etc}, it will be unlink() first.
Failure on any file link results in this worker to abort and triggers rollback.
Release() : Delete the links under /usr/local/{bin,lib,etc}/.
Ignore files that are not found.
Ignore unlink() failure.
Provider
DSM
Timing
FROM_ENABLE_TO_DISABLE
Environment Variables
None
Updatable
No
Syntax
"usr-local-linker": {
"bin" ["<relpath>", ...],
"lib" ["<relpath>", ...],
"etc" ["<relpath>", ...]
}
Example
"usr-local-linker": {
"bin": ["usr/bin/a2p", "usr/bin/perl"],
"lib": ["lib/perl5"]
}
85
Resource List
The above specifications generates the following symbolic links for the Perl package:
root@DS $ ls -l /usr/local/{bin,lib,etc}
/usr/local/bin/:
total 0
lrwxrwxrwx 1 root root 30 Aug 13 06:32 a2p -> /var/packages/Perl/target/usr/bin/a2p
lrwxrwxrwx 1 root root 31 Aug 13 06:32 perl -> /var/packages/Perl/target/usr/bin/perl
/usr/local/lib/:
total 0
lrwxrwxrwx 1 root root 28 Aug 13 06:32 perl5 -> /var/packages/Perl/target/lib/perl5
/usr/local/etc/:
total 0
86
Resource List
Acquire() : Copy the conf files to /usr/local/etc/httpd/sites-enabled/. Then reload Apache 2.2.
The files should have .conf extension, otherwise it will be ignored
Files will be prefixed by ${package}.
Existing files will be unlink() first.
Failure on any file copy results in this worker to abort and triggers rollback.
Release() : Delete previously created links
Ignore files that are not found.
Ignore unlink() failure.
Provider
WebStation
Timing
FROM_ENABLE_TO_DISABLE
Environment Variables
None
Updatable
No
Syntax
"apache22": {
"sites-enabled": [{
"relpath": "<conf-relpath>",
}, ...]
}
Example
{
"apache22": {
"sites-enabled": [{
"relpath": "synology_added/test_1.conf"
}, {
"relpath": "synology_added/test_2.conf"
}, {
"relpath": "synology_added/test_3.conf"
87
Resource List
}]
}
}
88
Resource List
Data Share
Description
This worker creates shared folder and set its permission during package startup. The share name can be hard-coded in the specification.
The shared folder will not be removed after package uninstallation, since it might delete the user’s personal data as well.
Provider
DSM
Timing
FROM_ENABLE_TO_POSTUNINST
Environment Variables
None
Updatable
No
Syntax
"data-share": {
"shares": [{
"name": "<share-name>",
"permission": {
"ro": ["<user-name>", ...],
"rw": ["<user-name>", ...]
},
"once": "<once>"
}, ...]
}
once 6.0-5914 Boolean, only try to create share on package's first start. (optional, default = false )
Example
The following specification creates a share music, and gives the user AudioStation read-only permission. Since once defaults to false ,
the above procedure is ran every time the package starts.
89
Resource List
"data-share": {
"shares": [{
"name": "music",
"permission": {
"ro": ["AudioStation"]
}
}]
}
since 7.0-41201, package center will create a symlink under /var/packages/[package_id]/shares/ named by share folder pointing
to share folder path.
90
Resource List
When in install/remove package stage, worker will create/remove docker-compose.yaml, volume on host directory, images and
containers.
When in start/stop package stage, worker will start/stop containers by calling docker-compose start/stop.
Acquire() : Create docker-compose.yaml and prepare host volume for container to mount. Worker will also create containers in
this stage.
Release() : Remove docker-compose.yaml, host volume, containers and images. Note that worker will not remove host volume
during upgrade docker package.
FROM_S TARTUP_TO_HALT
Provider
Docker
Timing
FROM_POSTINST_TO_PREUNINST FROM_STARTUP_TO_HALT
Environment Variables
None
Updatable
No
Syntax
"docker":{
"services": [{
service setting 1
},{
service setting 2
}...],
}
Default
Key S ince Type Required Nullable Description
Value
91
Resource List
services
services specify service configurations such as service name, image name and tag, container name, volume ... etc. Docker worker will
create docker-compose.yaml according to given service configurations.
Default
Key S ince type Required Nullable Description
Value
18.09.0-
service string true false N/A Service name.
1018
18.09.0-
image string true false N/A Image name.
1018
18.09.0-
tag string true false N/A Image tag.
1018
18.09.0-
container_name string false true N/A Container name.
1018
array
18.09.0-
ports of false true N/A Container ports specification.
1018
objects
array
18.09.0- Container environment variables
environment of false false N/A
1018 specification.
objects
array
18.09.0-
depends of false false N/A Specify dependent service.
1018
objects
build
build attribute is for building image with given Dockerfile path. The path will be relative path based on package target path
(/var/packages/PKG_NAM E/target/).
Syntax:
{
"build": "[Dockerfile directory]"
}
Transform to docker-compose.yaml:
{
"build": "odoo_docker"
}
92
Resource List
Transform to docker-compose.yaml:
build: /var/packages/Odoo/target/odoo_docker
volumes
Volumes contains two categories - shares and volumes which are for different purposes. Although those two categories will all be
transform into docker-compose's "volumes" section, we seperate them for different usage. That is, shares attribute is for persistant
data volumes while volumes is for configuration files or any other configurations relative files.
shares: The shares attribute is for containers to persistant data. User only need to fill in the a directory name in shares and the
worker will first create directory under docker share directory for user and, then, genterate SOURCE:TARGET pair under volumes section
in docker-compose.yaml.
Syntax:
{
"shares": [{
"host_dir": "[host directory]",
"mount_point": "[mount point]"
}, ... {
...
}]
}
Transform to docker-compose.yaml:
volumes:
- /volumeX/docker/PKG_NAME/[host directory]:[mount point]
Example:
{
"shares": [{
"host_dir": "odoo_data",
"mount_point": "/var/lib/odoo"
}]
}
Transform to docker-compose.yaml:
volumes:
- /volume1/docker/Odoo/odoo_data:/var/lib/odoo
volumes: The volumes attribute is similar to shares attribute but is design for configuration files or directory that user would like to
mount into contianer. User can specify relative path of host configuration file or directory based on package target path
(/var/packages/PKG_NAM E/target/) and the worker will genterate SOURCE:TARGET pair under volumes section in docker-
compose.yaml.
Syntax:
{
"volumes": [{
"host_dir": "[host config or directory]",
"mount_point": "[mount point]"
}, ... {
...
}]
}
93
Resource List
Transform to docker-compose.yaml:
volumes:
- /var/packages/PKG_NAME/target/[host config or directory]:[mount point]
Example:
{
"volumes": [{
"host_dir": "odoo_docker/config",
"mount_point": "/etc/odoo"
}]
}
Transform to docker-compose.yaml:
volumes:
- /var/packages/Odoo/target/odoo_docker:/etc/odoo
ports
ports attribute is for creating ports binding for container.
Syntax:
{
"ports": [{
"host_port": "[port on host]",
"container_port": "[port in container]",
"protocol": "[tcp or udp]"
}, ... {
...
}]
}
Transform to docker-compose.yaml:
ports:
- "[port on host]:[port in container]/[tcp or udp]"
Example:
{
"ports": [{
"host_port": "30076",
"container_port": "80",
"protocol": "tcp"
}, {
"host_port": "30078",
"container_port": "443",
"protocol": "tcp"
}]
}
Transform to docker-compose.yaml:
ports:
- "30076:80/tcp"
- "30078:443/tcp"
94
Resource List
environment
environment attribute is for creating environment variables and values for containers.
Syntax:
{
"environment": [{
"env_var": "[variable name]",
"env_value": "[value]"
}, ... {
...
}]
}
Transform to docker-compose.yaml:
environment:
- "[variable name]:[value]"
Example:
{
"environment": [{
"env_var": "HOST",
"env_value": "odoo_db"
}, {
"env_var": "USER",
"env_value": "odoo"
}, {
"env_var": "PASSWORD",
"env_value": "odoo"
}]
}
Transform to docker-compose.yaml:
environment:
- HOST=odoo_db
- USER=odoo
- PASSWORD=odoo
depends
depends attribute is for specifying dependent services, in the same way as docker-comopose.
Syntax:
{
"depends": [{
"dep_service": "[service name]"
}, ... {
...
}]
}
Transform to docker-compose.yaml:
depends_on:
- [service name]
Example:
95
Resource List
"depends": [{
"dep_service": "odoo_db"
}]
}
Transform to docker-compose.yaml:
depends_on:
- odoo_db
{
"docker": {
"services": [{
"service": "odoo",
"build": "odoo_docker",
"image": "odoo",
"container_name": "Odoo",
"tag": "12.0",
"environment": [{
"env_var": "HOST",
"env_value": "odoo_db"
}, {
"env_var": "USER",
"env_value": "odoo"
}, {
"env_var": "PASSWORD",
"env_value": "odoo"
}],
"shares": [{
"host_dir": "odoo_data",
"mount_point": "/var/lib/odoo"
}],
"ports": [{
"host_port": "{{wizard_http_port}}",
"container_port": "8069",
"protocol": "tcp"
}],
"depends": [{
"dep_service": "odoo_db"
}]
}, {
"service": "odoo_db",
"image": "postgres",
"tag": "10",
"container_name": "Odoo_db",
"shares": [{
"host_dir": "db",
"mount_point": "/var/lib/postgresql/data/pgdata"
}],
"environment": [{
"env_var": "POSTGRES_DB",
"env_value": "postgres"
}, {
"env_var": "POSTGRES_PASSWORD",
"env_value": "odoo"
}, {
"env_var": "POSTGRES_USER",
"env_value": "odoo"
}, {
"env_var": "PGDATA",
"env_value": "/var/lib/postgresql/data/pgdata"
}]
}]
}
96
Resource List
Transform to docker-compose.yaml:
version: '3'
services:
odoo:
build: /var/packages/Docker_Odoo_SynoCommunity/target/odoo_docker
image: odoo:12.0
container_name: Odoo
environment:
- HOST=odoo_db
- USER=odoo
- PASSWORD=odoo
volumes:
- /volume1/docker/Docker_Odoo_SynoCommunity//odoo_data:/var/lib/odoo
ports:
- "30076:8069/tcp"
depends_on:
- odoo_db
networks:
- Docker_Odoo_SynoCommunity
odoo_db:
image: postgres:10
container_name: Odoo_db
environment:
- POSTGRES_DB=postgres
- POSTGRES_PASSWORD=odoo
- POSTGRES_USER=odoo
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- /volume1/docker/Docker_Odoo_SynoCommunity//db:/var/lib/postgresql/data/pgdata
networks:
- Docker_Odoo_SynoCommunity
networks:
Docker_Odoo_SynoCommunity:
driver: bridge
97
Resource List
It's more flexible to Docker Worker which only provides limited configuration, and available to define multiple projects.
When the package install/uninstall stage, the worker will use the compose file inside to create (or update) the project according to the
provided path, and build it. And start or stop projects on package start or stop stage.
Provider
ContainerM anager>=1432 (since DSM 7.2.1)
Timing
FROM_POSTINST_TO_PREUNINST
Acquire() : According to the configuration provided, create (or update) and build these.
Release() : Delete projects
FROM_STARTUP_TO_HALT
Environment Variables
None
Updatable
No
Syntax
{
// ...
"docker-project": {
"projects": [{
"name": "django-project",
"path": "django"
}, {
"name": "wordpress-project",
"path": "wordpress-mysql"
}]
}
}
projects
98
Resource List
build_params
Example
Example: compose.yml :
services:
db:
# We use a mariadb image which supports both amd64 & arm64 architecture
image: mariadb:10.6.4-focal
# If you really want to use MySQL, uncomment the following line
#image: mysql:8.0.27
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=somewordpress
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress
expose:
- 3306
- 33060
wordpress:
image: wordpress:latest
ports:
- 9527:80
restart: always
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress
- WORDPRESS_DB_NAME=wordpress
volumes:
db_data:
target
├── django
│ ├── app
│ │ ├── Dockerfile
│ │ ├── example
│ │ │ ├── __init__.py
│ │ │ ├── settings.py
│ │ │ ├── urls.py
99
Resource List
│ │ │ └── wsgi.py
│ │ ├── manage.py
│ │ └── requirements.txt
│ ├── compose.yaml
│ └── README.md
└── wordpress-mysql
└── compose.yml
100
Resource List
Index DB
Description
Index / unindex package help and app index during package start / stop.
For detailed description on package app index and help index, please refer to Integegrate Help Document into DSM Help.
Provider
DSM
Timing
FROM_ENABLE_TO_DISABLE
Environment Variables
None
Updatable
No
Syntax
"indexdb": {
"app-index" : {
"conf-relpath": "<conf relpath>",
"db-relpath": "<app db relpath>"
},
"help-index": {
"conf-relpath": "<conf relpath>",
"db-relpath": "<help db relpath>"
}
}
Example
"indexdb": {
"app-index" : {
"conf-relpath": "app/index.conf",
"db-relpath": "indexdb/appindexdb"
},
"help-index": {
101
Resource List
"conf-relpath": "app/helptoc.conf",
"db-relpath": "indexdb/helpindexdb"
}
}
102
Resource List
Maria DB 10
Description
This worker register on the following timings:
PREINST/PREUNINST It checks the resource specification from user / wizard to avoid failure on another timing.
If worker fails on any stage, worker framework would rollback the performed operations.
Provider
M ariaDB10 package
Timing
FROM_PREINST_TO_PREUNINST
FROM_POSTINST_TO_POSTUNINST
Environment Variables
None
Updatable
No
Syntax
"mariadb10-db": {
"admin-account-m10": "<db account>",
"admin-pw-m10": "<db password>",
"admin-account-m5": "<m5 db account>",
"admin-pw-m5": "<m5 db password>",
"migrate-db": {
"flag": true | false,
"m5-db-name": "<db name>",
"m10-db-name": "<db name>",
"db-collision": "replace" | "error"
},
"create-db": {
"flag": true | false,
"db-name": "<db name>",
"db-collision": "replace" | "skip" | "error"
},
"grant-user": {
"flag": true | false,
103
Resource List
All fields are not necessary, but if you enable some stages then you have to fillup some fields. (e.g., enable create-db stage, then you
have to provide admin-account-m10 and admin-pw-m10 )
admin-account- 10.0.30-
m10 - M ariaDB10 account id which has full access permission(root)
0005
10.0.30-
admin-account-m5 - M ariaDB account id which has full access permission(root)
0005
10.0.30-
admin-pw-m5 - M ariaDB account password which has full access permission(root)
0005
10.0.30-
migrate-db flag whether to run the stage
0005
10.0.30-
m5-db-name migration source db name of M ariaDB
0005
10.0.30-
m10-db-name migration destination db name of M ariaDB10
0005
db- 10.0.30-
collision DB Collision Strategy on importdo not provide skip
0005
10.0.30-
create-db flag whether to run the stage
0005
10.0.30-
db-name db name to create on M ariaDB10
0005
db- 10.0.30-
collision DB Collision Strategy on create db
0005
10.0.30-
grant-user flag whether to run the stage
0005
10.0.30-
db-name target db name to grant for user
0005
10.0.30-
user-name create and grant user name
0005
10.0.30-
host user host (default = localhost)
0005
10.0.30-
user-pw user password
0005
10.0.30-
drop-db-inst flag whether to run the stage
0005
10.0.30-
ver target mariadb version (m5 / m10)
0005
104
Resource List
10.0.30-
db-name db name to drop
0005
10.0.30-
drop-db-uninst - whether to run the stage
0005
10.0.30-
drop-user-uninst - whether to run the stage
0005
DB Collision Strategy : when there are same db names as provided from migrate-db & create-db , it can solve the conflict by one of
the following strategies:
1. replace
drop exist db and replace it using new db
2. error
do not do anything and just report error, which might cause installation failure
3. skip
do not do anything and continue to execute as usual
Example
"mariadb10-db": {
"admin-account-m10": "root",
"admin-pw-m10": "password!@#123432",
"admin-account-m5": "",
"admin-pw-m5": "",
"migrate-db": {
"flag": false,
"m5-db-name": "",
"m10-db-name": "",
"db-collision": ""
},
"create-db": {
"flag": true,
"db-name": "myservice",
"db-collision": "error"
},
"grant-user": {
"flag": true,
"db-name": "myservice",
"user-name" : "myservice_dbuser",
"host" : "localhost",
"user-pw" : "password!@#123432asd123123"
},
"drop-db-inst": {
"flag": false,
"ver": "",
"db-name": ""
},
"drop-db-uninst": true,
"drop-user-uninst": false
}
105
Resource List
PHP INI
Description
Packages can carry custom php.ini and fpm.conf files. This worker installs / uninstalls these config files during package start / stop.
Acquire() : Copy the php.ini and fpm.conf files to /usr/local/etc/php56/conf.d/ and /usr/local/etc/php56/fpm.d/. Then reload
php56-fpm.
php.ini / fpm.conf files should have .ini / .conf extension, otherwise it will be ignored
Files will be prefixed by ${package}.
Existing files will be unlink() first.
Failure on any file copy results in this worker to abort and triggers rollback.
Release() : Delete previously created links
Ignore files that are not found.
Ignore unlink() failure.
Provider
PHP5.6
Timing
FROM_ENABLE_TO_DISABLE
Environment Variables
None
Updatable
No
Syntax
"php": {
"php-ini": [{
"relpath": "<ini-relpath>",
}, ...],
"fpm-conf": [{
"relpath": "<conf-relpath>",
}, ...]
}
Example
{
"php": {
"php-ini": [{
106
Resource List
"relpath": "synology_added/etc/php/conf.d/test_1.ini"
}, {
"relpath": "synology_added/etc/php/conf.d/test_2.ini"
}, {
"relpath": "synology_added/etc/php/conf.d/test_3.ini"
}],
"fpm-conf": [{
"relpath": "synology_added/etc/php/fpm.d/test_1.conf"
}, {
"relpath": "synology_added/etc/php/fpm.d/test_2.conf"
}, {
"relpath": "synology_added/etc/php/fpm.d/test_3.conf"
}]
}
}
107
Resource List
Port Config
Description
Install / uninstall service port config file during package install / uninstall.
For detailed description on what is and how to write a port config file, please refer to Install Package Related Ports Information into
DSM .
Timing
FROM_POSTINST_TO_POSTUNINST
Environment Variables
None
Updatable
Yes, please refer to Config Update on how to trigger update.
Syntax
"port-config": {
"protocol-file": <protocol_file>
}
Example
"port-config": {
"protocol-file": "port_conf/xxdns.sc"
}
108
Resource List
note that user unit cannot be related with normal systemd unit. If you need your package to be related with system service,
please refer to start_dep_services
The package should use synosystemctl start and synosystemctl stop to control user units inside scripts.
Extra
If you want to have systemd unit inside the system, you may just put your units at conf/systemd/pkg-[customname] without the need
to use this systemd-user-unit worker.
The package framework would copy systemd units to /usr/local/lib/systemd/system on acquired and remove them on released.
Provider
DSM
Since
7.0-40761
Timing
FROM_POSTINST_TO_POSTUNINST
Syntax
"systemd-user-unit": {}
109
Resource List
System Nofitication
Description
merge / unmerge package notification strings on package start / stop
Provider
DSM
Timing
FROM_STARTUP_TO_HALT
Environment Variables
None
Updatable
No
Syntax
"sysnotify": {
"texts_dir": "<related_path_from_target_to_your_app_config_texts_dir>",
"app_privileges": [
{
"app_id": "<app id in app config>",
"categories": ["<notification category in your notification string>"]
}
]
}
Examples
Example-1: apply the specified app privilege config to all categories of notifications
"sysnotify": {
"texts_dir": "ui/texts",
"app_privileges": [{
"app_id": "com.company.App1"
}]
}
110
Resource List
Example-2: apply the specified app privilege config to some categories of notifications
"sysnotify": {
"texts_dir": "ui/texts",
"app_privileges": [{
"app_id": "com.company.App1",
"categories": ["Admin Area"]
}]
}
"sysnotify": {
"texts_dir": "ui/texts",
"app_privileges": [{
"categories": ["Guest Area"]
}]
}
The system CPU utilization has reached %VALUE%%, which exceeds the pre-defined value of %THRESHOLD%%.
From %HOSTNAME%
Notification Level
NOTIFICATION_ERROR: desktop / mail / sms / mobile / cms
NOTIFICATION_WARN: desktop / mail / mobile / cms
NOTIFICATION_INFO: desktop / cms
Notifcation Target
the mail string can specify the notification target, it has higher priority than category
111
Resource List
Notification Variable
variables can only be used in Desktop
%IP_ADDR% 192.168.1.2
%HTTP_URL% http://192.168.1.2:5000
%DATE% 2022-1-1
%TIM E% 09:00
%OSNAM E% DSM
example
112
Resource List
Syslog Config
Description
Install / uninstall the syslog-ng and logrotate config file during package start / stop.
Provider
DSM
Timing
FROM_STARTUP_TO_HALT
Environment Variables
None
Updatable
No
Syntax
"syslog-config": {
"patterndb-relpath": "<relpath>",
"patterninc": [
{
"target-dir": "not2msg"
"conf-relpath": "<relpath>"
},
{
"target-dir": "not2kern"
"conf-relpath": "<relpath>"
}
],
"logrotate-relpath": "<relpath>"
}
patterndb- 6.0- String, syslog-ng's config file's relative path under /var/packages/${package}/target/, ignore this if
relpath 7145 the log is not generated by syslog-ng (optional)
patterndb- 6.1- object array, List of patterndb-inc configs. It defines extra syslog-ng configs to be installed in
inc 7610 specified path under the syslog configuration folder
6.1-
target-dir String, The installation target path under /usr/local/etc/syslog-ng/patterndb.d/include/
7610
conf- 6.1- String, The installation source path which is relative to /var/packages/${package}/target/
113
Resource List
logrotate- 6.0- String, logrotate's config file's relative path under /var/packages/${package}/target/, ignore this if log
relpath 5911 is saved to database (optional)
Example
"syslog-config": {
"patterndb-relpath": "etc/syslog-ng.conf",
"patterninc": [
{
"target-dir": "not2msg"
"conf-relpath": "etc/NotLog2Msg"
},
{
"target-dir": "not2kern"
"conf-relpath": "etc/NotLog2Kern"
}
],
"logrotate-relpath": "etc/logrotate.conf"
}
114
Resource List
FROM_PREINS T_TO_PREUNINS T
Acquire() : sync information in user specified /var/package/${package}/target/*.json into user setting, do migrate and setup
portal and service which user specify in resource file
Release() : remove user's setting
FROM_ENABLE_TO_DIS ABLE
Acquire() : copy *.json and .mustache under /var/packages/${package}/target/ into /usr/syno/etc/www/app.d/ and enable
service setting.
Release() : remove files which copied into /usr/syno/etc/www/app.d/ and disable service setting
Provider
WebStation
Timing
FROM_PREINST_TO_PREUNINST FROM_ENABLE_TO_DISABLE
Lower privilege
According to package center privilege policy, web package will get a confined privilege during installation and run time. In order to setup
environment for web package, webservice worker provide a mechanism called pkg_dir_prepare to assist web package creating website
root directory and setting corresponding owner, group. The detail of pkg_dir_prepare will be elaborate in pkg_dir_prepare section.
Environment Variables
None
Updatable
No
Syntax
"webservice":{
"services": [{
service setting 1
},{
service setting 2
}...],
"portals": [{
default portal setting 1
},{
default portal setting 2
}],
"migrate": {
Migration data
},
115
Resource List
"pkg_dir_prepare": [{
package directory prepare settings
}]
}
Default
Key S ince Type Required Nullable Description
Value
3.0.0- Empty
migrate Object false true M igrate information (Unnecessary)
0214 object
Framework will use default value when field is not required and doesn't exist or is null.
services
Web services which are going to register, allow multiple web services to register. For more detail please see Web Service
portals
Default portal which are going to register for access portal of services and will craete UI Shortcut. Devided into server portal and
alias portal .
Important: Default server portal is not allowed registered as name base portal, since you may not be able to lookup FQDN's
correct IP from client side.
Example:
Alias Portal
{
"service": "wordpress",
"name": "wordpress",
"app": "SYNO.SDS.WordPress",
"type": "alias",
"alias": "wordpress"
}
Server Portal
{
"service": "wordpress",
"name": "wordpress",
"app": "SYNO.SDS.WordPress",
"type": "server",
"http_port": [9000],
"https_port": [9001]
}
Default
Key S ince type Required Nullable Description
Value
3.0.0-
name string true false N/A portal name
0214
3.0.0- same as
display_name string false true the title of web UI portal shortcut
0302 name
116
Resource List
3.0.0- empty
app string false true pacakge's UI App name
0214 string
3.0.0-
type string true false N/A portal's type, could be alias or server
0214
true (if
3.0.0-
alias string type is false N/A alias name
0214
alias)
empty
Http port setting for server portal, only 1
3.0.0- int array (if
http_port false false port allowed. There should be at least
0214 array type is
http_port or https_port or both.
server)
empty
Https port setting for server portal, only
3.0.0- int array (if
https_port false false 1 port allowed. There should be at least
0214 array type is
http_port or https_port or both.
server)
migrate
M igrate assist package migration from older version ( < DSM 7.0 ) to newer version. Supporting two kinds of migrate setting - root
and vhost .
root
"root": [{
"old": "wordpress",
"new": "wordpress"
}]
Default
Key S ince type Required Nullable Description
Value
3.0.0-
old string true false N/A name of old package which in web share folder.
0214
vhost
"vhost": [{
"root": "wordpress",
"service": "wordpress"
}]
Default
Key S ince type Required Nullable Description
Value
3.0.0-
root string true false N/A name of old pacakge which in web share folder.
0222
3.0.0-
service string true false N/A new package's service name
0222
pkg_dir_prepare
117
Resource List
Webservice worker will set up website root directory under web_packages according to the information web package specified in worker
config. The worker will remove the target directory under web_package between preuninst and postuninst. M ake sure to backup
your website root in preuninst script during upgrade.
pkg_dir_prepare example:
"pkg_dir_prepare": [{
"source": "/var/package/WordPress/target/src",
"target": "wordpress",
"mode": "0755",
"group": "http",
"user": "WordPress"
}]
Default
Key S ince type Required Nullable Description
Value
3.0.0-
group string true false N/A Name of target directory group ownership.
0256
3.0.0-
user string true false N/A Name of target directory user ownership.
0256
Web Service
Package could register to WebStation via WebStation webapi or Package Worker.
common field
118
Resource List
3.0.0-
service string true false N/A service name
0214
3.0.0-
display_name string true false N/A service display name
0214
3.0.0-
type string true false N/A service type
0214
Default
Key S ince type Required Nullable Description
Value
3.0.0-
profile_desc string true false N/A Description of php profile
0214
3.0.0- empty key value pairs, define php ini setting, user
php_settings object false true
0214 object may modify this field.
119
Resource List
static service
When type is static, system will serve your pacakge with nginx.
Default
Key S ince type Required Nullable Description
Value
{
"service": "static",
"display_name": "static service",
"support_alias": true,
"support_server": true,
"type": "static",
"root": "static_dir",
"icon": "ui/Wordpress_{0}.png"
}
nginx_php service
When type is nginx_php, system will serve your package with nginx. The php file will be executed by php-fpm. Php-fpm default
behavior can be defined in field `php
Default
Key S ince type Required Nullable Description
Value
["index.htm",
3.0.0- string nginx service's index file. note use
index false true "index.html",
0214 array default value if null in this field.
"index.php"]
3.0.0-
php object true false N/A define default php profile
0214
{
"service": "wordpress",
120
Resource List
"display_name": "WordPress",
"support_alias": true,
"support_server": true,
"type": "nginx_php",
"root": "wordpress",
"icon": "ui/Wordpress_{0}.png",
"php": {
"profile_name": "WordPress Profile",
"profile_desc": "PHP Profile for WordPress",
"backend": 6,
"open_basedir": "/var/services/web_packages/wordpress:/tmp:/var/services/tmp",
"extensions": [
"mysql",
"mysqli",
"pdo_mysql",
"curl",
"gd",
"iconv"
],
"php_settings": {
"mysql.default_socket": "/run/mysqld/mysqld10.sock",
"mysqli.default_socket": "mysqli.default_socket",
"pdo_mysql.default_socket": "/run/mysqld/mysqld10.sock",
"mysql.default_port": "3307",
"mysqli.default_port": "3307"
}
},
"connect_timeout": 60,
"read_timeout": 3600,
"send_timeout": 60
}
apache_php service
When type is apache_php, nginx will pass request to apache server. The php file will be executed by php-fpm. Php-fpm default
behavior can be defined in field php . Compare to nginx_php, apache_php with additional filed backend to specify apache version
Default
Key S ince type Required Nullable Description
Value
3.0.0- 1 (Apache2.2) or 2
backend int true false N/A
0214 (Apache2.4)
3.0.0-
intercept_errors bool false false true true (on) or false (off)
0284
{
"service": "wordpress",
"display_name": "WordPress",
"support_alias": true,
"support_server": true,
"type": "apache_php",
"root": "wordpress",
"backend": 2,
"icon": "ui/Wordpress_{0}.png",
"php": {
"profile_name": "WordPress Profile",
"profile_desc": "PHP Profile for WordPress",
"backend": 6,
"open_basedir": "/var/services/web_packages/wordpress:/tmp:/var/services/tmp",
"extensions": [
"mysql",
"mysqli",
"pdo_mysql",
"curl",
"gd",
"iconv"
121
Resource List
],
"php_settings": {
"mysql.default_socket": "/run/mysqld/mysqld10.sock",
"mysqli.default_socket": "mysqli.default_socket",
"pdo_mysql.default_socket": "/run/mysqld/mysqld10.sock",
"mysql.default_port": "3307",
"mysqli.default_port": "3307"
}
},
"intercept_errors": false,
"connect_timeout": 60,
"read_timeout": 3600,
"send_timeout": 60
}
reverse_proxy service
When type is reverse_proxy, nginx will proxy request to target services
Default
Key S ince type Required Nullable Description
Value
You could define proxy header to modify proxy behavior, e.g. modify host or turn on websocket. If need support of websocket, you
should specify Upgrade and Connection header as shown below:
{
"service": "gitlab",
122
Resource List
Custom Rule
You could modify config via custom_rule field in json key value format. Json key is target name, json value is target config's
mustache file path
You can reference nginx_service_template.mustache , apache22_service_template.mustache and
apache24_service_template.mustache under /var/packages/WebStation/target/misc for routing rule that you can modify.
Field {{ \@json key\@ }} in mustache template will be replaced by files specified in custom_rule
You should consider the compatibility between server and alias , and could use {{#alias}} to seperate these two different
routing rules.
"custom_rule": {
"global_rule": "/var/packages/WordPress/target/misc/nginx_global.mustache",
"fastcgi_rule": "/var/packages/WordPress/target/misc/nginx_fastcgi.mustache",
"proxy_rule": "/var/packages/WordPress/target/misc/nginx_proxy.mustache",
"apache_rule": "/var/packages/WordPress/target/misc/apache.mustache"
}
affect service
key affect target effect
type
123
Resource List
M ake the registered nginx static config take effect at its desired time.
The required resources can be registered synchronously, including port and 80/443 alias. It can be declared separately without
additionally specifying config.
Acquire() : copies all registered configs under /var/packages/${package}/target/ to the corresponding nginx available folder and
create a config link with a timing of disable to the corresponding nginx enable folder.
Release() : removes all available configs and enable links.
FROM_S TARTUP_TO_HALT
Acquire()
removes the enable config link whose timing is disable from the corresponding nginx folder
creates the config link whose timing is enable to the corresponding nginx folder
Release()
removes the enable config link with a timing of enable from the corresponding nginx folder
create the config link with a timing of disable to the corresponding nginx folder
Note
When creating an enable link, it will first lock and test the nginx config to avoid race conditions and to ensure that it does not
conflict with the enabled config.
Acquire will end immediately if any failures occur during the process. Release will finish as much as possible even if errors occur
during the process.
If a config registers enable and disable the timing at the same time, the config will create an enable link after the Package is installed
and delete the enable link when the Package is removed. Package enable/disable will not operate the link.
When the configuration is copied to the available folder, its name will be hash calculated, and the corresponding prefix and suffix
will be added. There is no need to worry about collisions with other or your own configurations. The converted configuration name
will be {prefix of type}.{package}-hash({path}).conf.
Worker will not reload nginx, if you need to reload nginx service, please following the instructions below:
if there is a config with timing as enable, package owner needs to marked instuninst_restart_services = nginx.service in
INFO
if there is a config with timing as disable, package owner needs to marked instuninst_restart_services = nginx.service
Provider
DSM
Timing
FROM_POSTINST_TO_PREUNINST FROM_STARTUP_TO_HALT
Environment Variables
124
Resource List
None
Updatable
No
Syntax
"web-config": {
"nginx-static-config": {
"enable": [{
"type": "<config type>",
"relpath": "<config relpath>",
"ports": [{
"port": <config port used>",
"protocol": <config port protocol used>",
"schema": <config port schema used>",
}],
"alias": ["<config alias used>"]
}],
"disable": [{
"type": "<config type>",
"relpath": "<config relpath>",
"ports": [{
"port": <config port used>",
"protocol": <config port protocol used>",
"schema": <config port schema used>",
}],
"alias": ["<config alias used>"]
}]
}
}
nginx-static-config
nginx- 7.0-
static-config List the nginx static config to be used by the package
40120
7.0-
enable List the nginx static config to be applied when the package is enabled
40120
7.0-
disable List nginx static config to be applied when the package is disabled
40120
type
7.0- The type of config to be placed determines its include position in nginx config. Currently supports
40120 dsm, www, http, server, x-accel, main
7.0-
relpath The relative path of the config to be placed under /var/packages/${package}/target/
40120
7.1-
port Declare the port number used
42446
7.1-
protocol Declare the port number protocol used, can be filled in tcp/udb/both
42446
7.1-
schema Declare the port number schema used, http/https can be filled
42446
7.1-
alias The 80/443 alias used for the declaration
42446
type
125
Resource List
7.0-
dsm Valid for DSM Server block and DSM custom domain block (5000/5001)
40120
7.0-
www Valid for Default server block (80/443)
40120
7.0-
http Valid for HTTP context
40120
7.0-
server Independent server block
40120
x- 7.0- Valid for DSM Server block, DSM custom domain block and Default server block, used to place x-accel
accel 40120 settings
7.0- Valid for HTTP Context. It can place independent stream block, mail block or other settings that do not
main
40227 belong to HTTP Context
Example
{
"web-config": {
"nginx-static-config": {
"enable": [{
"type": "www",
"relpath": "synology_added/enable",
"alias": [
"www-test"
]
},
{
"type": "http",
"relpath": "synology_added/install"
},
{
"type": "server",
"relpath": "synology_added/enable",
"ports": [{
"port": 50400,
"protocol": "tcp",
"schema": "http"
}]
},
{
"ports": [{
"port": 50455,
"protocol": "tcp",
"schema": "http"
}],
"alias": [
"unique-test"
]
}],
"disable": [{
"type": "x-accel",
"relpath": "synology_added/disable"
},
{
"type": "http",
"relpath": "synology_added/install"
},
{
"type": "dsm",
"relpath": "synology_added/disable"
}]
}
}
}
126
Resource List
127
Port
Port
If your package service uses specific ports for communication (e.g. Surveillance Station uses ports 19997/udp for source port and
19998/udp for destination port), you should prepare a service configuration file for this package to describe which ports will be used.
After that, once the user creates firewall rules or port forwarding rules from the built-in application, your package service will also be
listed for selection.
[service_name]
title="English title"
desc="English description"
port_forward="yes" or "no"
src.ports="ports/protocols"
dst.ports="ports/protocols"
[service_name2]
…
Section/Key Descriptions
Please see the following statements for the strings and keys:
Default DS M
S ection/Key Description Value
Value Requirement
Required
Required
title English title N/A 4.0-2206
English title which will be shown on field Protocol
at firewall build-in selection menu.
Required
English
desc N/A 4.0-2206
English description which will be shown on field description
Applications at firewall build-in selection menu.
Optional
128
Port
be listed.
Optional ports/protocols
ports: 1~65535
If your package service has specified source ports, (separated by ‘,’
ports:
you can set them in this key. The value should and use ‘:’ to
N/A
src.ports contain at least the port numbers, and a default represent port 4.0-2206
protocols:
protocol that is tcp + udp. range)
tcp,udp
protocols:
Ex: 6000,7000:8000/tcp,udp means source ports are tcp,udp
6000, 7000 to 8000, all ports are tcp + udp. (separated by ‘,’)
Required ports/protocols
ports: 1~65535
Each service should have destination ports. The (separated by ‘,’
ports:
value should contain at least the port numbers, and a and use ‘:’ to
N/A
dst.ports default protocol that is tcp + udp. represent port 4.0-2206
protocols:
range)
tcp,udp
Ex: 6000,7000:8000/tcp,udp means destination protocols:
ports are 6000, 7000 to 8000, all ports are tcp + tcp,udp
udp. (separated by ‘,’)
[ss_findhostd_port]
title="Search Surveillance Station"
desc="Surveillance Station"
port_forward="yes"
src.ports="19997/udp"
dst.ports="19998/udp"
After the service configuration file is ready, add the following content to the resource specification file. Please refer to Port Config for
more detail.
"port-config": {
"protocol-file": "port_conf/xxdns.sc"
}
[dhcp_udp]
title="DHCP Server"
title_key="DHCP Server"
desc="DHCP Server"
desc_key="DHCP Server"
port_forward="no"
dst.ports="67,68/udp"
Please run the following instructions to check if the port is in use while you are trying to change the port number from 67 to 667
129
Port
The return code does not indicate port occupation, you need to parse the standard output to extract the IsConflict value.
If the IsConflict value is false, you can use that port number safely.
130
M onitor
Monitor
The DSM manages resource by slices or processes. It requires the information "who owns this process". For packages, they should tell
DSM which daemon belongs to them.
All you have to do is to fill the Slice field in your systemd unit with [package_name].slice . Here is an example field from units for
M yPackage:
...
[Service]
Slice=MyPackage.slice
...
If the field is properly set, you should be able to see your package shown on the resource monitor.
131
Package Examples
Package Examples
Open Source Tool: tmux
Open Source Tool: nmap
Docker package
Web Package: WordPress
132
Open Source Tool: tmux
You have to create SynoBuildConf/build, SynoBuildConf/install, and SynoBuildConf/depends before using Package Toolkit.
Unlike the previous example, compiling an application on most open source projects may require executing the following three steps:
1. configure
2. make
3. make install
The configure script consists of many lines which are used to check some details about the machine where the software is going to be
installed. This script will also check a lot of dependencies on your system. When you run the configure script, you will see a lot of
output on the screen, each being some sort of question with a respective yes/no as a reply. If any of the major requirements are missing
on your system, the configure script will exit and you will not be able to proceed with the installation until you meet the required
conditions. In most cases, compile applications on some particular target machines will require you to modify the configure script
manually to provide the correct values.
When running the configure script to configure software packages for cross-compiling, you will need to specify the CC , LD , RANLIB ,
CFLAGS , LDFLAGS , host , target , and build .
Preparation:
First download the tmux source code from the official github site or you can download example tmux package project from this link.
Note: The archive file you've downloaded from the above links is different from the official tmux source code. We have added the
necessary build scripts.
Project Layout:
tmux/
├── tmux related source code
├── SynoBuildConf/
| ├── build
| ├── depends
| └── install
└── synology
├── conf/
├── scripts/
└── INFO.sh
SynoBuildConf/depends:
The following is the depends file for this example. There is nothing special about the depends file.
[default]
all="7.0"
SynoBuildConf/build:
133
Open Source Tool: tmux
The build script is slightly different from the previous one. Here you will have to pass the following environment variables to configure:
CC
AR
CFLAGS
LDFLAGS
In addition, since tmux is dependent on ncurses, you will need to use pkg-config to resolve the necessary header files and libraries for
tmux.
#!/bin/sh
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
case ${MakeClean} in
[Yy][Ee][Ss])
make distclean
;;
esac
CFLAGS="${CFLAGS} ${NCURSES_INCS}"
LDFLAGS="${LDFLAGS} ${NCURSES_LIBS}"
autoreconf -if
make ${MAKE_FLAGS}
SynoBuildConf/install
Instead of copying the binary to the destination folder, most big projects will use make install to install the binaries and libraries. You
can pass the DESTDIR environment variable to specify where you want to install the binaries and libraries.
#!/bin/bash
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
PKG_NAME="tmux"
INST_DIR="/tmp/_${PKG_NAME}"
PKG_DIR="/tmp/_${PKG_NAME}_pkg"
PKG_DEST="/image/packages"
PrepareDirs() {
for dir in $INST_DIR $PKG_DIR; do
rm -rf "$dir"
done
for dir in $INST_DIR $PKG_DIR $PKG_DEST; do
mkdir -p "$dir"
done
}
InstallTmux() {
DESTDIR="${INST_DIR}" make install
}
GenerateINFO() {
synology/INFO.sh > INFO
cp INFO "${PKG_DIR}"
}
InstallSynologyConfig(){
134
Open Source Tool: tmux
cp -r synology/scripts/ "${PKG_DIR}"
cp -r synology/conf/ "${PKG_DIR}"
cp synology/PACKAGE_ICON{,_256}.PNG "${PKG_DIR}"
}
MakePackage() {
source /pkgscripts/include/pkg_util.sh
pkg_make_package $INST_DIR $PKG_DIR
pkg_make_spk $PKG_DIR $PKG_DEST
}
main() {
PrepareDirs
InstallTmux
GenerateINFO
InstallSynologyConfig
MakePackage
}
main "$@"
INFO.sh
As mentioned before, we will use INFO.sh to generate the INFO file.
#!/bin/sh
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
. /pkgscripts/include/pkg_util.sh
package="tmux"
version="1.9.1-1001"
os_min_ver="7.0-40850"
displayname="tmux"
arch="$(pkg_get_platform) "
maintainer="Synology Inc."
description="Tmux package for Synology DSM."
support_url="https://github.com/tmux/tmux"
thirdparty="yes"
startable="no"
silent_install="yes"
silent_upgrade="yes"
silent_uninstall="yes"
[ "$(caller)" != "0 NULL" ] && return 0
pkg_dump_info
After the build process, you can check the result in /toolkit/result_spk .
If you failed to install the package, it is possible to find out the error logs at /var/log/messages .
135
Open Source Tool: tmux
References
Toolkit
Package Format
Privilege
Resource
136
Open Source Tool: nmap
If you wish to compile an open source project manually, please refer to Appendix B: Compile Open Source Project M anually.
You have to create the SynoBuildConf/build, SynoBuildConf/install, and SynoBuildConf/depends before using Package Toolkit.
Unlike the previous example, compiling an application on most open source projects may require executing the following three steps:
1. configure
2. make
3. make install
The configure script consists of many lines which are used to check some details about the machine where the software is going to be
installed. This script will also check a lot of dependencies on your system. When you run the configure script, you will see a lot of
output on the screen, each being some sort of question with a respective yes/no as a reply. If any of the major requirements are missing
on your system, the configure script will exit and you will not be able to proceed with the installation until you meet the required
conditions. In most cases, compile applications on some particular target machines will require you to modify the configure script
manually to provide the correct values.
When running the configure script to configure software packages for cross-compiling, you will need to specify the CC , LD , RANLIB ,
CFLAGS , LDFLAGS , host , target , and build .
Preparation:
You can download the projects by following commands:
wget https://nmap.org/dist/nmap-7.91.tar.bz2
wget http://www.tcpdump.org/release/libpcap-1.9.1.tar.gz
Project Layout:
After you download the source code, your toolkit layout should look like the following figure.
/toolkit/
├── build_env/
│ └── ds.${platform}-${version}/
│ └── /usr/syno/
│ ├── bin
│ ├── include
│ └── lib
├── pkgscripts-ng/
└── source/
├──nmap/
│ ├── nmap related source code
│ ├── SynoBuildConf/
│ | ├── build
│ | ├── depends
137
Open Source Tool: nmap
│ | └── install
| └── synology
│ ├── PACKAGE_ICON.PNG
│ ├── PACKAGE_ICON_256.PNG
│ ├── INFO.sh
│ ├── conf/
│ | ├── privilege
│ | └── resource
│ └── scripts/
└──libpcap/
├── libpcap related source code
├── Makefile
└── SynoBuildConf/
├── build
├── depends
├── install-dev
└── install
The file, install-dev, is a special file which we will be covered in the following section.
SynoBuildConf/depends:
The SynoBuildConf/depends for nmap is slightly different from the previous example. Since nmap depends on libpcap, we have to add
the value to the BuildDependent field, so that the PkgCreate.py can resolve the dependency and compile the project in the correct order.
[BuildDependent]
libpcap
[default]
all="7.0"
However, the SynoBuildConf/depends for libpcap is the same as the Hello World Example.
[BuildDependent]
[default]
all="7.0"
SynoBuildConf/build:
The SynoBuildConf/build script is also different from the previous one.
Here you will have to pass several environment variables to configure, so that nmap can be compiled properly
CC
CXX
LD
AR
STRIP
RANLIB
NM
CFLAGS
CXXFLAGS
LDFLAGS
Since nmap will be compiled with many features by default, we will need to disable some of them to make it clean. The following list
contains the features that will be disabled:
138
Open Source Tool: nmap
ndiff
zenmap
nping
ncat
nmap-update
liblua
Note: If you are interested in some of the above features and you want to enable them, just change the --without-${feature}
into --with-${feature} .
#!/bin/sh
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
PKG_NAME=nmap
INST_DIR=/tmp/_${PKG_NAME}
case ${MakeClean} in
[Yy][Ee][Ss])
make distclean
;;
esac
make ${MAKE_FLAGS}
In this example, --with-libpcap is assigned with value /usr/local . We need to install libpcap's cross compiled product into
"/usr/local" so that nmap's configure can retrieve libpcap correctly.
#!/bin/bash
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
case ${MakeClean} in
[Yy][Ee][Ss])
make distclean
;;
esac
case ${CleanOnly} in
[Yy][Ee][Ss])
return
;;
esac
139
Open Source Tool: nmap
make ${MAKE_FLAGS}
make install
The above script will install libpcap related files into /usr/local/ in chroot environment. After installing libpcap, nmap can find
libpcap's cross compiled products in /usr/local .
--with-libpcap=${SysRootPrefix}
SynoBuildConf/install
Instead of copying the binary to the destination folder, most big projects will use make install to install the binaries and libraries.
Since we have used the --prefix flag when configuring the nmap project, we can just execute make install and it will install the nmap
related files to the folder specified by --prefix .
#!/bin/bash
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
PKG_NAME="nmap"
INST_DIR="/tmp/_${PKG_NAME}"
PKG_DIR="/tmp/_${PKG_NAME}_pkg"
PKG_DEST="/image/packages"
PrepareDirs() {
for dir in $INST_DIR $PKG_DIR; do
rm -rf "$dir"
done
for dir in $INST_DIR $PKG_DIR $PKG_DEST; do
mkdir -p "$dir"
done
}
SetupPackageFiles() {
make install
synology/INFO.sh > INFO
cp INFO "${PKG_DIR}"
cp -r synology/conf/ "${PKG_DIR}"
cp -r synology/scripts/ "${PKG_DIR}"
cp synology/PACKAGE_ICON{,_256}.PNG "${PKG_DIR}"
}
MakePackage() {
source /pkgscripts-ng/include/pkg_util.sh
pkg_make_package $INST_DIR $PKG_DIR
pkg_make_spk $PKG_DIR $PKG_DEST
}
main() {
PrepareDirs
SetupPackageFiles
MakePackage
}
main "$@"
140
Open Source Tool: nmap
conf/resource
{
"usr-local-linker": {
"bin": ["bin/nmap"]
}
}
conf/privilege
{
"defaults": {
"run-as": "package"
}
}
INFO.sh
As mentioned before, we will use INFO.sh to generate the INFO file.
#!/bin/sh
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
. /pkgscripts-ng/include/pkg_util.sh
package="nmap"
version="7.91-1001"
os_min_ver="7.0-40850"
displayname="nmap"
arch="$(pkg_get_platform) "
maintainer="Synology Inc."
description="This package will install nmap in your DSM system."
[ "$(caller)" != "0 NULL" ] && return 0
pkg_dump_info
After the build process, you can check the result in /toolkit/result_spk .
If you failed to install the package, it is possible to find out the error logs at /var/log/messages .
References
141
Open Source Tool: nmap
Toolkit
Package Format
Privilege
Resource
142
Docker package
To create a Gitlab docker container, you only need to depends on Docker package and fill in docker worker configuration and the worker
will do the reset for you.
As mentioned before, you have to create S ynoBuildConf/build, S ynoBuildConf/install and S ynoBuildConf/depends for packing
spk. However, since docker package will pull images or build image on the DSM , We don't need to build any code while packing the spk.
Project Layout:
docker-gitlab
├── conf
│ ├── privilege
│ └── resource
├── INFO.sh
├── scripts
│ ├── postinst
│ ├── postuninst
│ ├── postupgrade
│ ├── preinst
│ ├── preuninst
│ ├── preupgrade
│ ├── script_customized
│ └── start-stop-status
├── SynoBuildConf
│ ├── build
│ ├── depends
│ └── install
└── ui
├── config.png
├── Gitlab_120.png
├── Gitlab_16.png
├── Gitlab_24.png
├── Gitlab_256.png
├── Gitlab_32.png
├── Gitlab_48.png
├── Gitlab_64.png
└── Gitlab_72.png
INFO.sh:
We will use INFO.sh to generate the INFO file. The following is the INFO.sh file for this example. For more details of each key's
purpose, please see INFO.
#!/bin/bash
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
package="wordpress_sample"
. "/pkgscripts-ng/include/pkg_util.sh"
version="12.9.0-1"
os_min_ver="7.0-40337"
install_dep_packages="Docker>=18.09.0-1017"
maintainer="Gitlab"
thirdparty="yes"
arch="avoton"
adminurl="wordpress"
dsmuidir="ui"
displayname="Gitlab"
143
Docker package
package_icon="`/pkgscripts-ng/include/base64.php ${ICON_PATH}`"
SynoBuildConf/depends:
The following is the depends file for this example.
[default]
all="7.0"
SynoBuildConf/build:
The following is the build file for this example. Since WordPress is depends on PHP, there is nothing to do in build.
#!/bin/bash
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
case ${MakeClean} in
[Yy][Ee][Ss])
make clean
;;
esac
case ${CleanOnly} in
[Yy][Ee][Ss])
return
;;
esac
make ${MAKE_FLAGS}
SynoBuildConf/install:
The following is the install file for this example.
#!/bin/bash
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
144
Docker package
. "/pkgscripts-ng/include/pkg_util.sh"
pkg_make_package $INST_DIR $PKG_DIR
pkg_make_spk $PKG_DIR $PKG_DEST
UI config:
UI config is placed in ui folder.
{
".url": {
"SYNO.SDS.GitLab": {
"allUsers": true,
"desc": "Docker-GitLab",
"icon": "images/Docker_GitLab_SynoCommunity-{0}.png",
"port": "@PORT@",
"protocol": "http",
"texts": "texts",
"title": "GitLab",
"type": "url",
"url": "/"
}
}
}
Scripts:
The following are spk scripts for installing docker Gitlab spk into DSM .
preinst: There is nothing to do for preinst in this example. You can customize your own preinst script to fit your
circumstances.
#!/bin/sh
exit 0
postinst: In postinst stage, we set up port in ui/config after user specify in install wizard.
#!/bin/sh
PKG_NAME="Gitlab"
PORT_CONFIG_FILE="/var/packages/$PKG_NAME/etc/port_config"
port=""
if [ ! -z "$wizard_http_port" ]; then
# new install
port="$wizard_http_port"
elif [ -f "$PORT_CONFIG_FILE" ]; then
# upgrade
port=$(get_key_value "$PORT_CONFIG_FILE" port)
fi
if [ -f "$SYNOPKG_PKGDEST/app/config" ]; then
sed -i "s/@PORT@/$port/g" "$SYNOPKG_PKGDEST/ui/config"
fi
exit 0
145
Docker package
preuninst: There is nothing to do in preuninst in this example. You can customize your own preuninst script to fit your
circumstances.
#!/bin/sh
exit 0
#!/bin/sh
PKG_NAME="Gitlab"
PORT_CONFIG_FILE="/var/packages/$PKG_NAME/etc/port_config"
exit 0
preupgrade: There is nothing to do in preupgrade in this example. You can customize your own preupgrade script for upgrade
purpose.
#!/bin/sh
exit 0
postupgrade: There is noting to do in postupgrade in this example. You can customize your own postupgade script for upgrade
purpose.
#!/bin/sh
exit 0
start-stop-status: For start-stop-status in this example. You could call docker_inspect to see if your container is running.
#!/bin/bash
GITLAB_NAME="GitLab"
DOCKER_INSPECT="/usr/local/bin/docker_inspect"
case "$1" in
start)
;;
stop)
;;
status)
"$DOCKER_INSPECT" "$GITLAB_NAME" | grep -q "\"Status\": \"running\"," || exit 1
;;
log)
echo ""
;;
*)
echo "Usage: $0 {start|stop|status}" >&2
exit 1
;;
esac
exit 0
Privilege:
The following is the privilege file under conf directory. The privilege file is configuration for specifying the installation and run time
privilege. The detail of privilege will be elaborated under privilge section.
146
Docker package
{
"defaults": {
"run-as": "package"
},
"username": "Gitlab"
}
`
Worker:
The following is the resource file under conf directory. The resource file are configurations for calling workers. In this example, since
docker package only need docker worker to prepare container for them, we write docker worker configuration for setting up Gitlab
container. For more details, please see docker worker.
{
"docker": {
"services": [{
"service": "gitlab",
"image": "gitlab/gitlab-ce",
"container_name": "GitLab",
"tag": "12.9.0-ce.0",
"restart": "always",
"shares": [{
"host_dir": "gitlab/data",
"mount_point": "/var/opt/gitlab"
}, {
"host_dir": "gitlab/logs",
"mount_point": "/var/log/gitlab"
}, {
"host_dir": "gitlab/config",
"mount_point": "/etc/gitlab"
}],
"ports": [{
"host_port": "{{wizard_http_port}}",
"container_port": "80",
"protocol": "tcp"
}, {
"host_port": "{{wizard_https_port}}",
"container_port": "443",
"protocol": "tcp"
}, {
"host_port": "{{wizard_ssh_port}}",
"container_port": "22",
"protocol": "tcp"
}]
}]
}
}
After the build process, you can check the result in /toolkit/result_spk .
147
Docker package
If the building process was successful, you will see that the .spk file has been placed under result_spk folder. To test the spk file, you
can use manual install in Package Center to install your package.
148
Web Package: WordPress
WordPress is the largest self-hosted blogging Open Source Project that have been used by millions of websites. All it need is a PHP web
server and a database, then you can build your own blogging website. In this example, we will use WebStation and Apache as web server
to host WordPress, and use M ariaDB as database. Once the website was setted up, you could modify web server configurations for
WordPress via WebStation UI.
As mentioned before, you have to create S ynoBuildConf/build, S ynoBuildConf/install, S ynoBuildConf/depends and WordPress
source project before creating spk. However, since WordPress depends on PHP, we don't have to compile any source code.
Preparation:
First you need to download WordPress from official website and unarchive it into your spk source project. In this example, we put it
under src as shown in Project Layout.
Secondly, before installing your WordPress spk, you need to download the dependant packages such as WebStation, M ariaDB, PHP7.2
and Apache2.2 in DSM from Package Center. Noted that we use PHP7.2 and Apache2.2 in this example, you can choose whatever you
want in considering your circumstances.
Third, according to instructions from WordPress official website, you have to setup DB information for WordPress. For more details,
please see WordPress - how to install wordpress.
Project Layout:
/toolkit/source/wordpress_sample
├── PACKAGE_ICON.PNG
├── PACKAGE_ICON_256.PNG
├── conf
│ ├── privilege
│ └── resource
├── INFO.sh
├── Makefile
├── scripts
│ ├── postinst
│ ├── postuninst
│ ├── postupgrade
│ ├── preinst
│ ├── preuninst
│ ├── preupgrade
│ ├── script_customized
│ └── start-stop-status
├── src
│ └── wordpress
│ └── wp-admin
├── SynoBuildConf
│ ├── build
│ ├── depends
│ └── install
└── ui
├── Wordpress_120.png
├── Wordpress_16.png
├── Wordpress_24.png
├── Wordpress_256.png
├── Wordpress_32.png
├── Wordpress_48.png
├── Wordpress_64.png
└── Wordpress_72.png
149
Web Package: WordPress
#!/bin/bash
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
package="wordpress_sample"
. "/pkgscripts-ng/include/pkg_util.sh"
version="5.5.1-1001"
os_min_ver="7.0-40337"
startstop_restart_services="nginx.service"
instuninst_restart_services="nginx.service"
install_dep_packages="WebStation>=3.0.0-0226:MariaDB10:PHP7.3>=7.3.16-0150:Apache2.2>=2.2.34-0104"
install_provide_packages="WEBSTATION_SERVICE"
maintainer="WordPress"
thirdparty="yes"
silent_upgrade="yes"
arch="noarch"
adminprotocol="http"
adminport="80"
adminurl="wordpress"
dsmuidir="ui"
SynoBuildConf/depends:
The following is the depends file for this example.
[default]
all="7.0"
SynoBuildConf/build:
The following is the build file for this example. Since WordPress is depends on PHP, there is nothing to do in build.
#!/bin/bash
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
case ${MakeClean} in
[Yy][Ee][Ss])
make clean
;;
esac
case ${CleanOnly} in
[Yy][Ee][Ss])
return
;;
esac
make ${MAKE_FLAGS}
150
Web Package: WordPress
SynoBuildConf/install:
The following is the install file for this example. In this example, we install our package with the help of Makefile.
#!/bin/bash
# Copyright (c) 2000-2022 Synology Inc. All rights reserved.
. "/pkgscripts-ng/include/pkg_util.sh"
pkg_make_package $INST_DIR $PKG_DIR
pkg_make_spk $PKG_DIR $PKG_DEST
Makefile:
The following is the Makefile file for this example. Watch out the indent must be tab instead of space.
WORDPRESSDIR=src
WORDPRESS_INSTALL_DIR=$(INSTALLDIR)/$(WORDPRESSDIR)
all clean:
.PHONY:
install:
[ -d $(INSTALLDIR) ] || install -d $(INSTALLDIR)
[ -d $(WORDPRESS_INSTALL_DIR) ] || install -d $(WORDPRESS_INSTALL_DIR)
cp -a $(WORDPRESSDIR)/* $(WORDPRESS_INSTALL_DIR)
INFO: INFO.sh
env UISTRING_PATH=$(STRING_DIR) ./INFO.sh > INFO
package: INFO
[ -d $(PACKAGEDIR) ] || install -d $(PACKAGEDIR)
[ -d $(PACKAGEDIR)/scripts ] || install -d $(PACKAGEDIR)/scripts
cp -a scripts/* $(PACKAGEDIR)/scripts
chmod 755 $(PACKAGEDIR)/scripts/*
cp -a PACKAGE_ICON.PNG $(PACKAGEDIR)
cp -a PACKAGE_ICON_256.PNG $(PACKAGEDIR)
cp -a conf $(PACKAGEDIR)
install -c -m 644 INFO $(PACKAGEDIR)
clean:
151
Web Package: WordPress
preinst: There is nothing to do for preinst in this example. You can customize your own preinst script to fit your
circumstances.
#!/bin/sh
exit 0
postinst: In postinst stage, we move the source project into "/var/services/web_packages" since it's Web Station's working
directory.
#!/bin/sh
WEBSITE_ROOT="/var/services/web_packages/wordpress"
exit 0
preuninst: There is nothing to do in preuninst in this example. You can customize your own preuninst script to fit your
circumstances.
#!/bin/sh
exit 0
#!/bin/sh
exit 0
preupgrade: There is nothing to do in preupgrade in this example. You can customize your own preupgrade script for upgrade
purpose.
#!/bin/sh
exit 0
postupgrade: There is noting to do in postupgrade in this example. You can customize your own postupgade script for upgrade
purpose.
#!/bin/sh
exit 0
start-stop-status: There is nothing to do in start-stop-status in this example. You can customize your own start-stop-status
#!/bin/sh
case "$1" in
start)
exit 0
;;
152
Web Package: WordPress
stop)
exit 0
;;
status)
exit 0
;;
*)
exit 1
;;
esac
Privilege:
The following is the privilege file under conf directory. The privilege file is configuration for specifying the installation and run time
privilege. The detail of privilege will be elaborated under privilge section.
{
"defaults": {
"run-as": "package"
},
"username": "WordPress",
"join-groupname": "http"
}
`
Worker:
The following is the resource file under conf directory. The resource file are configurations for calling workers. In this example, since
we would like to integrate WordPress with WebStation, we will call WebStation's worker to run specific setup during installation. For
more details, please see webservice.
{
"webservice": {
"services": [{
"service": "wordpress",
"display_name": "WordPress",
"support_alias": true,
"support_server": true,
"type": "apache_php",
"root": "wordpress",
"backend": 1,
"icon": "ui/Wordpress_{0}.png",
"php": {
"profile_name": "WordPress Profile",
"profile_desc": "PHP Profile for WordPress",
"backend": 7,
"open_basedir": "/var/services/web_packages/wordpress:/tmp:/var/services/tmp",
"extensions": [
"mysql",
"mysqli",
"pdo_mysql",
"curl",
"gd",
"iconv"
],
"php_settings": {
"mysql.default_socket": "/run/mysqld/mysqld10.sock",
"mysqli.default_socket": "mysqli.default_socket",
"pdo_mysql.default_socket": "/run/mysqld/mysqld10.sock",
"display_errors": "1",
"error_reporting": "E_ALL",
"log_errors": "true"
153
Web Package: WordPress
},
"user": "WordPress",
"group": "http"
},
"connect_timeout": 60,
"read_timeout": 3600,
"send_timeout": 60
}],
"portals": [{
"service": "wordpress",
"type": "alias",
"name": "wordpress",
"alias": "wordpress",
"app": "SYNO.SDS.WordPress"
}],
"pkg_dir_prepare": [{
"source": "/var/packages/WordPress/target/src/wordpress",
"target": "wordpress",
"mode": "0755",
"user": "WordPress",
"group": "http"
}]
}
}
After the build process, you can check the result in /toolkit/result_spk .
154
Web Package: WordPress
proxy_send_timeout 60s;
proxy_pass http://localhost:914;
proxy_set_header X-Forwarded-By $server_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_http_version 1.1;
proxy_intercept_errors on;
}
}
3. run systemctl reload nginx then you can see original error page from wordpress now
155
Publish Synology Packages
156
Get Started with Publishing
2. Read and accept the Developer Distribution Agreement and Package Developer Guideline. Note that packages that you publish on
Package Center must comply with the Terms of Service in Package Center.
Please note that the package quality directly influences the long-term success of your package in terms of installation, online reviews,
engagement, and user retention.
157
Submitting the Package for Approval
Deciding whether your package will be free or paid is important because free packages must remain free.
Once your package is published as a free one, you cannot change it to a paid package.
If you publish your package as a paid one, you can change it to free at any time (but cannot be changed back to paid).
Prepare Screenshots
When you publish in Package Center, you must supply a variety of high-quality screen-shots to showcase your package or brand. After
you publish, they will appear on your package details page, or elsewhere. These screen-shots are a key part of a successful package
details page that will attract and engage users. Therefore, you may also consider hiring a professional to produce them for you.
We will have a completed and rigorous internal process to make sure the quality of the published package. There are four major
processes in short:
158
Submitting the Package for Approval
159
Responding to User Issues
There are many ways that you can keep in touch with users and offer them support. The most common way is to provide a support
email address in your package details page. You can also provide support in other ways, such as a forum or a mailing list. The Synology
technical support team provides user support for downloading, installing and payments issues, but issues that fall outside of these
topics will fall under your domain. Examples of issues you can support include: feature requests, questions about using the app and
questions about compatibility settings.
Provide a link to your support resources and set up any other support outlets such as a forum.
Provide an appropriate support email address on your package detail page and respond to users when they email you.
Acknowledge and fix issues with your package. It helps to be transparent and list known issues on your package details page
regularly.
Publish updates frequently, without sacrificing quality or annoying users with too-frequent updates.
With each update, make sure you provide a summary of what is new. Users will read it and appreciate that you are serious about
improving the quality of your package.
160
Appendix A: Platform and Arch Value M apping Table
In the below table, you will find the string value corresponding to the platform in question. For example, if the platform of your NAS is
M arvell ARM ADA 370, armada370, the value that should to be provided as a pair of the arch key is armada370 .
Please check the platforms of the NAS to be supported and refer to the table below for their corresponding string values:
Arch
Member platforms
Family
i686 evansport
armv5 628x
alpine
alpine4k
apollolake
armada370
armada375
armada37xx
armada38x
armadaxp
avoton
braswell
broadwell
broadwellnk
broadwellntb
broadwellntbap
bromolow
cedarview
coffeelake
comcerto2k
denverton
evansport
geminilake
grantley
kvmx64
monaco
purley
rtd1296
rtd1619
skylaked
v1000
161
Appendix A: Platform and Arch Value M apping Table
You can check the "Package Arch" field in the CPU list to find out which arch does your NAS belong to.
162
Appendix B: Compile Applications M anually
Compile Applications
The Synology NAS employs embedded SoC or x86-based CPUs, implementing several platforms -- such as ARM and x86 -- on a
variety of Synology NAS models. In order to run 3rd-party applications on the Synology NAS, it is necessary to compile applications
into an executable format for the corresponding platform.
This information will help you determine which DSM tool chain (please refer to the “Download DSM Tool Chain” section) to
download for each model.
Please refer to What kind of CPU does my NAS have for a complete model list.
To compile an application for the Synology NAS, a compiler that runs on Linux PC is required in order to generate an executable file for
the Synology NAS. This compiling procedure is called cross-compiling, and the set of compiling tools (compiler, linker, etc) used to
compile the application is called a tool chain.
163
Download DSM Tool Chain
You would need to know what your target platform is to download the corresponding tool chain. Here is the platform list
If you are not sure about which tool chain you need, please execute the following command on your Synology NAS.
DiskStation> uname -a
Linux DiskStation 4.4.59+ #24922 SMP PREEMPT Mon Aug 19 12:13:37 CST 2019 x86_64 GNU/Linux synology_apollolake_718+
DiskStation>
The output "synology_apollolake_718+" tells you which tool chain is appropriate. For example, apollolake means you need the tool
chain for "Intel x86 Linux 4.4.59 (Apollolake)" on the Synology Archive.
After you download the DSM tool chain, extract it to where you want it on your computer. For the following instructions we will
extract to /usr/local/ as an example. You can extract the tool chain by using the following command:
Please make sure the tool chain is located in the directory /usr/local on your computer to ensure proper integration.
164
Compile
Compile
You can start compiling an application called examplePkg.c”, for example, that looks like this:
#include <sys/sysinfo.h>
int main()
{
struct sysinfo info;
int ret;
ret = sysinfo(&info);
if (ret != 0) {
printf("Failed to get system information.\n");
return -1;
}
printf("Total RAM: %u\n", info.totalram);
printf("Free RAM: %u\n", info.freeram);
return 0;
}
EXEC= sysinfo
OBJS= sysinfo.o
CC= /usr/local/arm-marvell-linux-gnueabi/bin/arm-marvell-linuxgnueabi-gcc
LD= /usr/local/arm-marvell-linux-gnueabi/bin/arm-marvell-linuxgnueabi-ld
CFLAGS += -I/usr/local/arm-marvell-linux-gnueabi/arm-marvell-linuxgnueabi/libc/include
LDFLAGS += -L/usr/local/arm-marvell-linux-gnueabi/arm-marvell-linuxgnueabi/libc/lib
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS)
clean:
rm -rf *.o $(PROG) *.core
165
Compile Open Source Projects
1. configure
2. make
3. make install
The configure script basically consists of many lines which are used to check details about the machine on where the software is going to
be installed. The script will check for a lot of dependencies on your system. When you run the configure script, you will see a lot of
output on the screen, each being some sort of question with a respective yes/no reply. If there are any major requirements missing on
your system, the configure script will exit and you will not be able to proceed with the installation until you meet all the requirements.
In most cases, compile applications on some particular target machines will require you to modify the configure script manually to
provide the correct values.
When running the configure script to configure software packages for cross-compiling, you will need to specify the CC , LD , RANLIB ,
CFLAGS , LDFLAGS , host , target , and build , etc. All these values can be found in /env32.mak or /env64.mak in your chroot
environment. Some examples are given below.
env CC=/usr/local/x86_64-pc-linux-gnu/bin/x86_64-pc-linux-gnu-wrap-gcc \
LD=/usr/local/x86_64-pc-linux-gnu/bin/x86_64-pc-linux-gnu-ld \
RANLIB=/usr/local/x86_64-pc-linux-gnu/bin/x86_64-pc-linux-gnu-ranlib \
CFLAGS="-DSYNOPLAT_F_X86_64 -O2 -include /usr/syno/include/platformconfig.h -DSYNO_ENVIRONMENT -DBUILD_ARCH=64 -D_LARGEFIL
E64_SOURCE -D_FILE_OFFSET_BITS=64 -g -DSDK_VER_MIN_REQUIRED=600" \
./configure \
--host=i686-pc-linux-gnu \
--target=i686-pc-linux-gnu \
--build=i686-pc-linux \
--prefix=/usr/local
166
Appendix C: Publication Review & Verification
Package Review
We are excited that you are creating packages for the Synology DSM and want to help you understand our guidelines so you can be
confident your package will get through the review process quickly.
INFO: deprecated field Ensure deprecated fields in INFO does not exist (from DSM 7.0)
Lower priviledge The package should be run with non-privileged user (from DSM 7.0)
Network activity during installation There should not be any abnormal connection during installation
Security advisor scan The package should not cause any security advisor issue
Antivirus essential scan The package should pass the virus scanning
Clean up/file leftover Files belong to package should be removed after uninstallation
Clean up/process leftover Process belong to package should be stopped after uninstallation
Port conflict Registered port should not conflict with other services
Error log There should not be any error log left on system
Apparmor log There should not be any deny log from apparmor
Coredump file There should not be any coredump file left on system
167