Created
October 10, 2020 00:52
-
-
Save ivanmonteiro/82683fc41880a8799cf7bd3a53004db1 to your computer and use it in GitHub Desktop.
Best practice secure NGINX configuration for WordPress
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # From blog post https://www.getpagespeed.com/server-setup/nginx/best-practice-secure-nginx-configuration-for-wordpress | |
| server { | |
| server_name example.com; | |
| root /srv/www/example.com/public; | |
| security_headers on; | |
| # do not load WordPress when redirecting /index.php to / | |
| location = /index.php { | |
| return 301 /; | |
| } | |
| # do not load WordPress when redirecting /wp-admin to to /wp-admin/ | |
| location = /wp-admin { | |
| return 301 /wp-admin/; | |
| } | |
| location / { | |
| # any URI without extension is routed through PHP-FPM (WordPress controller) | |
| location ~ ^[^.]*$ { | |
| length_hiding on; | |
| fastcgi_param SCRIPT_FILENAME $document_root/index.php; | |
| include includes/php-example.com.conf; | |
| } | |
| # allow only a handful of PHP files in root directory to be interpreted | |
| # wp-cron.php ommited on purpose as it should *not* be web accessible, see proper setup | |
| # https://www.getpagespeed.com/web-apps/wordpress/wordpress-cron-optimization | |
| location ~ ^/wp-(?:comments-post|links-opml|login|mail|signup|trackback)\.php$ { | |
| length_hiding on; | |
| fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | |
| include includes/php-example.com.conf; | |
| } | |
| # other PHP files "do not exist" | |
| location ~ \.php$ { | |
| return 404; | |
| } | |
| } | |
| location = /xmlrpc.php { | |
| # allows JetPack servers only | |
| allow 192.0.0.0/16; | |
| deny all; | |
| fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | |
| include includes/php-example.com.conf; | |
| } | |
| location /wp-admin/ { | |
| index index.html index.php; | |
| location = /wp-admin/admin-ajax.php { | |
| # this location often spits json, which will be broken if length hiding is used | |
| # so no length hiding here | |
| fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | |
| include includes/php-example.com.conf; | |
| } | |
| # numerous files under wp-admin are allowed to be interpreted | |
| # no fancy filenames allowed (lowercase with hyphens are OK) | |
| # only /wp-admin/foo.php or /wp-admin/{network,user}/foo.php allowed | |
| location ~ ^/wp-admin/(?:network/|user/)?[\w-]+\.php$ { | |
| length_hiding on; | |
| fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | |
| include includes/php-example.com.conf; | |
| } | |
| } | |
| location /wp-content/ { | |
| # contents under wp-content are typically highly cacheable | |
| immutable on; | |
| # hide and do not interpret internal plugin or user uploaded scripts | |
| location ~ \.php$ { | |
| return 404; | |
| } | |
| } | |
| # hide any hidden files | |
| location ~ /\. { | |
| deny all; | |
| } | |
| # hide any backup or SQL dump files | |
| location ~ ^.+\.(sql|bak|php~|php#|php.save|php.swp|php.swo)$ { | |
| return 404; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment