Read more

Speed up file downloads with Rails, Apache and X-Sendfile

Henning Koch
February 09, 2011Software engineer at makandra GmbH

When you use the send_file Show archive.org snapshot method to send a local file to the browser, you can save resources on the application server by setting the :x_sendfile option to true. This option is activated by default for Rails 3, so you need to understand this.

Illustration web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
Read more Show archive.org snapshot

What this option does is not to send any data at all, but rather set the local file path as a new response header:

X-Sendfile: /opt/www/awesome-project/shared/downloads/image.png

When the response comes back from Rails to Apache for delivery, Apache will detect that header and replace the empty response body with the local file contents. This trick frees up the expensive Rails/Passenger worker process and lets the lightweight Apache worker do the heavy lifting.

You need to configure Apache to be aware of X-Sendfile or you will end up with unprocessed, zero-byte file dowloads.

Configuring the Apache module

Install the Apache module by saying

sudo apt-get install libapache2-mod-xsendfile

Check which version you got because that will be relevant later:

dpkg -l | grep libapache2-mod-xsendfile

If you have a module version < 0.10, add this to the virtual host config that needs to send files:

XSendFile On
XSendFileAllowAbove On

This allows any file path (not only those below your VHost root) to be sent through X-Sendfile, which is sort of bad practice. You can either live with it or compile a newer version of the module Show archive.org snapshot .

If you got a module version >= 0.10 you can whitelist the allowed paths instead:

XSendFile On
XSendFilePath /opt/www/awesome-project

Note that you cannot whitelist a symlink inside a current release directory, because Apache sees those downloads with their real paths (releases/123456).

Now restart Apache and you're good to go.

Posted by Henning Koch to makandra dev (2011-02-09 17:24)