Hoppa till huvudinnehållet
Version: TOS 7

Package Specification

This section defines the formal specifications for TOS 7 application packages. All applications must comply with this specification.

Application Lifecycle​

TOS 7 applications follow a clearly defined lifecycle:

  Install ──► Configure ──► Start ──► Running
│ │ │ │
│ │ │ ├── Stop ──► Stopped ──► Start (Restart)
│ │ │
│ │ └── Crash ──► Auto-restart (if configured)
│ │
│ └── Upgrade ──► Stop ──► Install New Version ──► Migrate ──► Start
│
└── Uninstall ──► Stop ──► Cleanup ──► Remove

Deb Application Lifecycle Stages:

StageTriggerScript/OperationExpected Behavior
Before Installdpkg -iDEBIAN/preinstCreate user, check prerequisites, create directories
Installdpkg -iPackage extractionFiles deployed according to the packaging specification (see Chapter 8); the application sees the directory as /usr/local/<appid>/, and the platform resolves it to /Volume<N>/@apps/<appid>/ on the user-selected data volume
After Installdpkg -iDEBIAN/postinstSet permissions, enable service, start service
Startsystemctl startsystemd / init.dApplication process starts
Stopsystemctl stopsystemd / init.dApplication process gracefully stops
Before Uninstalldpkg --removeDEBIAN/prermStop service
After Uninstalldpkg --removeDEBIAN/postrmClean up user, data, residual files
Upgradedpkg -i (new version)prerm → Upgrade → postinstStop old version, install new version, migrate data, start

Docker Application Lifecycle Stages:

StageTriggerOperationExpected BehaviorAdditional Notes
InstallApp Center (user clicks "Install" button)Pull image, create volumesImage available, data directories createdPlatform automatically executes the installation process; no additional developer intervention required
StartApp Center (user clicks "Start" button) / docker-compose upStart containerService accessibleUsers can also manually start via command line, consistent with platform operation logic
StopApp Center (user clicks "Stop" button) / docker-compose downStop containerService stopped, data retainedOnly stops the container process; mounted data volumes are not deleted
UpgradeApp Center (user clicks "Update" button when a new version is available)Pull new image, rebuild containerZero-downtime or brief downtimeIt is recommended that applications support smooth upgrades to avoid data interruption
UninstallApp Center (user clicks "Uninstall" button)Remove container, optionally clean up volumesAll resources releasedUsers can choose whether to retain data volumes to avoid accidental data deletion

Note: "App Center" refers to the built-in application management interface of the TOS system. Install/start/stop/upgrade/uninstall operations performed by users through this interface will trigger the corresponding lifecycle processes. In the current TOS version, upgrade is not supported for Docker applications — to move a Docker application to a new version, users must uninstall and then reinstall it (see Chapter 9 · Docker Development).

Version Number Specification​

Platform behaviour (current): The Developer Platform does not validate the version number. Non-standard formats, duplicate versions, and version numbers that do not increase are not rejected. The platform simply reads the version field from config.ini and displays it in the App Center. The rules below are therefore recommendations for compatibility, not submission requirements.

Why the format still matters — update detection:

The TOS App Center currently determines whether an update is available by comparing version numbers numerically, segment by segment. This is a functional dependency rather than a submission rule:

  • If the new version is numerically greater than the installed one, users see the update prompt.
  • If it is not greater (equal, lower, or not numerically comparable such as v2 or 1.0.0-rc1), the update may not be detected — the package is still accepted, but it may never reach existing users.

Recommended format:

RuleDescription
CharactersDigits (0-9) and dots (.) are recommended. Letters and hyphens (e.g. v1.2, 1.2.3-beta) cannot be compared numerically and may break update detection
Segments1 to 3 numeric segments (e.g., 1, 1.2, 1.2.3)
Segment lengthNo per-segment length limit; each segment can contain any number of digits
Total lengthNo length limit is enforced. Keeping the version string short (the previous limit was 20 characters) is still recommended
Beta versionsUse the "beta": true field in config.ini to mark beta releases. Suffixes such as -beta / -rc / -alpha are not rejected, but they break numeric comparison

Version ordering (comparison rules):

Versions are compared segment-by-segment as numbers, from left to right:

RuleDescription
Numeric comparisonEach segment is compared as an integer (leading zeros are ignored, e.g., 01.2 equals 1.2)
Missing segmentsMissing segments are treated as 0 (e.g., 1.2 equals 1.2.0; 1 equals 1.0.0)
Comparison resultThe first segment where values differ determines the order

Version consistency across files:

The platform does not compare the version numbers inside a package against each other, and it does not require them to match. The version is read from config.ini.

LocationFieldRead by
config.iniversionThe Developer Platform and the TOS App Center — this is the version displayed to users
DEBIAN/control (Deb apps only)VersionThe Debian package manager (dpkg) — this is the version recorded by the system
  • Still recommended: keep them consistent. A mismatch causes no rejection, but it does cause a confusing installation — users would see one version in the App Center while dpkg -l reports another, which complicates upgrades and support.
  • Keep DEBIAN/control Version non-decreasing. At the dpkg level, installing a package whose Version is lower than the installed one is refused (downgrade protection). This is package-manager behaviour and is independent of the Developer Platform.
  • Version source: the version is not entered manually on the Developer Platform, and the GitHub/Gitee Release tag is not used to determine it — it always comes from the version field inside the package you select.
  • Rollback: the platform does not roll an application back to a smaller version number automatically. If a rollback is needed, submit a rollback request on the Developer Platform (see Chapter 17).

Beta Version Management:

Beta status is controlled by the beta flag in config.ini, not by the version string:

Release Typeconfig.ini EntryPlatform Display
First beta"version": "1.0.0", "beta": true1.0.0 (Beta)
Second beta"version": "1.0.1", "beta": true1.0.1 (Beta)
Stable release"version": "1.0.2", "beta": false1.0.2
  • Version suffixes such as -beta, -rc, or -alpha are not rejected, but they break numeric comparison. Use the "beta": true field instead so beta builds are still recognised as new versions by beta users.
  • Multiple beta versions are distinguished by increasing the numeric part (recommended: increment the patch segment).
  • When promoting a beta to stable, set "beta": false. The version number can remain unchanged; if you do increase it, beta users are also offered the update.
  • A stable release whose version number is lower than a previously submitted beta build will not be offered to users still on that beta build as an update.
  • See Appendix M - Beta App Management for details

Release Asset Naming Specification​

When uploading application packages to GitHub/Gitee Releases, use the recommended names below. What the platform actually relies on is the file extension: a .deb file is treated as a single Deb package, and a .tar.gz archive as a dual-package Deb archive or a Docker package (matching the application type you declared when creating the application).

Important

The platform does not validate the package file name and no longer checks <app_id> or <platform> against it. The version is read from the version field inside config.ini; it does not need to appear in the file name, and the file name is no longer matched against any version. Package identity is verified after the download and parsing, by comparing config.ini (id, platform, and package type) with the application information you entered on the Developer Platform.

Application TypePackage FormatRecommended NameExample
Deb (Single Package).deb file<app_id>_<platform>.debmyapp_x86_64.deb
Deb (Dual Package).tar.gz archive<app_id>_<platform>.tar.gzmyapp_x86_64.tar.gz
Docker Application.tar.gz archive<app_id>.tar.gzmyapp.tar.gz

Field Definitions (recommended, not enforced):

  • <app_id>: Recommended to match the id field in config.ini (case-sensitive)
  • <platform>: Recommended to match the platform field in config.ini and be one of the two supported values (x86_64 or aarch64). It does not accept multiple values or all. For multi-architecture support, each target architecture must be submitted as a separate build. The platform does not read the architecture from the file name — it verifies the architecture after parsing the package.

Release tag: the GitHub/Gitee Release tag is not used to determine the version and does not have to match config.ini.version. Any tag is accepted; naming it after the version (e.g. v1.0.0 or 1.0.0) is recommended for readability only.

Upgrades​

Deb Application Upgrades:

  • During upgrade, preinst receives $1 = "upgrade" parameter
  • postinst receives $1 = "configure" parameter, with $2 being the old version number
  • Use $2 to detect the old version and perform data migration
  • Never delete user data during the upgrade process; only modify configuration formats or migrate data structures
  • Users store persistent business data in the /Volume<N>/<appid>/ shared folder, which is created by the application via ter_share_add. The platform will not delete or overwrite user data in this shared folder during application upgrades or reinstallation
  • Runtime data (caches, temporary files) is stored in /usr/local/<appid>/data/ and can be safely regenerated
  • It is recommended not to store data in system common directories such as /etc, /var, /usr/bin, as these directories may be overwritten by system updates or application upgrades, leading to data loss
# Example: postinst with migration logic
case "$1" in
configure)
if [ -n "$2" ]; then
# Upgrading from version $2
if dpkg --compare-versions "$2" lt "2.0.0"; then
# Migrate v1.x configuration format to v2.x
/usr/local/<appid>/bin/migrate.sh "$2"
fi
else
# Fresh install
echo "Fresh install"
fi
;;
esac

Docker Application Upgrades:

  • Pull new image tags
  • Rebuild containers using existing volume mounts
  • Preserve data across upgrades through persistent volumes (the platform resolves them to the application data root /Volume<N>/DockerAppData/<appid>/)
  • Include migration logic in the application entry script if needed
  • Docker applications do not use TNAS shared folders: no shared folder is created for them, and all persistent business data stays in the container's volume mounts

Compatibility Matrix​

TOS VersionBase SystemglibcPython3DockerNode.js
TOS 7.0Ubuntu 22.04-compatible2.353.1020.10+18.x
TOS 7.xUbuntu 22.04-compatible2.353.1020.10+ (or higher)18.x (or higher)
Note

Node.js versions are for reference within Docker containers only. Deb applications must not directly depend on them.

Important

Applications must declare the minimum TOS version requirement via the low_version field in config.ini. The platform will automatically filter out incompatible devices.

TOS 7.x Minor Version Compatibility: The TOS 7.x minor version series (including 7.1 and above) will maintain ABI/API compatibility for core dependencies (glibc/Python3/Docker/Node.js), compatible with the Ubuntu 22.04-compatible root filesystem. Applications developed for TOS 7.0 will run without additional adaptation.

TOS 7 Minor Version Compatibility:

  • The low_version field must specify the minimum required TOS version
  • When submitting updates, test on the latest TOS 7 minor version

Case Sensitivity Specification​

TOS employs a root filesystem compatible with Ubuntu Linux, and the filesystem is strictly case-sensitive. All applications must follow the rules below:

ElementRule
FilenamesStrictly match case. config.ini ≠ Config.ini ≠ CONFIG.INI
Directory namesStrictly match case. /images/icons/ ≠ /Images/Icons/
config.ini key namesAll key names must be lowercase. "version" correct, "Version" incorrect
Application ID (id)Strictly match case. MyApp ≠ myapp. Cannot be modified after creation
Systemd service nameMust strictly match, case-sensitive
Prohibited

Using case variants of the same file or directory within a single application package. This causes "file not found" and "service start failure" errors on Linux.


Cross-Platform Line Ending Specification (CRLF to LF)​

All scripts and configuration files running on the TOS system (Linux environment) must use LF (\n) as the line ending. Using Windows default CRLF (\r\n) line endings is prohibited.

Impact​

  • Script execution errors: bad interpreter: No such file or directory
  • Configuration file parsing failures (e.g., systemd service files, Nginx configurations)
  • Interpreter paths incorrectly recognized as non-existent binaries like /bin/bash\r

Mandatory Requirements​

  1. All .sh / .py / .ini / .lang / .service / .conf files must be converted to LF line endings before submission
  2. Deb package build scripts must include automatic conversion logic to prevent CRLF from being introduced during the build process
import os

def convert_crlf_to_lf(file_path):
with open(file_path, "rb") as f:
content = f.read()
content = content.replace(b"\r\n", b"\n")
with open(file_path, "wb") as f:
f.write(content)

# Before packaging, iterate over all files that need conversion
for root, _, files in os.walk("your_app_source/"):
for name in files:
if name.endswith((".sh", ".py", ".ini", ".lang", ".service", ".conf")):
convert_crlf_to_lf(os.path.join(root, name))

Option 2: Local Development Tool Configuration​

  • VS Code: Click CRLF in the bottom-right status bar, switch to LF, then save
  • Git Global Configuration (prevent subsequent files from being auto-converted to CRLF):
git config --global core.autocrlf input