我正在使用 proxy_pass 通过 nginx 为 Rails 应用程序处理文件上传,并且工作正常,除了文件权限之外。这是当前的配置块:
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
是我定义的上游,仅指向我的本地 Rails 服务器(127.0.0.1:3000)。
该文件通过并保存在一个 tmp 位置,我从中读取request.headers['X-FILE']
:到目前为止,一切都很好。
问题是该文件由不同的用户(www-data,这是 nginx 运行的)所拥有,并且没有组读取,所以如果不在sudo chmod
我的 Rails 中对其进行操作,我就无法获取它应用程序,事实证明它非常脆弱且不可靠。
-rw------- 1 www-data www-data 1430753 Feb 23 13:36 /path/to/app/tmp/0057375433
基于此页面: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass 我添加了这个选项
proxy_store_access user:rw group:rw all:r;
我认为将其设置为-rw-rw-r--
,这对于我的目的来说很好。然而,重新启动 nginx 并再次尝试后,它仍然可以通过-rw-------
.换句话说,新选项似乎不起作用。
任何人都可以看到我做错了什么,或者我如何诊断问题?我正在使用 Nginx 1.9.7 版。
我不是 100% 确定我确实安装了 ngx_http_proxy_module:我认为如果我没有安装,那么 proxy_pass 的东西就会完全失败,但也许情况并非如此。如何测试是否有这个模块?
谢谢,马克斯
编辑:我还刚刚注意到,在尝试使用不同的文件夹写入临时文件时,ngnix 也获得了该文件夹的所有权:即,在进行文件上传之前,该文件夹max:max
由www-data:max
.我只是提及这一点以防相关。
答案1
执行此操作的唯一方法是在编辑并更改from中的src/os/unix/ngx_files.c
文件创建掩码(或您需要的任何权限)后重新编译 nginx :(。ngx_open_tempfile
0600
0660
由于该值,更改 nginx 初始化脚本中的 umask 没有帮助0600
。
没有像代理模块那样可用的user:
或group:
配置other:
设置。client_body_temp_path
即使该ngx_open_tempfile
函数读取的access
变量可能会被设置为其他内容,而不是像这些模块那样0600
通过调用:ngx_conf_set_access_slot
src/http/modules/ngx_http_uwsgi_module.c
171: ngx_conf_set_access_slot,
src/http/modules/ngx_http_dav_module.c
102: ngx_conf_set_access_slot,
src/http/modules/ngx_http_scgi_module.c
111: ngx_conf_set_access_slot,
src/http/modules/ngx_http_fastcgi_module.c
254: ngx_conf_set_access_slot,
src/http/modules/ngx_http_proxy_module.c
291: ngx_conf_set_access_slot,
它不适用于作为 nginx 核心一部分的客户端代码。因此需要重新编译。
除了更新到您的应用程序所属组的目录外,还需要在其上设置gid()0600
,0660
以便nginx写入其中的文件归该组所有。chgrp your_app_server_group
client_body_temp_path
chmod g+s your_app_server_group
答案2
在我的项目中,我遇到了类似的问题。我的目标是让 Nginx 处理上传,然后将其传递给 Django 应用程序。即使 Django 应用程序出现问题,我仍然希望上传成功并存储到磁盘。
@jaygooby是对的,你不能在不改变源代码的情况下指示Nginx在不同的用户、组或权限下写入文件。
不过你可以使用绑定文件系统创建指向该文件夹的额外安装点client_body_temp_path
。
安装 BindFS
在 Ubuntu 下:apt-get install bindfs
如果您使用不同的操作系统,请查看绑定文件系统网站。
创建文件夹
确保文件夹存在。分配适当的所有权和权限。
mkdir /var/local/incoming
mkdir /var/local/processing
我指着client_body_temp_path
文件incoming
夹。该processing
文件夹将像一个自动镜像一样,提供对具有适当所有权和权限的文件的访问。
配置您的挂载点
将以下行添加到您的/etc/fstab
,以便它在重新启动后自动安装该文件夹。您可以快速sudo mount -a
重新加载您的fstab
.
/var/local/incoming /var/local/processing
fuse.bindfs force-user=myUser,force-group=myGroup,perms=ug+rw 0 0
该命令指示将processing
文件夹挂载到该incoming
文件夹,覆盖所有者/组并分配读+写权限。
在您的应用程序中处理文件$request_body_file
从标题中 提取(例如X-FILE
,如问题所示)。然后将/var/local/incoming
parh 重写为/var/local/processing
,您就可以毫无问题地使用这些文件。