mastodon 使用 minio 托管媒体文件

安装 minio

minio 发音是迷你欧,是一个兼容 S3 协议的存储系统,使用 Go 开发,推荐用 docker 部署。

docker pull minio/minio

用最少参数启动 minio:docker run -p 9000:9000 minio/minio server /data 这样启动的容器无法保留数据,重启后数据会清零,不能在生产环境使用。

实际环境中:docker run -p 9000:9000 --name minio1 -e "MINIO_ACCESS_KEY=YOURKEY" -e "MINIO_SECRET_KEY=YOURSECRET" -e "MINIO_BROWSER=off" -v /mnt/data:/data -v /mnt/config:/root/.minio minio/minio server /data,如果是第一次建立镜像,Key 参数可以省略,会自动生成 Key 和 Secret。

这些参数建立的容器可以把配置文件和数据文件持久化到 /mnt/ 目录下。带上访问 Key 参数否则每次新建的容器都会产生新的随机密钥。MINIO_BROWSER=off 带上这个环境变量可以关闭 web ui 界面。使用官方的 mc 客户端管理功能强大,不建议开启 web 界面,只会增加安全风险。

配置 nginx

server {
  listen 80;
  server_name example.com;
  ignore_invalid_headers off;
  client_max_body_size 0;
  proxy_buffering off;
 
  location / {
    proxy_http_version 1.1
    proxy_set_header Host $http_host;
    proxy_read_timeout 15m;
    proxy_send_timeout 15m;
    proxy_request_buffering off;
    proxy_pass http://localhost:9000;    
  }
 }

这是 80 端口的配置,443 端口类似。官方给的配置中包含 health_check uri=/minio/health/ready; 这个是商业版的 nginx 才有的功能。

mc 设置

mc 是连接 bucket 的客户端工具,安装在 rails app 所在的服务器上方便直接拷贝相关文件。

wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
./mc config

以上命令下载 mc 并生成默认配置文件。

vim .mc/config.json 编辑配置文件,直接修改 play 的 block,把 Key 填写进去。

mc admin info play 看到类似信息就说明连接成功了。

● example.com Uptime: 33 minutes
Version: 2019-07-17T22:54:12Z Storage: Used 2.9 GiB

bucket 设置

mc md play/mastodon 新建一个桶,mc policy download play/mastodon 使得可以通过 http(s)://base-url/mastodon/file-path.jpg 来直接访问文件。

以上设置会导致访问目录时列出所有文件。当前使用 mc 客户端无法设置 S3 兼容的 policy,所以还需要下载 aws-cli 来设置更精准的权限。

aws 安装后首先配置aws configure

AWS Access Key ID [****************9TA4]:
AWS Secret Access Key [****************Puw8]:
Default region name [None]:
Default output format [None]: text

准备好 /tmp/policy.json 文件,内容如下:

{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Principal":{
            "AWS":[
               "*"
            ]
         },
         "Action":[
            "s3:GetObject"
         ],
         "Resource":[
            "arn:aws:s3:::mastodon/*"
         ]
      }
   ]
}

把 policy 更新到 minio:aws --endpoint-url http://localhost:9000 s3api put-bucket-policy --bucket mastodon --policy file:///tmp/policy.json

注意本地文件名必须要以 file:// 协议打开,否则会返回如下错误:

An error occurred (MalformedPolicy) when calling the PutBucketPolicy operation: Policy has invalid resource.

复制文件到 minio

mc cp --recursive ~/live/public/system play/mastodon 会把 system 文件夹复制到 minio 的 mastodon 桶里。可以在切换 mastodon 配置时候重新执行一次 mc cp --recursive --newer-than 0d1h ~/live/public/system play/mastodon 这样会只复制 1 小时之前到现在产生的文件。

修改 mastodon 环境配置

 S3_ENABLED=true
 S3_PROTOCOL=https
 S3_BUCKET=mastodon
 S3_HOSTNAME=example.com
 AWS_ACCESS_KEY_ID=YOURKEY
 AWS_SECRET_ACCESS_KEY=YOURSECRET
 S3_ENDPOINT=http://example.com/

修改完毕后重启 web、streaming 和 sidekiq 服务。sudo systemctl restart mastodon-*。刷新前端,图片应该已经改为 minio 的网址了。格式为:http(s)://your-minio-domain/mastodon/media_attachments/files/***