A Virtual Path Gotcha with Nginx on Elastic Beanstalk

The Backstory

The product that I'm currently working on, Stre.am, runs on top of a pretty polyglot architecture. The various components utilize node + Express, Scala + Akka, Java + Play, and of course Java and Objective-C for the mobile clients. Most of my personal development efforts have been on the web application, which is the part that runs on top of node.

As longtime fanatics of AWS, we've opted to run the web app on top of Elastic Beanstalk, and we use the built-in support for Nginx to serve up static files and protect the app servers from excessively large request bodies.

This has all been working swimmingly, and we've enjoyed sitting back and watching our server logs explode with new users that some recent foreign press seems to have generated for us (watch out, Hasselhoff, now we're big in Germany!).

The Problem

Anyway, as we monitored logs we started to notice some strange 404's being generated by Nginx, resulting from failed lookups for files like var/app/current/public/dist/<some-user-name>. It's not uncommon for us to see some, shall we say, "exploratory" URLS make their way through the system, but this one turned out to be different. Fortunately, one of our team members noticed that this was only happening for usernames that started with "js".

Our Mistake (but enjoy the blame shifting...)

So, digging into our Nginx configurations (as surfaced through the Elastic Beanstalk console), we find the following Virtual Paths set:

Virtual Path (Example: /assets) Directory (Example: /static/assets)
/css /public/dist/css
/fonts /public/dist/fonts
/img /public/dist/img
/js /public/dist/js

Three things I want to highlight here:

  • There are no trailing slashes on the virtual paths or the directories they map to.
  • We did it this way because that's how the examples do it.
  • All the terminology surrounding these settings refers to actual directories.

After showing our settings, you can probably already tell what was wrong. Just to spell it out, though, Nginx was hijacking any requests to https://stre.am/<username> if that username was prefixed with one of our static directory names (css, fonts, img, and js).

At this juncture, I would like to protest that this is hardly expected behavior (at least for someone who has admittedly limited experience configuring Nginx). When dealing with virtual paths and directories, it seems strange to me that a configuration for /js would apply to paths like /jsfoobar. Not only is that counterintuitive, but the actual examples provided by Elastic Beanstalk encourage you to format the settings this way.

The Fix

Anyway, fortunately the fix is simple enough. Once you realize that we're basically just providing a find and replace on the URL path, we simply need to provide the trailing slashes. Here's our updated (and correctly functioning) virtual path configuration:

Virtual Path (Example: /assets) Directory (Example: /static/assets)
/css/ /public/dist/css/
/fonts/ /public/dist/fonts/
/img/ /public/dist/img/
/js/ /public/dist/js/

Thanks for reading, and if you happen to be more knowledgeable on the subject, please have at it in the comments!

comments powered by Disqus