接入
S3 兼容接口
用 aws、rclone、Cyberduck、boto3 或任何 AWS SDK 读写 Side Space。一个空间就是一个存储桶,路径就是对象键,每次写入都是一个版本。
会说 S3 的工具可以直接读写空间。给令牌加 --s3 就得到一对 S3 密钥:
sidespace token create rclone --scope files:write --space "Film A" --s3
# aws_access_key_id = SSAK7QF2M4XKD9WZ3T0B
# aws_secret_access_key = ssp_… (同时也是一个普通令牌)端点是服务器的 8070 端口(生产部署里由 Caddy 用同一张证书提供 HTTPS)。用 path-style 寻址;region 随便填,例如 us-east-1。
aws configure set aws_access_key_id SSAK7QF2M4XKD9WZ3T0B
aws configure set aws_secret_access_key ssp_…
aws --endpoint-url https://side.example.com:8070 s3 ls
aws --endpoint-url https://side.example.com:8070 s3 cp ./Ep01 s3://film-a/Ep01 --recursive# ~/.config/rclone/rclone.conf
[side]
type = s3
provider = Other
access_key_id = SSAK7QF2M4XKD9WZ3T0B
secret_access_key = ssp_…
endpoint = https://side.example.com:8070
force_path_style = true
# rclone copy side:film-a/Ep01 ./Ep01import boto3
s3 = boto3.client("s3", endpoint_url="https://side.example.com:8070",
aws_access_key_id="SSAK7QF2M4XKD9WZ3T0B", aws_secret_access_key="ssp_…",
region_name="us-east-1")
s3.upload_file("A001_C003.mov", "film-a", "Ep01/Shots/A001_C003.mov")
url = s3.generate_presigned_url("get_object", Params={"Bucket": "film-a", "Key": "Ep01/notes.md"}, ExpiresIn=3600)存储桶和对象键
- 存储桶名是空间名的小写,字母和数字以外的字符换成
-(Film A→film-a)。重名或太短时用空间 id(spc_01…写成spc-01…)。 - 对象键就是空间里的路径。
- 令牌带
admin权限的密钥可以用 CreateBucket 新建一个和桶同名的空间;同时带上x-sidespace-fork-source: 桶名[/文件夹]头,就是开一个分支。DeleteBucket 只删除从没放过东西的空间,和 S3 只删空桶一样;其余的返回BucketNotEmpty,要在 Side Space 里删。
写入会发生什么
一次写入就是一次正常保存:生成新版本,通知、Webhook、流水线照常触发。删除进回收站,30 天内可恢复。在同一空间及其分支内 CopyObject 不复制字节。
版本和过去
每个桶的版本控制都是 Enabled,因为 Side Space 里每次保存都是一个版本。认得 S3 版本的工具(rclone --s3-versions、备份工具、boto3)都能看到完整历史。
aws --endpoint-url https://side.example.com:8070 s3api list-object-versions --bucket film-a --prefix Ep01/
aws --endpoint-url https://side.example.com:8070 s3api get-object --bucket film-a --key Ep01/script.md \
--version-id ver_01JD… old.md
# 恢复旧版本:把它复制到原来的键上
aws --endpoint-url https://side.example.com:8070 s3api copy-object --bucket film-a --key Ep01/script.md \
--copy-source "film-a/Ep01/script.md?versionId=ver_01JD…"- S3 版本 id 就是 Side Space 的版本 id(
ver_…)。PutObject、CopyObject 和 CompleteMultipartUpload 返回x-amz-version-id。 - ListObjectVersions 列出每个文件的所有版本,同一个键里新的在前,支持键和版本 id 的分页标记,以及分隔符前缀。
- GetObject、HeadObject 和 CopyObject 的源都接受
versionId。 - 回收站里的文件显示为删除标记,id 是
del.<节点 id>。删除这个标记就把文件恢复回来,和 S3 一样。对一个键 DeleteObject 会留下删除标记:文件进回收站。 - 想看桶在过去的样子,带
x-sidespace-as-of头(时间、-2h或日志序号;预签名链接用同名查询参数),列表和读取得到的就是那一刻的内容。见看过去和整体回滚。 - 版本一直保留,直到文件被它的所有者在 Side Space 里永久删除。删除单个版本返回
MethodNotAllowed,暂停版本控制返回InvalidArgument。
支持的操作
ListBuckets、HeadBucket、CreateBucket、DeleteBucket、ListObjects v1 和 v2、ListObjectVersions、GetBucketVersioning(前缀、分隔符、分页)、GetObject 和 HeadObject(含 Range)、PutObject、CopyObject、DeleteObject、DeleteObjects、分段上传(Create、UploadPart、Complete、Abort、ListParts、ListMultipartUploads;分段没有 5 MB 下限)、预签名链接(SigV4 和 SigV2),以及 aws-chunked 流式上传。
不支持:桶策略、ACL、对象标签、暂停版本控制、删除单个版本。ETag 是内容哈希,不是 MD5。
权限照令牌来:files:read 只能读,files:write 才能写;限定空间的令牌只看得到那几个桶。吊销令牌后 S3 密钥立即失效。