fastcgi_cache_path /tmp/fcgi_cache levels=1:2 keys_zone=app_cache:10m max_size=256m inactive=10m use_temp_path=off; upstream php_fpm { server app:9000; keepalive 16; } server { listen 80; server_name _; root /var/www/html/public; index index.php; client_max_body_size 100M; charset utf-8; open_file_cache max=5000 inactive=30s; open_file_cache_valid 60s; open_file_cache_min_uses 2; open_file_cache_errors on; # --- FastCGI cache bypass rules --- set $skip_cache 0; if ($request_method = POST) { set $skip_cache 1; } if ($request_uri ~* "^/(boboko|up)") { set $skip_cache 1; } if ($query_string) { set $skip_cache 1; } # Vite build assets — content-hashed filenames, safe to cache forever location /build/ { add_header Cache-Control "public, max-age=31536000, immutable"; add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; try_files $uri =404; } location /static/ { add_header Cache-Control "public, max-age=31536000, immutable"; add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; try_files $uri =404; } location /packages/ { add_header Cache-Control "public, max-age=31536000, immutable"; add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; try_files $uri =404; } # User media — served directly from the storage volume (no symlink needed) location /storage/ { alias /var/www/html/storage/app/public/; add_header Cache-Control "public, max-age=31536000, immutable"; add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; try_files $uri =404; } location / { add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass php_fpm; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $realpath_root; fastcgi_read_timeout 300; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; fastcgi_keep_conn on; fastcgi_cache app_cache; fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_valid 200 10m; fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; fastcgi_ignore_headers Cache-Control Expires Set-Cookie; add_header X-Cache-Status $upstream_cache_status; } location /stoic/ { proxy_pass http://stoic:2727/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cookie_path / /stoic/; } location ~ /\.(?!well-known).* { deny all; } location = /sitemap.xml { root /var/www/html/storage/app; try_files /sitemap.xml =404; add_header Cache-Control "public, max-age=3600"; add_header Content-Type "application/xml; charset=utf-8"; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; }