TransFS DevBlog / Article RSS Feed
Nginx and Rails and Wordpress, oh my…
In our recent switch to EngineYard Cloud… one of the most annoying problems I ran into was getting our Wordpress blog configured properly so that it would play nicely with our Rails app. In our previous hosting environment, we ran with an Apache setup… and we used a simple virtualhost config that looked something like this:
Alias /blog /var/www/apps/tfs_blog <Directory /var/www/apps/tfs_blog> PassengerEnabled off allow from all AllowOverride All </Directory>
With the move to EngineYard, we have made the switch to Nginx… because, after all, that’s what all the cool kids are using these days. I admit that one reason I was looking forward to Nginx was to rid myself of the awful apache config file syntax. However, I quickly learned that Nginx (or at least the version that is installed by default on the EY Cloud images) requires its own voodoo tricks in order to do seemingly simple things.
In this case, all we want to do is host our blog, alongside our rails app, at /blog. (and of course, this blog is hosted at /devblog) Unfortunately, getting this working properly required endless hour of scouring google for nginx config snippets… until I finally landed on the following, working setup:
location /blog/ { alias /data/tfs_blog/; index index.php index.html index.htm; if (-e $request_filename) { break; } rewrite ^/blog/(.+)$ /blog/index.php?q=$1; } location = /blog { fastcgi_pass 127.0.0.1:1027; fastcgi_param SCRIPT_FILENAME /data/tfs_blog/index.php; include /etc/nginx/common/fcgi.conf; } location ~ /blog/?.*\.php$ { if ($fastcgi_script_name ~ /blog/?(.*)$) { set $valid_fastcgi_script_name /$1; } fastcgi_pass 127.0.0.1:1027; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /data/tfs_blog$valid_fastcgi_script_name; include /etc/nginx/common/fcgi.conf; }
The worst thing about this, aside from the complexity required to get such a simple thing working, is that the error condition you get when the nginx fastcgi setup is misconfigured is incredibly obscure: “No input file specified.” This apparently means that fastcgi is not receiving the SCRIPT_FILENAME parameter properly… but the actual cause of this can be anything from misconfigured permissions to location paths that aren’t grabbing the proper filename from the request uri. As you can see, the final result requires manually capturing the php filename from the uri path using a regex, and then setting the SCRIPT_FILENAME env variable accordingly.
It’s also worth mentioning that this snippet:
if (-e $request_filename) {
break;
}
rewrite ^/blog/(.+)$ /blog/index.php?q=$1;… from the first block is required to make wordpress’s pretty urls map correctly to the cgi handler.
That sure was a lot of work! Hopefully this post will save someone else all the pain and headache… or maybe someone will stumble across this and show me how it can all be done in a couple of simple config lines.
4 Comments
January 21st, 2010 Jon Christensen says:
I’m trying to do the same thing, and I have a couple of questions for you. Did you set up your wordpress blog as a separate application that engine yard knows about and can deploy, or did you just go in behind the scenes and upload it straight to the instance?
Also, where does this configuration go? I assume in one of the custom.locaitons.conf files, but which one? I have two. One for my rails app and one from the wordpress app.
January 22nd, 2010 josh says:
@Jon: I manually uploaded our blog to my instance… but I could also have written a custom chef recipe that checks the source out from github, migrates the db, etc.
We do, however, have custom chef recipes that make these nginx config changes so that the blog is hosted by the same nginx that is running rails. These changes get added into our main custom.locations.conf, which is uploaded to the server in a chef block like this:
Hope this helps!
January 22nd, 2010 Jon Christensen says:
Thanks! Definitely helps. I got it working late last night. The problem was that I didn’t have PHP or a fastcgi server on my instance. That created an amazingly cryptic 502 error message.
Also, here’s something cool: I put my wordpress blog on github, and just added it as an application to engine yard. Engine Yard doesn’t complain that there’s no rails app in it, and it also goes ahead and creates a database for me. I created a chef recipe to copy the db connection settings from the engine yard created db over to wp-config.php and I’m golden.
January 22nd, 2010 josh says:
Wow… that’s awesome. I didn’t know that Engine Yard wouldn’t care that it wasn’t a rails app like that.
That’s a great trick! Very cool, thanks.