# MOCACHE nginx snippet # Include this file from nginx's http {} context, or use it as a standalone server. # Replace the example origin, server_name, listen port, cache path and retention # values before production use. Public immutable media only. proxy_cache_path /var/cache/nginx/media levels=1:2 keys_zone=media:32m max_size=20g inactive=24h use_temp_path=off; log_format media_cache '$remote_addr - [$time_local] "$request_method $uri" $status ' '$body_bytes_sent cache=$upstream_cache_status upstream=$upstream_response_time'; server { listen 8080; server_name _; server_tokens off; keepalive_timeout 30; access_log /var/log/nginx/access.log media_cache; location = /healthz { access_log off; default_type text/plain; return 200 'ok\n'; } location = / { return 404; } # Origin errors are sanitized: upstream response bodies (e.g. S3 XML error # documents with request IDs) are never passed to clients. Client-side # errors collapse to a generic 404, upstream/server errors to a generic # 502. Stale-cache serving via proxy_cache_use_stale is unaffected. error_page 400 401 403 404 410 =404 /__media_cache_404; error_page 500 502 503 504 =502 /__media_cache_502; location = /__media_cache_404 { internal; return 404; } location = /__media_cache_502 { internal; return 502; } location / { limit_except GET { deny all; } proxy_http_version 1.1; proxy_set_header Host $proxy_host; proxy_set_header Connection ''; proxy_set_header Authorization ''; proxy_set_header Range ''; proxy_set_header Accept-Encoding ''; proxy_set_header Cookie ''; proxy_ssl_server_name on; proxy_hide_header Set-Cookie; proxy_hide_header Cache-Control; proxy_hide_header Expires; 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 Cache-Control Expires; proxy_pass https://s3.example.com/mastodon-media/; proxy_intercept_errors on; proxy_connect_timeout 3s; proxy_read_timeout 60s; proxy_cache media; proxy_force_ranges on; proxy_cache_key $proxy_host$uri; proxy_cache_valid 200 48h; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_lock on; proxy_cache_lock_timeout 30s; proxy_ignore_client_abort on; # One-year browser TTL for immutable media. Sent only for successful # responses (no `always`), so intercepted origin errors do not inherit # a year-long client TTL. Exactly one Cache-Control header is emitted: # `expires` is deliberately not used because it would add a second, # conflicting Cache-Control value. add_header Cache-Control 'public, max-age=31536000, immutable'; add_header Access-Control-Allow-Origin '*' always; add_header X-Mocache $upstream_cache_status always; add_header X-Mocache-Node $hostname always; add_header X-Content-Type-Options 'nosniff' always; add_header Content-Security-Policy "default-src 'none'; form-action 'none'" always; } }