Skip to main content
Version: TOS 7

权限模型

SPC(系统权限控制)概述​

TOS 7 引入 SPC(System Permission Control,系统权限控制) 系统,遵循最小权限原则,对应用的系统访问行为进行管控:

  • 应用无法直接修改系统文件或获取 root 权限,所有权限请求需通过平台 API 提交
  • 开发者需在权限声明中明确应用的权限需求,应用只有经平台审核通过后才能获得对应的访问权限
  • 禁止任何绕过 SPC 权限检查的行为,此类应用将无法通过审核或被下架

概述​

TOS7 遵循 最小权限原则。应用只能请求运行所必需的最小权限。TOS7 应用与 SPC(系统权限控制) 系统交互。应用必须:

  • 在权限声明(第 8 节)中声明权限需求
  • 不得绕过 SPC 权限检查
  • 使用平台 API 进行权限请求,而不是直接修改系统文件

平台为 Deb 和 Docker 应用提供结构化的权限模型。

用户与用户组模型​

严禁应用用户使用 root 权限。所有应用必须以非 root 专属用户运行。

Deb 应用:

场景用户说明配置要求
专属用户<appid>必须使用。平台在安装时自动创建该用户(非 root 权限)并分配 UID。强制

强制要求: 所有 Deb 应用必须将 config.ini 中的 user 字段设置为专属用户名(如 <appid>)。平台会在安装时创建对应的系统用户,应用以该用户权限运行,严禁使用 root 权限。

重要: 开发者不得在生命周期脚本(如 preinst)中手动创建该用户。开发者在这方面的唯一职责是:在 config.ini 中设置用户名,并确保它与 systemd 服务文件中的 User= 字段一致。

Docker 应用:

场景用户说明
非 rootUID:GID(如 1000:1000)必须使用。在 compose 中通过 user 字段指定。

文件系统权限​

Deb 应用的标准目录权限:

路径归属权限说明
/usr/local/<appid>/<appid>:<appid>755应用目录(服务只读)
/usr/local/<appid>/bin/<appid>:<appid>755可执行文件
/usr/local/<appid>/config/<appid>:<appid>750配置文件(服务只读)
/usr/local/<appid>/site/<appid>:<appid>755Web UI 文件
/usr/local/<appid>/data/<appid>:<appid>750运行时数据(读写)
/usr/local/<appid>/logs/<appid>:<appid>750应用日志(读写)

注意 1: 上述路径为你的应用所使用的路径。安装后,平台会将 /usr/local/<appid>/ 映射到用户所选卷上,该同一目录在物理上位于 /Volume<N>/@apps/<appid>/。* 是代表该卷号的文档记法(例如 Volume1、Volume2)—— 平台不会展开它,因此严禁将 /Volume*/… 写入 docker-compose.yml、systemd unit、生命周期脚本或任何会被机器读取的配置。
注意 2: 应用二进制和配置文件对服务用户应为只读。只有数据和日志目录应为可写。
注意 3:数据类型

  • 运行时数据(/usr/local/<appid>/data/)—— 应用生成的缓存、临时文件和运行时状态。此数据由应用管理,可安全重新生成。
  • 用户数据 —— 持久化的业务数据(文档、照片、数据库)。
    • Deb 应用:将其存储在通过 ter_share_add 创建的共享文件夹中,以便用户通过 SMB/NFS 访问。
    • Docker 应用:不使用共享文件夹。其持久化业务数据保存在容器的卷挂载中,平台会将其解析到 /Volume<N>/DockerAppData/<appid>/(参见第 6 节)。

网络权限​

权限Deb 应用Docker 应用说明
绑定端口在服务配置中绑定指定端口在 compose 中映射端口不得与系统端口冲突
访问本地服务默认允许使用 network_mode: host 或显式链接尽量减少网络暴露
出站连接允许允许出站无限制

共享文件夹访问​

适用范围: 本节仅适用于 Deb 应用。Docker 应用不参与 TNAS 共享文件夹机制:平台不会为其创建共享文件夹,它们不得调用 ter_share_add 或声明 share_folders,其所有持久化业务数据都存储在容器的卷挂载中,平台会将其解析到应用数据根目录 /Volume<N>/DockerAppData/<appid>/(参见第 9 章第 3 节与第 12.2 节)。

TNAS 共享文件夹是 Deb 应用主要的数据访问机制。需要访问用户数据的应用必须:

  1. 创建共享文件夹,通过 ter_share_add:
ter_share_add -name <appid>-data -owner <appid>
  1. 或请求访问现有共享文件夹,通过加入 allusers 组:
usermod -aG allusers <appid>

Docker 应用: 它们不使用共享文件夹。其持久化业务数据存储在容器的卷挂载中,平台会将其解析到 /Volume<N>/DockerAppData/<appid>/(参见第 12.2 节)。Docker 包中不得包含共享文件夹挂载项或 ter_share_add 调用。

重要

应用不得直接修改共享文件夹权限。使用 TOS 共享文件夹管理 API 或让用户手动配置访问权限。

权限请求流程​

当 Deb 应用需要访问共享文件夹时:

  1. 专用应用文件夹(推荐):

    • 在 postinst 中通过 ter_share_add 创建
    • 应用拥有完整的读写权限
    • 无需用户授权
  2. 用户共享文件夹(需要授权):

    • 应用请求 allusers 组成员资格
    • 用户通过 TOS 共享文件夹设置授权文件夹访问
    • 应用在权限声明中注明只读或读写需求
  3. 声明格式:共享文件夹及其访问模式在 README 权限表中声明(参见第 8 节),例如 共享文件夹:<文件夹名称>(只读)。Docker 应用始终声明 共享文件夹:无 —— 它们不使用共享文件夹。

系统资源限制​

应用安装路径

第三方应用完整安装在 存储卷(数据盘)上,而不是系统盘(/)。你的应用通过逻辑路径 /usr/local/<appid>/ 使用该位置;平台会将其解析到用户安装时选择的卷上的 /Volume<N>/@apps/<appid>/。

  • * 仅为文档记法,代表用户安装时选择的卷号(例如 Volume1、Volume2)。平台不会展开它 —— 严禁将 /Volume*/… 写入 docker-compose.yml、systemd unit、生命周期脚本或任何会被机器读取的配置。
  • 所有应用文件——包括二进制文件、配置文件、日志、脚本和 Web UI 文件——均存放在应用目录中,你的应用看到的是 /usr/local/<appid>/。
  • 系统盘上仅保留轻量级的 注册/入口记录(用于 TOS 识别已安装的应用)。此记录占用空间可忽略不计,不构成任何容量问题。
  • 只有系统内置应用才驻留在系统盘(/usr/local/system_app_data/)上。

对第三方开发者而言: 由于整个应用(包括程序文件、配置和日志)安装在数据盘上,系统盘容量对您的应用不是问题。所有业务数据也应存储在数据盘(/Volume*/)上,数据盘没有容量限制。

按应用类型的默认资源配额:

应用类型CPU 限制内存限制示例
媒体服务器200%(2 核)2048MJellyfin, Plex, Emby
下载管理器100%(1 核)512MAria2, qBittorrent
实用工具50%256M文件管理器, 文本编辑器
Web 服务100%(1 核)512MCMS, 博客, Wiki
数据库200%(2 核)2048MMySQL, PostgreSQL, Redis
安全类50%256M防火墙, 杀毒软件

以上为平台默认值。开发者可在权限声明中附合理理由申请更高的限制。

Deb 应用(通过 systemd):

[Service]
# 内存限制
MemoryMax=512M
# CPU 配额(200% = 2 核)
CPUQuota=200%
# 文件描述符限制
LimitNOFILE=65536
# 进程数限制
LimitNPROC=256

Docker 应用(通过 compose):

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

权限声明​

注意: 下表是一个 示例,展示如何记录应用的权限需求。请将表中的值(端口号、文件路径、用户名)替换为应用实际使用的值。

为保持透明,应用应在 README.md 中记录其权限需求:

权限理由
网络:端口 <你的端口>Web UI 访问
文件系统:<你的数据路径>运行时数据存储
用户:<你的 appid>(系统用户)隔离的服务执行
共享文件夹:无不需要用户数据访问

Docker 应用始终声明 共享文件夹:无:它们不创建也不挂载任何 TNAS 共享文件夹,其所有持久化数据都存储在应用数据根目录 /Volume<N>/DockerAppData/<appid>/ 中。

权限红线(自动驳回)​

以下权限请求将导致 自动驳回:

违规行为说明
Root 执行请求 root 用户运行应用(包括在 systemd 服务文件中设置 User=root,以及在 Docker 中不指定 user 字段(默认以 root 运行)两种情况)
特权模式请求 --privileged Docker 模式
系统目录写入请求写入 /etc/、/usr/、/boot/ 等系统目录
跨应用数据访问请求访问其他应用的数据目录
无限制网络访问未提供书面合理理由而申请 network_mode: host(仅系统级网络工具可申请)
过多端口暴露请求超过功能所需的端口数量