1

Our website is configured in the following way:

  • The front end is powered by static HTML files created by Next.js. When a request to the front-end comes in, users are viewing these HTML files
  • Next.js pulls its data from the Wordpress API
  • When a request is not fulfilled by a static HTML file, it is passed along to wordpress
  • Because of how routes are configured, we had to remove the forward slash from all URLs (getting past this might be a solution to the question below)
  • We also need to serve some MP3 files from a static directory listing, the names of which change each week
  • The static HTML files serve from /var/www/next/source/serve
  • The Wordpress files are located in /var/www/wordpress

Here is the primary configuration:

# Expires map
map $sent_http_content_type $expires {
  default                                off;
  #text/html                              epoch;
  text/css                               max;
  application/javascript                 max;
  ~image/                                max;
  font/ttf                               max;
  font/opentype                          max;
  application/font-woff                  max;
  font/woff2                             max;
  application/vnd.ms-fontobject          max;
}

server {
  # Initial setup
  listen 443 http2 ssl;
  server_name www.website.com;

  expires $expires;

  # Include SSL configutation
  include snippets/ssl-website.com.conf;
  include snippets/ssl-params.conf;

  # Set root directory
  root /var/www/next/source/serve;

  # Access and error logs
  access_log /var/log/nginx/next_access.log;
  error_log /var/log/nginx/next_error.log;

  # GZIP
  include conf.d/gzip.conf;

  # Cache locatons
  include locations/cache-locations.conf;

  # Non-critical / one-off locations
  include locations/special-locations.conf;

  # Get rid of all trailing slashes. This makes the root (/) location below function properly
  if (!-d $request_filename) {
    rewrite ^/(.*)/$ /$1 redirect;
  }

  location ~* \.(?:eot|ttf|svg|woff|woff2)$ {
    expires max;
    add_header Vary Accept-Encoding;
    add_header Cache-Control public;
    access_log off;
  }

  # First try for the static HTML file. If not found, go to Wordpress
  location / {
    try_files $uri $uri.html $uri.html/ $uri/ /index.php?q=$uri&$args;
  }

  # Wordpress
  location ~ \.php$ {
    root /var/www/wordpress;
    index index.php index.html index.htm;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    error_log /var/log/nginx/wordpress_error.log;
  }

  # Include redirects
  include redirects/primary-redirects.conf;

}

The special-locations.conf file contains a listing of a static directory called audiofiles:

location ^~ /audiofiles {
  root /var/www/wordpress;
  autoindex on;
  break;
}

Everything works as intended right now (front-end, WP-Admin, Wordpress static resources (CSS, JS), API requests, image files, etc.), except for the static directory listing at /audiofiles.

The problem is created by the rewrite rule in the root server block. We can't move it in to the location / block (I don't think anyway) because routes of every kind are based off of the root URL.

I've tried a million configurations to get this right. What can I do here to sort this out?

******** UPDATED POST-SOLUTION ********

Thanks to @Richard Smith for his simple and elegant solution. The final configuration looks like this:

# Expires map
map $sent_http_content_type $expires {
  default                                off;
  text/css                               max;
  application/javascript                 max;
  ~image/                                max;
  font/ttf                               max;
  font/opentype                          max;
  application/font-woff                  max;
  font/woff2                             max;
  application/vnd.ms-fontobject          max;
}

server {
  # Initial setup
  listen 443 http2 ssl;
  server_name www.website.com;

  expires $expires;

  # Include SSL configutation
  include snippets/ssl-website.com.conf;
  include snippets/ssl-params.conf;

  # Set root directory
  root /var/www/next/source/serve;

  # Access and error logs
  access_log /var/log/nginx/next_access.log;
  error_log /var/log/nginx/next_error.log;

  # GZIP
  include conf.d/gzip.conf;

  # Cache locatons
  include locations/cache-locations.conf;

  # Non-critical / one-off locations
  include locations/special-locations.conf; # This file contains the `audiofiles` static file directory

  location ~* \.(?:eot|ttf|svg|woff|woff2)$ {
    expires max;
    add_header Vary Accept-Encoding;
    add_header Cache-Control public;
    access_log off;
  }

  # First try for the static HTML file. If not found, pass along to @redirects below
  location / {
    try_files $uri $uri.html $uri.html/ $uri/ @redirect;
  }

  # Some clever redirect management. Try either static files or send to Wordpress
  location @redirect {
    rewrite ^/(.*)/$ /$1 redirect;
    rewrite ^ /index.php?q=$uri&$args last;
  }

  # Wordpress
  location ~ \.php$ {
    root /var/www/wordpress;
    index index.php index.html index.htm;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    error_log /var/log/nginx/wordpress_error.log;
  }

  # Include redirects
  include redirects/migrate-redirects.conf;
}
0

It's difficult to provide a difinitive answer for a complex Nginx setup. But the $uri/ component of the try_files statement should perform the !-d $request_filename test, and then you can use a named location to perform the two redirections.

For example:

location / {
    try_files $uri $uri.html $uri.html/ $uri/ @redirect;
}
location @redirect {
    rewrite ^/(.*)/$ /$1 redirect;
    rewrite ^ /index.php?q=$uri&$args last;
}
| improve this answer | |
  • This solved the issue. Can't tell you how much time I spent on this. Was even able to completely eliminate the intricate malevolence of if. Many thanks for the simple solution. – PaulIsLoud Dec 17 '19 at 12:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.