events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; # Logging access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # Training HTTP server server { listen 80; server_name _; root /var/www/public; index index.php index.html; # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; # API routes - pass directly to Laravel with original REQUEST_URI location /api/ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/index.php; include fastcgi_params; fastcgi_param HTTP_PROXY ""; fastcgi_param HTTPS $https if_not_empty; fastcgi_read_timeout 300; fastcgi_send_timeout 300; } # Training SPA (built with base=/training/) # Serve training frontend routes from /var/www/public/training location ^~ /training/ { add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; try_files $uri $uri/ /training/index.html; } # Serve assets under /training/assets/ location ~* ^/training/.*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; try_files $uri =404; } # Handle PHP files - connect to localhost PHP-FPM location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; # Additional FastCGI parameters fastcgi_param HTTP_PROXY ""; fastcgi_param HTTPS $https if_not_empty; fastcgi_read_timeout 300; fastcgi_send_timeout 300; } # Deny access to hidden files location ~ /\. { deny all; } # Health check endpoint for Docker location = /health { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/index.php; include fastcgi_params; fastcgi_param HTTP_PROXY ""; } location ^~ /horizon { add_header Content-Security-Policy "default-src 'self' http: https: data: blob 'unsafe-inline' 'unsafe-eval'" always; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/index.php; include fastcgi_params; fastcgi_param HTTP_PROXY ""; fastcgi_param HTTPS $https if_not_empty; fastcgi_read_timeout 300; fastcgi_send_timeout 300; } # TRAINING: Root path disabled - redirect to /training/ location = / { return 302 /training/; } # TRAINING: All other paths return 404 (production frontend disabled) location / { return 404; } } }