Michael MacDonald

Protecting paperclip files with nginx

In Rails on July 12, 2009 at 10:26 pm

In a Rails app I’m working on, there is a model that can have attachments and the paperclip gem is used to handle this. However, these files need to only be available to logged in users. They cannot be directly accessible to the public. For this, I used nginx’s X-Accel-Redirect response header. But, I couldn’t get it to work!

In the end, I discovered I was doing two small things wrong and thought I would share them here to help others who might make the same silly mistakes:

  • use the attachment’s url instead of its path
  • pass into response.headers[‘Content-Disposition’] a value for the filename

The last point ensures that the download file has the correct filename (if you are using something like a nested Rails route). Without it Safari would always return a word doc with an html extension.

Here’s my paperclip code inside a Report class:

has_attached_file :document,
                  :path => ':rails_root/reports/:id/:basename.:extension',
                  :url => '/reports/:id/:basename.:extension'

Here’s my reports controller code:

response.headers['X-Accel-Redirect']    = report.document.url
response.headers['Content-Type']        = report.document_content_type
response.headers['Content-Disposition'] = "inline; filename=#{report.document_file_name}"

Putting report.document.path was a mistake that caused me heaps of frustration, so don’t do it!

And finally, in my nginx.conf file:

location /reports {
  internal;
  alias /path/to/rails/root/reports;
}

One thing I also did, was to place the attached files outside of the public directory as a failsafe. If the internal setting in the nginx conf disappeared between deploys, then the sensitive files would still be protected whereas leaving them in a normally publicly accessible location is not good enough in my opinion.

See also:

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: