# Serves the Next.js static export. TLS and the public hostname are handled # by Nginx Proxy Manager in front of this container. server { listen 80; server_name _; root /usr/share/nginx/html; # Behind a TLS proxy: keep redirects relative so they stay on https absolute_redirect off; # Pages are exported as folder/index.html (trailingSlash: true) location / { try_files $uri $uri/ $uri.html =404; } # Content-hashed build assets never change location /_next/static/ { add_header Cache-Control "public, max-age=31536000, immutable"; } # Video and images: cache for a week (nginx handles range requests) location ~* \.(mp4|jpg|jpeg|png|webp|svg)$ { add_header Cache-Control "public, max-age=604800"; } # Client previz pages: never cached, so updated renders show up straight away. # ^~ beats the media regex above, so nothing in here gets the week-long cache. location ^~ /previz/ { add_header Cache-Control "private, no-store"; try_files $uri $uri/ $uri.html =404; } # Private shot previews: login required for the page and the clips (see DEPLOY.md). # The login file and the clips live on the server only. If the login file is missing, # nginx answers 500, so /drops/ is never left open. ^~ beats the media regex above, # so nothing in here is cached by the browser or Cloudflare. location ^~ /drops/ { auth_basic "Two Tales VFX"; auth_basic_user_file /etc/nginx/auth/drops.htpasswd; add_header Cache-Control "private, no-store"; add_header X-Robots-Tag "noindex, nofollow"; try_files $uri $uri/ $uri.html =404; location ^~ /drops/files/ { alias /srv/drops/; } } # Offline worker for /set must always be revalidated so updates roll out location = /set/sw.js { add_header Cache-Control "no-cache"; } location ~* \.webmanifest$ { types { application/manifest+json webmanifest; } add_header Cache-Control "no-cache"; } error_page 404 /404.html; gzip on; gzip_types text/css application/javascript image/svg+xml application/json text/plain application/xml; }