What’s the best way to run WordPress on the same domain as a Rails application?

I’ve got a standard Rails app with Nginx and Mongrel running at http://mydomain. I need to run a WordPress blog at http://mydomain.com/blog. My preference would be to host the blog in Apache running on either the same server or a separate box but I don’t want the user to see a different server in the URL. Is that possible and if not, what would you recommend to accomplish the goal?

Related posts

Leave a Reply

5 comments

  1. Actually, since you’re using Nginx, you’re already in great shape and don’t need Apache.

    You can run PHP through fastcgi (there are examples of how to do this in the Nginx wiki), and use a URL-matching pattern in your Nginx configuration to direct some URLs to Rails and others to PHP.

    Here’s an example Nginx configuration for running a WordPress blog through PHP fastcgi (note I’ve also put in the Nginx equivalent of the WordPress .htaccess, so you will also have fancy URLs already working with this config):

    server {
        listen       example.com:80;
        server_name  example.com;
        charset      utf-8;
        error_log    /www/example.com/log/error.log;
        access_log   /www/example.com/log/access.log  main;
        root         /www/example.com/htdocs;
    
        include /www/etc/nginx/fastcgi.conf;
        fastcgi_index index.php;
    
        # Send *.php to PHP FastCGI on :9001
        location ~ .php$ {
            fastcgi_pass 127.0.0.1:9001;
        }
    
        # You could put another "location" section here to match some URLs and send
        # them to Rails. Or do it the opposite way and have "/blog/*" go to PHP
        # first and then everything else go to Rails. Whatever regexes you feel like
        # putting into "location" sections!
    
        location / {
            index index.html index.php;
            # URLs that don't exist go to WordPress /index.php PHP FastCGI
            if (!-e $request_filename) {
                rewrite ^.* /index.php break;
                fastcgi_pass 127.0.0.1:9001;
            }
    
        }
    }
    

    Here’s the fastcgi.conf file I’m including in the above config (I put it in a separate file so all of my virtual host config files can include it in the right place, but you don’t have to do this):

    # joelhardi fastcgi.conf, see http://wiki.codemongers.com/NginxFcgiExample for source
    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    $document_root$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      $document_root;
    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;
    
    # PHP only, required if PHP was built with --enable-force-cgi-redirect
    #fastcgi_param  REDIRECT_STATUS    200;
    

    I also happen to do what the Nginx wiki suggests, and use spawn-fcgi from Lighttpd as my CGI-spawner (Lighttpd is a pretty fast compile w/o weird dependencies, so a quick and easy thing to install), but you can also use a short shell/Perl script for that.

  2. I think joelhardi’s solution is superior to the following. However, in my own application, I like to keep the blog on a separate VPS than the Rails site (separation of memory issues). To make the user see the same URL, you use the same proxy trick that you normally use for proxying to a mongrel cluster, except you proxy to port 80 (or whatever) on another box. Easy peasy. To the user it is as transparent as you proxying to mongrel — they only “see” the NGINX responding on port 80 at your domain.

    upstream myBlogVPS {
            server 127.0.0.2:80;  #fix me to point to your blog VPS
    }
    
     server {
        listen       80;
    
    
        #You'll have plenty of things for Rails compatibility here
    
        #Make sure you don't accidentally step on this with the Rails config!
    
        location /blog {
            proxy_pass         http://myBlogVPS;
            proxy_redirect     off;
    
            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
    

    You can use this trick to have Rails play along with ANY server technology you want, incidentally. Proxy directly to the appropriate server/port, and NGINX will hide it from the outside world. Additionally, since the URLs will all refer to the same domain, you can seemlessly integrate a PHP-based blog, Python based tracking system, and Rails app — as long as you write your URLs correctly.