Nginx Rewrite Rules for WordPress on a Subdirectory with Ruby on Rails in App

There was a Ruby on Rails (Unicorn) app running on domain root. Client wanted to have a WordPress blog on domain.com/blog. I had an idea what I should do to get this working. But it was still a challenge for me since I was a total noob to Ruby on Rails. But after few hours of searching around and seeking experts on the subject, I come up with proper rewrite rules for getting WordPress work with Ruby on Rails on an Nginx server.

Setting WordPress in a subdirectory on Nginx server is relatively easy if you have a php site on domain root. Since RoR has nothing to do with php, I had to come up with some special rewrite rules that will let RoR to handle domain root and php (fastcgi) to handle /blog directory. First thing I did was installing latest version of php5 and other WordPress requirements on the server. So I added launchpad repo to apt-sources.

sudo apt-get install python-software-properties
sudo add-apt-repository ppa:ondrej/php5

Then updated the apt cache

sudo apt-get update

Finally installed php5 and some other modules,

sudo apt-get install php5-common php5-mysql php5-xmlrpc php5-cgi php5-curl php5-gd php5-cli php5-fpm php-apc php-pear php5-dev php5-imap php5-mcrypt

Ruby on Rails developer already had rewrite rules for his app. So I made a backup of Nginx domain specific config file before touching anything. It looked like this,

upstream unicorn {
  server unix:/tmp/unicorn.app.sock fail_timeout=0;
}

server {

        listen 80;
        server_name domain.com;
        root /home/user/appname/current/public;

        location ^~ /assets/ {
        gzip_static on;
        expires max;
        add_header Cache-Control public;
        }

        try_files $uri/index.html $uri @unicorn;
             location @unicorn {
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             proxy_set_header Host $http_host;
             proxy_redirect off;
             proxy_pass http://unicorn;
             }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
}

All I had to do was to add new location block for blog and pass it to fastcgi. So first I created blog directory inside apps folder like this,

sudo mkdir /home/user/appname/blog

Then I setup WordPress there as I normally do. And then I should add a new location block to Nginx config file so requests get passed to fastcgi. New location block looked like below. Note that 2nd line, I deliberately did not include ‘blog’ in the root path so ‘blog’ becomes a part of resources. The other highlighted lines are for WordPress pretty links.

location /blog {
    root /home/user/appname;
    index index.php;

if (!-e $request_filename) {
        rewrite  ^(.*)$  /blog/index.php?q=$1  last;
      }

    location ~ .php(?|$) {
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
    }
} 

And the final site specific config file looked like this,

upstream unicorn {
    server unix:/tmp/unicorn.app.sock fail_timeout=0;
                 }

server {
    listen 80;
    server_name domain.com;
    root /home/user/appname/current/public;

        location /blog {
           root /home/user/appname;
           index index.php;

           if (!-e $request_filename) {
           rewrite  ^(.*)$  /blog/index.php?q=$1  last;
                                      }

                location ~ .php(?|$) {
                   include /etc/nginx/fastcgi_params;
                   fastcgi_index index.php;
                   fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                   fastcgi_pass unix:/var/run/php5-fpm.sock;
                                      }
                        }

         location ^~ /assets/ {
         gzip_static on;
         expires max;
         add_header Cache-Control public;
                             }

             try_files $uri/index.html $uri @unicorn;
                location @unicorn {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_pass http://unicorn;
                                  }

   error_page 500 502 503 504 /500.html;
   client_max_body_size 4G;
   keepalive_timeout 10;
        } 

Even though, I had trouble figuring it out. I came up with this solution in the end. And it doesn’t look so tough when it’s working ;).

Tharindu

Hey!! I'm Tharindu. I'm from Sri Lanka. I'm a part time freelancer and this is my blog where I write about everything I think might be useful to readers. If you read a tutorial here and want to hire me, contact me here.

5 Comments

  1. I am getting this error

    2015/09/06 15:54:43 [error] 27140#0: *1 FastCGI sent in stderr: “Primary script unknown” while reading response header from upstream, client: ***.***.*.***, server: localhost, request: “GET /blog HTTP/1.1”, upstream: “fastcgi://127.0.0.1:9000”, host: “tweelerts.com”

    1. The error message “primary script unknown” is always related to a wrongly set SCRIPT_FILENAME in the nginx fastcgi_param directive.

      Check your configuration and see if there’s line similar to this,
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button