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:
| Scenario | User | Description | Configuration 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 thepreinstscript 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:
| Scenario | User | Description |
|---|---|---|
| Non-root | UID:GID (e.g., 1000:1000) | Must be used. Specified via the user field in compose. |
File System Permissions
Standard Directory Permissions for Deb Applications:
| Path | Owner | Permissions | Description |
|---|---|---|---|
/Volume*/@apps/<appid>/ | <appid>:<appid> | 755 | Application directory (service read-only) |
/Volume*/@apps/<appid>/bin/ | <appid>:<appid> | 755 | Executables |
/Volume*/@apps/<appid>/config/ | <appid>:<appid> | 750 | Configuration files (read-only for service) |
/Volume*/@apps/<appid>/site/ | <appid>:<appid> | 755 | Web UI files |
/Volume*/@apps/<appid>/data/ | <appid>:<appid> | 750 | Runtime data (read-write) |
/Volume*/@apps/<appid>/logs/ | <appid>:<appid> | 750 | Application 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
| Permission | Deb Applications | Docker Applications | Description |
|---|---|---|---|
| Bind Port | Bind specified port in service config | Map port in compose | Must not conflict with system ports |
| Access Local Services | Allowed by default | Use network_mode: host or explicit linking | Minimize network exposure |
| Outbound Connections | Allowed | Allowed | Outbound is unrestricted |
Shared Folder Access
TOS shared folders are the primary data access mechanism. Applications requiring access to user data must:
- Create a shared folder via
ter_share_add:
ter_share_add -name <appid>-data -owner <appid>
- Or request access to existing shared folders by joining the
allusersgroup:
usermod -aG allusers <appid>
- Docker applications mount shared folders via volumes:
Volumes:
- /Volume*/<shared_folder>:/data:rw # Read-write access
- /Volume*/<shared_folder>:/media:ro # Read-only access
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:
-
Dedicated Application Folder (Recommended):
- Create via
ter_share_addin postinst - Application has full read-write permissions
- No user authorization required
- Create via
-
User Shared Folders (Authorization Required):
- Application requests
allusersgroup membership - User authorizes folder access through TOS shared folder settings
- Application declares read-only or read-write requirements in the permission declaration
- Application requests
-
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 Type | CPU Limit | Memory Limit | Examples |
|---|---|---|---|
| Media Server | 200% (2 cores) | 2048M | Jellyfin, Plex, Emby |
| Download Manager | 100% (1 core) | 512M | Aria2, qBittorrent |
| Utilities | 50% | 256M | File Manager, Text Editor |
| Web Service | 100% (1 core) | 512M | CMS, Blog, Wiki |
| Database | 200% (2 cores) | 2048M | MySQL, PostgreSQL, Redis |
| Security | 50% | 256M | Firewall, 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:
| Permission | Justification |
|---|---|
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: None | No user data access required |
Permission Red Lines (Automatic Rejection)
The following permission requests will result in automatic rejection:
| Violation | Description |
|---|---|
| Root Execution | Requesting 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 Mode | Requesting --privileged Docker mode |
| System Directory Write | Requesting write access to system directories such as /etc/, /usr/, /boot/ |
| Cross-App Data Access | Requesting access to other applications' data directories |
| Unrestricted Network Access | Requesting network_mode: host without written reasonable justification (only available to system-level network tools) |
| Excessive Port Exposure | Requesting more ports than functionally required |