Default nginx config for virtual servers does not work with wordpress using /postname/ styled permalinks

Using a new installation of Virtualmin, installed with --minimal and --bundle LEMP on a virtual machine AND/OR Using an installation of Virtualmin installed with --bundle LEMP on a VPS AND THEN Using default virtual server creation AND THEN Using the Script Installer for WordPress AND THEN Switching permalinks from default to /postname/ (what most people do):

The error occurs that subpages do not load. A Server (and not a Wordpress) 404 is received.

This is fixed by the following change to the conf in /etc/nginx/sites-available FROM:

fastcgi_param HTTPS $https; location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/php-nginx/154120111920698.sock/socket; } listen default_server ssl;


fastcgi_param HTTPS $https; location / { index index.php index.html index.htm; try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/php-nginx/154120111920698.sock/socket; } listen default_server ssl;

(Note the additional location directive)

It would be good to add this to the default skel file for virtual servers. Also, there is no way to address this file in the web gui as there is for the main config - this should be added.

Closed (won't fix)


Won't this potentially change the behavior of Nginx in a way that might break apps other than Wordpress?

Since all it adds is a "try" directive to make WordPress work, it shouldn't break anything. I suspect that it will fix a wide variety of CMSes besides WordPress.

Probably the better way to do it is to have a script/screen that adds directives for any common CMS. This should certainly be a part of the Virtualmin WordPress installation script, since right now, WordPress is delivered broken out of the box on nginx. I think a good place would be part of the "Create Virtual Server" installation module. In addition to all of the other choices, something like:

Configure Nginx for: * WordPress * Drupal * Joomla * (other scripts, etc.) * Koken

I list the last one because other than WordPress and Static sites, it is the only other script I have. That one required some other tweaking. I'll post my conf below in case it saves you some future time (I did not sanitize it, so please do not share):

server {
root /home/crwphoto/public_html;
index index.html index.htm index.php;
access_log /var/log/virtualmin/christopherwillingham.com_access_log;
error_log /var/log/virtualmin/christopherwillingham.com_error_log;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_FILENAME /home/crwphoto/public_html$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT /home/crwphoto/public_html;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param HTTPS $https;
    gzip on;
gzip_comp_level 6;

# By default, do not set expire headers
expires 0;

# Set expires header for console CSS and JS.
# These files are timestamped with each new release, so it is safe to cache them agressively.

# Standard site requests are cached with .html extensions
set $cache_ext 'html';

# PJAX requests contain the _pjax GET parameter and are cached with .phtml extensions
if ($arg__pjax) {
   set $cache_ext 'phtml';

# Do not check for a cache for non-GET requests
if ($request_method != 'GET') {
    set $cache_ext 'nocache';

# If share_to_tumblr cookie is preset, disable caching (long story)
if ($http_cookie ~* "share_to_tumblr" ) {
    set $cache_ext 'nocache';

location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/php-nginx/15487271894786.sock/socket;
location / {
try_files $uri $uri/ /index.php?$args;
    location ~ "console_.*\.(js|css)$" {
    expires max;
    # Catch image requests and pass them back to PHP if a cache does not yet exist
location ~ "^/storage/cache/images(/(([0-9]{3}/[0-9]{3})|custom)/.*)$" {
    # Cached images have timestamps in the URL, so it is safe to set
    # aggresive cache headers here.
    expires max;
    try_files $uri /i.php?path=$1;

# Catch .css.lens requests and serve cache when possible
location ~ "(lightbox-)?settings.css.lens$" {
   default_type text/css;
    try_files /storage/cache/site/${uri} /app/site/site.php?url=/$1settings.css.lens;

# Catch koken.js requests and serve cache when possible
location ~ koken.js$ {
    default_type text/javascript;
    try_files /storage/cache/site/${uri} /app/site/site.php?url=/koken.js;
    # Catch root requests
location ~ ^/?$ {
    try_files /storage/cache/site/index/cache.$cache_ext /app/site/site.php?url=/;

# All other requests get passed back to Koken unless file already exists
# location / {
    # try_files $uri $uri/ /storage/cache/site/${uri} /storage/cache/site/${uri}cache.$cache_ext /app/site/site.php?url=$uri&$args;
# }

Closed (won't fix)

RFE up to developer - wirkaround is good enough.