Skip to content

Instantly share code, notes, and snippets.

@dale-c-anderson
Created October 28, 2016 08:09
Show Gist options
  • Save dale-c-anderson/5d3eaeaf01fbf3ca3a10f30760f371f5 to your computer and use it in GitHub Desktop.
Save dale-c-anderson/5d3eaeaf01fbf3ca3a10f30760f371f5 to your computer and use it in GitHub Desktop.
Secure Wordpress + Drupal virtual host configuration for NGINX
server {
listen 80;
server_name www.example.com;
access_log /var/log/vhosts/myaccount/myproject/nginx-access.log;
error_log /var/log/vhosts/myaccount/myproject/nginx-error.log;
root /var/vhosts/myaccount/www/myproject/wwwroot;
index index.html index.php;
client_max_body_size 8m;
gzip_static on;
# Requests for this just clutters log files.
location = /favicon.ico {
log_not_found off;
access_log off;
}
# Requests for this just clutters log files.
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Very rarely should these ever be accessed outside of your lan
location ~* \.(txt|log|sql|zip|gzip|gz|tar)$ {
allow 192.168.0.0/16;
allow 10.0.0.0/8;
deny all;
}
# Drupal: Files that contain PHP, but shouldn't be served or processed directly
location ~* \.(module|install|inc|theme|profile|engine)$ {
return 403;
}
# Dont allow requests for PHP files in parent directories
location ~ \..*/.*\.php$ {
return 403;
}
# Drupal: Don't allow access to private directories (either at the root, or anywhere else)
location ~* /private/ {
return 403;
}
# Block access to "hidden" files and directories whose names begin with a
# period. This includes directories used by version control systems such
# as Subversion or Git to store control files.
location ~ (^|/)\. {
return 403;
}
# ------ Wordpress -----------
# Deny access to any files with a .php extension in the uploads directory
# Works in sub-directory installs and also in multisite network
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}
# Wordpress in a 'blog' subdirectory
# This order might seem weird - Static content is served (if it exists) without touching php.
location /blog {
try_files $uri $uri/ @wp_rewrite;
}
location @wp_rewrite {
rewrite ^ /blog/index.php?$args;
}
# ------ Drupal (7 and above) ------------
# No php is touched for static content
location / {
try_files $uri @d7_rewrite;
}
# Drupal: Clean URLs are handled in drupal_environment_initialize().
location @d7_rewrite {
rewrite ^ /index.php;
}
# Drupal: Image cache doesn't work without this.
location ~ /sites/.*/files/styles/ {
try_files $uri @rewrite;
}
# Dont spam log files, and cache static content forever.
# Note that this will interfere with internal handling of files (i.e. those that exist in the private directory, and are controlled / served through/by Drupal)
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
# PHP FPM on a socket
location ~ \.php$ {
## Properly deal with real 404 errors before we hand control off to php-fpm.
## Otherwise, when someone requests /some-file-that-doesnt-exist.php, fastcgi just gives back a cryptic "No input file specified".
## Only affects request URIs that end with a .php file extension
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_intercept_errors on;
fastcgi_pass unix:/var/run/php7.0-fpm.sock;
}
# Very basic Nginx connection stats
location /nginx_status {
stub_status on;
access_log off;
allow 192.168.0.1; # Adjust to your own real IP
deny all;
}
# PHP FPM status: Also depends on these paths being enabled in the PHP FPM pool config.
location ~ ^/(status|ping)$ {
access_log off;
allow 192.168.0.1; # Adjust to your own real IP
deny all;
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/var/run/php7.0-fpm.sock;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment