nginx sample conf for wordpress
mouse 1649 · person cloud · link
Last update
2019-02-01
2019
02-01
« — »

Main conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# https://www.nginx.com/resources/wiki/start/topics/recipes/wordpress/

server {
  listen      80;
  listen      localhost:8000;
  server_name www.mysite.net;

  root        /path/to/folder;  # path for static files

  access_log  /path/to/log/nginx.access.log main;
  error_log   /path/to/log/nginx.error.log  error;

  add_header  X-Frame-Options SAMEORIGIN;

  include     wp_restrictions.conf;

  index       index.php;

  # https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/
  # https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
  location ~ \..*/.*\.php$       { return 403; }          # don't exit from root
  location ~ (^|/)\.             { return 403; }          # hidden files

  # include "?$args" part so non-default permalinks doesn't break when using query string
  location / { try_files $uri $uri/ /index.php?$args; }

  location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$; # set $fastcgi_script_name and $fastcgi_path_info
    try_files $fastcgi_script_name =404;

    fastcgi_pass  unix:/var/run/phpX-fpm.sock;
    include fastcgi_params;

    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    # fix empty PATH_INFO  =>  https://trac.nginx.org/nginx/ticket/321
    set             $path_info      $fastcgi_path_info;
    fastcgi_param   PATH_INFO       $path_info;

    fastcgi_index index.php;
  }

  location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    expires max;
    log_not_found off;
  }
}

wp_restrictions.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Global restrictions configuration file.
# Designed to be included in any server {} block.
location = /favicon.ico {
  log_not_found off;
  access_log off;
}

# robots.txt fallback to index.php
location = /robots.txt {
  # Some WordPress plugin gererate robots.txt file
  allow all;
  try_files $uri $uri/ /index.php?$args @robots;
  access_log off;
  log_not_found off;
}

# additional fallback if robots.txt doesn't exist
location @robots {
  return 200 "User-agent: *\nDisallow: /wp-admin/\nAllow: /wp-admin/admin-ajax.php\n";
}

# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac) excepted .well-known directory.
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~ /\.(?!well-known\/) {
  deny all;
}

# Deny access to any files with a .php extension in the uploads directory for the single site
location /wp-content/uploads {
  location ~ \.php$ { deny all; }
}

# 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;
}