server { listen 80; listen [::]:80; server_name __DOMAIN__ www.__DOMAIN__; root /home/bitrix/www; index index.php index.html; charset utf-8; # ---- hard denies (order matters: regex locations match top-down) ---- location ~ /\. { deny all; } # dotfiles (.htaccess, .git...) location ~* ^/(bitrix|local)/modules/.*\.php$ { deny all; } # no direct module execution location ~* ^/upload/.*\.(php|phar|phtml)$ { deny all; } # uploads must never execute # ---- static assets straight from disk, no PHP ---- location ~* ^.+\.(jpg|jpeg|gif|png|webp|avif|svg|ico|css|js|woff|woff2|ttf|eot|otf|mp3|mp4|m4a|ogg|pdf|zip|csv|xlsx?)$ { expires 7d; add_header Cache-Control "public"; access_log off; try_files $uri =404; } # ---- optional rate-limit example zone (uncomment when needed) ---- #location /search { # limit_req zone=main_limit burst=20 nodelay; # rewrite ^(.*)$ /search/index.php last; #} # ---- Bitrix SEF routing (official pattern) ---- location / { index index.php; if (!-e $request_filename) { rewrite ^(.*)$ /bitrix/urlrewrite.php last; } } # ---- PHP execution ---- location ~ \.php$ { include snippets/fastcgi-bitrix.conf; } # security headers (TLS versions added by certbot block later) add_header X-Content-Type-Options nosniff always; add_header X-Frame-Options SAMEORIGIN always; add_header Referrer-Policy strict-origin-when-cross-origin always; } # certbot --nginx will extend this file with the :443 server block, # redirect 80->443 and ACME challenge handling automatically.