服务器 上线生产环境
上线生产环境
在应用的网盘向用户开放之前,需要设置和关注的事项。
本页内容
清单
secret要长且随机(openssl rand -hex 32),每个进程相同,来自环境变量,绝不写在代码中。identify来自你的会话,authorize使用byRoles或你自己的规则:绝不使用everyone()。- 存储桶的来源规则只包含你的域名,并暴露
ETag(存储)。 - 设置
maxSize和每个人的quota;设置trashDays让回收站自动清空。 - 至少使用
inspect: checkType();对于来自陌生人的文件,加上 ClamAV(检查上传)。 - 多个进程时使用 Postgres(元数据),并做好备份。
- 在存储桶中设置生命周期规则,如下所示。
- 在代理之后设置
clientIp,多个进程时使用基于 Redis 的limiter(钩子、日志与限制)。 - 前端使用 HTTP/2:每个监听的标签页占用一个连接,而在 HTTP/1.1 下浏览器对每个主机只有六个。看不见的标签页会释放自己的连接。
- 安装 sharp 和 pdf.js 并设置
derive: deriveAll(),为页面未生成的内容生成图片和文字(预览)。
未完成的上传
上传中途关闭的页面会把已上传的部分留在存储桶中,它们占用空间却不出现在任何地方。服务器会随请求每十分钟清理一次:超过令牌有效期(一天)的上传会被中止,仅限其 prefix 之下;在磁盘上则删除其部分文件。存储桶的生命周期规则无需服务器也能做到:
lifecycle.json
{
"Rules": [
{ "ID": "abort-unfinished", "Status": "Enabled", "Filter": { "Prefix": "" },
"AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 2 } }
]
}备份
条目说明了哪些字节属于哪个文件:没有它们,存储桶只是一堆 id。像备份数据库一样备份它们:Postgres 用 pg_dump,SQLite 用 sqlite3 drive.sqlite ".backup backup.sqlite",在服务器写入时也安全。
字节从不原地修改:每个版本都是新的键。因此网盘不需要存储桶的版本控制,存储桶的副本(R2 到 S3、rclone)就是只增不减的备份。只删除网盘已删除的内容。
轮换密钥
- 存储桶的密钥:创建新密钥,提供给每个进程,两小时后再撤销旧密钥:下载地址有效十五分钟,显示图片的地址有效两小时。
secret:更换后,进行中的上传(其令牌)会结束,链接的地址也会改变。之前创建的链接会失效,因为它们由它签名:请在空闲时段进行,并通知分享过链接的人。
在代理之后
location /api/files/ {
proxy_pass http://app;
proxy_request_buffering off; # the disk storage carries the bytes through the server
client_max_body_size 64m; # a part is 8 MiB, more for a file of over 80 GB
proxy_read_timeout 1h; # the events go on as long as the page watches
}使用存储桶时,字节完全不经过代理:只有网盘的小请求,以及持续的事件流。
需要关注的内容
服务器会把未能完成且未在响应中说明的事写到控制台:未保存的动态、失败的 onShare、未清理的上传、无法检查的文件,每条都附带错误。500 响应不会向页面透露内部信息;控制台会说明一切。