Seafile 支持为不同资料库分配不同的存储后端。例如,可以将日常使用的资料库存储在本地磁盘或 SSD 上,将归档资料库存储在其他存储系统中;也可以通过多个存储后端分担数据量,降低单一 NFS 卷或 S3 存储桶的容量、性能压力。
多存储后端以
资料库
为单位分配存储位置。一个资料库关联一个存储类(storage class),其存储类与资料库之间的映射关系保存在数据库中。同一存储类中的
commits
、
fs
和
blocks
可以分别使用文件系统、S3、Swift 或 Ceph 等存储方式。
配置多存储后端需要完成以下操作:
-
在 .env 中启用多存储后端模式。
-
在 seafile.conf 中指定存储类配置文件。
-
在 JSON 文件中定义存储类。
-
在 seahub_settings.py 中启用存储类,并选择资料库映射策略。
以下以 Docker 部署为例。Seafile 14.0 和 13.0 均可使用此配置方式;如果自定义过数据卷或使用非 Docker 部署,请按照实际目录调整路径。
启用多存储后端
1. 设置环境变量
打开 Seafile 的
.env
文件(默认位于
/opt/seafile/.env
),设置:
SEAF_SERVER_STORAGE_TYPE=multiple
不要将其设置为
s3
或
disk
,否则不能按照下文的存储类配置使用多个存储后端。
2. 创建存储类配置文件
建议将存储类文件与 Seafile 的其他配置文件放在同一持久化目录中。在默认 Docker 部署中,宿主机的配置文件目录为:
/opt/seafile-data/seafile/conf/
创建文件:
nano /opt/seafile-data/seafile/conf/seafile_storage_classes.json
按照下文的示例填写存储类定义。注意,JSON 文件中不能包含注释。
路径说明:
默认 Docker 数据卷将宿主机的
/opt/seafile-data
挂载为容器内的
/shared
,因此上面的文件在容器内对应:
/shared/seafile/conf/seafile_storage_classes.json
如果修改过数据卷映射,请使用容器
实际可访问的绝对路径
。可通过以下命令检查文件是否已经映射到容器中:
docker exec seafile ls -l /shared/seafile/conf/seafile_storage_classes.json
3. 修改
seafile.conf
打开宿主机上的配置文件:
nano /opt/seafile-data/seafile/conf/seafile.conf
添加或更新
[storage]
配置段:
[storage]
enable_storage_classes = true
storage_classes_file = /shared/seafile/conf/seafile_storage_classes.json
配置项
说明
enable_storage_classes
设置为
true
,启用存储类功能。
storage_classes_file
存储类 JSON 文件在
Seafile 运行环境(容器)内
的绝对路径。
确保已为 Seafile 配置缓存服务。使用默认 Docker 部署时,Redis 已集成到 Seafile 13.0 和 14.0 的部署配置中;如果使用外部缓存或非 Docker 部署,请检查缓存配置。相关参数请参阅
Seafile 配置项
。
定义存储类
存储类在
seafile_storage_classes.json
文件中定义。文件内容是一个 JSON 数组,每个对象代表一个存储类。
字段
说明
storage_id
存储类的唯一内部标识,不向普通用户显示。已投入使用的标识不应随意修改。
name
用户可见的存储类名称。
is_default
是否为默认存储类。通常应有一个适用的默认存储类。
commits
存放 commit 对象的后端配置。
fs
存放文件系统元数据(fs 对象)的后端配置。
blocks
存放文件块(block 对象)的后端配置。
is_default
主要在以下情况下生效:
-
使用用户选择策略时,如果用户未选择可用存储类,资料库使用默认存储类。
-
对于其他映射策略,在启用多存储后端前创建、尚无存储类映射记录的资料库,使用默认存储类。
存储类配置示例
以下示例定义四个存储类,分别使用 S3、本地文件系统、Swift 和 Ceph。
只保留实际使用的存储类
,并替换密钥、存储桶、容器路径及其他占位符。
[
{
"storage_id": "hot_storage",
"name": "Hot Storage",
"is_default": true,
"commits": {
"backend": "s3",
"bucket": "seafile-commits",
"key_id": "<your-key-id>",
"key": "<your-secret-key>"
},
"fs": {
"backend": "s3",
"bucket": "seafile-fs",
"key_id": "<your-key-id>",
"key": "<your-secret-key>"
},
"blocks": {
"backend": "s3",
"bucket": "seafile-blocks",
"key_id": "<your-key-id>",
"key": "<your-secret-key>"
}
},
{
"storage_id": "cold_storage",
"name": "Cold Storage",
"is_default": false,
"commits": {
"backend": "fs",
"dir": "/storage/seafile/cold-data"
},
"fs": {
"backend": "fs",
"dir": "/storage/seafile/cold-data"
},
"blocks": {
"backend": "fs",
"dir": "/storage/seafile/cold-data"
}
},
{
"storage_id": "swift_storage",
"name": "Swift Storage",
"is_default": false,
"commits": {
"backend": "swift",
"tenant": "<your-tenant>",
"user_name": "<your-username>",
"password": "<your-password>",
"container": "seafile-commits",
"auth_host": "<swift-auth-host>:5000",
"auth_ver": "v3.0"
},
"fs": {
"backend": "swift",
"tenant": "<your-tenant>",
"user_name": "<your-username>",
"password": "<your-password>",
"container": "seafile-fs",
"auth_host": "<swift-auth-host>:5000",
"auth_ver": "v3.0"
},
"blocks": {
"backend": "swift",
"tenant": "<your-tenant>",
"user_name": "<your-username>",
"password": "<your-password>",
"container": "seafile-blocks",
"auth_host": "<swift-auth-host>:5000",
"auth_ver": "v3.0",
"region": "RegionTwo"
}
},
{
"storage_id": "ceph_storage",
"name": "Ceph Storage",
"is_default": false,
"commits": {
"backend": "ceph",
"ceph_config": "/etc/ceph/ceph.conf",
"pool": "seafile-commits"
},
"fs": {
"backend": "ceph",
"ceph_config": "/etc/ceph/ceph.conf",
"pool": "seafile-fs"
},
"blocks": {
"backend": "ceph",
"ceph_config": "/etc/ceph/ceph.conf",
"pool": "seafile-blocks"
}
}
]
使用上述配置时,还需注意:
-
S3: 应分别准备存储 commits 、 fs 、 blocks 的存储桶。使用非 AWS 的 S3 兼容服务时,还可能需要配置 host 、 path_style_request 等参数。参阅 使用 S3 存储后端 。
-
文件系统: dir 必须填写 Seafile 容器内 可访问的 seafile-data 基础目录。对象实际保存在该目录下的 storage/commits 、 storage/fs 和 storage/blocks 子目录中。上例的 /storage/seafile/cold-data 仅为示例路径,必须事先将相应存储挂载到容器内,并确认 Seafile 具有读写权限。
commits
、
fs
和
blocks
的具体参数与单存储后端模式下
seafile.conf
中的
[commit_object_backend]
、
[fs_object_backend]
和
[block_backend]
类似。
资料库映射策略
资料库映射策略决定
新建资料库
使用哪个存储类。Seafile 提供以下三种策略:用户选择、基于角色映射、基于资料库 ID 映射。
资料库创建时,系统会确定其存储类并将映射关系保存在数据库中。
之后修改映射策略,不会自动迁移已存在资料库的数据。
首先,在宿主机
/opt/seafile-data/seafile/conf/seahub_settings.py
中启用存储类功能:
ENABLE_STORAGE_CLASSES = True
随后选择下面一种映射策略。
用户选择(
USER_SELECT
)
用户创建资料库时,可以从有权限使用的存储类中选择存储位置。
在
seahub_settings.py
中添加:
STORAGE_CLASS_MAPPING_POLICY = 'USER_SELECT'
开启
ENABLE_STORAGE_CLASSES
后,如果没有显式指定映射策略,默认使用用户选择策略。
基于角色映射(
ROLE_BASED
)
可以根据用户角色限制其可使用的存储类。例如,允许普通用户使用热存储和冷存储,而访客仅能使用冷存储。
在
seahub_settings.py
中配置:
ENABLE_STORAGE_CLASSES = True
STORAGE_CLASS_MAPPING_POLICY = 'ROLE_BASED'
ENABLED_ROLE_PERMISSIONS = {
'default': {
'can_add_repo': True,
'can_add_group': True,
'can_view_org': True,
'can_use_global_address_book': True,
'can_generate_share_link': True,
'can_generate_upload_link': True,
'can_invite_guest': True,
'can_connect_with_android_clients': True,
'can_connect_with_ios_clients': True,
'can_connect_with_desktop_clients': True,
'storage_ids': ['hot_storage', 'cold_storage'],
},
'guest': {
'can_add_repo': True,
'can_add_group': False,
'can_view_org': False,
'can_use_global_address_book': False,
'can_generate_share_link': False,
'can_generate_upload_link': False,
'can_invite_guest': False,
'can_connect_with_android_clients': False,
'can_connect_with_ios_clients': False,
'can_connect_with_desktop_clients': False,
'storage_ids': ['cold_storage'],
},
}
上面是完整示例。如果已有
ENABLED_ROLE_PERMISSIONS
配置,应在现有角色配置中加入
storage_ids
,不要直接覆盖原有角色权限。
-
一个角色只有一个可用存储类时,该角色下的用户无法选择其他存储类。
-
一个角色分配了多个存储类时,用户创建资料库时可以从中选择。
-
没有为角色分配存储类时,使用 JSON 文件中指定的默认存储类。
storage_ids
中的值必须与存储类 JSON 文件中的
storage_id
一致。
基于资料库 ID 映射(
REPO_ID_MAPPING
)
该策略根据资料库的 UUID 为新资料库分配存储类,可以将资料库分散到多个存储后端。
在
seahub_settings.py
中设置:
STORAGE_CLASS_MAPPING_POLICY = 'REPO_ID_MAPPING'
若希望某个存储类参与
新建资料库
的分配,可在相应存储类对象中添加
for_new_library
:
{
"storage_id": "new_backend",
"name": "New Store",
"for_new_library": true,
"is_default": false,
"commits": {
"backend": "fs",
"dir": "/storage/seafile/new-data"
},
"fs": {
"backend": "fs",
"dir": "/storage/seafile/new-data"
},
"blocks": {
"backend": "fs",
"dir": "/storage/seafile/new-data"
}
}
上述 JSON 对象应添加到存储类配置文件的数组中,不要用单个对象替换整个数组。
/storage/seafile/new-data
是示例路径,使用前必须确保其存在于 Seafile 容器内。
注意:
此策略不是完整的分布式存储或自动数据迁移方案。以后新增存储类时,已有资料库仍保留在原存储类中;只有新建资料库会按当前策略分配。部署前应规划各存储后端的容量。
使配置生效
确认
.env
、
seafile.conf
、
seahub_settings.py
以及 JSON 文件均已保存,且存储服务、存储桶和容器挂载均可正常访问。
在默认 Docker 部署的 Compose 目录运行:
cd /opt/seafile
docker compose up -d
如果仅修改已有的 Seafile 配置文件,可按部署情况重启 Seafile 服务。检查启动日志:
docker logs seafile --follow
若启动失败,应首先检查
storage_classes_file
指定的路径是否确实存在于容器中,以及 JSON 格式、存储类名称和后端访问权限是否正确。
多存储后端数据迁移
Seafile 提供
migrate-repo.sh
脚本,将资料库数据从一个存储类迁移到另一个存储类。
迁移前请备份数据库和相关存储数据,并在维护窗口执行。
迁移脚本操作的是现有资料库数据,不能将改变映射策略当作迁移的替代方法。
迁移资料库
在能访问 Seafile 迁移脚本及其配置的运行环境中,进入脚本所在目录,执行:
./migrate-repo.sh [repo_id] origin_storage_id destination_storage_id
参数说明:
参数
说明
repo_id
需要迁移的资料库 ID,可省略。方括号表示可选参数,执行命令时不输入方括号。
origin_storage_id
源存储类的
storage_id
。
destination_storage_id
目标存储类的
storage_id
。
例如,将指定资料库从
hot_storage
迁移至
cold_storage
:
./migrate-repo.sh 4c731e5c-f589-4eaa-889f-14c00d4893cb hot_storage cold_storage
不指定
repo_id
时,脚本将迁移源存储类上的全部资料库。执行前应确认源、目标存储类标识和迁移范围。
从 S3 迁移到其他存储时,应使用 S3 V4 签名认证协议。
使用旧版 V2 认证可能导致脚本无法正常列出对象。
保存迁移对象清单
运行迁移脚本前,可以通过
OBJECT_LIST_FILE_PATH
指定迁移对象清单的文件名前缀:
export OBJECT_LIST_FILE_PATH=/opt/test
例如,迁移资料库
4c731e5c-f589-4eaa-889f-14c00d4893cb
后,会在
/opt
目录下生成类似以下文件:
test_4c731e5c-f589-4eaa-889f-14c00d4893cb.fs
test_4c731e5c-f589-4eaa-889f-14c00d4893cb.commits
test_4c731e5c-f589-4eaa-889f-14c00d4893cb.blocks
保存对象清单有两个作用:
-
大型资料库需要分多次运行迁移脚本时,可以跳过此前已经迁移的对象。
-
如果迁移完成后需要删除源存储中的对象,则必须在迁移前设置 OBJECT_LIST_FILE_PATH 。
文件名前缀应位于脚本运行环境中可写、可保留的目录。请勿在迁移完成之前删除这些清单文件。
删除源存储中的对象
确认迁移成功且目标存储中的资料库可以正常访问后,可使用
remove-objs.sh
删除源存储类中指定资料库的对象:
./remove-objs.sh repo_id storage_id
其中
repo_id
为资料库 ID,
storage_id
为需要清理的
源
存储类 ID。
此操作涉及数据删除,必须在迁移前设置并保留
OBJECT_LIST_FILE_PATH
生成的对象清单。执行前请再次确认备份、目标数据完整性及源存储类,避免误删仍在使用的对象。
迁移整个存储类
需要将某个存储类上的资料库全部迁移到其他存储类时,可以按以下顺序操作:
-
将目标存储类加入 seafile_storage_classes.json ,并确认其可以正常访问。
-
避免新的资料库继续分配到源存储类:使用基于角色的映射策略时,调整各角色的 storage_ids ;使用基于资料库 ID 的映射策略时,将源存储类的 for_new_library 设为 false ,并为目标存储类设置适当的值。
-
在维护窗口执行迁移脚本, 不指定 repo_id ,迁移该源存储类中的全部资料库。
-
验证迁移结果和业务访问正常后,再决定是否清理源存储对象。
不要仅通过删除 JSON 文件中的旧存储类定义来替代数据迁移。