# Nginx Configuration for PHP-FPM Application # Optimized for production with security headers and performance tuning # Upstream PHP-FPM upstream php-upstream { server app:9000; } # Rate limiting zones limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; limit_req_zone $binary_remote_addr zone=general_limit:10m rate=30r/s; server { listen 80; server_name _; root /var/www/html/public; index index.php index.html; # Security Headers (additional to Traefik middleware) add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Client body size limit (adjust for file uploads) client_max_body_size 100M; # Gzip compression gzip on; gzip_vary on; gzip_min_length 1024; gzip_comp_level 6; gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss image/svg+xml; # Logging access_log /var/log/nginx/access.log combined; error_log /var/log/nginx/error.log warn; # Health check endpoint (for Docker healthcheck) location /health { access_log off; return 200 "healthy\n"; add_header Content-Type text/plain; } # Deny access to sensitive files location ~ /\. { deny all; access_log off; log_not_found off; } location ~ ^/(\.env|\.git|\.gitignore|\.gitattributes|composer\.(json|lock)|package(-lock)?\.json) { deny all; access_log off; log_not_found off; } # Static files - serve directly for performance location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot|webp)$ { expires 1y; add_header Cache-Control "public, immutable"; access_log off; try_files $uri =404; } # API endpoints - rate limited location ^~ /api/ { limit_req zone=api_limit burst=20 nodelay; limit_req_status 429; try_files $uri $uri/ /index.php?$query_string; } # PHP-FPM processing location ~ \.php$ { limit_req zone=general_limit burst=50 nodelay; try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php-upstream; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; # FastCGI parameters include fastcgi_params; # PHP-FPM timeouts fastcgi_connect_timeout 60s; fastcgi_send_timeout 180s; fastcgi_read_timeout 180s; # Buffer settings fastcgi_buffer_size 128k; fastcgi_buffers 256 16k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; # Hide PHP version fastcgi_hide_header X-Powered-By; } # Fallback to index.php for non-existent files (framework routing) location / { try_files $uri $uri/ /index.php?$query_string; } # Deny access to storage directory (except public subdirectory) location ^~ /storage { deny all; } location ^~ /storage/public { allow all; } }