Skip to main content

Permission Model

SPC Overview

TOS 7 introduces the SPC (System Permission Control) system, which follows the principle of least privilege and governs application system access behavior:

  • Applications cannot directly modify system files or obtain root privileges; all permission requests must be submitted through platform APIs
  • Developers must clearly specify application permission requirements in the permission declaration. Applications can only obtain corresponding access permissions after platform approval.
  • Any behavior that bypasses SPC permission checks is prohibited; such applications will fail review or be delisted.

Overview

TOS7 follows the Principle of Least Privilege. Applications can only request the minimum permissions necessary for operation. TOS7 applications interact with the SPC (System Permission Control) system. Applications must:

  • Declare permission requirements in the permission declaration (Section 10.7)
  • Not bypass SPC permission checks
  • Use platform APIs for permission requests instead of directly modifying system files

The platform provides a structured permission model for both Deb and Docker applications.

User and Group Model

Root permissions for application users are strictly prohibited. All applications must run as a dedicated non-root user.

Deb Applications:

ScenarioUserDescriptionConfiguration Requirement
Dedicated User<appid>Must be used. Created by preinst script. Minimal permissions.Mandatory

Mandatory Requirement: All Deb applications must create a dedicated user (<appid>) and run the application as that user. Running as root is strictly prohibited. The dedicated user must be created in the preinst script to ensure minimal permissions at runtime. Application data directories (such as /Volume*/@apps/<appid>/) must be owned by the dedicated user to avoid permission errors or unauthorized access.

Creating a Dedicated User:

# In preinst
# The system will automatically assign a unique UID to the new user.
useradd --system --no-create-home --shell /usr/sbin/nologin <appid>

Docker Applications:

ScenarioUserDescription
Non-rootUID:GID (e.g., 1000:1000)Must be used. Specified via the user field in compose.

File System Permissions

Standard Directory Permissions for Deb Applications:

PathOwnerPermissionsDescription
/Volume*/@apps/<appid>/<appid>:<appid>755Application directory (service read-only)
/Volume*/@apps/<appid>/bin/<appid>:<appid>755Executables
/Volume*/@apps/<appid>/config/<appid>:<appid>750Configuration files (read-only for service)
/Volume*/@apps/<appid>/site/<appid>:<appid>755Web UI files
/Volume*/@apps/<appid>/data/<appid>:<appid>750Runtime data (read-write)
/Volume*/@apps/<appid>/logs/<appid>:<appid>750Application logs (read-write)

Note 1: * in /Volume*/ represents the volume number (e.g., Volume1, Volume2) chosen by the user during installation.

Note 2: Application binaries and configuration should be read-only for the service user. Only data and log directories should be writable.

Note 3: Data Types

  • Runtime data (/Volume*/@apps/<appid>/data/) — Application-generated caches, temporary files, and runtime state. This data is managed by the application and can be safely regenerated.
  • User data (shared folder created via ter_share_add) — Persistent business data (documents, photos, databases). This data must be stored in a shared folder under /Volume*/ to allow user access via SMB/NFS.

Network Permissions

PermissionDeb ApplicationsDocker ApplicationsDescription
Bind PortBind specified port in service configMap port in composeMust not conflict with system ports
Access Local ServicesAllowed by defaultUse network_mode: host or explicit linkingMinimize network exposure
Outbound ConnectionsAllowedAllowedOutbound is unrestricted

Shared Folder Access

TOS shared folders are the primary data access mechanism. Applications requiring access to user data must:

  1. Create a shared folder via ter_share_add:
ter_share_add -name <appid>-data -owner <appid>
  1. Or request access to existing shared folders by joining the allusers group:
usermod -aG allusers <appid>
  1. Docker applications mount shared folders via volumes:
Volumes:
- /Volume*/<shared_folder>:/data:rw # Read-write access
- /Volume*/<shared_folder>:/media:ro # Read-only access
Important

Applications must not directly modify shared folder permissions. Use the TOS shared folder management API or let users manually configure access permissions.

Permission Request Process

When an application requires access to shared folders:

  1. Dedicated Application Folder (Recommended):

    • Create via ter_share_add in postinst
    • Application has full read-write permissions
    • No user authorization required
  2. User Shared Folders (Authorization Required):

    • Application requests allusers group membership
    • User authorizes folder access through TOS shared folder settings
    • Application declares read-only or read-write requirements in the permission declaration
  3. Permission Format:

    # Docker volumes
    - /Volume*/<shared_folder>:/data:rw # Read-write access
    - /Volume*/<shared_folder>:/media:ro # Read-only access

System Resource Limits

Application Installation Path

Third-party applications are completely installed on storage volumes (data disks) at /Volume*/@apps/<appid>/, not on the system disk (/).

  • * represents the volume number (e.g., Volume1, Volume2, etc.) chosen by the user during installation.
  • All application files — including binaries, configuration files, logs, scripts, and web UI files — are stored under /Volume*/@apps/<appid>/.
  • Only a lightweight registration/entry record (used by TOS to recognize installed applications) resides on the system disk. This record occupies negligible space and does not pose any capacity concern.
  • Only system-built-in applications reside on the system disk (/usr/local/system_app_data/).

For third-party developers: Since your entire application (including program files, configs, and logs) is installed on the data disk, system disk capacity is not a concern for your app. All business data should also be stored on data disks (/Volume*/), which have no capacity limits.

Default Resource Quotas by Application Type:

Application TypeCPU LimitMemory LimitExamples
Media Server200% (2 cores)2048MJellyfin, Plex, Emby
Download Manager100% (1 core)512MAria2, qBittorrent
Utilities50%256MFile Manager, Text Editor
Web Service100% (1 core)512MCMS, Blog, Wiki
Database200% (2 cores)2048MMySQL, PostgreSQL, Redis
Security50%256MFirewall, Antivirus

The above are platform defaults. Developers may request higher limits in the permission declaration with reasonable justification.

Deb Applications (via systemd):

[Service]
# Memory limit
MemoryMax=512M
# CPU quota (200% = 2 cores)
CPUQuota=200%
# File descriptor limit
LimitNOFILE=65536
# Process count limit
LimitNPROC=256

Docker Applications (via compose):

services:
myapp:
deploy:
resources:
limits:
cpus: '2.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 128M

Permission Declaration

📝 Note: The following table is an example showing how to document your application's permission requirements. Replace the values (port numbers, file paths, usernames) with those actually used by your application.

For transparency, applications should document their permission requirements in README.md:

PermissionJustification
Network: Port <your-port>Web UI access
File System: <your-data-path>Runtime data storage
User: <your-appid> (system user)Isolated service execution
Shared Folder: NoneNo user data access required

Permission Red Lines (Automatic Rejection)

The following permission requests will result in automatic rejection:

ViolationDescription
Root ExecutionRequesting root user to run the application (including setting User=root in systemd service files, and not specifying the user field in Docker, which defaults to running as root)
Privileged ModeRequesting --privileged Docker mode
System Directory WriteRequesting write access to system directories such as /etc/, /usr/, /boot/
Cross-App Data AccessRequesting access to other applications' data directories
Unrestricted Network AccessRequesting network_mode: host without written reasonable justification (only available to system-level network tools)
Excessive Port ExposureRequesting more ports than functionally required