I'm using proxy_pass to handle file uploading via nginx for a Rails app, and it's working fine, , except for the file permissions. Here's the current config block:

location ~ ^my_filename_regex$ {

  limit_except POST { deny all; }
  client_body_temp_path      /path/to/app/tmp;
  client_body_in_file_only   on;
  client_body_buffer_size    128K;
  client_max_body_size       1000M;

  # try_files $uri @slow-rails;
  proxy_pass                 http://elrs;
  proxy_pass_request_headers on;
  proxy_set_header           X-FILE $request_body_file; 
  proxy_set_body             off;
  proxy_redirect             off;

  # might not need?
  proxy_read_timeout         3m;

elrs is an upstream i have defined to just point to my local rails server (

The file comes through, and is saved in a tmp location, which i read from request.headers['X-FILE']: so far, so good.

The problem is that the file comes in owned by a different user (www-data, which is what nginx runs under), and doesn't have group read, so i can't get at it without doing a sudo chmod on it in my rails app, which is proving quite fragile and unreliable.

-rw------- 1 www-data www-data 1430753 Feb 23 13:36 /path/to/app/tmp/0057375433

Based on this page: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass i've added this option

      proxy_store_access user:rw group:rw all:r;

which i'd thought would set it to -rw-rw-r--, which is fine for my purposes. However, after restarting nginx and trying again, it's still coming through just with -rw-------. The new option doesn't seem to work, in other words.

Can anyone see what i'm doing wrong, or how i can diagnose the problem? I'm using Nginx v 1.9.7.

I'm not 100% sure that i do have the ngx_http_proxy_module installed: i'd assumed that if i didn't then the proxy_pass stuff would all just completely fail, but maybe that's not the case. How can i test whether it has this module?

thanks, Max

EDIT: I also just noticed, while experimenting with using a different folder to write the temp file into, that ngnix is taking ownership of that folder too: ie, before doing the file upload the folder was owned by max:max and now it's owned by www-data:max. I just mention this in case it's relevant.

  • 1
    Are you sure that nginx is responsible for creating the file and not your rails app? proxy_store_access seems to be related to proxy_store. – Richard Smith Feb 23 '16 at 18:39
  • It's definitely nginx - the file appears on the server in the location specified in the nginx config, and if i change this then it appears in the new location next time i do an upload. The rails app just reads the file location out of the request header, where nginx has written it. – Max Williams Feb 24 '16 at 8:57
  • Oh, but do you mean that i may need to set proxy_store on; as well? That sounds plausible. I'm a bit hazy on the difference between proxy_pass and proxy_store to be honest. – Max Williams Feb 24 '16 at 8:59
  • 1
    No, the xxx_store directives all relate to storing the response (and not the client request body). I cannot see how you specify permissions for client_body_temp_path. – Richard Smith Feb 24 '16 at 10:31

The only way to do this is to recompile nginx :( after editing src/os/unix/ngx_files.c and changing the file creation mask in ngx_open_tempfile from 0600 to 0660 (or whatever perms you require).

Changing the umask in the nginx init script doesn't help because of that 0600 value.

There's no user:, group: or other: configuration setting available for client_body_temp_path like there is for the proxy module.

Even though the ngx_open_tempfile function reads the access variable that might otherwise be set to something other than 0600 by calling ngx_conf_set_access_slot like it is for these modules:

171:      ngx_conf_set_access_slot,

102:      ngx_conf_set_access_slot,

111:      ngx_conf_set_access_slot,

254:      ngx_conf_set_access_slot,

291:      ngx_conf_set_access_slot,

it's not available for the client code which is part of nginx core. Hence the need for the re-compile.

As well as updating the 0600 to 0660 you'll need to chgrp your_app_server_group the client_body_temp_path directory to the group that your app belongs to, and then also setgid on it (chmod g+s your_app_server_group), so files written into it by nginx are owned by that group.


In my project I was having a similar issue. My goal was to let Nginx handle the upload and then pass it to a Django application. Even if something went wrong in the Django app I still wanted the upload to succeed and get stored to disk.

@jaygooby is right, you can't instruct Nginx to write the file under a different user, group or permissions without changing the source code.

However you can use bindfs to create an extra mount-point that points to the client_body_temp_path folder.

Install BindFS
Under Ubuntu: apt-get install bindfs
If you are using a different OS, have a look at the bindfs website.

Create the folders
Make sure that the folders exist. Assign the proper ownership and permissions.

mkdir /var/local/incoming
mkdir /var/local/processing

I point client_body_temp_path to the incoming folder. The processing folder is going to act like an automatic mirror that will provide access to the files with the proper ownership and permissions.

Configure your mount-point
Add the following line to your /etc/fstab, so that it automatically mounts the folder after a reboot. You can do a quick sudo mount -a to reload your fstab.

/var/local/incoming /var/local/processing
fuse.bindfs force-user=myUser,force-group=myGroup,perms=ug+rw 0 0

The command instructs to mount the processing folder to the incoming folder, overriding the owner/group and assigning read + write permissions.

Handle the file in your application
Extract the $request_body_file from a header (e.g. X-FILE as illustrated the question). Then rewrite the /var/local/incoming parh to /var/local/processing and you can work with the files without any issues.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.