Skip to content
Syno Package Land
Language: English

dsm-package.yaml reference

Use dsm-package.yaml for a native-go or binary project. This example passes check in a native-go project created with --with files,jobs,login --package MyApp.

# Package identity and SPK version: 0.1.0-0001.
schema: 2
package: MyApp
version: "0.1.0"
build: 1
displayname: My App
description: A native DSM package with files, jobs, and login.
maintainer: Your Name
os_min_ver: "7.1-42661"
arches: [x86_64, aarch64]
# Go CGI backend. A binary project uses kind: binary and files instead.
backend:
kind: go
dir: backend
main: ./cmd/app
# Build the Vue frontend before copying its static output.
ui:
dir: frontend/dist
build:
cwd: frontend
command: [npm, run, build]
# CLI login maps to the identity field.
capabilities:
files: session
jobs: {worker: sha256-v1}
identity: standalone
# Add root scripts and capability code with synopkgland add root-ops.
# rootOps: true
# Add delegate code with synopkgland add delegate.
# delegate:
# scope: install-selected
# operations: [files.moveFromStaging]
# destinations: [save]
# lifetime: until-revoked
# Catalogs and glossary are included in the generated project.
i18n:
messages: i18n/messages
glossary: i18n/glossary.json
info:
zh-TW:
displayname: 我的 App
description: 提供檔案、背景工作與登入功能的 DSM 套件。
# Select an existing Shared Folder during installation.
install:
sharedFolder:
mode: select
key: shared
permission: rw
# Optional publisher information.
metadata:
license: MIT
contact_email: you@example.com
homepage: https://example.com
# Optional entry policy; requires the Go entry gate and suitable API routes.
# entry: app-privilege
# Enable with synopkgland add portal; requires rootOps or delegate and the portal DSM minimum.
# portal: {alias: my-app}
# Optional foreground service; supply your own payload directories.
# With jobs, this also requires an until-revoked delegate.
# daemon:
# exec: bin/service
# targets: {x86_64: daemon/x86_64, aarch64: daemon/aarch64}
# args: []
# env: {}
# timeouts: {start: 30, stop: 30, status: 5, uninstall: 60}
# uninstall_args: [cleanup]

Defaults below are parser defaults; values supplied by templates are labelled separately. dsm-package.yaml and compose.yaml cannot coexist (PROJECT_RUNTIME_EXCLUSIVE). Unknown top-level keys raise STANDALONE_FIELD_UNKNOWN. See errors for fixes.

FieldTypeRequiredDefaultDescription
schemaintegerYes—Exactly 2; STANDALONE_SCHEMA_INVALID.
packagestringYes—Matches ^[A-Za-z][A-Za-z0-9]{1,63}$; STANDALONE_PACKAGE_INVALID.
versionstringYes—One to four numeric parts separated by dots; STANDALONE_VERSION_INVALID. Quote the value in YAML.
buildintegerYes—Range 1–9999; appended to version with four-digit padding; STANDALONE_BUILD_INVALID.
displaynamestringYes—Nonempty single line without double quotes or backslashes; STANDALONE_TEXT_INVALID.
descriptionstringYes—Same text rule as displayname; STANDALONE_TEXT_INVALID.
maintainerstringYes—Same text rule as displayname; STANDALONE_TEXT_INVALID.
os_min_verstringYesTemplate: 7.1-42661Full version/build matching ^\d+\.\d+(\.\d+)?-\d+$; STANDALONE_OS_MIN_VER_INVALID. Feature floors are in platforms.
archesstring[]YesTemplate: [x86_64, aarch64]Nonempty unique list of x86_64, aarch64, armv7; STANDALONE_ARCHES_INVALID.
backendobjectYes—Go source or per-architecture CGI binaries; STANDALONE_BACKEND_INVALID.
uiobjectYes—Static output directory and optional build command; STANDALONE_UI_INVALID.
iconpathNoSDK default iconSquare PNG of at least 256×256, or a directory of icon_<size>.png (16, 24, 32, 48, 64, 72, 256; icon_256.png required, missing sizes scaled from it). SVG is not accepted. The build writes PACKAGE_ICON.PNG, PACKAGE_ICON_256.PNG and ui/images/app_<size>.png; each Package Center icon must stay within the package source’s 256 KiB limit. check and inspect report whether a build uses a custom or the default icon; STANDALONE_ICON_INVALID.
capabilitiesobjectNo{}Explicit capability declarations; invalid names or values raise CAPABILITY_INVALID.
i18nobjectNoNoneMessage catalogs, glossary, and translated Package Center text; STANDALONE_I18N_INVALID.
daemonobjectNoNoneFixed foreground service; STANDALONE_DAEMON_INVALID.
installobjectNoNoneOnly sharedFolder is accepted; STANDALONE_SHARED_FOLDER_INVALID.
entrystringNoAPI permissions policyadmin-only or app-privilege; STANDALONE_ENTRY_INVALID.
portalobjectNoDisabled{} or {alias: ...}; STANDALONE_PORTAL_INVALID. Needs rootOps or delegate; STANDALONE_PORTAL_REQUIRES_EXECUTOR.
login_styleobjectNoCLI default styleLogin Portal colour, wallpaper and title image; needs portal. See login_style; STANDALONE_LOGIN_STYLE_INVALID, STANDALONE_LOGIN_STYLE_IMAGE_INVALID.
rootobjectNoNoneSettings of the root/ programs: programs.<name> (kind, params schema, run and job limits), stop (the program the executor runs at package stop and upgrade) and state: true (a root-only /volumeN/@synopkgland/<package> kept across upgrades). Needs capabilities.rootOps: true; STANDALONE_ROOT_PROGRAMS_INVALID. The App’s SDK executor must support them; EXECUTOR_ROOT_PROGRAMS_UNSUPPORTED.
uninstallobjectNoNonepurge (exec, args, env, timeout 2–120 s, optional root) runs as the package account on a real uninstall before the executor purge; state.items[].key lists the state the uninstall wizard may delete, each with an uninstall.state.<key> text. UNINSTALL_INVALID.
metadataobjectNoNonePublisher text, links, and screenshots; invalid metadata raises STANDALONE_TEXT_INVALID.
reproducibleobjectNoNoneSettings for build --verify-reproducible: inputs lists dependency files for the fingerprint, clean lists paths removed before the second build (may use {arch}). See reproducible builds; REPRODUCIBLE_INVALID.

Use project-relative paths in the fields below.

RuleValidation error
Path must be a nonempty string.STANDALONE_PATH_INVALID
Path must resolve inside the project and cannot be absolute.STANDALONE_PATH_OUTSIDE_PROJECT

Choose one backend shape.

FieldTypeRequiredDefaultRule and validation error
kindstringYes—go or binary; STANDALONE_BACKEND_INVALID. Unknown backend keys raise the same code.
dirpathFor Go—Source directory; path rules apply. Go API policy in backend/internal/api/permissions.json must be valid; STANDALONE_API_PERMISSIONS_INVALID.
mainstringNo; Go only./cmd/appMatches ^\./[A-Za-z0-9_./-]*$ and contains no ..; STANDALONE_BACKEND_INVALID.
filesmap of architecture to pathFor binary—Exactly the declared architectures; missing entry: STANDALONE_BINARY_ARCH_MISSING; extra entry: STANDALONE_BACKEND_INVALID; path rules apply.
Binary file ruleValidation error
File must exist.STANDALONE_BINARY_MISSING
File must be regular, not a symlink or directory.STANDALONE_BINARY_NOT_REGULAR
Resolved file must stay inside the project.STANDALONE_PATH_OUTSIDE_PROJECT
Maximum size: 256 MiB.STANDALONE_BINARY_TOO_LARGE
Little-endian Linux ELF with the correct bit width.STANDALONE_BINARY_NOT_ELF
ELF machine must match the architecture.STANDALONE_BINARY_ARCH_MISMATCH
Static linking; no dynamic interpreter.STANDALONE_BINARY_DYNAMIC

Build produces the static UI files that the package copies.

FieldTypeRequiredDefaultRule and validation error
dirpathYes—Must contain app.js and app.css at build time; STANDALONE_UI_ENTRY_MISSING; path rules apply.
buildobjectWith identityNonecapabilities.identity requires a build declaration; CAPABILITY_COMBINATION_INVALID.
build.cwdpathWith build—Working directory; path rules apply.
build.commandstring[]With build—Nonempty array of nonempty strings, executed as arguments without a shell; STANDALONE_UI_BUILD_INVALID.

CLI login writes identity; CLI root-ops writes rootOps.

FieldTypeRequiredDefaultRule and validation error
filesstringNoDisabledOnly session; binary rejects this capability with CAPABILITY_UNSUPPORTED. Other values: CAPABILITY_INVALID.
jobsboolean or objectNoDisabledtrue or {worker: sha256-v1}; binary rejects it with CAPABILITY_UNSUPPORTED. Invalid declaration: CAPABILITY_INVALID.
identitystringNoDisabledOnly standalone; requires a UI build declaration (CAPABILITY_COMBINATION_INVALID); binary: CAPABILITY_UNSUPPORTED; other values: CAPABILITY_INVALID.
rootOpsbooleanNoDisabledOnly true; requires valid root/*.sh files. Other values: CAPABILITY_INVALID. Administrator approval is required to run operations.
delegateobjectNoDisabledEnables jobs automatically; invalid policy: CAPABILITY_INVALID; binary: CAPABILITY_UNSUPPORTED. Administrator approval is required.

Use true as shorthand for this worker declaration.

FieldTypeRequiredDefaultRule and validation error
workerstringIn object formsha256-v1 with jobs: trueExactly sha256-v1, with no other object keys; CAPABILITY_INVALID.

Place only fixed operation scripts in root/.

RuleValidation error
At least one script is required when enabled.STANDALONE_ROOT_OPS_MISSING
A root/ directory requires rootOps: true.STANDALONE_ROOT_OPS_UNUSED
Each filename matches ^[a-z][a-z0-9_]{0,31}\.sh$; only regular files, no symlinks.STANDALONE_ROOT_OP_INVALID
Each script is at most 16 KiB and starts with #!/bin/sh followed by a newline; valid UTF-8, no NUL bytes.STANDALONE_ROOT_OP_INVALID
Minimum DSM: 7.1-42661.STANDALONE_OS_MIN_VER_INVALID

init --with delegate and add delegate write {scope: install-selected, operations: [files.moveFromStaging], destinations: [save], lifetime: until-revoked}. This is a CLI-generated declaration, not a parser default.

FieldTypeRequiredDefaultRule and validation error
scopestringYesCLI: install-selectedhome, shared:<name>, or install-selected. Shared names cannot contain slashes, backslashes, control characters, colons, edge whitespace, or equal . / ... install-selected requires until-revoked; CAPABILITY_INVALID.
operationsstring[]YesCLI: [files.moveFromStaging]Nonempty unique list. With until-revoked, exactly [files.moveFromStaging]. Without lifetime and destinations, choose from files.list, files.info, files.createFolder, files.checkPermission, files.write; CAPABILITY_INVALID.
destinationsstring[]With until-revokedCLI: [save]1–64 unique keys matching ^[a-z][a-z0-9_-]{0,63}$; CAPABILITY_INVALID. Omit when lifetime is omitted.
lifetimestringWith destinations or moveFromStagingCLI: until-revokedOnly until-revoked; omit when using the other listed file operations; CAPABILITY_INVALID.

Declare one fixed foreground executable and its architecture-specific payload directories.

FieldTypeRequiredDefaultRule and validation error
execstringYes—Payload-relative path; at most 200 characters, no . / .. segments; first segment uses letters, digits, _, -, later segments also allow .; STANDALONE_DAEMON_INVALID.
targetsmap of architecture to pathYes—Exactly one directory per declared architecture; relative, nonempty, within the project, no .. segments or NUL; STANDALONE_DAEMON_INVALID.
argsstring[]No[]At most 64 strings, each at most 4096 bytes, no NUL; substitutions only ${SYNOPKG_PKGDEST} and ${SYNOPKG_PKGVAR}; STANDALONE_DAEMON_INVALID.
uninstall_argsstring[]NoNoneSame argument rules; must be nonempty if present; runs the fixed executable after stop on uninstall; STANDALONE_DAEMON_INVALID.
envmap of string to stringNo{}At most 64 entries; values use the argument string rules; STANDALONE_DAEMON_INVALID.
env.<name>stringNo—Key matches ^[A-Z][A-Z0-9_]{0,63}$. Rejects PATH, HOME, TMPDIR, ENV, BASH_ENV, SHELLOPTS, BASHOPTS, GODEBUG, GOTRACEBACK, LD_*, DYLD_*, SYNOPKG_*; STANDALONE_DAEMON_INVALID.
timeoutsobjectNo{start: 30, stop: 30, status: 5, uninstall: 60}Only the four keys below; STANDALONE_DAEMON_INVALID.
timeouts.startinteger secondsNo30How long start waits for the daemon to stay up. Range 2–120; STANDALONE_DAEMON_INVALID.
timeouts.stopinteger secondsNo30After SIGTERM, the daemon has stop - 1 seconds before SIGKILL. Range 2–120; STANDALONE_DAEMON_INVALID.
timeouts.statusinteger secondsNo5Range 1–10; STANDALONE_DAEMON_INVALID.
timeouts.uninstallinteger secondsNo60How long uninstall_args may run on uninstall, after the stop, before SIGTERM. Independent of stop. Range 2–120; STANDALONE_DAEMON_INVALID.

Choose the timeouts from what you measure on a loaded NAS, not an idle one. At boot many packages start together, and a busy volume can make a start take more than 5 seconds and a revoke more than 9 seconds. Time start, stop and the uninstall_args command while the NAS is busy (for example during a scrub or a large copy), then allow about twice the slowest time, within the ranges above. A higher value only makes DSM wait longer when something hangs; a daemon that is ready or exits quickly is not slowed down. DSM’s own package unit allows 3600 seconds for start and stop; a separate limit for preuninst is unknown.

Combination or payload ruleValidation error
Jobs may coexist with daemon only with delegate.lifetime: until-revoked.CAPABILITY_COMBINATION_INVALID
Payload directories contain regular files and directories only, stay in the project, have no symlinks or setuid/setgid files, and total at most 512 MiB.STANDALONE_DAEMON_PAYLOAD_INVALID
Executable must pass the binary file rules.Binary errors listed above

Select an existing Shared Folder or create a named one; neither mode deletes the Shared Folder on uninstall.

FieldTypeRequiredDefaultRule and validation error
modestringYes—select or create; STANDALONE_SHARED_FOLDER_INVALID.
keystringYesCLI init: sharedMatches ^[a-z][a-z0-9_]{0,31}$; cannot start with pkgwizard_, synopkg, or change_; STANDALONE_SHARED_FOLDER_INVALID.
namestringWith create only—Matches ^[A-Za-z0-9][A-Za-z0-9_-]{0,31}$; DSM system names such as homes, users, volume1, usbshare1 are refused. Forbidden with select; STANDALONE_SHARED_FOLDER_INVALID.
permissionstringYesCLI init: rwro or rw; select mode needs an administrator to grant the package account this access after installation. Create mode grants it through DSM; STANDALONE_SHARED_FOLDER_INVALID.

Catalog locales and DSM language codes are listed in platforms.

FieldTypeRequiredDefaultRule and validation error
messagespathWith glossaryNoneDirectory of <locale>.json catalogs; path rules apply. Missing English catalog: STANDALONE_I18N_MESSAGES_MISSING; unsupported locale: STANDALONE_I18N_LOCALE_UNSUPPORTED.
glossarypathNoNoneJSON glossary; requires messages (STANDALONE_I18N_INVALID); path rules apply; invalid file: STANDALONE_I18N_GLOSSARY_INVALID.
infomap of locale to objectNo{}Supported locales except en; English uses top-level text. Unknown keys or locale: STANDALONE_I18N_INVALID.
info.<locale>.displaynamestringNoTop-level textSame single-line text rule as displayname; STANDALONE_TEXT_INVALID.
info.<locale>.descriptionstringNoTop-level textSame single-line text rule as description; STANDALONE_TEXT_INVALID.

info also names the app in DSM. With at least one translation the build writes ui/texts/<DSM language>/strings for English and each translated locale and points the main-menu entry and window title at them. A locale without its own displayname or description shows the English text. Without info the title stays the literal English displayname.

Catalog or glossary fieldTypeRequiredDefaultRule and validation error
Catalog message keystringPer message—Flat JSON object; dotted keys match ^[A-Za-z][A-Za-z0-9_-]*(\.[A-Za-z0-9_-]+)*$, values are strings; STANDALONE_I18N_CATALOG_INVALID.
Catalog key setstring keysYesEnglish keysExactly the en.json keys; STANDALONE_I18N_KEYS_MISMATCH.
Catalog placeholders{placeholder} setYesEnglish placeholdersSame placeholders for each translated message; STANDALONE_I18N_PLACEHOLDER_MISMATCH.
termsobject[]Yes in glossary—JSON array; STANDALONE_I18N_GLOSSARY_INVALID.
terms[].idstringYes—Term identifier; STANDALONE_I18N_GLOSSARY_INVALID.
terms[].textmap of locale to stringYes—Supported locales, nonempty text; STANDALONE_I18N_GLOSSARY_INVALID.
terms[].keysstring[]No[]Existing English message keys; STANDALONE_I18N_GLOSSARY_INVALID. Each listed translation must contain its locale’s term, ignoring case; STANDALONE_I18N_GLOSSARY_MISMATCH.

Entry policy supplements your API permissions.

Value or ruleEffect and validation error
admin-onlyOnly administrators can enter. Administrators are the floor of every route, including the routes a capability adds, and the launcher is hidden from other users. A permissions.json route marked authenticated or public raises STANDALONE_ENTRY_WIDENED.
Any other valueSTANDALONE_ENTRY_INVALID.
app-privilegeChecks DSM Application Privileges; requires at least one authenticated route in permissions.json, otherwise STANDALONE_ENTRY_INVALID.
OmittedUses the API permissions policy.
Backend prerequisiteGo backend with the entry gate wired in main.go; missing support or a binary backend raises STANDALONE_ENTRY_UNSUPPORTED.

An empty object enables Application Portal with a generated alias.

FieldTypeRequiredDefaultRule and validation error
aliasstringNoLowercase package ID, or app- plus a stable hash if reserved1–64 lowercase letters, digits, and hyphens; starts and ends with a letter or digit. Unknown portal keys or invalid alias: STANDALONE_PORTAL_INVALID.
Reserved aliasstring——dsfile, indexdb, mobile, oauth, scripts, sharing, ssdp, synosdsjslib, synohdpack, webapi, webman, calendar, chatplus, contacts, drive, file, photo, sso, synologymeet are refused; STANDALONE_PORTAL_INVALID.
Minimum DSMversion/buildYes when enabled—7.1-42661; STANDALONE_PORTAL_MIN_DSM.
ExecutorcapabilityYes when enabled—capabilities.rootOps or capabilities.delegate; STANDALONE_PORTAL_REQUIRES_EXECUTOR.

A portal App carries a DSM login style: Control Panel > Login Portal > Applications shows a thumbnail, and the alias login page gets a wallpaper, a button colour and a title image. Without login_style the CLI uses its neutral default style with the App icon as the title. check and inspect print the style in use.

FieldTypeRequiredDefaultRule and validation error
colorstringNo#2F6BD8#RRGGBB; STANDALONE_LOGIN_STYLE_INVALID.
wallpaperpathNoCLI default wallpaperJPEG inside the project, at least 1920×1080 and at most 2 MiB; set together with wallpaper_thumbnail. STANDALONE_LOGIN_STYLE_IMAGE_INVALID.
wallpaper_thumbnailpathWith wallpaperCLI default thumbnail320×200 JPEG inside the project; STANDALONE_LOGIN_STYLE_IMAGE_INVALID.
titlepathNoApp icon680×124 PNG inside the project; STANDALONE_LOGIN_STYLE_IMAGE_INVALID.

login_style without portal, or any other key: STANDALONE_LOGIN_STYLE_INVALID.

All metadata fields are optional; invalid fields or values raise STANDALONE_TEXT_INVALID.

FieldTypeRequiredDefaultRule and validation error
long_descriptionstring or locale mapNoNoneText rules below; STANDALONE_TEXT_INVALID.
changelogstring or locale mapNoNoneText rules below; English map entry supplies INFO text, or the first entry if English is absent; STANDALONE_TEXT_INVALID.
contact_emailstringNoNoneEmail address with a domain containing a dot, no whitespace; STANDALONE_TEXT_INVALID.
support_emailstringNoNoneSame email rule; supplies a mailto: support link when support_url is absent; STANDALONE_TEXT_INVALID.
homepagestringNoNoneURL rules below; STANDALONE_TEXT_INVALID.
source_urlstringNoNoneURL rules below; STANDALONE_TEXT_INVALID.
issues_urlstringNoNoneURL rules below; STANDALONE_TEXT_INVALID.
licensestringNoNoneText rules below; STANDALONE_TEXT_INVALID.
maintainer_urlstringNoNoneURL rules below; STANDALONE_TEXT_INVALID.
distributorstringNoNoneText rules below; STANDALONE_TEXT_INVALID.
distributor_urlstringNoNoneURL rules below; STANDALONE_TEXT_INVALID.
support_urlstringNoNoneHTTP(S) URL or valid mailto: address; STANDALONE_TEXT_INVALID.
helpurlstringNoNoneURL rules below; STANDALONE_TEXT_INVALID.
screenshotsstring[]NoNoneAt most 12 HTTP(S) URLs; STANDALONE_TEXT_INVALID.
Metadata ruleLimit and validation error
Text valuesAt most 16,000 characters; no control characters except tab, newline, and carriage return; STANDALONE_TEXT_INVALID.
Locale mapsAt most 32 entries; keys match ^[a-z]{2}(-[A-Za-z]{2})?$; values use the text rules; STANDALONE_TEXT_INVALID.
URLsHTTP(S), at most 2048 characters, no username or password; STANDALONE_TEXT_INVALID.
Entire objectJSON representation at most 32,000 characters; unknown keys are refused; STANDALONE_TEXT_INVALID.