It is very simple to use S3 as a storage for your static content in Rails application. Just add paperclip and aws-sdk gems. But what to do if you want to hide the direct links to S3 items, or even restrict access to some files by user’s roles and access rights? Here is a working example:
What we want to achieve:
img src="/p/thumb/123/cat.jpg"
This example assumes that we have two nginx endpoints: one for frontend (SPA) application, and another for backend (API) application.
At the first, let’s create a helper in your model:
The requests will be pointed to host and catched in the nginx location:
Then they will be served at your backend (Rails) application:
Note that we use secret ‘X-Project-Private’ header to prevent direct calls to your secret location.
The requests going to your Rails router:
And then to your controller:
How it works? The controller will parse request’s params, find @model, and prepare special ‘X-Accel-Redirect’ header with path (not URL) to your S3 item relatively to your bucket. The nginx catches this header internally, and sends a subrequest to “secret_store” location. Note that your visitor will not see the redirection.
In the “secret_store” location, we just rewrite it and make usual proxy request to S3 endpoint. We append a secret ‘S3_SECRET_UA’ header to respect S3 policy (see below).
Make sure it works at this step! Make sure you have all ENV values setted properly! You could broke your working website. Let’s go forward if all is OK:
S3 policy:
Please do not copy-paste policy content. Use S3 policy generator instead (you can find it in your bucket propertis). To make sure the protection works, try to open any of your S3 item’s URL directly from the browser – you should see ‘Access denied’.
If all works properly, now you can check your user’s roles and permissions in the controller to pass his requests or to block it.