docs-mastodon/content/zh-cn/admin/optional/object-storage-proxy.md

4.7 KiB
Raw Blame History

title description
通过 nginx 代理对象存储 从自己的域名提供 Mastodon 中用户上传的文件

当使用 Amazon S3、Wasabi、Google Cloud 或其他对象存储提供商作为 Mastodon 的对象存储时,默认情况下,文件及其 URL 会通过存储提供商本身提供。这有以下缺点:

  • 带宽通常是按量计费且非常昂贵
  • 如果你决定稍后更换提供商URL 将会失效

你可以选择从自己的域名提供文件,并在此过程中加入缓存机制。在 Mastodon 中,访问模式显示新文件经常被多个客户端同时访问,因为它们出现在通过流式 API 提供的新贴文中或通过联邦与州共享;相比之下,旧内容的访问频率较低。因此,仅依靠缓存并不能显著减少代理到实际对象存储的带宽使用。为了解决这个问题,我们可以实现一个缓存锁定机制,确保一次只进行一个代理请求。

以下是实现这一目标的nginx配置示例

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name files.example.com;
  root /var/www/html;

  ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
  ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

  keepalive_timeout 30;

  location = / {
    index index.html;
  }

  location / {
    try_files $uri @s3;
  }

  set $s3_backend 'https://YOUR_BUCKET_NAME.YOUR_S3_HOSTNAME';

  location @s3 {
    limit_except GET {
      deny all;
    }

    resolver 8.8.8.8;
    proxy_set_header Host YOUR_BUCKET_NAME.YOUR_S3_HOSTNAME;
    proxy_set_header Connection '';
    proxy_set_header Authorization '';
    proxy_hide_header Set-Cookie;
    proxy_hide_header 'Access-Control-Allow-Origin';
    proxy_hide_header 'Access-Control-Allow-Methods';
    proxy_hide_header 'Access-Control-Allow-Headers';
    proxy_hide_header x-amz-id-2;
    proxy_hide_header x-amz-request-id;
    proxy_hide_header x-amz-meta-server-side-encryption;
    proxy_hide_header x-amz-server-side-encryption;
    proxy_hide_header x-amz-bucket-region;
    proxy_hide_header x-amzn-requestid;
    proxy_ignore_headers Set-Cookie;
    proxy_pass $s3_backend$uri;
    proxy_intercept_errors off;

    proxy_cache CACHE;
    proxy_cache_valid 200 48h;
    proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    proxy_cache_lock on;

    expires 1y;
    add_header Cache-Control public;
    add_header 'Access-Control-Allow-Origin' '*';
    add_header X-Cache-Status $upstream_cache_status;
    add_header X-Content-Type-Options nosniff;
    add_header Content-Security-Policy "default-src 'none'; form-action 'none'";
  }
}

{{< hint style="info" >}} 我们使用 $s3_backend 作为变量来强制 nginx 对其值执行 DNS 解析,因为对象存储提供商的 IP 地址可能不会始终保持不变。 {{</ hint >}}

上述配置实现了以下效果:

  • 阻止针对对象存储提供商的除 GET 请求之外的请求
  • 阻止任何经过身份验证的请求到达对象存储提供商
  • 阻止对象存储提供商设置cookie
  • 移除对象存储提供商返回的不必要的标头信息
  • 缓存有效文件最多 48 小时
  • 如果对象存储不可用,允许使用旧缓存
  • 使用缓存锁防止同时向对象存储发出请求
  • 使返回的所有文件可被浏览器缓存长达一年
  • 添加 Mastodon 网页界面所需的 CORS 头信息
  • 添加一个特殊的头信息,告诉用户请求是否命中缓存

确保替换以下内容:

  • files.example.com
  • YOUR_BUCKET_NAME
  • YOUR_S3_HOSTNAME

使用你的实际值,将配置保存到 /etc/nginx/sites-available/files.example.com,然后通过以下命令启用它:

ln -s /etc/nginx/sites-available/files.example.com /etc/nginx/sites-enabled/
systemctl reload nginx

你还需要为其获取SSL证书

certbot --nginx -d files.example.com
systemctl reload nginx

最后,你需要确保 Mastodon 使用你的新代理生成文件 URL。编辑 Mastodon 的 .env.production 添加:

S3_ALIAS_HOST=files.example.com

(可选)如果你的 S3_ALIAS_HOST 使用了 301 重定向或类似方式,请将最终跳转的目标地址添加到 EXTRA_MEDIA_HOSTS。

EXTRA_MEDIA_HOSTS=https://data.example1.com,https://data.example2.com

然后重启 Mastodon

systemctl restart mastodon-sidekiq
systemctl reload mastodon-web

{{< hint style="success" >}} 现在你可以在浏览器中访问你的 Mastodon 以确认一切正常加载 {{< /hint >}}

{{< translation-status-zh-cn raw_title="Proxying object storage through nginx" raw_link="/admin/optional/object-storage-proxy/" last_translation_time="2025-04-06" raw_commit="5e2b739ee193896bea937addc2843146ea0bc870">}}