worker_processes auto; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; gzip on; gzip_disable "msie6"; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_min_length 1000; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml font/woff2; server { listen 8080; server_name _; root /usr/share/nginx/html; index index.html index.htm; # Security headers add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), interest-cohort=()" always; add_header Cross-Origin-Opener-Policy "same-origin" always; add_header Cross-Origin-Embedder-Policy "require-corp" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'nonce-astro'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://cdn.pixabay.com https://raw.githubusercontent.com; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" always; # Error pages error_page 404 /404.html; location = /404.html { internal; } # Main route fallback location / { try_files $uri $uri/index.html =404; } # 🚫 Block hidden and sensitive files (e.g., .env, .git) location ~ /\.(?!well-known).* { deny all; } # 🚫 Block access to config and archive files location ~* \.(cjs|ts|json|sh|zip|log|env)$ { deny all; } # 🧠 Optional: cache static assets for 6 months location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|otf|webp)$ { expires 6M; access_log off; add_header Cache-Control "public"; } } }