2

To use Nginx's X-Accel-Redirect feature with passenger, apparently you use passenger_set_header and, if mapping to another location, passenger_set_cgi_param. For instance, here is a configuration which apparently used to work for someone else:

passenger_set_cgi_param HTTP_X_ACCEL_MAPPING "/home/user/rails_app/shared/files/=/documents/";
passenger_pass_header X-Accel-Redirect;

location ~ ^/documents/(\d\d\d)/(\d\d\d)/(\d\d\d)/(.*)$ {
  alias /home/user/rails_app/shared/files/$1/$2/$3/$4;
  internal;
}

But with passenger 5 they say in release notes:

[Nginx] The passenger_set_cgi_param option has been removed and replaced by passenger_set_header and passenger_env_var.

Not much information about how to use the two together though for X-Accel-Redirect. No up-to-date tutorials or blogs seem to show how to do it either. How is this done? I can get the following nginx.conf to work for the rails development server (non-passenger) but it does not work with passenger.

upstream api_server {
   server localhost:5000;
   # (starting passenger with ``` RAILS_ENV=development passenger start -a 127.0.0.1 -p 5000 -d ```) not using unix:socket for a good reason
}

server {
    listen              9000;
    server_name         $host;
    return 301          https://$host:9443$request_uri;
    #error_page 497 https://$host:9443$request_uri;
}

server {
    charset UTF-8;

    server_name  localhost 0.0.0.0;

    root /var/www/html/app;

    listen 9443 ssl;
    ssl on;
    ssl_certificate /opt/nginx/conf/ssl/app.chain.pem;
    ssl_certificate_key /opt/nginx/conf/ssl/app.key.pem;

    error_page 497 https://$host:9443$request_uri;

    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Type, Keep-Alive, Date, Server, Transfer-Encoding, Cache-Control';
    add_header 'Access-Control-Allow-Headers' 'Content-Length, Content-Type, Keep-Alive, Date, Server, Transfer-Encoding, Cache-Control';


    passenger_env_var X-Sendfile-Type "X-Accel-Redirect";
    passenger_env_var X-Accel-Mapping  "/special/place/on/filesystem/=/protected_files/";
    passenger_pass_header X-Accel-Redirect;
    passenger_pass_header X-Sendfile-Type;


    # --------- Serve static applications --------

    location / {
        try_files $uri $uri/ /index.html;
    }


    # --------- API --------

    location /protected_files/{
        # Used for X-Accel-Redirect
        internal;
        add_header Pragma "no-cache";
        alias /special/place/on/filesystem/;
    }

    location ~ /(api|auth|raw)/ {

        # Host + forwarding headers
            proxy_set_header  Host              $http_host;
            proxy_set_header  X-Real-IP         $remote_addr;
            proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;

                        passenger_pass_header Host;
                        passenger_pass_header X-Real-IP;
                        passenger_pass_header X-Forwarded-For;


        # Configuration for X-Sendfile style fast & authenticated static serving
              proxy_set_header  X-Sendfile-Type   X-Accel-Redirect;
                          # proxy_set_header  X-Accel-Mapping   /mounts/test_data_filesystem/=/protected_files/;
              proxy_set_header  X-Accel-Mapping   /special/place/on/filesystem/=/protected_files/;

              passenger_env_var X-Sendfile-Type "X-Accel-Redirect";
              passenger_env_var X-Accel-Mapping  "/special/place/on/filesystem/=/protected_files/";
              passenger_pass_header X-Accel-Redirect;
              passenger_pass_header X-Sendfile-Type;


        proxy_pass http://api_server;
    }
Purrell
  • 12,461
  • 16
  • 58
  • 70
  • If you're reading this, I imagine there is still no answer. I ended up using uwsgi instead of passenger, pretty much because of this issue. Works great! – Purrell Jul 07 '15 at 05:22

1 Answers1

6

Looks like you found an alternate solution, but posting this in case others run into the same issue and wish to upgrade from Passenger 4 syntax to Passenger 5 along with X-Accel-Redirect.

The following is the changes that worked for me:

Passenger 4 version:

passenger_set_cgi_param HTTP_X_ACCEL_MAPPING /path/to/railsapp/public/=/storage/;
passenger_pass_header X-Accel-Redirect;

location /storage {
  root /var/www/shared;
  internal;
}

Passenger 5 version:

passenger_set_header X-Sendfile-Type "X-Accel-Redirect";
passenger_env_var HTTP_X_ACCEL_MAPPING /path/to/railsapp/public/=/storage/;
passenger_pass_header X-Accel-Redirect;

location /storage {
  root /var/www/shared;
  internal;
}

Also, there's a symbolic link to the rails app in /var/www/shared, ln -s /path/to/railsapp/public /var/www/shared/storage, however this can be different based on your nginx configuration.

Hope this helps!

remo
  • 498
  • 5
  • 8
  • Excellent hope it helps someone! – Purrell Jan 12 '16 at 21:13
  • The only problem about this solution (I'm using Rails 5) is that now I'm not able to take advantage of ETag headers anymore. Apparently Rails is forwarding the baton berfore the etag headers are sent back to Nginx. Any ideas? – leandroico Feb 13 '17 at 20:01
  • I checked, and it still appears to be generating ETags for me. Are you using nginx >= 1.7.3? [Nginx stripped ETags](http://stackoverflow.com/questions/31125888/nginx-missing-etag-when-gzip-is-used) prior to this version when combined with gzip. – remo Feb 14 '17 at 15:21