4.7 KiB
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">}}